尝试制作具有接受触摸事件的表面视图的android游戏。
直到我真正触摸屏幕并读取MotionEvent.ACTION_DOWN中的代码,它才能正常工作。
这是发生错误的Java文件:
package com.irksomesloth.botbreaker;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class GameView extends SurfaceView implements SurfaceHolder.Callback{
private GameLogic session;
private SurfaceHolder holder;
private FrameThread thread;
private Point pntTouch;
private int[] intTouchedTimer;
private Bitmap bmpLaneIdle;
private Bitmap bmpLaneTouched;
private Bitmap bmpLaneBroke;
private Point pntLane;
private ShotLane[] lanes;
private Bitmap bmpBullet;
private Point pntBullet;
private Bitmap bmpPlayerIdle;
private Bitmap bmpPlayerDead;
private boolean blnInstanced = false;
private boolean blnGameLoss;
private Paint p;
private Matrix m;
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
holder = getHolder();
//instance animation thread
thread = new FrameThread(this);
//instance lane sprites
bmpLaneIdle = BitmapFactory.decodeResource(getResources(), R.drawable.laneidle);
bmpLaneTouched = BitmapFactory.decodeResource(getResources(), R.drawable.lanetouched);
bmpLaneBroke = BitmapFactory.decodeResource(getResources(), R.drawable.lanebroke);
//instance point for positioning lanes
pntLane = new Point();
//instance bullet sprite
bmpBullet = BitmapFactory.decodeResource(getResources(), R.drawable.bullet);
//instance point for rotating bullet sprite
pntBullet = new Point();
//instance player sprites
bmpPlayerIdle = BitmapFactory.decodeResource(getResources(), R.drawable.player);
bmpPlayerDead = BitmapFactory.decodeResource(getResources(), R.drawable.playerdead);
//instance lane data variables
intTouchedTimer = new int[6];
lanes = new ShotLane[6];
//instance drawing tools
p = new Paint();
m = new Matrix();
//add our callback
holder.addCallback(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//now that our surfaceview has dimensions
//we can instance our game logic contoller
session = new GameLogic(getWidth(), getHeight());
//...and start the animation thread
thread.setState(true);
thread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean blnRetry = true;
thread.setState(false);
while(blnRetry){
try{
thread.join();
blnRetry = false;
}
catch(InterruptedException e){
}
}
}
@SuppressLint("DrawAllocation")
@Override
public void onDraw(Canvas canvas){
canvas.drawColor(Color.BLACK);
//lets update our game controller
//and see if we got a game over
blnGameLoss = session.Update();
//on our first ondraw well instance our lanes
for(int i = 0; i < 6; i++){
if(!blnInstanced){
pntLane.x = session.getPlayerX() - (bmpLaneIdle.getWidth() / 2);
pntLane.y = session.getPlayerY() - bmpLaneIdle.getHeight();
lanes[i] = new ShotLane(bmpLaneIdle, bmpLaneTouched, bmpLaneBroke, (i + 1), pntLane.x, pntLane.y, session.getCornerAngle());
}
Rect recTouchCheck = lanes[i].getBox();
//now we check it the user has triggered our ontouchevent
if(pntTouch != null){
//if so lets see if the user touched one of the lanes
if(recTouchCheck.contains(pntTouch.x, pntTouch.y)){
if(lanes[i].getCurrentSprite().getPixel(pntTouch.x - recTouchCheck.left,
pntTouch.y - recTouchCheck.top) != Color.TRANSPARENT){
boolean hit = session.Shoot(i + 1);
if(hit){
//if they touched a lane containing a bullet
//validate their input
lanes[i].setBitmap(1);
intTouchedTimer[i] = 20;
}
else{
//if the lane didn't have a bullet
//the player died so lets turn the lane
//that killed them red
lanes[i].setBitmap(2);
}
}
}
//if a touch was processed wipe the touch data
pntTouch = null;
}
//positioning and rotating lanes before they're drawn
m.reset();
m.postTranslate(lanes[i].getX(), lanes[i].getY());
m.postRotate((float) lanes[i].getAngle(), session.getPlayerX(),
session.getPlayerY());
//draw the lanes
canvas.drawBitmap(lanes[i].getCurrentSprite(), m, p);
//run the timer that resets a touched lane
if(intTouchedTimer[i] == 0){
lanes[i].setBitmap(0);
}
else{
intTouchedTimer[i]--;
}
}
//the lanes were instanced in this loop
//so we wont need to re-instance them
blnInstanced = true;
//process and draw any bullets that are in play
for(int b = 0; b < session.getBulletCount(); b++){
pntBullet.x = session.getBulletX(b) - (bmpBullet.getWidth() / 2);
pntBullet.y = session.getBulletY(b) - (bmpBullet.getHeight() / 2);
m.reset();
m.postTranslate(pntBullet.x, pntBullet.y);
m.postRotate((float) session.getBulletAngle(b), session.getBulletX(b), session.getBulletY(b));
canvas.drawBitmap(bmpBullet, m, p);
}
//handle any confirmed game losses
if(blnGameLoss){
thread.setState(false);
canvas.drawBitmap(bmpPlayerDead, session. getPlayerX() - (bmpPlayerDead.getWidth() / 2), session.getPlayerY() - (bmpPlayerDead.getHeight() / 2), p);
}
else{
//if we haven't lost, draw the player as normal
canvas.drawBitmap(bmpPlayerIdle, session. getPlayerX() - (bmpPlayerIdle.getWidth() / 2), session.getPlayerY() - (bmpPlayerIdle.getHeight() / 2), p);
}
}
@Override
public boolean onTouchEvent(MotionEvent event){
if(event.getAction() == MotionEvent.ACTION_DOWN){
//the following 2 lines are the cause of an exception
pntTouch.x = (int) event.getX();
pntTouch.y = (int) event.getY();
}
return true;
}
}
调试后,我发现仅在以下情况下才发生此问题:
pntTouch.x = (int) event.getX();
pntTouch.y = (int) event.getY();
没有被注释掉。
这是随附的logcat供参考:
04-23 02:35:48.264: W/Surface(3126): WARNING: Surface's mNativeObject (0xb7602558) != mLockedObject (0xb7601d10)
04-23 02:36:08.894: E/InputEventReceiver(3126): Exception dispatching input event.
04-23 02:36:08.894: E/MessageQueue-JNI(3126): Exception in MessageQueue callback: handleReceiveCallback
04-23 02:36:09.024: E/MessageQueue-JNI(3126): java.lang.NullPointerException
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at com.irksomesloth.botbreaker.GameView.onTouchEvent(GameView.java:183)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.View.dispatchTouchEvent(View.java:7690)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2066)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1515)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.app.Activity.dispatchTouchEvent(Activity.java:2457)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2014)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.View.dispatchPointerEvent(View.java:7870)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3919)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3808)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3406)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3456)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3425)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3510)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3433)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3567)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3406)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3456)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3425)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3433)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3406)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5520)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5500)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5471)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5594)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:182)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.os.MessageQueue.nativePollOnce(Native Method)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.os.MessageQueue.next(MessageQueue.java:137)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.os.Looper.loop(Looper.java:124)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at android.app.ActivityThread.main(ActivityThread.java:4998)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at java.lang.reflect.Method.invokeNative(Native Method)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at java.lang.reflect.Method.invoke(Method.java:515)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
04-23 02:36:09.024: E/MessageQueue-JNI(3126): at dalvik.system.NativeStart.main(Native Method)
04-23 02:36:09.024: D/AndroidRuntime(3126): Shutting down VM
04-23 02:36:09.034: W/dalvikvm(3126): threadid=1: thread exiting with uncaught exception (group=0xb1a58b90)
04-23 02:36:09.134: E/AndroidRuntime(3126): FATAL EXCEPTION: main
04-23 02:36:09.134: E/AndroidRuntime(3126): Process: com.irksomesloth.botbreaker, PID: 3126
04-23 02:36:09.134: E/AndroidRuntime(3126): java.lang.NullPointerException
04-23 02:36:09.134: E/AndroidRuntime(3126): at com.irksomesloth.botbreaker.GameView.onTouchEvent(GameView.java:183)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.View.dispatchTouchEvent(View.java:7690)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1917)
04-23 02:36:09.134: E/AndroidRuntime(3126): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2066)
04-23 02:36:09.134: E/AndroidRuntime(3126): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1515)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.app.Activity.dispatchTouchEvent(Activity.java:2457)
04-23 02:36:09.134: E/AndroidRuntime(3126): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2014)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.View.dispatchPointerEvent(View.java:7870)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3919)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3808)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3406)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3456)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3425)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3510)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3433)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3567)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3406)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3456)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3425)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3433)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3406)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5520)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5500)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5471)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5594)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:182)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.os.MessageQueue.nativePollOnce(Native Method)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.os.MessageQueue.next(MessageQueue.java:137)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.os.Looper.loop(Looper.java:124)
04-23 02:36:09.134: E/AndroidRuntime(3126): at android.app.ActivityThread.main(ActivityThread.java:4998)
04-23 02:36:09.134: E/AndroidRuntime(3126): at java.lang.reflect.Method.invokeNative(Native Method)
04-23 02:36:09.134: E/AndroidRuntime(3126): at java.lang.reflect.Method.invoke(Method.java:515)
04-23 02:36:09.134: E/AndroidRuntime(3126): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
04-23 02:36:09.134: E/AndroidRuntime(3126): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
04-23 02:36:09.134: E/AndroidRuntime(3126): at dalvik.system.NativeStart.main(Native Method)
最佳答案
pntTouch尚未初始化,请尝试以下操作:
private Point pntTouch = new Point();
对Hashir Sheikh表示感谢!