Thursday, 8 March 2012

Out With The Old...Part Two

Man am I not very good at keeping up with blog posts. Apologies. So here we go, part two of what I changed about a month ago, and case you've forgotten what this was all about here's part one to remind yourself.

What's Changed

Tiles and their interfaces
How It Was: Interfaces are great. They are C sharps answer to multiple inheritance (granted not a very good one). I used interfaces in order to define my tiles and create some commonality between them. This also means that I can deal with all tiles by just casting to their inherited interfaces and performing code based on the cast interface. An example would be an IAnimatable interface that is applied to all tiles that animate. By casting to this I could animate all animatable tiles.

The problem with this approach was that I was safe casting each tile (using the as keyword) in the level to my main interfaces and then performing interface logic to the tile if the cast was successful. However, this is a very expensive thing to do as I was casting each tile about 5 different times every frame. So what could I do to keep the greatness of interfaces but reduce the expensive calls.

How It Is Now: I have exactly the same interfaces that I had before (plus a few additional ones), but I now have some "cheat" properties on my base interface; ITile. These cheat properties tell me if the given tile implements my main interfaces (e.g. movable, interactable), which are set up during construction of each tile. This means that I no longer have to safe cast in my main game loop, but instead check the respective cheat property, which is just a boolean value and therefore much cheaper and has helped to improve frame rate.

Updating every tile every frame probably isn't the best idea
How It Was: On each update call in my tile engine, I checked collision between the player and each level tile and performed interface specific code on each level tile (using the old method). As you can probably see this can get quite costly, especially when most of the tiles aren't visible to the player because they are off the screen.

How It Is Now: Now whenever the player moves I update a global variable that stores the min and max X and Y co-ordinates. These co-ordinates specify the area of the level that needs updating and drawing. I've currently set this catchment area to two screen widths/heights surrounding the player. Ultimately, this could be further improved by reducing the catchment area for the tiles which are drawn, but as frame rates are holding up there's no need at the moment.

Reducing and refining collision detection checks
How It Was: I used to update the players location, first along the X axis and then along the Y performing AABB and PPC checks against each and every tile in the level for collisions with each change in the players location. Once I built a level of any size, I realised I needed to reduce these checks, so I reduced it down to only be done on the tiles that were visible.

How It Is Now: These checks, while not needing to be reduced due to the first AABB check, were still to much. So I have reduced the number of checks to only tiles that surround the player. However, because not all my tiles are the same size (but multiples of 64 pixels), I needed to increase these checks to surround the player of the greatest tile size on the level. For example if the maximum size of a tile was only 64 pixels, then the checks only need to be done one tile deep around the player. But if the maximum size is 128 pixels then the checks need to be two tiles deep. And this continues, but I'm not going to spell it out to you because you are all probably an intelligent bunch.

What's New!

Yes that's right, not only did I rewrite stuff, but I also produced some new stuff. Well, one new thing. Because I was getting to the point where I was adding new tiles all the time, I needed to update my level descriptions constantly. I also needed to create levels that produced different scenarios to squish a few bugs. My levels are structured as Xml documents, and while being readable were not a joy to edit. So until I've created an in game level editor, I needed an out of game editor. So I've developed a level editor using existing software (*cough* Excel *cough*) for which I then parse the document to create my needed Xml document.

My proposed level in my Excel spreadsheet

The resulting level

As you can see the level editor is very colourful, for which there is a reason behind this madness. Each colour represents a different tile and the contents of the cell describes certain characteristics of that tile (like texture). Considering this editor took my only a few hours to create and is easily updateable for when I create new tiles, I'm pleased. And who knows, maybe I'll get the community (whoever they are) to make levels using this so I can include the levels in future updates. But then again, maybe I'm getting ahead of myself...

No comments:

Post a comment

Got an opinion? Who hasn't? Post it here...