Wednesday, November 30, 2011

Performance Updates

I'm been focusing a lot on performance this past week.  I started merging the world and structuresManager draw() methods and that seemed to go well, until I realized that this drew all of the structures behind the player.  I didn't want that, but I was able to use the same technique to further optimize the structuresManager drawing code to increase framerate.

For the sake of documentation, I'll admit that I made a very, very newbie mistake.  When I was drawing structures before, I was simply iterating through every single structure the player had built and drawing it.  Then at some point I put in a method that checks to make sure that the object is within view before drawing it.  This was stupid because I was still iterating through every single object that the player had built.

Then one day I was inside of the world draw() method.  I was toying around with adding another liquid when I realized that the structure was different.  In the world draw(), I had a nested loop that simply went from the top left of the viewport to the bottom right.  It only drew what was on the screen and ignored everything else.

Why the heck wasn't I doing this in structuresManager?  Stupid newbie mistake, that's why.  After changing that, it increased my frame rate by 30fps.  You won't notice this much of an increase in the beginning of your game, but in my Alpha base I have a lot of structures.  I have 9 forges, 3 chests, at least 20 light posts, 5 fuel posts, at least 20 turrets, 5 laser doors and the real structure hit:  2 sets of tractor beams.  You see, each tractor beam can be up to 500 blocks long.  That means that I was drawing every single tractor beam on every single frame.  This is clearly a waste.

After that was fixed, I noticed that my frame rate dropped drastically when I was around water.  This is because the game updates any water within range.

Now while in theory that makes sense, it sucks in execution.  The best example I have is a waterfall.  Say I release 100 units of water and let it fall down.  It will continue to fall and fall and fall until it gets out of range.  When it's out of range, it'll just float there in space until I get close enough to it for the game to update it.  Meanwhile, the game is constantly going through all the water around me and updating them, even if they have nothing to update to!  This is all waste, waste, waste, waste.

The new water method 'checks in'.  When the game generates water, it 'checks in' the water block.  Each water block has 10 ticks to do something (1 tick = 1 update() execution).  If the water block is ran 10 times and it hasn't made a single change, it's removed from the update() list.  Whenever I do something around the block that could effect it, I re-add it to the update() list and it again has 10 ticks to do something.

If I add water that flows into other water, I add both waters to the update() list.  What this gets me is a constantly changing list of water blocks to update.  The nice thing is I can be in an area with 500 blocks of water and not need to update a single one because they're just sitting there.  When the player drops in, they splash water so now 5 blocks need to be updated.  Eventually they fizzle out and now we're back to 0 updates.  If I remove a block underneath the water, a huge waterfall will form.  This waterfall can cause every single water block to update.  That's ok because at the most, it will be 500 blocks of water to update.  As soon as all that water is done flowing, I return back to my original 0 water updates.

It still has some minor glitches to work out, but overall testing has been very successful and the game now runs at an average of 170fps when I don't limit the framerate.  I'm very happy with these two performance updates.

On a more graphical note, all items now have their own drop graphic.  Beforehand, I was simply taking the original texture and re-scaling down to 16x16.  This worked temporarily but was ugly.

I'm going to spend the week focusing on the water update and removing all the little glitches.  For some reason, the water doesn't like to go near the laser door.  The current functionality is that when water is at the door, if it's open the water will go through.  If it's closed, it doesn't.  Well for some reason, when the water is falling straight down to the left side of the door (but not the right), it stops at the block above the door.  No idea why.

So that's my week.  No screenshots this time, but hopefully once I get these done I can start to put some serious code towards terraforming.  I'm torn between terraforming and netcode (multiplayer).  We'll see what I feel like doing when the time comes.

No comments: