在调用onDraw时没有绘制Android?

时间:2013-10-15 01:35:12

标签: 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调用,我知道它会执行。它也不会产生错误消息。感谢先进的帮助!

2 个答案:

答案 0 :(得分: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

希望这会有所帮助:]

答案 1 :(得分: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);
}