当您按下主页或返回按钮说“不幸的是,Rocks 已崩溃”时,我的应用程序当前崩溃。我已将其缩小到如下代码行:
// draws the canvas on the panel
this.gamePanel.render(canvas);
在这种情况下:
package com.background.rocks;
import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;
public class MainThread extends Thread {
private static final String TAG = MainThread.class.getSimpleName();
// desired fps
private final static int MAX_FPS = 50;
// maximum number of frames to be skipped
private final static int MAX_FRAME_SKIPS = 5;
// the frame period
private final static int FRAME_PERIOD = 1000 / MAX_FPS;
// Surface holder that can access the physical surface
private SurfaceHolder surfaceHolder;
// The actual view that handles inputs
// and draws to the surface
private Graphics gamePanel;
// flag to hold game state
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder, Graphics gamePanel) {
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
@Override
public void run() {
Canvas canvas;
Log.d(TAG, "Starting game loop");
long beginTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped
sleepTime = 0;
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing
// in the surface
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
beginTime = System.currentTimeMillis();
framesSkipped = 0; // resetting the frames skipped
// update game state
this.gamePanel.update();
// render state to the screen
// draws the canvas on the panel
this.gamePanel.render(canvas);
// calculate how long did the cycle take
timeDiff = System.currentTimeMillis() - beginTime;
// calculate sleep time
sleepTime = (int) (FRAME_PERIOD - timeDiff);
if (sleepTime > 0) {
// if sleepTime > 0 we're OK
try {
// send the thread to sleep for a short period
// very useful for battery saving
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
// we need to catch up
this.gamePanel.update(); // update without rendering
sleepTime += FRAME_PERIOD; // add frame period to check if in next frame
framesSkipped++;
}
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}
}
但我是使用画布的新手,所以我不知道如何修复它。它会创建一个 NullPointerException,因此我假设它与恢复应用程序或暂停应用程序时画布未正确存储有关。
编辑:图形类(没有导入):
package com.background.rocks;
public class Graphics extends SurfaceView implements SurfaceHolder.Callback {
private static final String TAG = Graphics.class.getSimpleName();
private MainThread thread;
private Player player;
private ArrayList<Rock> rocks = new ArrayList<Rock>();
private Random random = new Random();
private CountDownTimer countdown;
public Graphics(Context context) {
super(context);
// adding the callback (this) to the surface holder to intercept events
getHolder().addCallback(this);
// create shape and load bitmap
player = new Player(BitmapFactory.decodeResource(getResources(), R.drawable.player_orange), 540, 1500);
// create the game loop thread
thread = new MainThread(getHolder(), this);
// make the GamePanel focusable so it can handle events
setFocusable(true);
timer();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// at this point the surface is created and
// we can safely start the game loop
thread.setRunning(true);
thread.start();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Surface is being destroyed");
// tell the thread to shut down and wait for it to finish
// this is a clean shutdown
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
Log.d(TAG, "Thread was shut down cleanly");
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// delegating event handling to the shape
player.handleActionDown((int) event.getX(), (int) event.getY());
// check if in the lower part of the screen we exit
if (event.getY() > getHeight() - 50) {
thread.setRunning(false);
((Activity) getContext()).finish();
} else {
Log.d(TAG, "Coords: x=" + event.getX() + ",y=" + event.getY());
}
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
// the gestures
if (player.isTouched()) {
// the shape was picked up and is being dragged
player.setX((int) event.getX());
player.setY((int) event.getY());
}
}
if (event.getAction() == MotionEvent.ACTION_UP) {
// touch was released
if (player.isTouched()) {
player.setTouched(false);
}
}
return true;
}
**public void render(Canvas canvas) {
if (canvas != null) {
canvas.drawColor(Color.WHITE);
player.draw(canvas);
Rock[] rockArray = rocks.toArray(new Rock[0]);
for (Rock rock : rockArray) {
rock.draw(canvas);
}
}
}**
/**
* This is the game update method. It iterates through all the objects and
* calls their update method if they have one or calls specific engine's
* update method.
*/
public void update() {
Rock[] rockArray = rocks.toArray(new Rock[0]);
for (Rock rock : rocks) {
rock.update();
}
}
public void timer() {
if (countdown != null) {
countdown.cancel();
}
countdown = new CountDownTimer(30000, 800) {
public void onTick(long millisUntilFinished) {
rocks.add(new Rock(BitmapFactory.decodeResource(getResources(), R.drawable.rock), random.nextInt(1080 - 1) + 1, 0));
}
public void onFinish() {
countdown.start();
}
}.start();
}
}
编辑 2:所以我设法在 Graphics 中更改了我的 Render 方法,因此当您按下 home 或 back 时,应用程序现在不会崩溃,但是当我尝试恢复应用程序时,我得到一个黑屏。我假设是因为它没有重新加载画布,但我不知道该怎么做,有什么帮助吗?