Tuesday 30 July 2013

Castle Under Siege! Weekend Jam Game.



This (currently unplayable) game was done as a weekend game jam in 48 hours. To read about about my development process, check this previous post! I will be posting the updated playable version if it ever comes out!

Weekend Game Jam with HanMD82

Free source on GitHub
Snow Castellum on SoundCloud

Why this weekend?

So one day, Mr. HanMD82 randomly commented on Facebook that we should do a game jam. It was quite random but I love game jamming, so I try not to turn down a game jam offer nowadays, at least if it's done with some friends, we can always rearrange to a timing that works best. So we decided to do a game jam this past weekend.

Why Tower Defense?

I was itching to do a Tower Defense (TD) game because actually I was rather jaded about design cloning in the games industry. So I decided to make a clone for this game jam to learn about the genre and try to see why it makes people tick so much. I have to qualify though, that I play a lot of TD games myself and I love them too. In fact, I've probably played most of the popular TD games. I wanted to also test my game making skills and see how much faster I can build a game if I was already familiar with the design.

Approach

Having made a tower offense game (perhaps the first of its kind), I knew what I was getting myself into, but the difference here is that I would be hacking my way through everything, and picking the fastest-possible/production-efficient way to do the game. I picked up many lessons through making my previous games and I used these lessons to speed up the process in the jam. I'll share some tips here.

1030am Sat - Idea Generation and TD References

We started the jam around 1030am on Saturday. I showed HanMD82 a slew of TD games that were popular including but not limited to the classic Desktop Defense, Kingdom Rush and Field Runners. We then broke down the games and noticed there's a slight variation in design.

We noticed that in Kingdom Rush you cannot choose to place your towers anywhere on the map, while you could do that Desktop Defense / Field Runners. Therefore, as a player, you would solely focus on eliminating enemies and upgrading towers and you need not plan your placement of towers.

Kingdom Rush

Field Runners


Both designs have different implications on the tech that needs to support it. In Kingdom Rush, a way-point system would be used for AI and level design requires way-points to be placed. But for Field Runners, no level design is required but the paths of the enemies will have to be calculated on the fly, typically using an A star algorithm.

For the jam, we decided to go with the latter, but we would be modding the design a bit and have the enemy units move to a fixed location which would be the castle.

1130am Sat - Begin Production!

Because we already knew we'd be making a TD game, we could break down the game into its parts quite easily.

  • Towers (duh)
  • Tower Upgrades
  • Enemy Units
  • Path-finding
  • Waves
  • Projectiles
  • User Interface
And of course, we'll have some art and music to do as well.
From here, Mr. HanMD82 chose to do the Towers, Tower Upgrades and Projectiles, while I worked on the Enemy Units, Path-finding, Waves and User Interface. I volunteered to do the music as well.

From here, we set up the project on GitHub and started setting up the project folder and structure. We chose to use Starling Framework as we were familiar with it, so the project was done in Actionscript 3 (AS3).

130pm Sat - Enemy Units & Movement

I started working on the enemy units and immediately implemented a quick code to control speed and direction. Basically, we have four things we can set:
  1. Speed : the distance in pixels to move per frame or per second
  2. Direction: the angle in degrees to move
  3. VelocityX or Horizontal Speed: the distance in pixels moved in the x-axis per frame or per second
  4. VelocityY or Vertical Speed: the distance in pixels moved in the y-axis per frame or per second
Setting the Speed or Direction affects Velocities, and setting Velocities affect Speed and Direction, so for e.g. we have a function like:
function setSpeed(value:Number):void
{
    speed = value;

    // update velocities
    velocityX = speed * cos(direction * PI/180);
    velocityY = speed * sin(direction * PI/180);
}

The implementation for Direction and Velocities will be left to the reader (or you can just check the code on GitHub). The point here is that suddenly all you need to do to control the movement of an object becomes very easy since speed and direction are more intuitive to us humans, and also explains why direction has to be in degrees instead of radians (a necessary sacrifice for efficiency over code usability). And in the update function, we can just do:

function update():void
{
    sprite.x += velocityX;
    sprite.y += velocityY;
}

After this we had a quick lunch and I continued to work on various small things here and there like setting up the assets pipeline for importing sprites, etc.

3pm Sat - ...

I had to go to do some Remedial Training at this time, as I failed my yearly physical fitness test from National Service (Army). So that's 5 hours gone.

9pm Sat - Pathfinding

After I came back and had some dinner, I quickly dived into pathfinding. I grabbed the Wikipedia A star algorithm and translated it into AS3. Technically, I've implemented A star a few times before, but I decided to do it again from scratch this time as I was confident of getting it done in a few hours or less. The more times we rinse and repeat, the faster we get.

After translating the algorithm for a bit, I remembered I needed a priority queue to implement the openset. I quickly turned (once again) to the Wikipedia Binary Heap and started implementing that too.

As the game was not coded yet, I couldn't really test my code at this point (without diverting to write unit tests), so I left it alone, while I carried on with other stuff.

12am Sun - Castle Art

Was feeling a little itchy, so I wanted to start drawing stuff. I looked up "castle" on deviantart  and found this image:  http://www.deviantart.com/art/Neuschwanstein-Castle-285791596
DarkSilverflame - Neuschwanstein Castle
I really liked it and even thought it was a photo until writing this blog post, so I used it as a reference to make a sprite for the castle. I picked the color palette for our game using the above image.

