Last week I posted a presentation overview of the performance gains that I found in switching over to a GPU masking implementation of rendering the terrain for Hades and I cannot say I was more satisfied with how things went.
Since then I have spent a lot of time optimizing, learning why you cannot overlap reference and value types in structs and trying to get the final pieces of the first phase of the game to come together. I have come to the conclusion that until I wean myself off of distractions I will likely be destined to spin my wheels. But there is always performance to be had.
That said, lets look slightly deeper into the terrain implementation.
Farseer – Threaded in these parts
I spent a cool week playing with threading farseer, inspired by the implementation on Sgt. Conker. The idea put forth is to wrap the key data elements in structs, which optimizes for XBox 360 porting and is also a neat means of handling signals between the two threads. Two buffers are created, one deemed the game buffer and one the physics buffer, and after each frame the two spin off, process their messages and sync, only to repeat the process again.
Messages are composed of a flag and all of the required data hangs off the end, aligned manually to help compact things. My implementation is no where near as well optimized as it could be, but it holds pretty true for what it does currently.
Every couple days I walk back through the code and revise my implementations, which I probably shouldn’t be doing considering the due date is creeping up, but I can’t help myself – new ideas come and if music is playing things just kind of happen.
The approach that I take for terrain is very different than anything I have seen elsewhere, and it comes in phases. First, the LevelManager is created, it accepts a seed, which the user will ultimately provide, and that is passed into the level randomizer, which is where the fun begins. Inside, the randomizer maintains a dictionary lookup of height values from (0,0) where the player starts, and walks out in either direction as far as the player chooses to go. These height values are used later in the GPU masking shader to provide the marker points. The LevelManager loads the (0,0) region, generating its image and passing a request off to the physics thread, requesting a new terrain object.
Farseer has a really neat marching squares implementation of terrain which handles collision, position and all of this, which in my eyes is probably one of the cooler things to be found in the last three weeks. It can be modified on the fly, adding or removing chunks as the player decides she would like.
Since I have threaded farseer, it typically takes about 2 frames for the physics object to be created and hooked in appropriately, but I’ve not yet run into issues. and optimizing for the size of the region has also been something to play with.
When I added Enemies I also subscribed to their collisions, specifically with the player, but it gets called on all collisions so I can filter later if I choose. On collision with the player I check their velocities, and given that they collide above a threshold of speed I damage the player & enemy. Seemed pretty straight forward but I played with the amount of energy and a few other setups before I was satisfied.
I did run into an issue at one point where the player was too massive and he didn’t respond to impulses, and thus didn’t move =( Things settled down once I decreased his density though.
I have to finish up digging and a little of the interaction with enemies then it should be pretty smooth sailing through to Saturday/Tuesday. Ill do my best to post on a daily basis to keep things updated. If there is anything in particular anyone has questions on please don’t hesitate to send it across.