Your first Game in Cocos2D – Part 3: The Gameplay

The time has come!. No more boring stuff. We are going to write the gameplay. We are going to create two sprites, the hero and the enemy. When we drag the hero, the enemy will follow him, if he reaches the hero, the game is over.

T he time has come!. No more boring stuff. We are going to write the gameplay. We are going to create two sprites, the hero and the enemy. When we drag the hero, the enemy will follow him, if he reaches the hero, the game is over.

If you just found this page you may like to know where are the previous parts of the series:

Part I:

http://www.oscarvgg.com/your-first-game-in-cocos2d-part-1-menus-and-transitions/

Part II:

http://www.oscarvgg.com/your-first-game-in-cocos2d-part-2-sprites-and-more-transitions/


Adding Characters

I looked up in google and found the perfect characters for our game: Mario and Bowser. Drag the following images to the resources folder just like we did with other images in the previous chapters. Check “Copy items into destination group’s folder” and click Add.

Cocos2D Tutorial | Your first Game in Cocos2D image 1Cocos2D Tutorial | Your first Game in Cocos2D image 2

Go to GamePlay.m and add the following code to create the tags that we are going to give to our sprites:

1
2
3
4
enum {
	kTagHero,
	kTagEnemy
};

We need to give tags to our objects in the scene to be able to find them later because they are not attributes of the class. You will understand this better when we use it.

Scroll down to the init method and position yourself right before the closing curly brace of the if statement. Here we need to tell the world this view is going to receive touches adding the following line:

1
	self.isTouchEnabled = YES;

Then we create the two characters and give them the tags we created to identify them.

1
2
3
4
5
6
7
CCSprite *hero = [CCSprite spriteWithFile:@"hero.png"];
hero.position = ccp(60, 160);
[self addChild:hero z:2 tag:kTagHero];
 
CCSprite *enemy = [CCSprite spriteWithFile:@"enemy.png"];
enemy.position = ccp(440, 160);
[self addChild:enemy z:1 tag:kTagEnemy];

Now we need to make the enemy move to the position of the hero.

1
2
3
[enemy runAction:[CCMoveTo actionWithDuration:5.0
			   position:ccp(hero.position.x, hero.position.y)]
];

Responding to touches

Ok, at the moment, if you run the project, the enemy will move to the position of the hero. What we need now is let the hero scape from the enemy’s claws. To do so we need drag it to a different position, so let’s add touch listener.

1
2
3
4
5
6
-(BOOL) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
	return YES;
}
-(BOOL) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
	return YES;
}

ccTouchesBegan to know that the screen has been touched and ccTouchesMoved to know that our finger is moving over the screen. We are interested in the second one.

In ccTouchesMoved we have to grab that touch and convert it from real world coordinates to a point in game coordinates. Adding the next code before the return statement will do it for us:

1
2
3
UITouch *myTouch = [touches anyObject];
CGPoint point = [myTouch locationInView:[myTouch view]];
point = [[CCDirector sharedDirector] convertToGL:point];

Then we call the hero by the tag and set it position to our finger position:

1
2
CCNode *hero = [self getChildByTag:kTagHero];
[hero setPosition:point];

The hero is in a safe place now, but the enemy did not stand idly. We need to make him follow the hero to it’s new point:

1
2
3
4
CCNode *enemy = [self getChildByTag:kTagEnemy];
[enemy runAction:[CCMoveTo actionWithDuration:5.0
 			   position:ccp(hero.position.x, hero.position.y)]
];

ccTouchesMoved should look like this after all this changes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-(BOOL) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
 
  	UITouch *myTouch = [touches anyObject];
 	CGPoint point = [myTouch locationInView:[myTouch view]];
 	point = [[CCDirector sharedDirector] convertToGL:point];
  	CCNode *hero = [self getChildByTag:kTagHero];
 	[hero setPosition:point];
  	CCNode *enemy = [self getChildByTag:kTagEnemy];
  	[enemy runAction:[CCMoveTo
 		actionWithDuration:5.0
 		position:ccp(hero.position.x, hero.position.y)
 	]];
  	return YES;
}

