java - Android 调用 onDraw 时没有绘制任何内容?

标签 java android surfaceview ondraw

好的,我一直在开发一个小游戏,渲染代码有问题。因此,我尝试遵循使用 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 调用,我知道它会执行。它也不会产生错误消息。感谢您的提前帮助!

最佳答案

试试这个:

改变你的方法:

    @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 循环运行得非常快,没有机会绘制 Canvas 。线程 sleep 工作得不太好。看看这个资源,其中解释了游戏如何正确循环。如果您想立即测试它,只需删除 while 即可。

Android game loop explained Android game basic structure

希望这有帮助:]

关于java - Android 调用 onDraw 时没有绘制任何内容?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19371942/

相关文章:

java - 在刽子手游戏中用缺失的字母填充每个位置

java - 如何在单个集合中获取 grails 域类的所有持久属性及其约束?

java - 从 JUnit 命令行获取测试列表

android - 编译和引擎项目时出错

android - 在 SurfaceView Canvas 上平铺位图

android - 从另一个 Activity 返回时 SurfaceView 崩溃

android - 在相机预览中不工作 setAlpha

java - 将 Winstone 嵌入 jetty 服务器

android - 在 android 中打开与 facebook 应用程序的链接

android - 使用 Gradle 在 Dalvik 中自定义类加载(Android 新构建系统)