Building a Ninja Turtles Game with jQuery

April 09, 2010

In this tutorial we’ll build a Teenage Mutant Ninja Turtles game as a fun and simple project to learn jQuery grep, queue/dequeue, delay and animation as well as jQuery UI draggable, droppable, effects and button.

View the jQuery Game

I grabbed the ninja turtle sprites and renamed them and organized them into folders. The animated sprite of april is off another site.

Download Just the Images

First, lets setup a couple global variables and put our “good guys” and “bad guys” information in an array of objects.

<!—var game = {};
var battlenum = 0;

var goodguys = [
{
"name" : "Leonardo",
"bio": "images/bio/leo.gif",
"stand": "images/stand/leo.png"
},
{
"name" : "Michaelangelo",
"bio": "images/bio/mike.gif",
"stand": "images/stand/mike.png"
},
{
"name" : "Donatello",
"bio": "images/bio/don.gif",
"stand": "images/stand/don.png"
},
{
"name" : "Raphael",
"bio": "images/bio/raph.gif",
"stand": "images/stand/raph.png"
}
];

var badguys = [
{
"name" : "Foot Soldier",
"stand": "images/stand/footsoldier.png"
},
{
"name" : "Rock Steady",
"stand": "images/stand/rocksteady.png"
},
{
"name" : "Bebop",
"stand": "images/stand/bebop.png"
},
{
"name" : "Lt Granitor",
"stand": "images/stand/ltgranitor.png"
},
{
"name" : "General Traag",
"stand": "images/stand/traag.png"
},
{
"name" : "Krang (in exosuit)",
"stand": "images/stand/exo.png"
},
{
"name" : "The Shredder",
"stand": "images/stand/shredder.png"
}
];

Now that we have our game information setup, lets create the HTML markup for our game. We’ll have a player chooser, an arena to fight in, and then add an attack button which could have other actions in the future.

<h1>Teenage Mutant Ninja Turtles Battler</h1>
<h2>Drag and drop a turtle into battle.</h2>
<div id="chooser">
<img class="bio" src="images/bio/leo.gif" alt="Leonardo">
<img class="bio" src="images/bio/mike.gif" alt="Michaelangelo">
<img class="bio" src="images/bio/don.gif" alt="Donatello">
<img class="bio" src="images/bio/raph.gif" alt="Raphael">
</div>
<div id="arena"></div>
<div id="actions" style="display:none">
<button class="action-attack">Attack</button>
</div>

I used jQuery UI CSS framework to build a ninja turtles CSS theme. Hit download on the left side and download jQuery UI as well.

Now we’ll setup the CSS for the game, it is pretty simple. We have hover style for the player chooser, the arena, and inside the arena we’ll set some absolute positions for the goodguy, badguy and april.

body {
font-size: 12px;
}
#chooser {
z-index: 1;
}
#chooser .bio {
cursor: move;
border: 1px solid white;
}
#chooser .bio:hover {
border: 1px solid black;
}
#arena {
background: white;
height: 80px;
width: 225px;
padding: 20px;
position: relative;
z-index: -1;
}
#arena .goodguy {
position: absolute;
left: 20px;
top: 20px;
}
#arena .enemy {
position: absolute;
top: 20px;
right: 45px;
}
#arena .april {
position: absolute;
top: 20px;
right: 0;
}

Next we’ll setup our characters by adding them to the arena. The goodguy doesn’t have an src because the player has to choose it. We are using the way to create HTML elements that is in jQuery 1.4 $("&amp;lt;tag /&amp;gt;", { options/events }).

  // characters
april = $(&lt;img /&gt;, { "src": "images/apriltiedup.gif", "class": "april" });
enemy = $(&lt;img /&gt;, { "src": badguys[0].stand, "class": "enemy" });
goodguy = $(&lt;img /&gt;, { "class": "goodguy" });

// setup arena
arena = $("#arena")
.append(april)
.append(enemy)
.append(goodguy);

Lets add the ability to choose your character. I think it is fun to choose your character by dragging and dropping them into the arena. First, we’ll make the character bios draggable, using their alt attribute name it filter through our goodguys object.

// setup chooser
bios = $("#chooser img")
.draggable({
helper: function(e, ui){
guy = $.grep(goodguys, function(guy){
return guy.name == $(e.target).attr(alt);
})[0];
return $(&lt;img /&gt;, { "src": guy.stand });
},
cursorAt: { "right": 5, "top": 0 }
});

We want to change the drag helper to the image of the character standing. We do this by returning the image path in the helper function in the draggable options.