What is next?. We have to create a function that check if the enemy reached the hero and a game over scene. Let’s go first for the Game Over scene.


Game Over Scene

Right click the “Classes” folder and click add->New File. Select Cocos2D->ccNode and click Choose. Give it a name, mine is going to be called “GameOver.m”

Open GameOver.m. Add the scene method like we did with the other scenes we created previously. it should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
+(id) scene {
	// 'scene' is an autorelease object.
	CCScene *scene = [CCScene node];
 
	// 'layer' is an autorelease object.
	GameOver *layer = [GameOver node];
 
	// add layer as a child to scene
	[scene addChild: layer];
 
	// return the scene
	return scene;
}

Right after that we create the init method. Add two labels, one to let the user know the game is over and other to tell him to touch the screen to go to main menu:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-(id) init{
 
	if( (self=[super init] )) {
 
		self.isTouchEnabled = YES;
 
		CCLabel* label = [CCLabel labelWithString:@"Game Over"
                                      fontName:@"Marker Felt"
                                      fontSize:60];
		label.position = ccp(240, 240);
 
		CCLabel* label2 = [CCLabel labelWithString:@"Touch to go to main menu"
                                      fontName:@"Marker Felt"
                                      fontSize:35];
		label2.position = ccp(240, 131.67f);
 
		[self addChild: label];
		[self addChild: label2];
 
	}
	return self;
}

To make it true we have to add the touch listener and the call to go to main menu:

1
2
3
4
5
6
7
8
9
-(BOOL) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
 
	[[CCDirector sharedDirector]
		replaceScene:[CCFadeTransition
			transitionWithDuration:1
			scene:[HelloWorld node]
	]];
	return YES;
}

Don’t forget to: #import “HelloWorldScene.h”. Now Let’s go back to GamePlay.m.


Detecting Collisions

To see if the characters collided we need to add a little of mathematic.

By checking the distance between the two pivot points of the sprites we can determinate how close or far they are from each other. Fist we need to determinate the size of the collision body of the character (this is not a real body, is just the distance other sprite should be from the pivot of my sprite to consider they are colliding). i’m going to say that for my characters the body is going to be 45 points, so when they are 45 points or less from each other they are colliding.

Cocos2D Tutorial | Your first Game in Cocos2D image 3

But when should i check the distance between them?. Well, all the time, so we need to schedule our collisions method to be called as often as we want. I’m going to call it every 0.01 seconds. How?. Easy, before the closing curly brace of the if statement of the init method add:

1
2
[self schedule:@selector(SpritesDidColide) 
		       interval:.01];

Now init should look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
-(id) init {
 
	if( (self=[super init] )) {
 
		CCMenuItem *Pause = [CCMenuItemImage
 					itemFromNormalImage:@"pausebutton.png"
					selectedImage: @"pausebutton.png"
					target:self
					selector:@selector(pause:)];
 
		CCMenu *PauseButton = [CCMenu menuWithItems: Pause, nil];
		PauseButton.position = ccp(25, 295);
		[self addChild:PauseButton z:1000];
 
		self.isTouchEnabled = YES;
 
		CCSprite *hero = [CCSprite
					spriteWithFile:@"hero.png"];
		hero.position = ccp(60, 160);
		[self addChild:hero z:2 tag:kTagHero];
 
		CCSprite *enemy = [CCSprite
					spriteWithFile:@"enemy.png"];
		enemy.position = ccp(440, 160);
		[self addChild:enemy z:1 tag:kTagEnemy];
 
		[enemy runAction:[CCMoveTo
				actionWithDuration:5.0
				position:ccp(hero.position.x,
					hero.position.y)
		]];
 
		[self schedule:@selector(SpritesDidColide)
		 interval:.01];
 
	}
	return self;
}

