触摸时出现 andEngine 空异常

andEngine Null Exception on Touch

我是 Android 开发的新手,今天遇到了一个问题。当我点击一个切换场景的按钮时,它给了我一个空指针异常。奇怪的是,即使我从触摸事件中注释掉 "setScene" 行,它仍然会崩溃。这是我的完整代码..

GameActivity.java:(游戏activity的基础class——不是游戏场景)

public class GameActivity extends BaseGameActivity {

 static final int CAMERA_WIDTH = 480;
    static final int CAMERA_HEIGHT = 800;
    Camera mCamera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);
    
    static SceneManager sceneManager;
      
  @Override
 public void onCreateResources(
   OnCreateResourcesCallback pOnCreateResourcesCallback)
   throws Exception {
   sceneManager = new SceneManager(this, mEngine, mCamera);
     sceneManager.loadSplashSceneResources();
     pOnCreateResourcesCallback.onCreateResourcesFinished();
  
 }
... Just to make you see sceneManager is not null ...

MenuScene.java: "Play" 按钮位于.. 点击

时游戏崩溃

public class MenuScene extends mScene{
//mScene is a class extends Scene and has abstract methods such as //"LoadResources". I call the methods on the loading screen 
 BitmapTextureAtlas LogoAtlas;
 TextureRegion LogoRegion;
 Sprite LogoSprite;
 Rectangle StartGame;
 
 public MenuScene(BaseGameActivity activity) {
  super(activity);
  // TODO Auto-generated constructor stub
 }

 @Override
 public void LoadResources() {
  // TODO Auto-generated method stub
  LogoAtlas=new BitmapTextureAtlas(activity.getTextureManager(),300, 300); 
  LogoRegion=BitmapTextureAtlasTextureRegionFactory.createFromAsset(LogoAtlas, activity, "Logo.png", 0, 0);
  LogoAtlas.load();
 }

 @Override
 public void CreateSceneObjects() {
  // TODO Auto-generated method stub
  this.setBackground(new Background(new Color(1f,1f,1f)));
  LogoSprite=new Sprite(80, 30, LogoRegion, activity.getVertexBufferObjectManager()){
    @Override  
        protected void preDraw(GLState pGLState, Camera pCamera)
  
        {
           super.preDraw(pGLState, pCamera);
          pGLState.enableDither();
          this.setCullingEnabled(true);
          
        }
  };
  LogoSprite.registerEntityModifier(new MoveYModifier(0.6f, 200, 10){
   @Override
         protected void onModifierFinished(IEntity pItem)
         {
                 super.onModifierFinished(pItem);
                 StartGame=SpriteFactory.CreateNextSceneButton(120, 350, "Play", new Color(0.95f,0f,0f), activity,SceneType.GAME);
           MenuScene.this.attachChild(StartGame);
         }
  });
  
  this.registerTouchArea(StartGame);
  this.attachChild(LogoSprite);
  
 }
 @Override 
 public void DestroyScene(){
    
 }
 
 
}

SceneManager.java:(处理场景事件并显示"loading"场景的class..)

public class SceneManager {
 public SceneType currentScene;
 
 
 public enum SceneType
 {
  SPLASH,MENU,GAME
 }

 private BaseGameActivity activity;
 private Engine engine;
 private Camera camera;
 mScene Scn_splash,Scn_menu,Scn_Game; 
 
 public SceneManager(BaseGameActivity activity,Engine mEngine, Camera mCamera) {
  this.activity = activity;
  this.engine = mEngine;
  this.camera = mCamera;
  
  
 }

 public void loadSplashSceneResources() {
   Scn_splash=new SplashScene(activity);
   Scn_splash.LoadResources();
   Scn_splash.CreateSceneObjects();
   
 }

 public void loadGameSceneResources() {
  
 }

 public Scene createSplashScene() {
  
  return Scn_splash;
 
 }

 //Method creates all of the Game Scenes
 public void createGameScenes() {
  Scn_menu=new MenuScene(activity);
  Scn_menu.LoadResources();
  Scn_menu.CreateSceneObjects();
  Scn_Game=new GameScene(activity);
  Scn_Game.LoadResources();
  Scn_Game.CreateSceneObjects();
 }
 //Method allows you to get the currently active scene
 public SceneType getCurrentScene() {
  return null;
  
 }

 //Method allows you to set the currently active scene
 public void setCurrentScene(SceneType scene){
 switch (scene) {
 case MENU:engine.setScene(Scn_menu);
  if(Scn_splash!=null) Scn_splash.DestroyScene();
  break;
 case GAME:engine.setScene(Scn_Game);
  break;
 
 default:
  break;
 }
 }
 
 
}

