I have spent quite a bit of time scripting since the previous episode in this tutorial [002]. The tutorial starts with this first post [001]. I will warn you now if I gave you the impression this tutorial would be easy for beginners then I need to clear that up. It will not be as it will require a lot of scripting.
I was going to dive straight into the scripting in this tutorial, but the amount of scripting would likely overwhelm anyone following this tutorial.
I ended up coding a fairly complex system that will enable us to expand the tile system fairly easily, but what it can support is more complex than some people might have wanted.
I did this because this system will actually be useful to make other Rogue Likes beyond this tutorial. I will likely use some of this code myself rather than making it some simple throw away tutorial.
This episode of the tutorial is going to be explaining the design decisions and what can be expected in the scripts. I will then publish however many tutorial episodes it takes to cover the scripts I coded since yesterday. There is quite a bit of ground to cover so that may be more than I can fit in only a single post.
Here is an example output from what I have generated with this code. This will give you and idea of where we will end up after this section of code. While the level generated is not that impressive, all the tools are complete to make far more interesting and more useful levels.
Remember this is not optimized. Those set pass calls could be significantly reduced if we were to use an atlas instead of individual file based sprites. That is something we will address later.
Still getting 1000+ Frames Per Second with the experiment is not bad. What I am getting at is with atlasing that can be improved. I do expect performance to drop significantly as we add more tile variations.
This current one has 5 shadow sprites, 3 different ground sprites, and 4 different wall sprites. That alone will take 12 set pass calls due to each being an individual sprite. If it was properly atlased I'd expect to be able to do all of those in a single set pass call.
So until we get around to optimizing you should expect the set pass calls to climb dramatically. This does not matter a huge amount for a Rogue Like as even a few frames per second are sufficient for this type of game.
What do the new scripts do?
The new scripts support defining new tile types both STATIC (not animated) and ANIMATED on the library prefab without needing to script them. You can add as many tile type definitions as you want.
The script also handles the animation if we do any animated sprites, though I didn't actually do any of those here.
I am going to go ahead and add a third tile that is animated simply so we can make sure that part of the code is actually working properly before I go over that section. That way we don't have to revisit that code later if it doesn't work.
Animated fountains added. They only have two frames with this Dungeon Crawl CC0 tileset, but it is working.
Each tile location can support a base tile, and a detail tile. Later we'll also add a character layer, and likely a UI or some other things.
For the moment every map location essentially stores two different tile pieces of information. You can see this with the fountains. I made the random map generator in this experiment have a 10% per floor tile of placing a fountain as the detail object.
Design
Tile Definitions
The previous prefab we put the list of tiles on has been expanded. It has the text definition of the tiles.
Each important element of the definition is delimited by | symbols.
The first parameter is the Name. I have it setting the name of the tiles instantiated to match these.
The second parameter is the Tile Type and it is not case sensitive. Valid values for this are:
Floor, Wall, Object, Character, and UI, but currently only Floor, Wall, and Object are coded.
The third parameter is the Draw Method which currently supports two methods. Valid values for this are:
Static, or Animated. How these are handled is different and will be described in a moment.
The fourth parameter is the Sorting Order which is used to tell which sprites should appear on top of the others when they are in the same physical location. If you have a sprite with a draw order of zero then every other sprite greater than zero will appear on top of it. This is adjustable per tile definition here so that the draw order is something you can manipulate to achieve different effects. I decided in this example to start at 2, that way if I ever use a transparent floor there is room to put two layers of other effects below the floor if needed. Some examples of use of this are putting a character down, and then slapping hair on it. The hair would be a greater sorting layer to make it show up properly.
The fifth parameter is the sprite appearances to use with this tile. WALLS, and FLOORS pull all of their appearances from the Terrain array that you dragged sprites into. The OBJECT type pulls from the object array of sprites.
Each sprite number is delimited (separated) by commas. In the Dirt Ground definition you see 0,1,2 and this corresponds to Element 0 - 2 in the Terrain array.
When you choose a Static draw method the tile will have an appearance randomly chosen from the tiles you listed. If you choose the Animated draw method then it is used to specify the frames of animation that it should flip through to simulate the animation.
The Map/Level
The current design allows you to specify a map size on a map object with the correct script. It will allocate for those tiles in a square design. If you specify size 32 then it will plan for a 32x32 map.
The plan is that these maps/levels can actually exist with multiple maps. The maps position centers around the center of the object it is attached to.
So you could link multiple occurrences of smaller maps together to make faster maps and you could even stream them if needed.
There is also the possibility of say making a map called SHIP and having that ship move over the top of another map.
That is the plan anyway.
The scripts are getting pretty involved, but the idea with building systems like this if you do a good enough job you hopefully have to revisit the scripts less to produce powerful and flexible results.
I'll dive into the scripts soon. They are not for the faint of heart.
I have some older posts I made a long time ago that may or may not help if the coding is just too much for you: