How To Make A Simple iPhone Game with Cocos2D 3.0 Tutorial
Let there be ninjas! In this Cocos2D 3.0 tutorial, you’ll learn how to make a simple iPhone game, even if you’re a complete beginner. By Martin Walsh.
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 Simple iPhone Game with Cocos2D 3.0 Tutorial
30 mins
Collision Detection and Physics
So you have a ninja, monsters and projectiles flying all over the screen. It looks good but it would be a lot more fun with a bit of impact, for that you need collision detection between your projectiles and your monsters.
One of the great new features of Cocos2D 3.0 is the deeply integrated physics engine, making this task a breeze. Physics engines are great for simulating realistic movement, however they are also very useful for handling collision detection.
You are now going to use the Cocos2D physics engine to determine when monsters and projectiles collide. There are four steps to do this:
- Set up the physics world. A physics world is the simulation space for running physics calculations. You will set one up for the scene and modify a few properties like gravity. The physics world is then added to your scene. You will modify the existing game objects so they are added to the physics world so they will be part of the physics simulation.
- Create physics bodies for each sprite. In Cocos2D you can associate a physics body to each sprite for collision detection purposes and set certain properties on it. Note that the physics body does not have to be the exact same shape as the sprite. Usually it’s a simpler shape such as a box or circle, rather than a pixel-perfect outline. Since that is generally good enough for most games and offers better physics performance.
- Set CollisionType for each type of sprite. One of the handy features of Cocos2D physics is you don’t have to play around with integer bitmasks to define your collision types. You can set an easily readable string to define your collision types.
- Set a collision handler delegate. By default when two physics bodies collide they will be handled by the physics simulation however you will want to do something when a projectile collides with a monster such as kill the monster. So you will be adding a collision handler delegate to handle the collision between your monster and projectile collision types.
Let’s get started. First, you will now need to add another private instance variable for you physics world.
Ensure you have HelloWorldScene.m open and add the following to the @implementation HelloWorldScene
declaration after your CCSprite
.
CCPhysicsNode *_physicsWorld;
Now you need to setup the physics simulation and add it to your scene, add the following code after the CCNodeColor
in the init
method.
_physicsWorld = [CCPhysicsNode node];
_physicsWorld.gravity = ccp(0,0);
_physicsWorld.debugDraw = YES;
_physicsWorld.collisionDelegate = self;
[self addChild:_physicsWorld];
Gravity is set to (0,0) as you are using the physics simulation primarily for collision detection. Cocos2D has some handy debug functionality, the debugDraw
flag is really useful to help visualise your physics world. You will be able to see any physics bodies added to the simulation. You are also setting the collisionDelegate
to self
, this allows you to add collision Handlers to the scene and the physics simulation knows to look in HelloWorldScene
for these handlers.
You will notice that Xcode will throw up a warning around the collisionDelegate
line; this is easily resolved. Open HelloWorldScene.h and mark the interface as implenting the CCPhysicsCollisionDelegate
.
@interface HelloWorldScene : CCScene <CCPhysicsCollisionDelegate>
Now you need to set up the player with a physics body and add the player to the _physicsWorld
instead of directly to the scene.
Back in HelloWorldScene.m, find the following code in the init
method:
[self addChild:_player];
Replace that code with the following:
_player.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){CGPointZero, _player.contentSize} cornerRadius:0]; // 1
_player.physicsBody.collisionGroup = @"playerGroup"; // 2
[_physicsWorld addChild:_player];
Quick review of this code snippet:
- Creates a physics body, in this case a box using the player’s
contentSize
to create an bounding box rectangle around the player. - Set physics body
collisionGroup
, by default everything will collide. If you set physics bodies to the samecollisionGroup
they will no longer collide with each other, this is handy when you have a player that is made up of multiple bodies but you don’t want these bodies to collide with each other, for example a player holding a weapon. You will use this to ensure the projectile does not collide with the player.
You have setup physics simulation and created a player physics body and added it to the simulation. Now see if you can do this yourself, by adding the monster to the physics simulation.
[spoiler]
Look inside the addMonster: method and locate the following code:
[self addChild:monster];
Replace with:
monster.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){CGPointZero, monster.contentSize} cornerRadius:0];
monster.physicsBody.collisionGroup = @"monsterGroup";
monster.physicsBody.collisionType = @"monsterCollision";
[_physicsWorld addChild:monster];
[/spoiler]
This is nearly identical to creating the _player
physics body, but I was being a little tricky as I introduced a new property. This time you are setting the collisionType
property, this will be used in setting up a physics simulation collision delegate between the ‘monsterCollision’ and the ‘projectileCollsion’ collisionType
.
You are nearly there now! This time, see if you can add the projectile to the simulation. I’ll give you a clue: it will use both the collisionType
and the collisionGroup
properties.
[spoiler]
Look inside the touchBegan:withEvent method and locate find the following code:
[self addChild:projectile];
Replace with:
projectile.physicsBody = [CCPhysicsBody bodyWithRect:(CGRect){CGPointZero, projectile.contentSize} cornerRadius:0];
projectile.physicsBody.collisionGroup = @"playerGroup";
projectile.physicsBody.collisionType = @"projectileCollision";
[_physicsWorld addChild:projectile];
[/spoiler]
Build and run, and you should see a lot of pretty pink boxes:
The pink boxes around the sprites are created by the _physics
property debugDraw
. They are handy when you are first setting up your physics, so you can make sure that it’s all working as you expect. Notice that the box around the shuriken doesn’t look so great; it would much better if it used a circle.
There is of course a method you can use to create a circular body shape bodyWithCircleOfRadius:
which is a much better fit for your projectile. Replace the projectile body code with the following:
projectile.physicsBody = [CCPhysicsBody bodyWithCircleOfRadius:projectile.contentSize.width/2.0f andCenter:projectile.anchorPointInPoints];
By default the center point will be at the bottom left of the sprite however you want the circle to be placed in the middle of your sprite.
Great, you have now modified your game objects to be part of the physics simulation. Now you really want to be able to execute some of your own code when the projectileCollision
and monsterCollison
collisionType
make contact.
The Cocos2D physics engine has some really nice functionality to do this. Just add the following method into HelloWorldScene.m:
- (BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair monsterCollision:(CCNode *)monster projectileCollision:(CCNode *)projectile {
[monster removeFromParent];
[projectile removeFromParent];
return YES;
}
That snippet of code is pretty powerful. When the physics simulation is set up, the physics engine will check for CCPhysicsCollisionDelegate
methods and call them if they exist. The parameter names will be taken to be the collisionTypes you want to deal with yourself.
In this method you are completely removing both the ‘projectile’ and ‘monster’ nodes from the simulation and scene. You could of course add a score counter, apply a special effect or anything else you would like to do each time a projectile collides with monster.
Build and run and you finally should be able to destroy those monsters. Go go power ninja!