At first, I didn't think too much and started drawing, and I came up with this:

I quickly put it into the game and realized I need to draw it in perspective!!! I knew we were going for the top-down perspective so I tried drawing some boxes but they didn't turn out so well:

So then I quickly looked up some references, first thing that came to mind is Zelda, so google images led me to:
http://zelda.salagir.com/dossier/jeux/castle3.jpg

1am Sun - Sleep

Even though I wanted to finished drawing the castle, it was time to sleep. We don't really believe in crunching, so sleep is good.

9am Sun - Music

Music is the fun part for me. I had some experience writing music for previous game jams so this time it was a little easier perhaps. I came up with the tune while on the bus to training the day before (efficient use of traveling time!) and hummed it into my iPhone, so this piece was done a little quicker than other pieces before. I wanted it to sound a little snowy / cold / icy as well as a little bit epic / Skyrim / Zelda. You can listen to Snow Castellum on SoundCloud

12pm Sun - Back to Castle Art

Learn from the masters! I decided to redraw the castle again with the new perspective. It took me a while, but I learned how to use the photoshop line tool along the way. Here's the result:

It was my first time drawing something this complex so it took me a while, about 1 or 2 hours. I drew it in parts starting with the main keep on the left and adding little towers on castle wall, then the big tower with snowy roof.

2pm Sun - Back to code

After lunch, it was back to code again. At this point, I had not finished the Waves, or tested the Path-finding algorithm. I jumped straight back into creating castle object and the spawn point for the enemy, which I needed to start creating a path for the enemies, which will then allow them to walk from the spawn point to the castle.

230pm Sun - Pathfinding Thoughts

I decided the spawn point should just be an object that holds a grid coordinate, and that the waves object would be the actual one spawning the enemies, since that's where most of the spawn data should be stored.

I also thought that doing an A Star search for every enemy unit would be too expensive, so I thought I could optimize it by allowing enemy units from the same spawn point to share a path and then they would only ever need to keep a reference to one path that would be updated and they would search for the nearest node on the path that they could use to follow the path.

>> In hindsight however, this was a mistake as the enemy units ended up failing to re-route correctly when a player placed a tower in the way of some enemies and they would end up passing through the towers to move to the nearest node on the path.

5pm Sun - Waves

Next up was implementing the waves. I created a SpawnParams class and stored them in the waves object, so that each wave can easily tell an Enemy Unit how to spawn, for e.g. the position to spawn at and the delay to use for the spawn. It was quite straightforward.

6pm Sun - Bugs!

Inevitably the Pathfinding had some bugs. I made some very simple mistakes which I should not have made, like for e.g. my Binary Heap did not test the correct value to decide which node is less than which other node, so that led to some strange behaviour where the enemies would walk through some tiles, then suddenly make a loop around some tiles in a triangular fashion, since the generated path was incorrect.

I also made another bug in the getNeighbors function for the nodes, where I missed out on checking if a grid tile was empty or filled with a tower for the left and right directions, but the up and down directions were OK. I guess it was a code readability issue since I knew to add it to some directions but not the others. 

These were minor bugs, and I didn't spend too much time on them, but I'm just recording them here to remind myself not to make them again. Ok, moving along...

I also added the background, which I actually stole from a photo of a mountain with snow, and then reduced the colors palette to 5 colors, which would create the dithering effect you see here:

background with reduced colors

9pm Sun - More Sprites & User Interface

At this time, I had dinner and took a walk with my dogs. I then started to go back to drawing stuff. I drew the UI for the game start and also drew some sprites for the towers and the enemy units. I added a bitmap font and the castle icon to draw the castle hp:


I was thinking about what to draw for the towers, then started with snowman, then my girlfriend was saying that I should draw a rabbit, and then next a pao (chinese bun). Yes, it's kinda weird, but I like it that way, and I figured I could make it 'reasonable' by adding little army men standing on their heads.

As for the enemies, she wanted a fox-like thing and pumpkin, based off the colors I had already picked. I was not ready to animate anything yet, so I decided to just go with some floaty/ghost-like foxes.

12am Mon - Snow!

I grabbed some crappy (but working) Particle code that I wrote before and dumped it into the game. I didn't really want the code anyway since it was badly designed, but I need something quick to make particles. I drew some quick snow images and added it to the game. After some tweaking, I finally managed to get this:
screenshot with snow particles


2am Mon - Sleep

Once again time to sleep. I was happy with the progress so far. Things were shaping up.

10am Mon - Final Touches

For some reason, in my head, I was thinking this would be a 48-hour jam. So yes, Monday morning is still legit. In the final hour, I added some explosion effects to the enemies. And I also fixed up the game retry so that the player could play again if they wanted.

Overall, I think I neglected design quite a bit for this weekend jam, but I'm still happy with the result so far. I'm also glad I got to draw the sprites and get to practice picking colors.

The current game state is not really playable; the waves are not designed, enemy units and towers are not balanced and we're missing a currency system.

However, here is the current state of the demo anyway for those of you who want it, check my next post!

Get Adsense

Want to earn money like me? Get Google Adsense now by clicking this