Let’s write SpritesDidColide:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-(void) SpritesDidColide {
 
	CCNode *enemy = [self getChildByTag:kTagEnemy];
	CCNode *hero = [self getChildByTag:kTagHero];
 
	float xDif = enemy.position.x - hero.position.x;
	float yDif = enemy.position.y - hero.position.y;
	float distance = sqrt(xDif * xDif + yDif * yDif);
 
	if (distance < 45) {
		[self unschedule:@selector(SpritesDidColide)];
		[[CCDirector sharedDirector]
			replaceScene:
				[CCFadeTransition
				transitionWithDuration:1
				scene:[GameOver node]
		]];
	}
 
}

Here we calculated the distance between the two pivot points, then we checked if it was lower than 45 points. If it is, then we stop calling the method and send the player to the game over scene.


Conclusion

Congratulations!. You just finished your first Cocos2D for iPhone game. That bring us to the end of this series. But don’t worry, i will be posting more Cocos2D tutorials in the future.

Where to go from here

If you are serious about this you should practice making some games. Do them more and more complicated every time and you’ll get more experience. Maybe some day i will download one of your games from the AppStore.

Tags: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,

Software Engineer and iOS developer, from Caracas, Venezuela, with a tremendous weakness for hamburgers.

28 Responses to “Your first Game in Cocos2D – Part 3: The Gameplay” Subscribe

  1. eastlandgrl October 18, 2010 at 6:12 AM #

    interesting, thanks

  2. Soumya October 22, 2010 at 5:20 PM #

    Hi

    Thank you so much for your tutorial.It is working very well.Now i am adding some more features in to this,how to quit from the entire application if i am clicking a “Quit” or “Exit”menu item.I used [[CCDirector sharedDirector] end],but not working.Please help me to solve this problem.

    • OscarVGG October 24, 2010 at 8:14 PM #

      Ok, here is the thing. You can not quit iPhone Apps from the app itself…

  3. ibi sum December 6, 2010 at 6:29 PM #

    Nice Tutorial, Oscar!

    One thing – Bowser moves real slow when you’re touching the screen .. maybe you can address that in the next tutorial?

  4. IronMike December 8, 2010 at 9:07 PM #

    Hero and Enemy won’t display during gameplay. I’ve double checked all the code and must be missing something. Can you post the entire project as a download so I can check it against the one I made in the tutorial?

    • IronMike December 8, 2010 at 9:18 PM #

      Never mind. I accidentally had a “return self;” just before the part that adds the sprite characters.
      You can just deny these 2 comments. Thanks

  5. sonu January 5, 2011 at 7:17 AM #

    Hi,

    I got a error when i wrote self.isTouchEnabled = YES; in init method. If i remove it then it was running successfully but i didnt get touch events. Please give me your solution.

    • Christopher Farley July 18, 2011 at 8:15 PM #

      i actually have the same problem. it says Request for member ‘isTouchEnabled’ in something not a structure or union. here is my init:

      -(id) init {
      if( (self=[super init] )) {
      CCMenuItem *Pause = [CCMenuItemImage itemFromNormalImage:@"pausebutton.png"
      selectedImage:@"pausebutton.png"
      target:self
      selector:@selector(pause:)];
      CCMenu *PauseButton = [CCMenu menuWithItems: Pause, nil];

      PauseButton.position = ccp(25, 295);

      [self addChild:PauseButton z:1000];

      self.isTouchEnabled = YES;

      CCSprite *hero = [CCSprite spriteWithFile:@"mainguy.png"];
      hero.position = ccp(60, 160);
      [self addChild:hero z:2 tag:kTagHero];

      CCSprite *enemy = [CCSprite spriteWithFile:@"base2.png"];
      enemy.position = ccp(440, 160);
      [self addChild:enemy z:1 tag:kTagZombie];

      [enemy runAction:[CCMoveTo actionWithDuration:5.0
      position:ccp(hero.position.x, hero.position.y)]
      ];

      }
      return self;
      }

      • OscarVGG July 18, 2011 at 11:46 PM #

        You most be missing a curly brace or an @ sign or forgot to import the header. Double check your class definition.

  6. lotus January 12, 2011 at 7:20 AM #

    This rocks my world.

    This stuff is great.

    I’m just getting my head around obj c and you have really helped explain it a lot.

    Cheers,

    • OscarVGG July 12, 2011 at 5:22 PM #

      Thank you, I actually find objective-c very different than common languages, the syntax is hard to learn when you have worked all your life with java, c# or any similar, but it have become a challenge to me to learn this, and I love challenges!

  7. lee January 12, 2011 at 3:43 PM #

    Hi,

    Your tutorial is excellent :) just one question though i keep getting warnings on these 2:

    ***GamePlay.m:81: warning: conflicting types for ‘-(BOOL)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event’

    -(BOOL) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    return YES;
    }

    ***GamePlay.m:86: warning: conflicting types for ‘-(BOOL)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event’***

    -(BOOL) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *myTouch = [touches anyObject];
    CGPoint point = [myTouch locationInView:[myTouch view]];
    point = [[CCDirector sharedDirector] convertToGL:point];

    CCNode *hero = [self getChildByTag:kTagHero];
    [hero setPosition:point];

    CCNode *enemy = [self getChildByTag:kTagEnemy]; [enemy runAction:[CCMoveTo actionWithDuration:5.0 position:ccp(hero.position.x, hero.position.y)]];

    return YES;
    }

    Any ideas at all|?

    Cheers

  8. sam February 2, 2011 at 1:43 AM #

    can you please provide the complete source code for this project?

    • OscarVGG July 12, 2011 at 5:16 PM #

      Ummm, don’t think so – sorry

  9. Pradeep February 4, 2011 at 12:31 AM #

    Its really great… Thanks for ur tutorial…..

  10. tursesePoth February 26, 2011 at 7:15 AM #

    Hi. I like your website but i can tell it probably isn’t getting much traffic? If you want to help imrpove that check this website out, he has a short video that i really suggest you watch. Commission Crusher P.S this isn’t my website and i’m not spamming your blog, i don’t care if you delete this comment. I am only trying to help you improve your site.

  11. Jonathan March 20, 2011 at 8:51 PM #

    Hi Oscar,

    Thanks for the great tutorials. Son geniales!

    I wanted to add something: in your ccTouchesBegan: and ccTouchesMoved: methods, I was getting warnings saying something like “conflicting data types”, so I changed the return type of each of these methods to (void) instead of (BOOL).

    One question: should we be releasing any objects here or doing any other memory management? I’m pretty new to Objective-C and Cocos2D, so I’m still trying to figure out when to manage memory and when it’s managed for me.

    Thanks,
    Jonathan

  12. Chandu March 26, 2011 at 10:41 AM #

    Hi OscerVGG

    Thanks for posting tutorials.

    • OscarVGG July 12, 2011 at 5:04 PM #

      My pleasure!

  13. Boogle April 11, 2011 at 3:37 PM #

    Great tutorial, really enjoyed it. Just a few issues:

    -(BOOL) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    return YES;
    }
    -(BOOL) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    return YES;
    }

    Should be:

    -(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    }
    -(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    }

    And:

    CCLabel* label = [CCLabel labelWithString:@"Game Over"
    fontName:@"Marker Felt"
    fontSize:60];

    should be:

    CCLabelTTF* label = [CCLabelTTF labelWithString:@"Game Over"
    fontName:@"Marker Felt"
    fontSize:60];

    And:

    CCLabel* label2 = [CCLabel labelWithString:@"Touch to go to main menu"
    fontName:@"Marker Felt"
    fontSize:35];

    should be:

    CCLabelTTF* label2 = [CCLabelTTF labelWithString:@"Touch to go to main menu"
    fontName:@"Marker Felt"
    fontSize:35];

    And:

    [[CCDirector sharedDirector]
    replaceScene:
    [CCFadeTransition
    transitionWithDuration:1
    scene:[GameOver node]
    ]];

    Should be:

    [[CCDirector sharedDirector]
    replaceScene:
    [CCTransitionFade
    transitionWithDuration:1
    scene:[GameOver node]
    ]];

    Finally a bounding box collision detection can be more accurate in this case:

    - (void)spritesDidCollide
    {
    CCNode *enemy = [self getChildByTag:kTagEnemy];
    CCNode *hero = [self getChildByTag:kTagHero];

    float enemyHalfHeight = enemy.contentSize.height / 2;
    float enemyHalfWidth = enemy.contentSize.width / 2;
    float heroHalfHeight = hero.contentSize.height / 2;
    float heroHalfWidth = hero.contentSize.width / 2;

    if ((enemy.position.x – enemyHalfWidth hero.position.x – heroHalfWidth) && // Enemy right side, hero left side
    (enemy.position.y + enemyHalfHeight > hero.position.y – heroHalfHeight) && // Enemy top side, hero bottom side
    (enemy.position.y – enemyHalfHeight < hero.position.y + heroHalfHeight)) // Enemy bottom side, hero top side
    {
    [self unschedule:@selector(spritesDidCollide)];
    [[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1 scene:[GameOver node]]];
    }
    }

  14. Boogle April 11, 2011 at 3:41 PM #

    My previous comment didn’t appear to copy correctly (third time’s the charm!). The correct collision detection if statement is:

    if ((enemy.position.x – enemyHalfWidth hero.position.x – heroHalfWidth) && // Enemy right side, hero left side
    (enemy.position.y + enemyHalfHeight > hero.position.y – heroHalfHeight) && // Enemy top side, hero bottom side
    (enemy.position.y – enemyHalfHeight < hero.position.y + heroHalfHeight)) // Enemy bottom side, hero top side

  15. Jho Philippines July 6, 2011 at 6:04 PM #

    Great tutorial!!!

    • OscarVGG July 12, 2011 at 12:10 PM #

      thanks! :)

  16. Jho Philippines July 28, 2011 at 9:25 AM #

    [self unschedule:@selector(spritesDidCollide)];
    [[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1 scene:[GameOver node]]];
    }
    }

    hi…. oscar. i have a question in this part can you help me. i want to try to code in this replaceScene part that if they collide the hero cannot pass through to the enemy. like a game “un block me”. can you give me an example on how to do that?

    thank you