最后是游戏崩溃的行:

public class SpriteFactory {
 public static final int DOT_RED =0,DOT_BLACK =1;
 //method that creates buttons for switching scenes..
 public static Rectangle CreateNextSceneButton(final float pX,final float pY,String Text,Color c,final BaseGameActivity activity,final SceneManager.SceneType type){
    
  Rectangle r=new Rectangle(pX, pY, 190, 70, activity.getVertexBufferObjectManager()){
    @Override
       protected void preDraw(final GLState pGLState, final Camera pCamera)
       {
           super.preDraw(pGLState, pCamera);
           pGLState.enableDither();
           this.setCullingEnabled(true);
       }
    @Override
    public boolean onAreaTouched(TouchEvent pSceneTouchEvent,float X,float Y){
     super.onAreaTouched(pSceneTouchEvent, X, Y);
     GameActivity.sceneManager.setCurrentScene(type);
//Here is the line where tha game crashes. It also creashes if i comment out the previous line. Namely just clicking on the button is enough to make it crash  
     return true;
    }
  };
  WindowManager windowManager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
  
  Display display = windowManager.getDefaultDisplay();
  DisplayMetrics displayMetrics = new DisplayMetrics();
  display.getMetrics(displayMetrics);
  float density = displayMetrics.density;

  
  int fontSize = (int) (25 * density);

  BitmapTextureAtlas mFontTexture = new BitmapTextureAtlas(activity.getTextureManager(),256, 256, TextureOptions.BILINEAR_PREMULTIPLYALPHA);

        Font mFont = new Font(activity.getFontManager(),mFontTexture, Typeface.create(Typeface.DEFAULT, Typeface.BOLD), fontSize, true, Color.WHITE);
        
        activity.getEngine().getTextureManager().loadTexture(mFontTexture);
        activity.getFontManager().loadFont(mFont);
  Text t=new Text(20, 20, mFont,Text, 30, activity.getVertexBufferObjectManager()){
      @Override
      protected void preDraw(final GLState pGLState, final Camera pCamera)
      {
          super.preDraw(pGLState, pCamera);
          pGLState.enableDither();
          this.setCullingEnabled(true);
      }
  };
 
  r.setPosition(pX, pY);
 
  
  r.attachChild(t);
  r.setColor(c);
  t.setY(t.getY()-5);
 
    
 return r;
 }
这是完整的错误代码:

05-23 12:43:42.921: E/AndroidRuntime(6178): FATAL EXCEPTION: UpdateThread
05-23 12:43:42.921: E/AndroidRuntime(6178): java.lang.NullPointerException
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.entity.scene.Scene.onSceneTouchEvent(Scene.java:356)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.engine.Engine.onTouchScene(Engine.java:452)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.engine.Engine.onTouchEvent(Engine.java:438)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.input.touch.controller.BaseTouchController$TouchEventRunnablePoolItem.run(BaseTouchController.java:102)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.util.adt.pool.RunnablePoolUpdateHandler.onHandlePoolItem(RunnablePoolUpdateHandler.java:54)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.util.adt.pool.RunnablePoolUpdateHandler.onHandlePoolItem(RunnablePoolUpdateHandler.java:1)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.util.adt.pool.PoolUpdateHandler.onUpdate(PoolUpdateHandler.java:88)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.input.touch.controller.BaseTouchController.onUpdate(BaseTouchController.java:62)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.engine.Engine.onUpdate(Engine.java:584)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.engine.LimitedFPSEngine.onUpdate(LimitedFPSEngine.java:56)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.engine.Engine.onTickUpdate(Engine.java:548)
05-23 12:43:42.921: E/AndroidRuntime(6178):  at org.andengine.engine.Engine$UpdateThread.run(Engine.java:820)

我很抱歉这个问题太长了,但我认为添加相关代码是必不可少的

在 Logo moveModifier 的 onModifierFinished() 中创建 StartGame Rectanlge 不是一个好主意。这意味着 StartGame 在创建 Logo 后立即注册为触摸区域,但仅在修改器的末尾初始化。

准确地说,您在 "StartGame=SpriteFactory.CreateNextSceneButton(..." 之前调用了 "this.registerTouchArea(StartGame)"。通过在 StartGame 为空时注册它,您将导致空指针。

这样的顺序会更好:

创建徽标精灵;

创建开始游戏矩形;

this.registerTouchArea(开始游戏);

StartGame.setVisible(假);

然后编辑 onModifierFinished() 以执行 StartGame.setVisible(true)