问题
I am using a method of loading an xml file into a game as a level very similar to this:
private void loadLevel(int levelID)
{
final SimpleLevelLoader levelLoader = new SimpleLevelLoader(vbom);
final FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(0, 0.01f, 0.5f);
levelLoader.registerEntityLoader(new EntityLoader<SimpleLevelEntityLoaderData>(LevelConstants.TAG_LEVEL)
{
public IEntity onLoadEntity(final String pEntityName, final IEntity pParent, final Attributes pAttributes, final SimpleLevelEntityLoaderData pSimpleLevelEntityLoaderData) throws IOException
{
final int width = SAXUtils.getIntAttributeOrThrow(pAttributes, LevelConstants.TAG_LEVEL_ATTRIBUTE_WIDTH);
final int height = SAXUtils.getIntAttributeOrThrow(pAttributes, LevelConstants.TAG_LEVEL_ATTRIBUTE_HEIGHT);
// TODO later we will specify camera BOUNDS and create invisible walls
// on the beginning and on the end of the level.
return GameScene.this;
}
});
levelLoader.registerEntityLoader(new EntityLoader<SimpleLevelEntityLoaderData>(TAG_ENTITY)
{
public IEntity onLoadEntity(final String pEntityName, final IEntity pParent, final Attributes pAttributes, final SimpleLevelEntityLoaderData pSimpleLevelEntityLoaderData) throws IOException
{
final int x = SAXUtils.getIntAttributeOrThrow(pAttributes, TAG_ENTITY_ATTRIBUTE_X);
final int y = SAXUtils.getIntAttributeOrThrow(pAttributes, TAG_ENTITY_ATTRIBUTE_Y);
final String type = SAXUtils.getAttributeOrThrow(pAttributes, TAG_ENTITY_ATTRIBUTE_TYPE);
final Sprite levelObject;
if (type.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_PLATFORM1))
{
levelObject = new Sprite(x, y, resourcesManager.platform1_region, vbom);
PhysicsFactory.createBoxBody(physicsWorld, levelObject, BodyType.StaticBody, FIXTURE_DEF).setUserData("platform1");
}
else if (type.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_PLATFORM2))
{
levelObject = new Sprite(x, y, resourcesManager.platform2_region, vbom);
final Body body = PhysicsFactory.createBoxBody(physicsWorld, levelObject, BodyType.StaticBody, FIXTURE_DEF);
body.setUserData("platform2");
physicsWorld.registerPhysicsConnector(new PhysicsConnector(levelObject, body, true, false));
}
else if (type.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_PLATFORM3))
{
levelObject = new Sprite(x, y, resourcesManager.platform3_region, vbom);
final Body body = PhysicsFactory.createBoxBody(physicsWorld, levelObject, BodyType.StaticBody, FIXTURE_DEF);
body.setUserData("platform3");
physicsWorld.registerPhysicsConnector(new PhysicsConnector(levelObject, body, true, false));
}
else if (type.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_COIN))
{
levelObject = new Sprite(x, y, resourcesManager.coin_region, vbom)
{
@Override
protected void onManagedUpdate(float pSecondsElapsed)
{
super.onManagedUpdate(pSecondsElapsed);
/**
* TODO
* we will later check if player collide with this (coin)
* and if it does, we will increase score and hide coin
* it will be completed in next articles (after creating player code)
*/
}
};
levelObject.registerEntityModifier(new LoopEntityModifier(new ScaleModifier(1, 1, 1.3f)));
}
else
{
throw new IllegalArgumentException();
}
levelObject.setCullingEnabled(true);
return levelObject;
}
});
levelLoader.loadLevelFromAsset(activity.getAssets(), "level/" + levelID + ".lvl");
}
If I add an entity with some random type string in my level XML file that is not defined in that method and I run it, I get this stacktrace:
05-02 16:56:40.880: E/AndroidRuntime(3665): FATAL EXCEPTION: UpdateThread
05-02 16:56:40.880: E/AndroidRuntime(3665): org.andengine.util.level.exception.LevelLoaderException: java.lang.IllegalArgumentException
05-02 16:56:40.880: E/AndroidRuntime(3665): at org.andengine.util.level.LevelLoader.loadLevelFromStream(LevelLoader.java:127)
05-02 16:56:40.880: E/AndroidRuntime(3665): at org.andengine.util.level.LevelLoader.loadLevelFromAsset(LevelLoader.java:97)
05-02 16:56:40.880: E/AndroidRuntime(3665): at org.andengine.util.level.LevelLoader.loadLevelFromAsset(LevelLoader.java:88)
05-02 16:56:40.880: E/AndroidRuntime(3665): at org.andengine.util.level.LevelLoader.loadLevelFromAsset(LevelLoader.java:82)
05-02 16:56:40.880: E/AndroidRuntime(3665): at com.package.game.GameScene.loadLevel(GameScene.java:478)
05-02 16:56:40.880: E/AndroidRuntime(3665): at com.package.game.GameScene.setLevel(GameScene.java:1693)
05-02 16:56:40.880: E/AndroidRuntime(3665): at com.package.game.SceneManager$1.onTimePassed(SceneManager.java:117)
05-02 16:56:40.880: E/AndroidRuntime(3665):
I need to be able to load different entities at different time from one level file, so how can I modify this method somehow so that it just kind of "ignores" entities that are not defined?
回答1:
I have just looked in LevelParser.java method startElement(), you can bypass where the IllegalArgumentException exception is thrown in Andengine by creating a default Entity Loader. I.e.,
levelLoader.setDefaultEntityLoader( new IEntityLoader()
{
@Override
public void onLoadEntity(String pEntityName, Attributes pAttributes) {
// TODO Auto-generated method stub
Log.w("setDefaultEntityLoader","Unknown Entity");
}
});
This default onLoadEntity() will then get called instead of the exception being raised. I tested it on GLES 1 and it works as expected.
Hope this helps.
来源:https://stackoverflow.com/questions/16376949/how-to-have-levelloader-method-ignore-undefined-entities