So the last week was kind of hectic for me. First there was the Fronteers conference in Amsterdam, where I volunteered. Two full days of speakers of various levels. Met some great people, did not get a whole lot of sleep. So it was great, I loved it.
After that I went to Hilversum to the Google/Spil games
HTML5 game jam contest/hackathon. The objective was to write a game while being there. I was happy finally one of these events finally took place nearby so I kinda had to go. Even though I knew I’d be exhausted from the conference.
Just interested in the result? Scroll down :)
So let me start by saying that if there is an html5 game contest, I expect the participants to be fairly knowledgeable about html5. Having talks about how great html5 is (especially after having seen two days of such talks, I guess), was kind of a downer to me. I just wanted to start coding.
So first I thought the event made the classic error of having speakers tell the audience that what they already know. Seems that I was wrong about that. And I was shocked. People there did in fact hardly know about the power of html5/css3/unicorns. Bwueh, okay. But even the Spil games guys, whom I had expected to know about the developments in their area (I mean, come on...) hardly seemed to know anything about it. I'm not sure which discovery surprised me most.
Anyways, at about noon we could finally start coding. I met
Kornel at the conference after somebody (I don't remember who...) told me to talk to him because he'd also be at the jam. And I already knew
Edwin from
Fronteers meetups, so we formed a group. I was kind of surprised that they told us to create groups of one or two people, but I guess there's no point in working on a game with five. So I asked whether three was okay and it was. So we could start, yay!
Kornel had the idea of creating a game like
Syndicate. It's a
1993 classic DOS game by
Bullfrog. The sequel,
Syndicate Wars, was published on PC and several consoles (snes, psx, ...). In case you don't follow links, it's an isometric strategy game where you control one to four characters in a real-like world environment. Your job is basically to take out the enemies from other "Syndicates", so your characters can move around and shoot people. You are able to select any combination of characters and move them individually. There were also cars and houses and what not. So yeah, we set a high bar.
We first wasted about two hours setting up a decent file collaboration system. Seriously, wtf? Yeah yeah, github. Well github
requires payment for private repo's, so we didn't want to go with that. I'm on Windows and don't really set up repo's very often. Kornel and Edwin did but ran into various problems. So eventually we ended up with a simple SVN repo. So NOW we could finally get coding. Woot!
We actually worked together pretty good. I mean, I had never worked with Edwin and didn't even know Kornel up till a few days ago. So that was really cool. Basically Kornel worked on the engine. He had a tile grid up 'n running pretty quickly and amazed everybody with a simple sinus wave on the tiling (which in turn surprised me, again, because it was a cool effect but seemed to impress more than it should). I worked on the game logic, moving and selecting characters, implementing the AI, collision detection, etc. Edwin worked on the effects, since both Kornel and I were pretty much useless in that area. So Edwin took it upon him to create the gfx.
This was something that bothered me anyways. It seems to me like this was a good team. I mean, you need two coders to do the general coding work. But you also really need a designer. We determined pretty quickly that the winner of this contest would have good graphics, regardless of the game. That feeling only grew larger as time passed. But I figured these contests would only draw in coders. Maybe it didn't, but for teams sized of two people, it seems like the designer was obligatory. Ohwell, Edwin wasn't a designer but he figured he'd be the best for that so we agreed on our roles and started to work.
Like I said, Kornel had the tiling mechanism up 'n running pretty quickly. It wasn't long before we had sprites that moved around. Edwin had worked on some character animation sprites and I created a mechanism for being able to animate them. It was a simple method which would take an image and assume all sprites in that image were horizontally aligned. There was an animator, just a callback function, and some state so the animators would wait a few ms and switch the sprite being used, depending on several factors. It was nice to see them work so well. We didn't really use animations in our final demo though.
After making the characters individually selectable I started some work on the collision detection. The tiles were rather small, like diamonds in a 40 by 60 rectangle, so I figured tile based collision detection would suffice. First I implemented the tile collision detection. It's very basic really. Tiles have meta data and one of their properties would determine whether the tiles collide or not. At the game loop, when movement is applied, the target cell is checked to be colliding. If so, the velocity of either or both directions would be muted to try and prevent ending up on the colliding tile. That naive implementation worked fine for our engine because there was no object that could move more than a single tile per step. I never got around to implementing more advanced path finding though.
The movement was really simple too. Kornel gave every object a position and velocity. At every game loop iteration, the speed would be applied to the position and that was it. Eventually, the program would call a collision method on the moving object if it somehow ran into a colliding tile. This is used for the rockets explosion.
Edwin was fighting with photoshop and eventually Kornel whipped up a tool in PHP to cut a map into the diamond shaped tiles and Edwin used them to simply create the map and whatever using that. It was awesome seeing how that came to together :)
So at that (/some) point we had friendly characters moving around on a map, individually movable. At first I wanted to do an all nighter, seeing how we had too little time anyways. But eventually I had to cave in to the sleep deprivation of the past few days and took a whopping three hour power nap. Kornel had too so by 6am we were both up and running again. Edwin had gone home (his home was like 10 minutes away from the venue) for sleep. By the time I woke up Kornel had improved the gui and was working on movement, I think.
The rest of the day went by pretty quickly. The bit of sleep was enough for me and I was happily coding on the AI. Edwin continued on the map, which was very time consuming. And Kornel worked on rockets.
I created three types of AI enemies. After mangling the friendly character sprite through some weird filter (it's like playing street fighter all over again; just keep mashing those buttons) they kind of turned up like zombies. The three types of enemies are sentry, patrol and random. Sentry has a point it wants to be at. When it's not, it will try to walk to it. Patrol has a set of waypoints it will walk to, endlessly. Random will walk to random positions in the map, picking a new position in a five tile distance from the current.
Whenever the AI detects a player, which currently simply means a player character is within x tiles of the enemy, it will ignore all of it's commands and try to walk to the closest player instead. Obviously, if it were able to shoot, it would :p Whenever an enemy loses sight of a player (no longer in range) it will have a cool down period during which it will still walk to the last known player position. After this cool down period passes the enemy will try to return to it's regular duties.
So you see, it's a very simple AI but the effect works great. The enemies interact, follow you and lose interest after the cool down period. The generic collision detection makes sure they don't need any path finding algorithm (although they do get stuck quite easily). The next step would be giving them a sight cone. When the game gets a height map (Kornel really wanted to add this), obstacles could be taken into account for visibility. But that's not in right now.
So now we're nearing the deadline. I figured we really needed a game, since we had simple rocket shooting. But for that we would need some kind of health. Kornel did the rocket launcher so I hoped he'd be able to hack in health real quickly. We only had like half n hour to go! However, sleep deprivation kind of turned him into a zombie and I couldn't really get anything out of him. I tried hacking it in myself but got stuck on some bug with the rocket launcher (multiple bugs actually, like one was that the rockets would immediately hit yourself, throwing you in an endless loop of dying :)). So I gave up and polished some minor things. A few minutes before the deadline Kornel woke up and it turns out he'd been working on the rocket/explosion animation, the rocket collision with buildings and an alternative tile for the collision map. Meh, that wasn't going to get us to win. But whatever, the deadline passed, we're all tired, no point arguing.
So then the entries were shown. We had been coding for 24 hours straight, minus the sleep and like 15 minutes for diner and breakfast. We hardly saw anything from the competitors, only heard some guys doing webgl and stuff. Basically, we had no idea what our chances were at all. Especially since we didn't even produce a real game, just an almost ready engine.
But having seen the other entries, I feel pretty good about our result. I mean, come on! We built a frigin game engine FROM SCRATCH in less than 24 hours. With just three people. It would take an average development company at least a few weeks to get to the same results. And that's not even using
scrum.
So the other entries showed a two player tetris, a physics game where you had to put blocks to protect a monkey from falling coconuts, a flying F16 with parallax background (this was the webgl thing... kind of disappointing because it could have easily been made using canvas or even just dom), a multiplayer snake, some kind of social network game, an item catching game with exploding cat, a zombie touching kind of multiplayer game (like tag, the zombie infects others, etc) and an atom learning game (which was actually quite nice).
So we ended up third. Although it surprised me that the tetris game ended up above us (#2) (sorry, but tetris has been done and done), I guess it didn't surprise me that finished games would end up higher than us. Likewise, the coconut physics game (#1) obviously used an existing library (
box2d), but at least it worked. So in that light, we should be happy to become third :)
But I'm not really mourning. In fact, we got to pick our prizes from the pool first. So I landed a
Ingenious game (web play!) which looked nice (and was, as we played it later when I got home). I'm pretty sure I wouldn't have gotten that if the winner was to pick first :p And while on the subject, it struck me as a little odd that a google driven event would give away ipod nano's (for first and second place). The first place was a
galaxy tab (which, I heard, crashes on multi touch? nice one!). I don't want to complaint or anything, but it's just a little weird :)
So I know the tone of this blog post has been a little negative. I'm sorry that it did. I really had a lot of fun creating the game. It's been a while since I had a chance to do some power coding. And this certainly was power coding :) I guess I anticipated a different kind of crowd at that event. My bad.
Well, I'd like thank google and spil for organizing the whole thing. And of course Edwin and Kornel for the collaboration. It was great fun guys!
Friendly headsup; the demo is
cpu heavy and only really works nicelyon chrome or opera (for us, at the time of writing...).
Kornel put the source on
github, which we will maybe/probably continue developing.
I’ve put up a
live demo of the original entry (like, the way we finished it) with full sources.
To see a version improved after the jam ended you can visit his website
here (Kornel updates it every now and then). The water effect is especially working out great :)