Trackbacks/Pingbacks

  1. The Programmer Lifestyle - October 13, 2010

    [...] Go forward: Your first Game in Cocos2D – Part 3: The Gameplay [...]

  2. The Programmer Lifestyle - October 13, 2010

    [...] Go forward: Your first Game in Cocos2D – Part 2: Sprites and More Transitions Or if you feel ready: Your first Game in Cocos2D – Part 3: The Gameplay [...]

  3. Oscarvgg - October 26, 2010

    Oscarvgg…

    [...] something about oscarvgg[...]…

  4. Buy Facebook Fans - November 12, 2010

    Trackback…

    [...] I found your entry interesting thus I’ve added a Trackback. [...]…

Leave a Reply

 

Marketie – Build your brand on twitter


The last few weeks a friend and I have been working on an app to help people market their brand [...]

First Look: Foundation Framework


Foundation is a framework for prototyping flexible web pages quickly and for any devices. It was created by ZURB, a U.S. [...]

Cocos2D Tips: Performance: CCSprite


Older iDevices (previous to iPhone 3GS) used to store images in power-of-two sizes of length and width. This means that [...]

Guess who’s back?


People is reading less, that’s a fact!. So blogs with very long posts are almost obsolete, at least in the [...]

How to make an iPhone App – Part 5: The Accelerometer


Yes, your iPhone has an accelerometer. I know this is not a physics class but the best way to define it is saying that it is a device to detect the magnitude and direction of acceleration. iDevices uses it to detect rotation, shake gestures, among others.

How to make an iPhone App – Part 4: Navigation Controller


Now that we know how to create a table views, we are going to use that knowledge to create a new project using a navigation controller to see a more detailed view of the tittle in the cell of the table view.