Thursday, November 09, 2006

About Spritesheets, explosions, infantry and enlargement...

First of all, I have done quite some work in the past few days. I needed something to do, because I was low on workload. I decided to start coding again, and before I knew it, I was on a coding spree.

I finished the spritesheets, which had quite a few issues in the first attempt. Eventually I narrowed it down to being the code that was responsible for finding the proper location inside the sheet. I re-wrote it in a more manageable manner, and it worked. This is the result(The blue is used for debugging purposes, and will remain blue. This will automatically show the programmer what's going wrong.):

Spritesheet in action, showing 1 subsheet

After I finished the spritesheet system, I decided I needed to do some front-end work, because I was bored with doing things without results shown in game. So, I ended up working on explosions. Yes, you read it correct: Explosions.

The system is quite simple: There's an Explosion class which houses the necessary functionality to run through the explosion sheets, do the timing and rendering. It's a GameObject, so you just shove it in the SceneManager and forget about it. When it's done, it informs the SM that it would like to be moved into the trash can for recycling. From the Explosion class, I derive a subset of explosion types: LightUnitExplosion, HeavyUnitExplosion, and the most interesting one: ExplodingBuilding.

Light/HeavyUnitExplosion refer to the number of steps and the used images. An exploding Light Unit(Quad/Trike) has 2 explosion steps, while a heavy unit has 5 steps. And there's only 1 image for an exploding light unit, and several for an exploding heavy unit. It picks the explosion in the constructor and then runs it. Now the interesting part:

The ExplodingBuilding was more tricky, because it needs to be dynamic in size, and look 'realistic'(As realistic as you can get with graphics from 1990, you get the idea). So, I started out by creating a BuildingExplosion class, which handles the explosion of 1 single building tile. It picks a random explosion from the list of explosion sprites for buildings and does it's thing. However, creating an M x N explosion in this way would look strange. All the explosions would start/end at the same time, and that would just look fake.

So, in the ExplodingBuilding, I build a list of each section(Say, 3x2, a refinery), place a random delay on it between 0.0 and 0.5 seconds and put an timer on it. When the timer expires, I stop it, spawn a random explosion at the section coordinates and start it. After all the delay timers are expired, the ExplodingBuilding removes itself from the SM. The BuildingExplosions then expire at some point and are removed aswell. The result(Including some failures):

As you can see, random explosions for heavy units. The selection rectangle shows up because of the rigged mouse. More on that below.

In the above image, I rigged the mouse to create random 4x4 ExplodingBuilding objects when clicked. I hacked it in, so when you'd drag the mouse, the selection rectangle wouldn't go away. Anyway, in this image the explosions REFUSED to go away, they kept going on forever. Turns out: Never ever use a .NET struct in a list. It will not retain variables you change.

And the last screenie demonstrating the delay system: A huge 20x20 explosion to see it in action. In the bottom you see the FPS rate from FRAPS. Also, the shown revision is incorrect, it should be 14. There's a problem with my PostBuild step, so the revision number doesn't update.

After this I was on a spree and added Infantry units. Infantry units ARE a bit different than other units, since they have only 4 directions, and have moving legs. Most other units are reasonably static, except the carry-all which has 2 states(Tanks with turrets are 2 sprites, so they're still static). At first, I decided to go with the standard Unit class, which didn't cut it due to the movement and the Direction property. However, I discovered you cannot overload the C# Properties, so overloading this in the Infantry class doesn't work(Would have saved me the hassle of going through the pain of using a bigger texture and some work).

However, I noticed that Stefan had a 2nd sheet of infantry/trooper sprites. 8 directions, just repeated for the wind directions. So I used that and just had to overload the Update function in the Infantry class. 43 lines of code and an hour of work.

However, I discovered that the infantry was rather, erm, small. And with small, I mean, near invisible. They're 8x6 or something, so you have to look REALLY hard to see them. And Ravuya said the exact same thing:He then continued to link to me HQ2X. An application to enlarge images and still look smooth. Have a look at the examples, it looks really good. So I experimented a bit with that. The results are astounding:
That's a Quad enlarged 2x. Looks very smooth. Only problem with HQ2X is that it can't work with palletized bitmaps, and converts them to 24-bit images, which is a problem.

I intend to let HQ2X loose on ALL the images for the game, and enlarge the entire game to 32x32 tiles instead of 16x16. However, I need a way to change the colors during runtime. I've been suggested to write my own Sprite replacement, which is what I did. It works, but only for single textures. I intend to add support for multi-texturing and use the Fixed Function pipeline to do some color changing for me. I'm still working on that, so I'm not sure how long it's going to take.

Until it works, I'm going to use the original images for everything and alternate it with doing some real work. Before I want to make the pass to enlarge everything, I want to have at least ALL the units in. This means I have to add the ornithopter, the frigate and the sandworm(Those are the ones still not done). Not a lot of work, but I need to make some changes in the code, and move all the aircraft specific code into a separate class to make full use of it.

That's the end of my long story for now.

1 comment:

Anonymous said...

"Never ever use a .NET struct in a list. It will not retain variables you change."

Or learn the differences between value and reference types.