Advertisement
Drakim

Tile system

Nov 12th, 2011
334
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.46 KB | None | 0 0
  1. The easiest way to do tilemaps is to have ints in a 2d array, and just act upon those ints as the player moves around. But this gives us several limitations. Ints cannot hold extra values, so what if we want blocks that can store extra information? (damagetaken, etc). Also, you have to leave a lot of tile code outside the actual tile class, which is annoying.
  2.  
  3. But at the same time, having an object per tile is pretty costy. Also, the traditional way of using extends or implements to create diffrent kinds of tiles is very costy. If we have an interface with render() that all tiles implements, we can't inline that, and we get 20x20 = 400 render calls per frame to draw the scene. Pretty stupid to throw away your resources at! But if we drop the idea that tiles are responsible for their own rendering (perhaps they simply have an int property that tells the rendering loop to look up x tile data) then we are again outsourcing the tile logic outside the actual tile class! Also, some things just can't be done with properties alone. What about tiles with special reactions?
  4.  
  5. This is my idea for how to solve these issues and gain some bonuses:
  6.  
  7. Before the game starts, the raw tile data of the map is stored as ints. So you have 0,0,1,1,1,0 type of data. In the game, you have a static class called TileCollection, which has a tilelist property containing an array. In this array, diffrent kinds of tiles are stored. When the game starts, we loop over the raw tile data and use the tile array as a lookup table, so that 0 on the raw data means [0] on the array. Pretty standard stuff.
  8.  
  9. So, what is inside the tile array? This is where my idea gets a bit wacky. There are basically two categories of tiles, and each category can have an unlimited amount of tiles under it. But they all (no matter what category) comes from the same Tile class.
  10.  
  11. The categories are thus:
  12.  
  13. 1. Static
  14. A static tile basically means that if you take tiles of the same kind and look at them, they will be identical. For instance, a stone tile is a good example. Stone tiles are simple. They just have a simple image and they are 100% solid. So if you use two stone tiles, they will always be identical.
  15.  
  16. That's why, if you have 100 stone tiles in a scene, it's stupid to have 100 diffrent objects, since they are all identical. The trick is that when the map generator at the game startup needs one of these static tiles, it doesn't create a new instance of the class. Instead, it uses the already existing stone tile, saved in our TileCollection singleton.
  17.  
  18. That means, if you have 100 stone tiles on the screen at the same time, they are actually all the same instance. This has a huge advantage in saving memory, but it also means that if you ever edit the stone tile in realtime, ALL stone tiles will have that change.
  19.  
  20. 2. Dynamic
  21. a dynamic tile is the exact opposite. When the game starts and the code loops over the raw data, finds a tile type 5, and sees that type 5 is dynamic, it constructs a new instance of that tile and saves into the map structure you use.
  22.  
  23. That means, when you see 10 dynamic cakes on the map, they are all diffrent instances, and if you modify one only that cake gets modified.
  24.  
  25.  
  26.  
  27.  
  28.  
  29. Now, this is all swell, but what's the point? Aren't we just saving a bit of memory? There is actually one more thing I mentioned above. All these tiles, both static and dynamic, comes from one Tile class. But how does that work? It's pretty simple.
  30.  
  31. You make a general purpose Tile class that has the most common property such as "solidness" (solid, none, water, quicksand) and "graphics" (pixmap, animated pixmap, none). But also the very important property "mode" (static, dynamic).
  32.  
  33. So when the game starts, you have to do this:
  34.  
  35. tiletype = new Array();
  36. tiletype[0] = new Tile( static, solid, pixmap, stone.png );
  37. tiletype[1] = new Tile( static, solid, pixmap, dirt.png );
  38. tiletype[2] = new Tile( static, water, animated pixmap, water.png );
  39. tiletype[3] = new Tile( dynamic, custom, animated pixmap, springboard.png );
  40.  
  41. The great aspect is that this, I think, will run faster than the common extends or implements solution with diffrent tiles. After all, it's all from one base class, so everything can be inlined just fine. (and pooling is also possible due to it all being of one class).
  42.  
  43. Remember, as I said above. If the first value is "static" then the actual instance inside tiletype[x] is set into your map2d array, so all static tiles shares the same base instance. But with dynamic, a new one has to be constructed each time it's "fetched" out of the tiletype. So the actual tile object in tiletype[3] is never used, it's just a blueprint for how to construct new tiles for springboards.
  44.  
  45. As you can see, I've added one value I didn't talk about above. Custom. Custom is the magic that allows you to use this system and not suffer any downsides or restrictions. Custom is basically when you have tile behavior that cannot be expressed with a simple "solid" or "water". A good example is the springboard. When an object touches the springboard you want that object to gain a lot of upwards speed.
  46.  
  47. So how do you setup custom? Well, you simply have a property that holds a function. It's often called lambada or something like that, but nevermind the name. You have this:
  48. public var customSolidnessFunction:Void->Void; which is called upon collision if the "solidness" property is custom. All you need to do is just setup the springboard tile to have a custom function that adds such speed to the object that touches it (from the right direction) and you are good to go. Obviously this particular function won't be inlined, so we are basically gracefully degrading back to the regular way of doing things.
  49.  
  50. Advantages of using this system:
  51. *Less memory used due to static tiles
  52. *Keeps all tile code inside the tile class
  53. *Allows for inlined methods
  54. *Allows for object pooling (20*20 tiles per screen would be 400 objects)
  55. *Allows for creation of new tiletypes at runtime
  56. *Allows for easy saving and loading of a scene (only dynamic tiles needs any effort)
  57.  
  58.  
  59. The main reason I think this system is so awesome is because you could in theory supply an external map file that contains both raw map data AND the tiles it uses. That way, the whole world can be truly dynamic modular. You can have a main hub that allows you to walk to player created maps with their own graphics and special tiles.
  60.  
  61. The only thing you wouldn't be able to do is invent entirely new custom methods, as these need to be hardcoded (but you could combine existing ones freely).
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement