尝试制作具有接受触摸事件的表面视图的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表示感谢!

10-06 10:05