Question

I have a large tmx map for my Andengine game, which is 9000*30 in size, and when I want to load it into the application, I get an outOfMemory error. Can anyone help me with this problem? Any idea?

Was it helpful?

Solution

Andengine automatically allocates textures into memory by design. If you are getting OOM error thrown by the engine, you're probably doing something wrong or, at least, discouraged by design, and should reconsider an alternative.

In your case, you should separate your tmx map into several different files and load them within the Scene as batches.

That way you allocate the same number of tiles into several different memory regions, whom will be much smaller and hence be supported by many more devices, and not just the high-end ones.

However if you insist into having a single large tmx map mapped into memory, you have to modify the following in Andengine:

Replace in org/andengine/entity/sprite/batch/SpriteBatch.java:

public SpriteBatch(final ITexture pTexture, final int pCapacity, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) {
                this(pTexture, pCapacity, new HighPerformanceSpriteBatchVertexBufferObject(pVertexBufferObjectManager, pCapacity * SpriteBatch.SPRITE_SIZE, pDrawType, true, SpriteBatch.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT));
        }

With:

public SpriteBatch(final ITexture pTexture, final int pCapacity, final VertexBufferObjectManager pVertexBufferObjectManager, final DrawType pDrawType) {
                this(pTexture, pCapacity, new LowMemorySpriteBatchVertexBufferObject(pVertexBufferObjectManager, pCapacity * SpriteBatch.SPRITE_SIZE, pDrawType, true, SpriteBatch.VERTEXBUFFEROBJECTATTRIBUTES_DEFAULT));
        }

However keep in mind that with this you are relying on device hardware limitations directly.


Edit:

I would suggest something like:

First you load the initial map (always considering only 1 TMXLayer) and attach it to the Scene:

TMXLoader tmxLoader;

try {
    tmxLoader = new TMXLoader(this.getAssets(), this.mEngine.getTextureManager(), TextureOptions.BILINEAR_PREMULTIPLYALPHA, this.getVertexBufferObjectManager(), new ITMXTilePropertiesListener() {
        @Override
        public void onTMXTileWithPropertiesCreated(final TMXTiledMap pTMXTiledMap, final TMXLayer pTMXLayer, final TMXTile pTMXTile, final TMXProperties<TMXTileProperty> pTMXTileProperties) {
        }
    });
    this.mTMXTiledMap = tmxLoader.loadFromAsset("tmx/map1.tmx");

} catch (final TMXLoadException e) {
Debug.e(e);
}

final TMXLayer tmxLayer = this.mTMXTiledMap.getTMXLayers().get(0);
scene.attachChild(tmxLayer);

Then, assuming your game is side-scroller oriented (because of the large witdh of the Scene), whenever the user is about to reach the end of the current tmx (any of the last column tiles), or the opposite edge, you swap. For example, something similar to this:

You execute this.mTMXTiledMap = tmxLoader.loadFromAsset("tmx/" + fileName);

And then changeTmxMap(this.mTMXTiledMap);.

Which is something like:

private void changeTmxMap(TMXTiledMap mTMXTiledMap){
    final TMXLayer tmxLayer = this.mTMXTiledMap.getTMXLayers().get(0);
    scene.attachChild(tmxLayer);
}

OTHER TIPS

I'm not sure, try putting this in your AndroidManifest.xml

<Application
android:largeHeap="true"
...
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top