И исключение Null andEngine на ощупь
Я новичок в Android Devolopment и сегодня поощряется проблема. Когда я нажимаю на кнопку, которая переключает сцены, это дает мне исключение нулевого указателя. Странно, он продолжает падать, даже если я закомментирую строку "setScene" из события касания. Вот мой полный код..
GameActivity.java: (базовый класс для игровой активности - не игровая сцена)
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: (Класс, который обрабатывает события сцены и показывает сцену "загрузки"..)
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)
Я действительно сожалею о том, что вопрос слишком длинный, но я думаю, что добавление соответствующих кодов имеет важное значение
1 ответ
Не рекомендуется создавать StartGame Rectanlge в onModifierFinished() логотипа moveModifier. Это означает, что StartGame регистрируется как сенсорная область сразу после создания логотипа, но инициализируется только в конце модификатора.
Чтобы быть точным, вы вызываете "this.registerTouchArea(StartGame)" перед "StartGame=SpriteFactory.CreateNextSceneButton(...". Регистрируя StartGame, когда он нулевой, вы вызываете нулевой указатель.
Это был бы лучший заказ:
создать логотип спрайт;
создать StartGame Rectangle;
this.registerTouchArea (StartGame);
StartGame.setVisible (ложь);
и затем отредактируйте onModifierFinished(), чтобы сделать StartGame.setVisible(true)