AndEngine Tutorials
Contact me!
  • Blog
  • Tutorials
  • Devices Library
  • Newsletter
  • Download
  • Contact
  • My Work
  • About me

Part 11. Loading level from XML, platforms and coins.


Now we will focus on some game-play aspects, name of our game is "jumper game" - we will have to control 2d character, jumping between platforms and collecting coins. First of all, in this game I am NOT going to create beautiful graphics because:

  • this is tutorial about coding.
  • I am not artist.
  • you should not receive everything on a gold plate, some effort is necessary.

1. Platform types:

In our game, we will have 3 types of platforms:
Picture
Platform 1 - normal static platform, no special features.
Picture
Platform 2 - trap platform, fall down after 2 sec. after contact with player.
Picture
Platform 3 - falling down only if there is contact with player.

2. Coin object:
Picture
Player will be able to collect coins, gaining score. We will use graphic used above.
3. Loading graphics for platforms and coin:

  • Open our ResourcesManager class, and create fields for texture regions for our graphics, and for new texture:

// Game Texture
public BuildableBitmapTextureAtlas gameTextureAtlas;
    
// Game Texture Regions
public ITextureRegion platform1_region;
public ITextureRegion platform2_region;
public ITextureRegion platform3_region;
public ITextureRegion coin_region;

  • lets initialize our new game texture and load game resources (platforms and coin) inside previously created loadGameGraphics() method.

private void loadGameGraphics()
{
    BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/game/");
    gameTextureAtlas = new BuildableBitmapTextureAtlas(activity.getTextureManager(), 1024, 1024, TextureOptions.BILINEAR);
    
    platform1_region = BitmapTextureAtlasTextureRegionFactory.createFromAsset(gameTextureAtlas, activity, "platform1.png");
    platform2_region = BitmapTextureAtlasTextureRegionFactory.createFromAsset(gameTextureAtlas, activity, "platform2.png");
    platform3_region = BitmapTextureAtlasTextureRegionFactory.createFromAsset(gameTextureAtlas, activity, "platform3.png");
    coin_region = BitmapTextureAtlasTextureRegionFactory.createFromAsset(gameTextureAtlas, activity, "coin.png");
   
    try 
    {
        this.gameTextureAtlas.build(new BlackPawnTextureAtlasBuilder<IBitmapTextureAtlasSource, BitmapTextureAtlas>(0, 1, 0));
        this.gameTextureAtlas.load();
    } 
    catch (final TextureAtlasBuilderException e)
    {
        Debug.e(e);
    }
}

As you can see we created new texture, and loaded 4 texture regions for our platforms and coin, loading assets from gfx/game/ folder. Okay, our resources loading code is done, now lets take care about different aspects.

4. Loading level from xml file:
Now open GameScene class again, lets take care about loading level!
  • firstly, we will create some variables needed for our level loader:

private static final String TAG_ENTITY = "entity";
private static final String TAG_ENTITY_ATTRIBUTE_X = "x";
private static final String TAG_ENTITY_ATTRIBUTE_Y = "y";
private static final String TAG_ENTITY_ATTRIBUTE_TYPE = "type";
    
private static final Object TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_PLATFORM1 = "platform1";
private static final Object TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_PLATFORM2 = "platform2";
private static final Object TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_PLATFORM3 = "platform3";
private static final Object TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_COIN = "coin";

  • now lets create method responsible for loading and parsing level from xml file, we will use built in andengine class called SimpleLevelLoader.

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");
}

Now I will try to explain what this code does, in registerEntityLoader,

1) we return "mother entity" for all entities loaded from xml file. In another words, entity where all loaded entities are going to be attached to. As you can conclude, we should return our game scene (like we do in the code above)

2) in second registerEntityLoader we actually parse our xml file, we check what type variable equals, if it equals "platform1" we create and return new sprite for our first platform type, we also create body and set user data to "platform1" (we will later need those user data to recognise physical objects inside contact listener) You can ask why we also register physics connector in platform 2 and platform 3, we do it, because as you should conclude from platforms description on the beginning of this article, those two platforms are going to collapse in certain circumstances, that`s why we register it (so sprite will update its positions, following body) We also have code responsible for creating our coin, as you can see, we overridden onManageUpdate method, we will later use it to check if player collide with coin, to execute certain code, such as setting coin invisible and adding score. We also registered loop scale entity modifier to the coin to make it looks better (bit animated) 

  • execute our newly created method inside createScene method:

@Override
public void createScene()
{
    createBackground();
    createHUD();
    createPhysics();
    loadLevel(1);
}

In this example, we load file called 1.lvl from assets/level/ directory.

  • create following file in give directory, and here`s example:

<?xml version="1.0" encoding="utf-8"?>
<level width="1000" height="780">    
    <entity x="100" y="100" type="platform1"/>
    <entity x="200" y="200" type="platform1"/>
    <entity x="400" y="200" type="platform3"/>
    <entity x="550" y="300" type="platform2"/>
    <entity x="720" y="240" type="platform3"/>
    <entity x="400" y="270" type="coin"/>
    <entity x="500" y="400" type="coin"/>
    <entity x="600" y="400" type="coin"/>
</level>

Picture
After running game code, you should be able to see following result after entering game scene, for now there are no actions, we just load game objects from xml. In next articles, I will describe how to create player, game controller controlling player`s movement and code responsible for described platforms functionalities. Making our game play-able. 

Previous article
Next article


HTML Comment Box is loading comments...
Powered by Create your own unique website with customizable templates.