How To Make a Cross-Platform Game with Cocos2D Javascript Tutorial: Getting Started
In this tutorial, you will port the raywenderlich.com classic Ninjas Going Pew-Pew game to Cocos2D-Javascript. I like implementing this game when learning new frameworks because it’s simple, but covers the most important aspects of making a game. By Ray Wenderlich.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
How To Make a Cross-Platform Game with Cocos2D Javascript Tutorial: Getting Started
35 mins
Hello, Cocos2D-HTML5!
As I mentioned earlier, you will first get the HTML5 version of this game working first, then you’ll switch to the other platforms later in this series.
So download the latest version of Coos2D-HTML5, which is v2.1.1 at the time of writing this tutorial. Unzip the directory and save it somewhere safe on your hard drive.
Then, inside the Cocos2D-HTML5 directory, copy the cocos2d, CocosDenshion, and extensions directory into the Cocos2DSimpleGame\Platform\HTML5 directory from your starter kit:
This copies all of the Cocos2D-HTML5 framework code into a subdirectory of your project so you can reference it easily. Note that you won’t actually ship your game like this – there’s a better way you’ll learn more about in part 2 of this series – but this is great for debugging and development.
Next, create a new file named Cocos2DSimpleGame\index.html and replace the contents with the following:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Cocos2D-JS Simple Game Demo | raywenderlich.com</title>
</head>
<body style="text-align: center;background: #f2f6f8;">
<img style="clear:both;margin-bottom: 20px" src="logo.png"/>
<div></div>
<div style="display:inline-block;width:auto; margin: 0 auto; background: black; position:relative; border:5px solid black; border-radius: 10px; box-shadow: 0 5px 50px #333">
<canvas id="gameCanvas" width="800" height="450"></canvas>
</div>
<script src="cocos2d.js"></script>
</body>
</html>
This is some simple HTML to present a Cocos2D view in the middle of the page. Don’t worry if you’re rusty on HTML – you can use this as a template and tweak it for your needs.
There are two important tags to point out:
<canvas id="gameCanvas" width="800" height="450"></canvas>
This sets up the HTML5 canvas where the Cocos2D drawing occurs and gives it the “gameCanvas” id that the framework will look for. If you want it to be a different size (like in the header of this tutorial), you can just change the numbers here.
<script src="cocos2d.js"></script>
This tells the browser to look for (and run) a Javascript file called cocos2d.js, which you haven’t written yet.
So let’s add that next! Create a new file a new file named Cocos2DSimpleGame\cocos2d.js and replace the contents with the following:
(function () {
var d = document;
var c = {
// 1
menuType:'canvas',
COCOS2D_DEBUG:2,
box2d:false,
chipmunk:false,
showFPS:true,
frameRate:60,
loadExtension:true,
tag:'gameCanvas',
// 2
engineDir:'./Platform/HTML5/cocos2d/',
appFiles:[
'./Src/resource.js',
'./Src/MainLayer.js',
'./Src/main.js'
]
};
// 3
window.addEventListener('DOMContentLoaded', function () {
var s = d.createElement('script');
if (c.SingleEngineFile && !c.engineDir) {
s.src = c.SingleEngineFile;
}
else if (c.engineDir && !c.SingleEngineFile) {
s.src = c.engineDir + 'platform/jsloader.js';
}
else {
alert('You must specify either the single engine file OR the engine directory in "cocos2d.js"');
}
document.ccConfig = c;
s.id = 'cocos2d-html5';
d.body.appendChild(s);
});
})();
This file is mostly boilerplate, however there are a few sections you might want to tweak so let’s go over it.
- These are various Cocos2D settings, such as the debug level for the framework and which libraries to enable (Box2D, etc).
- Here you specify where the Cocos2D framework code resides – remember how you copied it into the Platform/HTML5/cocos2d directory? You also specify all the Javascript files in your game.
- This is just some boilerplate that starts the Cocos2D framework running.
You may have spotted that the appFiles in section 2 listed a file named main.js, but you haven’t written that yet. That is the last file you have to write to get this all working.
So create a new file named Cocos2DSimpleGame\Src\main.js and replace the contents with the following:
var cocos2dApp = cc.Application.extend({
config:document['ccConfig'],
ctor:function (scene) {
this._super();
this.startScene = scene;
cc.COCOS2D_DEBUG = this.config['COCOS2D_DEBUG'];
cc.initDebugSetting();
cc.setup(this.config['tag']);
cc.Loader.getInstance().onloading = function () {
cc.LoaderScene.getInstance().draw();
};
cc.Loader.getInstance().onload = function () {
cc.AppController.shareAppController().didFinishLaunchingWithOptions();
};
cc.Loader.getInstance().preload(g_ressources);
},
applicationDidFinishLaunching:function () {
var director = cc.Director.getInstance();
director.setDisplayStats(this.config['showFPS']);
director.setAnimationInterval(1.0 / this.config['frameRate']);
// 1
director = cc.Director.getInstance();
winSize = director.getWinSize();
centerPos = cc.p( winSize.width/2, winSize.height/2 );
director.runWithScene(new this.startScene());
return true;
}
});
// 2
var director;
var winSize;
var centerPos;
var myApp = new cocos2dApp(MainLayer.scene);
To run your game, you need to create a class that derives from cc.Application – and that is exactly what this does here. It has an applicationDidFinishLaunching method, just like in iOS.
Most of this is boilerplate, except for the two sectoins I noted:
- Initializes those global helper variables I mentioned earlier.
- Declares the global variables, and specifies the scene to run (MainLayer.scene – that helper method you wrote earlier to create a scene with the MainLayer in it).
And you’re finally done! To test this out, open index.html in the web browser of your choice. Note that I have had best luck with Firefox, as Safari doesn’t always work with local debugging.
If all goes well, you should see your ninja appear on the screen!
Moving Monsters
Next you want to add some monsters into your scene for your ninja to combat. To make things more interesting, you want the monsters to be moving – otherwise there wouldn’t be much of a challenge! So let’s create the monsters slightly off screen to the right, and set up an action for them telling them to move to the left.
First, open Cocos2DSimpleGame\Src\resource.js and modify the list of resources to include the other two images:
var dirArt = "Art/";
var s_player = dirArt + "player.png";
var s_monster = dirArt + "monster.png";
var s_projectile = dirArt + "projectile.png";
var g_ressources = [
{type:"image", src:s_player},
{type:"image", src:s_monster},
{type:"image", src:s_projectile}
];
Then open Cocos2DSimpleGame\Src\MainLayer.js and replace the start of the file with the following:
var MainLayer = cc.LayerColor.extend({
_monsters:[],
ctor:function() {
// Rest of file...
This creates an instance variable for the list of monsters in the scene, and initializes the list to an empty array.
Next add a comma after the onEnter method, and add this new method:
addMonster:function() {
var monster = cc.Sprite.create(s_monster);
// Determine where to spawn the monster along the Y axis
var minY = monster.getContentSize().height / 2;
var maxY = winSize.height - monster.getContentSize().height / 2;
var rangeY = maxY - minY;
var actualY = (Math.random() * rangeY) + minY; // 1
// Create the monster slightly off-screen along the right edge,
// and along a random position along the Y axis as calculated above
monster.setPosition(winSize.width + monster.getContentSize().width/2, actualY);
this.addChild(monster); // 2
// Determine speed of the monster
var minDuration = 2.0;
var maxDuration = 4.0;
var rangeDuration = maxDuration - minDuration;
var actualDuration = (Math.random() % rangeDuration) + minDuration;
// Create the actions
var actionMove = cc.MoveTo.create(actualDuration, cc.p(-monster.getContentSize().width/2, actualY)); // 3
var actionMoveDone = cc.CallFunc.create(function(node) { // 4
cc.ArrayRemoveObject(this._monsters, node); // 5
node.removeFromParent();
}, this);
monster.runAction(cc.Sequence.create(actionMove, actionMoveDone));
// Add to array
monster.setTag(1);
this._monsters.push(monster); // 6
}
I’ve spelled out things in a verbose manner here to make things as easy to understand as possible. The first part should make sense based on what we’ve discussed so far: you do some simple calculations to determine where you want to create the object, set the position of the object, and add it to the scene the same way you did for the player sprite.
I’ll explain the rest of the code in two different ways, based on whether you’re already familiar with the Cocos2D iOS API or not.
[spoiler title=”I’m Familiar with Cocos2D-iOS”]
Here are some things to point out for those transitioning to Cocos2D-Javascript from Cocos2D-iOS:
- Javascript has various handy built-in libraries/functions, like Math.random(). You can find a good reference in the Javascript book I recommended.
- Instead of using dot syntax like monster.position in Objective-C, you always have to call setters like setPosition() with the Javascript bindings.
- cc.p is the equivalent of ccp.
- You can either pass in the name of a method (like this.monsterMoveDone) to cc.CallFunc.create, or you can pass in an anonymous function like you see here (which is similar to using CCCallBlock in Objective-C).
- Cocos2D has a helper function to remove an element from a Javascript array: cc.ArrayRemoveObject.
- In Javascript you use this, not self. I can’t tell you how many times I forget this and use self out of habit, causing everything to fail miserably, gah!
[/spoiler]
[spoiler title=”I’m Completely New to Cocos2D”]
The new element here is adding actions. Cocos2D provides a lot of extremely handy built-in actions you can use to animate your sprites, such as move actions, jump actions, fade actions, animation actions, and more. Here you use three actions on the monster:
- cc.MoveTo: You use the cc.MoveTo action to direct the object to move off-screen to the left. Note that you can specify the duration for how long the movement should take, and here you vary the speed randomly from 2-4 seconds.
- cc.CallFunc: The cc.CallFunc action allows you to specify a callback function to run when the action is performed. You can either pass in the name of a function (like this.monsterMoveDone) or you can use an anonymous function like shown here. In this game, you add some code to remove the moster from the game (and the monsters array) after it moves offscreen to the left. This is important so that you don’t leak memory over time by having tons of unused sprites sitting off-screen. Note that there are other (and better) ways to address this problem such as having reusable arrays of sprites, but for this beginner tutorial you are taking the simple path.
- cc.Sequence: The cc.Sequence action allows you to chain together a sequence of actions that are performed in order, one at a time. This way, you can have the cc.MoveTo action perform first, and once it is complete perform the cc.CallFunc action.
[/spoiler]
Back to Business
That’s it for explanations – now let’s make sure your addMonster function is called periodically.
To do so, add a comma after addMonster and add this new method:
gameLogic:function(dt) {
this.addMonster();
}
Then add this line to the end of onEnter:
this.schedule(this.gameLogic, 3);
This schedules your gameLogic method to spawn a monster every three seconds.
Save your file and refresh your web browser, and you should now have monsters flying across the screen!