sean@seanmccambridge.com   (843) 696-7237
RSS feed

My first JavaScript game: Captain Adam’s Bar Harbor Birthday Boat Race

October 28, 2009

screenshot of Capt. Adam's Bar Harbor Birthday Boat Race

I built a fully-functional (except in IE, of course) JavaScript game for my nephew’s birthday.  Here’s a cheesy video introduction:

Play Capt. Adam’s Bar Harbor Birthday Boat Race, my first JavaScript game, here

So if you’re a developer, you might be wondering how this game works.  There is some rudimentary animation as the boat scoots around the game based on your keyboard input using the arrow keys.  There is also constant collision testing going on to make sure you’re not over any land and also to see if you’re over a buoy.  There are several variables tracking things like your speed, heading, position, the next buoy you’re supposed to hit, etc.

It’s pretty basic yet kind of complicated, I suppose.  Check out the source files if you’re really curious.  I’ll just explain some basic features here.

Animation

JavaScript animation isn’t anything new.  Using the setTimeout and clearTimeout functions, you can incrementally move a node around the page by changing its CSS position.  Be sure the node you want to move has position: absolute and a top and left value.  Also, its parent node must be either position: relative or position: absolute.  Otherwise, it will be positioned absolutely in the page, and you probably don’t want that.

This game relies on .png graphics.  GIFs, for the most part, just won’t do.  The boat heading rotation is changed with the use of sprites.  Here are the three boats’ sprites:

Friendship V spriteMargaret Todd spriteStarfish Enterprise sprite

The one thing I wish I could do is go back and make the boats bigger and nicer looking.  The first boat was just supposed to be a placeholder, but I ran out of time.  Maybe I’ll go back and improve them later, but I think it’s more likely I’ll just start a new game from scratch based on this code and go from there.

Collision Testing

Obviously, there’s no way the browser knows my intent with the gameplay.  It doesn’t know the map in the background is a map, no less where the islands and ocean are.  So we have to set up some polygons and test whether the boat is about to enter those before every movement.  This is where the program breaks in Internet Explorer.  I haven’t pinned down where the error lies, but I have a hunch.  More about that later.

So I found this inside/outside polygon script by Jonas Raoni Soares Silva:

// from this guy’s fine work
//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/math/is-point-in-poly [v1.0]
 
function collision(poly, pt){
  poly = typeof(poly) != ‘undefined’ ? poly : [ {x:0, y:0},{x:0, y:500},{x:950, y:500},{x:950, y:0} ];
  for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
    ((poly.y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly.y))
    && (pt.x < (poly[j].x - poly.x) * (pt.y - poly.y) / (poly[j].y - poly.y) + poly.x)
    && (c = !c);
  return c;
}

I added a default polygon to test in case it tried to test before the poly parameter was defined.

Now I created all of my polygons in a separate file to keep things clean called coastlines.js.  Here’s a sample polygon:


ironbound = [
  {x: 405, y: 147},
  {x: 386, y: 125},
  {x: 400, y: 100},
  {x: 412, y: 94},
  {x: 417, y: 121}
];

The collision function is called by a function called navigable that tests for collisions with islands, buoys and whether the game has started yet.  Here’s a sample of navigable() testing for a collision with the above shape, ironbound:


function navigable(bX,bY) {
  } if (collision(ironbound, {x: bX, y: bY})) {
    return false;
  }

Since the function that moves the boat calls navigable(), it will not move the boat when navigable() returns false.

I have a feeling testing for all of the polygons on this map is resource-intensive, especially while the boat is being animated, sometimes every 20ms.  But I don’t know how else this would be possible.

Keeping track

As a compulsive devsigner, I spread myself a little thin, and I haven’t fully learned object-oriented JavaScript.  So my code might look a little sloppy.  I created a Boat object to keep track of the boat’s properties:


function Boat() {
  this.h = 0; //heading
  this.i = 0; //old heading
  this.s = 0; //speed
  this.r = 0; //rudder
  this.t = 0; //throttle
  this.x = 0; //locx
  this.y = 0; //locy
}

I ended up not keeping track of the rudder position.  Originally, I was going to have a wheel and throttle graphic overlaid on the page to add some cheesy realism.  But time became a factor when I was scrambling to finish this game at 6 a.m. the day of my nephew’s birthday.

Obviously, you’ve got to track which captain was picked, which boat, which difficulty, etc. so you can change the game elements depending on what was chosen.

This is not a JavaScript game tutorial

To cover in detail all that went into making this game would take quite a long time.  Maybe down the road I’ll be able to compose a 10-part tutorial.  Until then, I just wanted to touch on some of the code that went into making this game.  If you have any feedback, hit me up on Twitter:  

Comments

No comments yet.

 

I appreciate your feedback. Comments are moderated. Email is required but won't be printed. Include your website if you have one.

Website question?
Just ask! :D

(843) 696-7237

sean@seanmccambridge.com

Twitter: @mccambridge

A LOT OF PEOPLE HAVE ASKED about the background photo on this site. It was taken on the beach by Fort Moultrie on the harbor side of Sullivan's Island, SC. The old, wooden sea wall has been there as long as I've lived in Charleston. The beach is a great place to watch the ships and shrimpers come in and has one of the best views of downtown Charleston.