0

好的,所以我一直在做一个小游戏,渲染代码有问题。因此,我尝试按照使用 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;
}
}

和中的代码

游戏线程.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 调用,我知道它会执行。它也不会产生错误消息。感谢您在高级的帮助!

4

2 回答 2

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游戏循环讲解 Android游戏基本结构

希望这可以帮助 :]

于 2013-10-15T02:23:18.563 回答
1

好的,事实证明这是 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);
}
于 2013-10-15T03:37:14.963 回答