Save Christmas with Bazooka

December 20, 2012

This post will probably not make much sense, because I’m documenting the process of creation through out many days, which means that there might not be as much contextual sense as one would like. But I felt like I wanted to write down my thoughts as I created the game.

Now, first and foremost, this game is not supposed to be the most elegant or sophisticated game that has ever been created on the internet. I got the idea in early December an I’ve only got so and so much free time to pour into the idea. I had a set deadline, release before Christmas, which gave me at most 24 days of development, considering I work full time (15 of these days) and I’m going to Finland the 22nd of December (2 days) means that I in reality only got 7 days of completely free days. I wanted to create the game during my free time because of two issues, I’ve got way too many projects at work that I need to get done and secondly, by doing this on my spare time I own the complete set of code for the game (if I want to create more games based on this engine).

The decision to use the engine for bazooka came in at a later date, which also meant that I got a team of really talented visual designers to create the look of the game and have added a lot of ideas for the engine and how to game play should be, so I can in no way take full credit for the game itself.

Building a 2d platform game

A 2d platform game is probably one of the easiest games to get working, at least as a prototype. you generally need only a few things to get it to work. You need a simple “physics engine” meaning that when the player jumps, he should, eventually, fall down. You need some kind of platform engine, because a game where the player only falls will become quite dull, fast. And thirdly, you need player movement. I’d say that these three things are the bear minimum that you need to have working if you expect to actually have a playable game at the end of the day.

Optionally you’ll probably want some kind of graphics for the game. Me not being a good visual designer, I decided to build on somebody else’s work, specifically this sprite sheet. I only created a few new items, and winter-fied some of the already existing ones. (This later changed when bazooka decided to pick the engine up for their Christmas card)

Player Movement

When I develop a game, I always start with player movement. This is because that’s one of the most visual parts of the game engine, and some how ties together everything. The easiest and most straight forward way to create movement is to just bind the different keys to different moves.

Have some pseudo-code:

function onKeyPress( keyPressed ) {
	switch( keyPressed ) {
		case 'up':
			player.top -= 1;
		break;
		case 'down':
		player.top += 1;
		break;
		case 'left':
			player.left -= 1;
		break;
		case 'right':
			player.left += 1;
		break;
	}
}

In essence that will give you what you want, the player moves around. Though there’s a few problems with this technique. When a key-event is fired, it usually fires one time first, then pauses and then continues to rapidly fire the event as the key is held down. This doesn’t really give you any control of the speed of movement other than increasing or decreasing the pixelcount. The second problem with it is that if the key-event is interrupted with another keypress the first one will be canceled, which means the player can’t move diagonally, which sucks.

In this particular game, all movement is made with key-listeners and timer-intervals. Which means I only care when the button is being pressed the first time, and when it’s released.

Have some pseudo-code from the actual game (lots of extra logic has been ripped out to simplify the core objective):

this.moveStart = function( e ) {
	var keyCode = e.keyCode;
	switch( keyCode ) {
		case 87: // w, up
			if( this.move.up === 0 ) {
				this.move.up = setInterval(
					function() {
						this.playerMove( e );
					}.bind(this)
					,10
				);
			}
		break;
		case 68: // d, right
			if( this.move.right === 0 ) {
				this.move.right = setInterval(
					function() {
						this.playerMove( e );
					}.bind(this)
					,60
				);
			}
		break;
		case 65: // a, left
			if( this.move.left === 0 ) {
				this.move.left = setInterval(
					function() {
						this.playerMove( e );
					}.bind(this)
					,60
				);
			}
		break;
	}
}

this.moveStop = function( e ) {
	var keyCode = e.keyCode;
	switch( keyCode ) {
		case 68: // d, right
			clearInterval( this.move.right );
			this.move.right = 0;
		break;
		case 65: // a, left
			clearInterval( this.move.left );
			this.move.left = 0;
		break;
	}
}

this.playerMove = function( e ) {
	var $player = $( this.playerElement );
	var keyCode = e.keyCode;

	switch( keyCode ) {
		case 87: // w, up
			p = this.calculateObjectPositions( this.playerElement );
			$player.css( { 'top': ( p.top - 15 )+'px' } );
		break;
		case 68: // d, right
			p = this.calculateObjectPositions( this.playerElement );
			$player.css( { 'left': ( p.left + 10 )+'px' } );
		break;
		case 65: // a, left
			p = this.calculateObjectPositions( this.playerElement );
			$player.css( { 'left': ( p.left - 10 )+'px' } );
		break;
	}
}

What I’m essentially doing is when ‘key-left’ is pressed I start an interval which keeps on moving the player to the left, when the key is released the timer is cleared and the player stops moving. This process won’t be interrupted by other key presses nor will there be a lag between the first fired event and the consecutive ones. Though yes, the code base just got expanded by a multitude of factors. But I’ve also gained the power to decide how often the movement should happen (timing on the setInterval) and the speed per movement (the amount of pixels moved).

Platform engine (hit-detection)

