作为我大学的最后一年项目,我正在用AndEngine GLES1在Eclipse中开发一个使用ODK的OUYA游戏。我有一些制作Android游戏的经验,但这是我的第一次OUYA,所以请原谅我。
我的问题是,在尝试部署到OUYA时,它有时成功,有时返回NullPointerException。
我的主要活动扩展了BaseGameActivity,我正在重写所有必要的方法(onLoadEngine等)。
首先,我创建了一个Vehicle类型的成员变量,它扩展了Sprite:
private Vehicle mVehicle;我在TextureRegion中为此设置了一个onLoadResources,然后在onLoadScene中调用Vehicle类构造函数:
mVehicle = new Vehicle(SCREEN_WIDTH/2.0f, SCREEN_HEIGHT/2.0f, mVehicleTexReg); mVehicle实例有一个update方法,该方法在注册更新处理程序和重写onupdate之后在onLoadComplete中调用。我正在使用onGenericMotionEvent的覆盖来检测控制器输入并调用适当的车辆功能(旋转、加速等)。
我的问题是:大约每4次我就有3次尝试运行我的代码,我在onGenericMotionEvent函数中得到一个nullpointerexception (指针是我的mVehicle)。在我看来,onGenericMotionEvent在onLoadScene还没来得及建造我的车之前就开火了。下面是我的整个MainActivity类,以及关于这个问题的LogCat输出。这可能是一件非常愚蠢的事情,但任何帮助都将是非常感谢的。
守则:
package *****.*****.ssr;
import java.util.ArrayList;
import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.engine.camera.Camera;
import org.anddev.andengine.engine.handler.IUpdateHandler;
import org.anddev.andengine.engine.options.EngineOptions;
import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
import org.anddev.andengine.engine.options.resolutionpolicy.RatioResolutionPolicy;
import org.anddev.andengine.entity.scene.Scene;
import org.anddev.andengine.entity.sprite.Sprite;
import org.anddev.andengine.extension.physics.box2d.PhysicsFactory;
import org.anddev.andengine.extension.physics.box2d.PhysicsWorld;
import org.anddev.andengine.extension.physics.box2d.util.Vector2Pool;
import org.anddev.andengine.opengl.texture.TextureOptions;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
import org.anddev.andengine.opengl.texture.region.TextureRegion;
import org.anddev.andengine.ui.activity.BaseGameActivity;
import org.anddev.andengine.util.Debug;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import tv.ouya.console.api.OuyaController;
//import ie.itcarlow.C00113480.ssr.R.layout;
import android.util.Log;
import android.view.MotionEvent;
public class MainActivity extends BaseGameActivity {
private static final int SCREEN_WIDTH = 800;
private static final int SCREEN_HEIGHT = 600;
private static final int MAP_WIDTH = 800;
private static final int MAP_HEIGHT = 600;
private static final int NUM_VEHICLES = 1;
//private PhysicsWorld mPhysicsWorld;
//Game Objects
private Camera mCamera;
private Vehicle mVehicle;
private Track mTrack;
//Construction Values
private int mTrackRows = 5;
private int mTrackCols = 5;
private int mTrackTileSize = 400;
private String mTrackLayout = "5000216661166611666140003";
ArrayList<TextureRegion> mTrackTexs;
//Controller Fields
private float conDZ = 0.3f;
//Visual Assets
private BitmapTextureAtlas mVehicleTex;
private TextureRegion mVehicleTexReg;
private BitmapTextureAtlas mTrackStraightTex;
private TextureRegion mTrackStraightTexReg;
private BitmapTextureAtlas mTrackBendTex;
private TextureRegion mTrackBendTexReg;
private BitmapTextureAtlas mTrackEmptyTex;
private TextureRegion mTrackEmptyTexReg;
@Override
public Engine onLoadEngine() {
this.mCamera = new Camera(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
//setContentView(layout.game);
return new Engine
(new EngineOptions(true, ScreenOrientation.LANDSCAPE,
new RatioResolutionPolicy(SCREEN_WIDTH, SCREEN_HEIGHT),
this.mCamera));
}
@Override
public void onLoadResources() {
//asset paths
BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("vfx/");
this.mTrackTexs = new ArrayList<TextureRegion>();
//visuals
this.mVehicleTex = new BitmapTextureAtlas(64, 64, TextureOptions.BILINEAR);
this.mVehicleTexReg = BitmapTextureAtlasTextureRegionFactory.createFromAsset(
this.mVehicleTex, this, "vehicle.png", 0, 0);
this.mTrackStraightTex = new BitmapTextureAtlas(1024, 1024, TextureOptions.BILINEAR);
this.mTrackStraightTexReg = BitmapTextureAtlasTextureRegionFactory.createFromAsset(
this.mTrackStraightTex, this, "straight.png", 0, 0);
this.mTrackBendTex = new BitmapTextureAtlas(1024, 1024, TextureOptions.BILINEAR);
this.mTrackBendTexReg = BitmapTextureAtlasTextureRegionFactory.createFromAsset(
this.mTrackBendTex, this, "bend.png", 0, 0);
this.mTrackEmptyTex = new BitmapTextureAtlas(1024, 1024, TextureOptions.BILINEAR);
this.mTrackEmptyTexReg = BitmapTextureAtlasTextureRegionFactory.createFromAsset(
this.mTrackEmptyTex, this, "empty.png", 0, 0);
this.mEngine.getTextureManager().loadTextures(this.mVehicleTex, this.mTrackStraightTex,
this.mTrackBendTex, this.mTrackEmptyTex);
this.mTrackTexs.add(mTrackStraightTexReg);
this.mTrackTexs.add(mTrackBendTexReg);
this.mTrackTexs.add(mTrackEmptyTexReg);
}
@Override
public Scene onLoadScene() {
Debug.d("Calling OnloadScene");
final Scene scene = new Scene();
//final Vector2 v = Vector2Pool.obtain(0,0);
//mPhysicsWorld = new PhysicsWorld(v, false);
//Vector2Pool.recycle(v);
//scene.registerUpdateHandler(mPhysicsWorld);
ArrayList<ArrayList<Sprite>> trackTexs;
//create game objects
mVehicle = new Vehicle(SCREEN_WIDTH/2.0f, SCREEN_HEIGHT/2.0f, mVehicleTexReg);
mTrack = new Track(mTrackRows, mTrackCols, mTrackTileSize, mTrackLayout, mTrackTexs);
//attach to scene
scene.attachChild(mVehicle);
trackTexs = mTrack.getSprites();
for(int i = 0; i < mTrackRows; i++){
for(int j = 0; j < mTrackCols; j++){
scene.attachChild(trackTexs.get(i).get(j));
}
}
//controller setup
OuyaController.init(this);
return scene;
}
@Override
public boolean onGenericMotionEvent(final MotionEvent event){
float xOffset = event.getAxisValue(OuyaController.AXIS_LS_X);
float lOffset = event.getAxisValue(OuyaController.AXIS_L2);
float rOffset = event.getAxisValue(OuyaController.AXIS_R2);
if(xOffset >= conDZ || xOffset <= -conDZ)
//Debug.d("Rotating");
mVehicle.rotate(xOffset);
else {
mVehicle.rotate(0);
//Debug.d("Not Rotating");
}
if(rOffset >= conDZ || lOffset >= conDZ){
if(rOffset > lOffset)
//Debug.d("Accelerating");
mVehicle.accelerate(rOffset);
else if(lOffset > rOffset)
//Debug.d("Braking");
mVehicle.brake(lOffset);
}
else
//Debug.d("Not Moving");
mVehicle.accelerate(0);
return true;
}
@Override
public void onLoadComplete() {
this.mEngine.registerUpdateHandler(new IUpdateHandler(){
@Override
public void onUpdate(float pSecondsElapsed){
OuyaController.startOfFrame();
mVehicle.update(pSecondsElapsed);
mCamera.setCenter(mVehicle.getX(), mVehicle.getY());
}
@Override
public void reset(){}
});
}
}logcat输出:
Enabling debug mode 0
Exception dispatching input event.
Shutting down VM
threadid=1: thread exiting with uncaught exception (group = 0x411fc300)
FATAL EXCEPTION: main
java.lang.NullPointerException
at ie.itcarlow.C00113480.ssr.MainActivity.onGenericMotionEvent(MainActivity.java:155)
at android.app.Activity.dispatchGenericMotionEvent(Activity.java:2459)
at com.android.internal.policy.imp1.PhoneWindowDecorView.dispatchGenericMotionEvent(PhoneWindow.java:1887)
..................
.................
.................发布于 2013-11-05 21:43:18
我对AndEngine一无所知,但从您的描述中可以很明显地看出,它的API并不保证在处理运动事件之前执行onLoadScene ( onLoadScene +onLoadComplete的异步特性也表明了这一点)。
因为API不能提供这种保证,所以您必须准备好处理这种情况。这可以简单到创建一个boolean sceneReady = false;标志(如果有必要的话,我也不知道这个volatile的细节),在加载完成时将它设置为true,当标志是false时忽略运动事件。其他的选择可能更适合你。
另外,您还应该验证API文档中的线程保证,并再次检查您是否以适当的方式处理数据--问题的性质引发了一个危险信号,即可能存在其他潜在的问题。
发布于 2013-11-05 21:42:53
在onCreate()中初始化尽可能多的内容是处理这些问题的最佳方法。
https://stackoverflow.com/questions/19799518
复制相似问题