【问题标题】:Android nothing being drawn when onDraw is called?调用onDraw时Android什么也没画?
【发布时间】:2013-10-15 01:35:12
【问题描述】:

好的,我一直在做一个小游戏,但渲染代码有问题。因此,我尝试按照使用 SurfaceView 的教程进行操作,这就是我目前所拥有的:

GameSurface.java

package com.spng453.afirelitroom;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {

private GameThread thread;
public SurfaceHolder surfaceHolder;



DisplayMetrics metrics = GameActivity.metrics;
final private int sX = metrics.widthPixels;
final private int sY = metrics.heightPixels;
private Paint mainBTheme = new Paint();
Rect fireButton = new Rect(0, sY/2+50, sX, sY/2-50);

public GameSurface(Context context) {
    super(context);
    surfaceHolder = getHolder();
    surfaceHolder.addCallback(this);
    this.setWillNotDraw(false);
    thread = new GameThread(surfaceHolder, this);
    this.setFocusable(true);
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    // TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    thread.setRunning(true);
    thread.run();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    boolean done = false;
    while(!done) {
        try {
            thread.join();
            done = true;
        } 
        catch (InterruptedException e) {
        }
    }
}

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawRGB(255, 255, 0);
}

@Override 
public boolean onTouchEvent(MotionEvent event) {
    return true;
}
}

以及

中的代码

GameThread.java:

package com.spng453.afirelitroom;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;

public class GameThread extends Thread {

DisplayMetrics metrics = GameActivity.metrics;
final private int sX = metrics.widthPixels;
final private int sY = metrics.heightPixels;
private int FPS = 30;
private boolean running;
public SurfaceHolder surfaceHolder;
public GameSurface gameSurface;
public Canvas canvas;
private long firstTime = 0L, secondTime = 0L; //fps stuff

private Paint mainBTheme = new Paint();


//fire page
Rect fireButton = new Rect(0, sY/2+50, sX, sY/2-50);
Rect leftButton = new Rect();
Rect rightButton = new Rect();


//city/resources page


public void setRunning(boolean running) {
    this.running = running;
}

public GameThread(SurfaceHolder surfaceHolder, GameSurface gameSurface) {
    super();
    this.surfaceHolder = surfaceHolder;
    this.gameSurface = gameSurface;
    mainBTheme.setColor(Color.BLACK);
}

@Override
public void run() {
    while (running) {
        //hey i guess i have to cap fps :(
        firstTime = System.nanoTime();
        //do the game here
        canvas = null;
        canvas = surfaceHolder.lockCanvas();
        gameSurface.onDraw(canvas);
        surfaceHolder.unlockCanvasAndPost(canvas);


        secondTime = System.nanoTime();
        if (secondTime/1000000 - firstTime/1000000 < 1000/FPS) { //the if the lag is less than the distance between frames at 30 fps
            try {
                Thread.sleep(1000/FPS - (secondTime/1000000 - firstTime/1000000));
            } catch (InterruptedException e) {
            }
        }
    }
}
}

所以,我的问题是,当我在这里尝试在 GameThread 中调用 onDraw 时:

canvas = null;
canvas = surfaceHolder.lockCanvas();
gameSurface.onDraw(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);

它完全没有任何作用。它不会绘制我放入 onDraw 的任何内容,但如果我在 onDraw 中放入 Log 调用,我知道它会执行。它也不会产生错误消息。感谢您的帮助!

【问题讨论】:

    标签: java android surfaceview ondraw


    【解决方案1】:

    试试这个:

    改变你的方法:

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawRGB(255, 255, 0);
        }
    

    通过这个:

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawRGB(255, 255, 0);
            super.onDraw(canvas);
        }
    

    另外,请尝试更改以下行:

        //do the game here
        canvas = null;
        canvas = surfaceHolder.lockCanvas();
        gameSurface.onDraw(canvas);
        surfaceHolder.unlockCanvasAndPost(canvas);
    

    通过这些:

        Canvas canvas = null;
    
        try {
            canvas = surfaceHolder.lockCanvas();
            synchronized (surfaceHolder) {
                gameSurface.onDraw(canvas);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (canvas != null)
                surfaceHolder.unlockCanvasAndPost(canvas);
        }
    

    还要注意,while 循环运行得非常快,没有机会绘制画布。线程睡眠不是很好。查看此资源,其中解释了游戏如何正确循环。如果你现在想测试它,只需抹掉这段时间。

    Android game loop explained Android game basic structure

    希望这会有所帮助:]

    【讨论】:

    • 这并没有做任何事情,很遗憾。我不完全确定我是否正确或在正确的位置调用了 onDraw,但我不确定。另外,最后,为了显示表面视图,我调用了 setContentView(new GameSurface(this));在 GameActivity.java (我的活动类)中。不过谢谢!
    • @qwertyman 我更新了我的答案。我只是根据你的代码检查我自己的代码行。如果这对您没有帮助,请告诉我。
    • 还有this.setWillNotDraw(false);这行好像有点不对劲,你为什么用它?
    • 嗯,这真的很奇怪。这段代码也没有工作,但我有一个问题。同步的(surfaceHolder)究竟做了什么?另外,@astinx,我正在使用 this.setWillNotDraw(false);因为我阅读了其他一些可以帮助解决问题的线程,对于有类似问题的人。我开始认为这是一个潜在问题,因为我在测试设备上收到此应用程序没有响应错误消息。我会尝试进一步调查。我怎样才能找出应用程序挂起的位置?
    • @qwertyman 当任何消息被发送到surfaceHolder时执行块内的代码,我认为这是为了避免一些线程在你绘制之前解锁画布。我发现了问题,现在我将更新我的答案。
    【解决方案2】:

    好的,事实证明这是 FPS 代码执行速度过快的问题。我通过这样做解决了它:

    @Override
    public void run() {
        // TODO Auto-generated method stub
        final int fps = 30;
        Timer fpsTimer = new Timer();
        fpsTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                Canvas canvas;
                canvas = null;
                try {
                    canvas = surfaceHolder.lockCanvas(null);
                    synchronized (surfaceHolder) {
                        onDraw(canvas);
                    }
                } finally {
                    if (canvas != null) {
                        surfaceHolder.unlockCanvasAndPost(canvas);
                    }
                }
            }
    
        }, 0, 1000/fps);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多