Rendering Multi-Layer Tilemap w/ Animations

Hey everyone,

I’m working on a rather large 2D tile based game similar to a 2D zelda in style. I recently redid my maps and map editor to allow for more layers so that I could have an upstairs/downstairs type system going like in Zelda, link to the past. But now I am having trouble rendering a lot of layers on a map where some of them are animated and some aren’t and I have a couple issues/questions.

Also, I’m programming the “game engine” as well this is a learning experience and it was going extremely well but I keep finding cool things I think I can add and this last one has become a major problem.

Dynamic Animated Tile Maps & High Frame Rates
A map usually has around 5-7 layers, but MOST of the tiles on the layer is empty especially when you get to the top layers. So in order to speed up FPS I started having the layers render to their own BufferedImage same size as the Graphics object’s dimensions, then render that image to the screen each frame so it didn’t redraw every tile. This got my frames up to 200 or so again. However that is making it rather difficult to have only a handful of tiles redraw if they’re animated on a given frame. The maps have a Tileset class that has the tile images for all the tiles in it and I know one problem is scaling up those images each frame to draw.

Map Classes: All graphics tiles hold integer ids for the tile that they render, animated tiles simply have list of ids.

  • Tile
    - GraphicsTile
    - AnimatedTile
  • TileLayer
    - GraphicsTileLayer
  • TileMap

Scene classes: Handle rendering objects to screen. There are others besides these. They all worked beautifully besides this problem.

  • Scene (abstract)
    - TileLayerScene
    - TileMapScene (list of TileLayerScenes)
  • SceneEvent
  • SceneObserver interface
    - SceneAdapter (implemeted version of SceneObserver)

The general rendering order is following:
(1) Game state tells current scene to render (TileMapScene)
(2) TileMapScene will either (a) draw it’s buffered image if no changes were made or (b) redraw all the TileLayerScenes
(3) TileLayerScenes will either (a) draw its buffered image if no changes or (b) redraw all GraphicsTiles (doesn’t need to know if its animated or not, that’s handled in update() method call part of game loop)
(4) GraphicsTiles are drawn by the TileLayerScene getting the integer id, then accessing the Tileset that it has, grabbing that image, and rendering it.

So I’m trying to figure out what is the best concepts to implement when it comes to getting the fastest rendering time while still having tile maps that have a lot of layers and dynamically changing or animating tiles? I’m also trying to keep the Scene packages decoupled as possible from the rest of the game so I don’t want to do what most of these engines do now a days and pass references to everything in every object. I can’t figure out how to approach this. Any insight would be greatly appreciated!



Okay, I’ve made some improvements.

b Added a SceneTile class:[/b]
This does for GraphicsTile and AnimatedTile what the others did for Layers. Basically wrapped a map tile in a Scene class, so that it could be observed by the TileLayerScene (through SceneObserver interface). So the SceneTile will update, and if the id of the tile image changes it will notify it’s oberver (the TileLayerScene), then the TileLayerScene.

b TileLayerScene update:[/b]
When the TileLayerScene gets a callback from the SceneTile that changed it’s image, it will redraw its full layer and then notify it’s observer that it has redrawn, which it’s observer will be the TileMapScene

This has gotten me full animated tiles without having to know where they are, and a frame rate of 170-180 frames!

I’m happy with the fact that the Scene objects are still only observing the actual physical Map and Tile objects and they don’t know anything about how they’re being rendered …but, still have no idea if this is smart to do, or if there are techniques and concepts i’m oblivious to how other game designers or engines do this and I still love to know if any of you have thoughts on this?