The platform engine is in reality just simple hit-detection, you need to check if the player is touching an element that is deemed to be solid. In this game I’ve implemented the most simple one you can create. Overlapping box detection. The idea is that all elements are square and if one square is overlapping another one fire an event. So what I’ve basically done is created a div with all the interact-able objects within (including the player), every object that is solid has a css class named ‘static’, I then continuously monitor if the player is touching one of these objects, if it touches the player will be placed on a set position based on the way the player is touching the element. For example, if the player is falling down on an object, the position of the player will be above the object. If the player is walking into an object, then the player is placed beside the object. Simple right?

Here’s a function to do simple hit-detection (named after hittest() in actionscript), and yes, that’s a freakishly long if-statement.

this.hitTest = function(item, target)
{
	item._x = item.offsetLeft;
	item._y = item.offsetTop;

	item._height = item.clientHeight;
	item._width = item.clientWidth;

	target._x = target.offsetLeft;
	target._y = target.offsetTop;

	target._height = target.clientHeight;
	target._width = target.clientWidth;

	if	( (item._x+item._width) >= target._x && (target._x+target._width) >= item._x && (item._y+item._height) >= target._y && (target._y+target._height) >= item._y ) {
		return true;
	}
	return false;
}

Too improve the performance of the engine, I decided to load and unload blocks of the game during runtime, this means that, in theory, the hitTest’s will run against a lot less objects at once.

To make the engine as versatile as possible, I needed to keep the level-data outside of the level-builder. So I created an object for each level that contains everything that isn’t considered static. This means that all blocks, backgrounds, texts, enemy-types and positions are saved in one large object per level. What you gain from separating the level logic from the level elements is that it’s easier to create and change levels, and you’ll be more confident that the rendering of the level will be same each time the game is being loaded. As a bonus to this approach is that it’s very easy to build a level-designer for the game, because the level objects can be created anywhere and then be loaded into the engine for rendering.

{
	// A static block (which is able to block player movement).
	// notice that the type of static blocks can change based on
	// css class
	left:0,
	top:448,
	type:'block darkbrick static'
},
{
	// A scenery item, fixed to the level, but non-interactable.
	// Notice that the type of scenery item can change based on
	// css class
	left:2176,
	top:265,
	type:'sceneryItem christmasTreeLarge'
},
{
	// A gift package that the player is able to pick up
	left:320,
	top:416,
	type:'giftPackage'
},
{
	// An enemy, spawn position is set (but the object will move later).
	// Notice that the type of enemy can change based on
	// css class
	left:640,
	top:384,
	type:'enemy green'
},

Physics engine

This part I also opted for a seemingly simple idea, yet it’s sadly quite expensive resource wise. What I do is I check what state the player currently is in, e.g. if the player jumps, ignore all physics while player is going upward (except if the player hits something going up, then cancel the jump sequence). Once the upwards movement stops, the player should start falling. I’ve applied the same concept as I do when moving the player sideways. I just increment on the css-top property, and every time I increment I check if the player is hitting something. If it hits something, the gravity “stops”. The physic engine is applied on the player object and is constantly polled via a setInterval (this interval should be faster then the movement interval).

Enemies

While this is not something that needs to exist in a platform engine, I’ve decided to write a few lines about it anyway. The way I’ve implemented the enemy object is that I’ve based it on the code base of the player object. Then I’ve added automatic movement. I change the movement of the enemy if it hits a wall or static object, this way the enemy will move back and forth infinitely.
In my implementation I’ve completely removed gravity from the enemies, the reason is that I wanted to save as much resources as possible, and because I can decide where to place the enemies during level creation, I’ve always spawned the enemies in between two walls (which means if the enemy would be deployed without walls, it would just hover over the ground moving forward until it hits something).
To kill an enemy, I again use simple hit-detection between the enemy element and the player element. If an hit occurs I check the state of the player. If the player is falling (or jumping), the enemy will destruct itself, if the player is not falling, the enemy will call on the destruct method of the player object.

// Hit detect
if( core.hitTest( this.element, this.playerElement ) ) {
	// Check if the player is falling and the player is not dead already
	if( !core.player.falling && !core.player.killed ) {
		// Destruct the player
		core.player.destruct();
		return false;
	} else {
		// Cancel the players fall, and force the player to jump
		core.player.falling = false;
		core.player.moveStart( { keyCode:87 } );

		// Self destruct
		this.element.enemyHandler.destruct( true );
	}
}

Conclusion

While building a basic platform game isn’t necessarily that hard, removing all elements of bugs does take a lot of time (And this engine does still have a lot of bugs in it, I had to make a call when we’ve met the good-enough requirement). I’ve only scratched the surface of all the work that goes in to actually creating a fully functional game, but I do feel like I’ve covered some of the most basic things needed.

I believe this game ended up being one of my most complete engines, I did have to make a few ugly hacks in the end of the day to meet the deadline. For example the splash screens, sound and high score was made more like an after thought than actually being correctly implemented, and if I’d code this game again, I’d probably opt for a better working physics engine. But otherwise I am quite happy over the end results, and for every time a build a game engine I feel like I learn a lot new tricks that I can apply in my daily work.

This game is less then 2000 lines of Javascript (Not counting level data).

Play it here!

Tags