声明: 我2天前第一次开始为Android(手机)编程,所以我不是那么有经验。我对C ++相当不错,但我几次只触及Java。
问题: 当我在我的模拟器中运行我的游戏时,该应用程序正常工作。但是,当我按下Home按钮时,我的LogCat中通常会出现一些红线,并且在模拟器中,消息“Unfortunatly,[app name]已停止。”弹出。如果没有发生这种情况,那么当我尝试再次打开应用程序时,它就会出现。
可能有助于找到问题的一些信息: 我从这个教程开始: http://www.edu4java.com/androidgame.html 当我尝试使用onDraw函数时,我必须添加“@SuppressLint(”WrongCall“)”abow使用“onDraw”的函数。该教程没有说明任何内容,所以我有点困惑。
logcat的:
06-09 01:51:43.161: E/AndroidRuntime(23830): FATAL EXCEPTION: Thread-1173
06-09 01:51:43.161: E/AndroidRuntime(23830): java.lang.NullPointerException
06-09 01:51:43.161: E/AndroidRuntime(23830): at com.example.braincollect.Background.onDraw(Background.java:24)
06-09 01:51:43.161: E/AndroidRuntime(23830): at com.example.braincollect.GameView.onDraw(GameView.java:132)
06-09 01:51:43.161: E/AndroidRuntime(23830): at com.example.braincollect.GameLoopThread.run(GameLoopThread.java:37)
Background.java代码:24:
canvas.drawBitmap(bmp, 0, 0, null);
GameView.java代码:117
introBackground.onDraw(canvas);
GameLoopThread.java代码:37:
view.getHolder().unlockCanvasAndPost(c);
我的项目中有7个java类: MainActivity(活动), GameView(视图), GameLoopThread(游戏循环), 背景图片), 脑(图像), 僵尸(图像), 计时器(只是一些数字handeling)
MainActivity.java:
package com.example.braincollect;
import android.media.AudioManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.view.KeyEvent;
import android.view.Window;
public class MainActivity extends Activity {
private AudioManager am;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new GameView(this));
am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
return true;
case KeyEvent.KEYCODE_MENU:
return true;
case KeyEvent.KEYCODE_VOLUME_UP:
am.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
return true;
case KeyEvent.KEYCODE_VOLUME_DOWN:
am.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI);
return true;
default:
return false;
}
}
}
GameView.java:
package com.example.braincollect;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.media.MediaPlayer;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView {
private Bitmap bmp;
private Bitmap bmp2;
private Bitmap bmp3;
private Bitmap bmp4;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private Timer timer;
public Background introBackground;
public Background background;
private Zombie zombie;
private Brain brain;
private int score = 0;
MediaPlayer mTheme;
MediaPlayer mGameover;
MediaPlayer mBrain;
MediaPlayer mCollect;
Context myContext;
int pauseTimer;
boolean intro = true;
public GameView(Context context) {
super(context);
myContext = context;
gameLoopThread = new GameLoopThread(this);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
gameLoopThread.setRunning(false);
mTheme.stop();
while (gameLoopThread != null) {
try {
gameLoopThread.join();
gameLoopThread = null;
} catch (InterruptedException e) {
}
}
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
});
timer = new Timer(context);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.zombie);
zombie = new Zombie(this, bmp);
bmp2 = BitmapFactory.decodeResource(getResources(), R.drawable.brain);
brain = new Brain(this, bmp2);
bmp3 = BitmapFactory.decodeResource(getResources(), R.drawable.background);
background = new Background(this, bmp3);
bmp4 = BitmapFactory.decodeResource(getResources(), R.drawable.intro);
introBackground = new Background(this, bmp4);
// Music
mTheme = MediaPlayer.create(context, R.raw.theme);
mTheme.setLooping(true);
mTheme.setVolume(0.99f, 0.99f);
mBrain = MediaPlayer.create(context, R.raw.brain);
mBrain.setVolume(0.9f, 0.9f);
mCollect = MediaPlayer.create(context, R.raw.getbrain);
mCollect.setVolume(0.2f, 0.2f);
mGameover = MediaPlayer.create(context, R.raw.gameover);
mGameover.setVolume(0.2f, 0.2f);
pauseTimer = 0;
}
@SuppressLint({ "WrongCall", "DrawAllocation" })
@Override
protected void onDraw(Canvas canvas) {
if(intro == true) {
introBackground.onDraw(canvas);
Paint paint;
paint = new Paint();
paint.setARGB(200, 255, 0, 0);
paint.setTextSize(30);
if(pauseTimer >= 20) {
canvas.drawText("Click to play!", 100, getHeight() - 200, paint);
}
pauseTimer += 1;
}
else if(gameLoopThread.pause == false) {
background.onDraw(canvas);
brain.onDraw(canvas);
zombie.onDraw(canvas);
timer.onDraw(canvas);
if(zombie.isWalking) {
timer.update();
}
Paint paint;
paint = new Paint();
paint.setARGB(200, 255, 0, 0);
paint.setTextSize(25);
canvas.drawText(Integer.toString(score), 10, 30, paint);
if(zombie.isCollition(brain.x, brain.y, brain.width, brain.height)) {
brain.changePos();
if(zombie.isWalking) {
score += 1;
mBrain.start();
}
timer.reset();
}
if(timer.width <= 0) {
mGameover.start();
pauseTimer = 0;
gameLoopThread.pause = true;
mTheme.setVolume(0.3f, 0.3f);
}
} else {
background.onDraw(canvas);
Paint paint;
paint = new Paint();
paint.setARGB(200, 255, 0, 0);
paint.setTextSize(30);
canvas.drawText("Your Score: " + Integer.toString(score), 100, (getHeight() / 2) - 40, paint);
if(pauseTimer >= 20) {
canvas.drawText("Click to play again!", 100, getHeight() / 2, paint);
}
pauseTimer += 1;
}
}
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN) {
zombie.changeDir();
if(intro == true && pauseTimer >= 20) {
intro = false;
mTheme.start();
mCollect.start();
pauseTimer = 0;
gameLoopThread.pause = false;
mTheme.setVolume(0.99f, 0.99f);
mTheme.start();
timer.width = timer.widthMax;
score = 0;
zombie.x = zombie.xStart;
zombie.y = zombie.yStart;
zombie.isWalking = false;
zombie.xSpeed = 1;
zombie.ySpeed = 0;
zombie.currentFrame = 0;
brain.changePos();
}
if(gameLoopThread.pause == true && pauseTimer >= 20) {
pauseTimer = 0;
gameLoopThread.pause = false;
mTheme.setVolume(0.99f, 0.99f);
mTheme.start();
mCollect.start();
timer.width = timer.widthMax;
score = 0;
zombie.x = zombie.xStart;
zombie.y = zombie.yStart;
zombie.isWalking = false;
zombie.xSpeed = 1;
zombie.ySpeed = 0;
zombie.currentFrame = 0;
brain.changePos();
}
}
return super.onTouchEvent(event);
}
}
(“bmp”名称只是暂时的,所有声音都不是MediaPlayer对象)
GameLoopThread.java:
package com.example.appname;
import android.annotation.SuppressLint;
import android.graphics.Canvas;
public class GameLoopThread extends Thread {
static final long FPS = 10;
private GameView view;
public boolean running = false;
public boolean pause = false;
public GameLoopThread(GameView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
@SuppressLint("WrongCall") @Override
public void run() {
long ticksPS = 1000 / FPS;
long startTime;
long sleepTime;
while (running) {
Canvas c = null;
startTime = System.currentTimeMillis();
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.onDraw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
try {
if (sleepTime > 0)
sleep(sleepTime);
else
sleep(10);
} catch (Exception e) {}
}
}
}
如果您需要查看更多代码,请告诉我们。我不知道故障在哪里。
答案 0 :(得分:1)
我很确定该视图将等于null传递给GameLoopThread构造函数,因此当您调用setRunning(true)
时,此行将抛出NPE:
c = view.getHolder().lockCanvas();
您应该通过调用GameLoopThread(view)
发布其他代码片段,以便更好地了解问题。
祝你好运
答案 1 :(得分:0)
这很简单,在Grass.java
文件的第24行,您有一个NullPointerException
,因此使用断点和Debug
模式(而不是Run
)可以轻松检查该行的值,并查看哪些变量可能为null,并在该行之前放置一个空检查器或捕获异常:
1
if(canvas != null) {
...
}
2
try {
...
} catch (NullPointerException e) {
....
}