免责声明:我在 2 天前第一次开始为 Android(手机)编程,所以我没有那么有经验。我对 C++ 相当熟悉,但我只接触过几次 Java。
问题:当我在模拟器中运行游戏时,该应用程序按预期运行。但是,当我按下 Home 按钮时,我的 LogCat 中通常会出现一些红线,并且在模拟器中会显示“不幸的是,[app name] 已停止”的消息。弹出。如果这没有发生,当我尝试再次打开应用程序时它会发生。
一些可能有助于找到问题的信息:我从本教程开始: http : //www.edu4java.com/androidgame.html 当我尝试使用 onDraw 函数时,我必须添加“@SuppressLint(” WrongCall")" abow 使用“onDraw”的函数。教程没有说什么,所以我有点困惑。
日志猫:
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(activity)、GameView(view)、GameLoopThread(处理游戏循环)、Background(image)、Brain(image)、Zombie(image)、Timer(只是一些数字处理)
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;
}
}
}
游戏视图.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) {}
}
}
}
如果您需要查看更多代码,请告诉我。我不知道错在哪里。