So now you may be thinking, what is $.grep? Grep allows us to dive into the goodguys array and then it decides what should be in the array. Returning true keeps the item in the array, returning false removes it. So here, if they drag the bio image that has an alt description $(e.target).attr('alt') of “Donatello”, this function will only match true guy.name == "Donatello" for the guy with name Donatello. Grep returns an array of the objects [{"name":"Donatello"...}], so we can use 0 to get the first one, which will be the only one that is matched.

cursorAt just allows us to position the helper image at a certain point relative to the mouse position.

Now lets make the arena droppable to add your character to the battle. Add this to your $("#arena") chain.

  .droppable({
accept: ".bio",
drop: function(e, ui){
guy = $.grep(goodguys, function(guy){
return guy.name == $(ui.draggable).attr(alt);
})[0];
goodguy.attr(src, guy.stand);
$("#actions").show();
}
});

Using the “droppable options”http://docs.jquery.com/UI/Droppable#options, we can set what draggable elements the arena should accept. We set a “bio” class to the bio images, so that will let us accept them.

We’ll do the same thing we did with draggable with $.grep. Keep in mind we could have done some setup and attached the object data to the bio images, but there are so many ways to do things, I’m showing you just one way.

Then we’ll show our actions, which is just an attack button. jQuery UI 1.8 added a button widget that allows us to theme the button easily.

$("#actions button").button();

We’ll do a few things with the attack button. First, we want to only allow them to hit the attack button if there is no game action happening. So we’ll return the function (do nothing) if game.action is true. Then we’ll set game.action to true to indicate we’ve started action on the game.

$("#actions .action-attack").click(function(){
if (game.action) return;
game.action = true;

goodguy
.animate({ left: 100 }, 700)
.effect(shake, { times: 3 }, 150, function(){
$(this).animate({ left: 20 }, 300);
badguydie();
});
});

The attack action is kind of fun. With animate we move the goodguy forward, and then with effect we get to shake the guy a few times. jQuery UI gives us effects, like shake. In the callback function we’ll move the goodguy back into place and start our kill the bad guy function:

function badguydie(){
++battlenum;
enemy.hide(explode, {}, 500);
enemy.queue(function(){
if (badguys[battlenum] == undefined) return gameend();

$(this)
.css(right, 0)
.attr(src, badguys[battlenum].stand)
.delay(800)
.fadeIn(fast).animate({ right: 45 }, 300)
.queue(function(){
game.action = false;
$(this).dequeue();
});
$(this).dequeue();
});
}

Here we use the explode effect which extends hide by .hide(effect, options, speed).

With battlenum we just want to increment it so we can go through all the badguys, and if there are no badguys left we’ll run the gameend() function. We could have bound gameend to the arena with a custom event, but this is done just for simplicity.

Once the explode animation is done it will run the next function in the queue. queue allows us to add functions to the ‘fx’ queue which is what happens when you chain multiple animations together.

delay is nice because we can have a little time to soak in that you just killed a bad guy before the next one shows up.

Then we move the next enemy into place and dequeue our functions.

Once the enemies are gone.. hooray! Now the player won with this function which changes April’s image to the waving image of here and pops up a jQuery UI Dialog that the player won.

function gameend(){
april.attr(src, images/aprilwave.gif);
setTimeout(function(){
$("<div />", {
title: "You win!",
html: "April is now safe, thanks to you." }).dialog({ modal: true });
}, 1000);
}

Download the Final Files

“View the jQuery Game”http://assets.marcgrabanski.com/resources/jquery-game-tmnt/

15 comments

#1. Alex on April 09, 2010

HAHAHA!!!! I slain shredder!!!! that was hard.

#2. Royal on April 09, 2010

Cowabunga!

#3. Marc Grabanski on April 09, 2010

“Pizza time”

#4. Avinash on April 09, 2010

Very Funny :)

Great Job!

#5. Name on April 09, 2010

You’re a genius! :)

#6. TheDiLab on April 09, 2010

Haha, interesting.

#7. Erik on April 10, 2010

Amazing!
Missed the Konami code though :D

#8. wespai on April 11, 2010

nice game

#9. Thijs Damen on April 12, 2010

Thanks for this. Particulary showed me the way to keep track of variables and states of the game (game.action) and if (badguys[battlenum] == undefined).

#10. Wai Phyo Han on April 20, 2010

Very interesting! . thanks for this tuts!

#11. Andy on April 23, 2010

holds head in hands in dispair

You have FAR too much time on your hands Marc

#12. matt on May 05, 2010

How come I can’t seem to get it to work? The anims don’t work

#13. Marc Grabanski on May 05, 2010

matt: at the bottom of the article, you can download the entire example. Compare with your and see what went wrong. Maybe you didn’t download the jQuery UI effects JavaScript?

#14. inwebdeveloper on June 29, 2010

awesome, i like this game.

#15. Oussama on November 13, 2010

I’ve been playing this game for hours :P

Leave a comment

Comment in textile images by gravatar