Tutorial 2 – Parallax Backgrounds & Enemies (Cocos2d Game)

This tutorial is the next in line as it walks you through the creation of a small Cocos2d game using a scrollable TileMap. This is the next long video about 100 min but includes a ton of great items such as creating the parallax background and adding enemies based on tilemap locations.

I strongly recommend watching the tutorial 1 before watching this tutorial.

The source code can be downloaded from the link below.

The game is created using only one class so it is not an example of how to layout the game structure but instead just illustrate how I used the tilemap in a sample game.

Here is a sneak Peak at the Game from Tutorial 2

(Since the tut video is 100 min.)

Some features of this tutorial include:

  • Create parallax background
  • Set transparency / opacity of tileMap tiles.
  • Set start location for player from tilemap.
  • Create two types of enemies for the game.
  • Set the enemy locations from within the TileMap
  • Collision between player and moving enemy.
  • Set repeating actions for moving enemies.
  • Blinking player when it gets hit by enemy.

Now that is a tutorial if you ask me. Jamb packed full of stuff. BUT…just a reminder this is not to show how to setup game structure but to instead introduce you to some of the great tools Cocos2d offers you. Everything is contained so far within one class, which is in my opinion, a very bad way to program a game, but for explanation of features purposed it makes it easier.

I really hope these tutorials are or will be helping you with your cocos2d project and if so please leave a comment. Also if you have any questions leave a comments and I will get back to you.

!!! EDIT TO CODE SINCE VIDEO MADE!!!

I have a section of code to make the player blink. There is a better way so here is the revision:

Replace the action with:

[ball runAction:[CCSequence actions:

[CCBlink actionWithDuration:4 blinks:12],

[CCCallFuncN actionWithTarget:self selector:@selector(playerHitDone:)],

nil]];

Tutorial 2 Video

Tutorial 2 source code link

Advertisements

54 Responses to Tutorial 2 – Parallax Backgrounds & Enemies (Cocos2d Game)

  1. John says:

    Thanks for the great tutorial. I downloaded the source code and it looks like the main tilemap doesn’t have the “baddies” layer in it.

    • paulsondev says:

      Sorry about the crappy source code everyone..I know the resources are a little screwed up, and I have miss placed the source used for that tutorial, so cannot update it. BUT my hopes are that everyone understands what I was doing and can then go out and produce an image or tilemap similar to implement.

      • John says:

        No worries. The source code and video and both really easy to understand. The tutorial was very helpful to me. Thanks for taking the time to put it together.

  2. Steve Robinson says:

    Hi Paul, thanks for making the effort for the videos. I have seen you have done your code research on the same sites as myself. I just started my first iPhone app a few days ago and I have got the basics of moving my player and background. Still very new to Objective-C. Using the COCOS2D test suite does help, but not always. I am also building a 2D platform game. I will keep in touch as I learn more.

    Questions: I am wanting an ememy to be roaming back and forth on a fixed location on a fixed platform, but it is not in view until the character gets there. Do you use the off screen position and then see when you get there, or do you move the enemies relative to the screen scroll position? The latter is more code intensive.

    I also was wondering if you use the TileMap for all collisions and platforms?

    Also how do you implement falling gravity manually with a the main game llop timer/delta or with physics code?

    • paulsondev says:

      Thank you for the comment.

      To answer your question the enemy is place at the position of the level or map node position you want them to be at. Once the enemy is in its position you use a CCMoveBy action to move the enemy then reverse it to have it move back.

      I am using Box2d for all my collisions now including enemies and platforms.

      The gravity is controlled with physics, Box2D.

      I hope this helps.

  3. Steve Robinson says:

    Thanks for the prompt reply.

    I thought this was the case, just wanted to make sure as no point in going done the wrong path. Can I rightly assume that you are using COCOS2D when you can and the BOX2D provides the rest when C2D doesn’t cut the mustard?

    Regarding TileMaps: Are they the used for just look and feel? Does the TileMap provide any other location information look-ups i.e. where the enemy or treasure is initially?

    Do you use a class to define where platforms are or do you use arrays?

    Regarding movement, is this all controlled with a move scheduler with action like MoveBy? MoveTo has an exponential move effect ie it slows down as it reaches the destination position. I have used MoveBy for my player. Did you do something similar in your later versions?

  4. Steve Robinson says:

    Sorry I had not watched the tutorial as my inet was slow today. Anyway it answered the enemy position using TM symbols. I am more interested in the best way to stop player falling through platform, ie they cn jump through it but not fall through it. But as you say you use box2D. Can you throw a bone on the way you do this? Is there an example in the tests? Or did you find some sample code elsewhere or was it home grown?

  5. Noodle says:

    Thank you so much for both of these tutorials, they where exactly what I was looking for. Hugely appreciate the effort you made!!

    A quick question about box2d collision approach, does each occupied tile in the map have its own collision box?

    • paulsondev says:

      The Tiledmap in my game is completely separate from the box2d. It is used for simple the look and feel. The box2d side create separate bodies for each item that will be used for a collision of sensor. I use code to work through my level and create each body based on a particular class. I will try and complete some tutorials on how this stuff works but I have to find time to do it. With work and the small bit of free time for developing my game it is sometimes hard to get tutorial creating time. But I will definitely try and for sure once the game is complete I will go back and create tutorials.

  6. Steve Robinson says:

    Do you move the Box2D world and let the sprites follow suit as required ? or do you move the Box2D world based on the player sprite movement?

    • paulsondev says:

      The Box2d bodies are set at a specific position within the level. Then the only thing that moves is the player and the Camera follows the player which reveals the level map and box2d bodies on the screen. So all I need to worry about is placing the bodies in there appropriate locations in the level.

      You can probably do this same effect using just a tilemap to located everything as you would run through all your tiles to see the location of certain things. Once you have the locations or tiles you would create a box2d body at that tile. Then when your level is finished loading all you elements would be ready for when the camera shows that portion of the level.

      I hope that makes sense.

      • Steve Robinson says:

        Paul do you use the CCCamera class or actually just make a moving tilemap background by positioning like you did in your early examples?

      • paulsondev says:

        Just so you no my name is Jason…but no worries.

        I dont use CCCamera except where it is already implemented in the Cocos2d classes.

      • Steve Robinson says:

        Hi Jason, do you use Actions ie MoveTo for baddie sprites.I find that using continuous actions with Box2D makes things hard as the Body has the follow the sprite.

      • paulsondev says:

        @Steve Yes I use actions…it actually works really well since i have so many things moving and all with animation…keeps things simple. I have not had any real big problems…some minor things i would like to see better but thats just me being to picky.

      • Steve Robinson says:

        thanks, I have a problem when I move the player that the body of the baddies follows the player relatively. How do you ensure that your badies body stays put following the baddie action, yet allow the players body to move?

      • Steve Robinson says:

        Do you use box2D for collision with baddies? or home grown?

      • Steve Robinson says:

        Jason, I am stuck. I cannot see to get actions for baddies and Box2D bodys working and also allow box2D to follow the player. How did you do this?

        Cheers

      • paulsondev says:

        Well do you have a method to update sprites from your game look: like this

        -(void) updateSprites
        {
        for (b2Body* b = world_->GetBodyList(); b; b = b->GetNext())
        {
        BodyNode *node = (BodyNode*) b->GetUserData();
        if( node ) {
        //Synchronize the AtlasSprites position and rotation with the corresponding body
        node.position = ccp( b->GetPosition().x * kPhysicsPTMRatio, b->GetPosition().y * kPhysicsPTMRatio);
        node.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
        }

        }
        }

        it could be a couple other things with how you body is setup….maybe change userdata to nill instead of self.

        Also maybe try setting body type to

        body->SetType(b2_kinematicBody);

        That is the best I can do for now, hope it helps.

      • Steve Robinson says:

        Yes I do, I must have a flaw in my thinking. I will try the body->SetType(b2_kinematicBody);

        Will let you know.

        Thanx

  7. Steve Robinson says:

    My problem is that I am moving my player sprite based on a joypad similar to what you do (in main update routine). I want my player boxshape to follow the player so when he gets near a baddies boxshape their is a collision.

    My map moves based on player movement. Are you suggesting I start using box2D for my camera as opposed to moving map?

    Maybe I need to do more research on best way to move player?

  8. paulsondev says:

    Well my joypad moves my player then I update my camera in my gameloop to match the player. The only thing I am not 100% happy on is that the player is always in the center but it actually is a good way to do it as there is less problems in a small screen size.

    Then you place a hud layer above the game layer. The hud layer has your joypad and everything else that should not move with the game. This is how I got the look I have. 2 layers, hud and game.

  9. Steve Robinson says:

    cool, thanks…
    So does your player move routine make the players Box2D move with the player or is it the camera that does this. I may need to read up on this as maybe I misunderstand the concept of Camera with Box2D…I will read up on this.

    I admit I have a only just begun programming again from a near 5 year gap. My iPhone game is challenging me to really make sense of all these new concepts.

    • paulsondev says:

      Wel I apply my force to my player in my player class, then my gamenode updates the [self position:] from the player location. There is a little more to it but that is the basic explanation.

  10. Steve Robinson says:

    I cannot seem to get this working.

    If I create a subclass of CCSprite, how would I create the Box2D inside it?.

    I can get my box2D shape to follow a sprite as it moves, but I am confused by the Box2D shape as it is always a few pixels out in debug mode. Maybe the debug is rendering wrong?

    Do you use the tick timer to move the player based on delta X,Y or do you move the Box2D shape then make the sprite follow that?

    Also, I am not sure how to apply the gravity to the sprite and get movement etc Maybe my concepts of the world are wrong?

    Sorry, but not sure what’s best.

    • paulsondev says:

      Well it would be a very long reply to answer but I will say that I use the joypad to set a direction of travel then I use a static force to move the player in that direction. I simply apply a force to the player body in Box2D. The when my game class runs through its tick it updates the parallax node and moves it based on the player position.

      • Steve Robinson says:

        Thanks Paul, good lad. You have really given some good advice. I can confirm that after all my trials and tribulations with Cocos2D I was finding out the hard way like you must have done.

        It is always nice to have someone offer up help even though like all of us you are busy too with work and your own endeavors.

        I am personally not trying to write games for money, but doing this for enjoyment and research for a team of developers who work for me. Later in the year we will start building apps for business which I think has better commercial appeal.

        I have learned a lot from the community, however your blog roll has been a good practical start for many I am sure.

      • paulsondev says:

        Thank you for your comments. And I do wish I could place more tutorials on the site but my actuall app is taken all of my free time. I have to agree with you and am also doing this project or game for the enjoyment of it, not so much the money. If you are building an app for only financial reasons then I believe you are in the wrong hobby. Although it is true you can make some good money, as others have done, it is very hard due to the amount of apps currently out there and being produced. The number one reason should be passion/enjoyment and the second reason should be making a couple bucks.

        Keep reading the blog and comments. Thank you.

  11. Richard says:

    Hi Paul,

    Many thanks for an excellent series of tutorials, you really are a great teacher.

    A quick request, could you please tell me where I can download the ‘baddie’ image that you are using, many thanks!

  12. Steve Robinson says:

    Paul, I am moving my player body using Box2D body, however my enemy sprites are using actions to move around in predefined areas. I can get body of player to move with player, but it seems the body of the enemy is following relative to player? I iterate the body list and use tags to determine which sprite I am dealing with but once the camera moves with the player the center of the world changes and thus the baddies body shapes move with the player, but I want them to stay following the baddies coordinates as the baddies have not moved.

    Any ideas what logic I have wrong?

    • Steve Robinson says:

      I found the problem, I was also adding the baddies to the tilemap background layer which the camera is moving. I made my player be a child of the tilemap background layer and thus the tilemap moved expected, but now the baddies do not move as they are children of the game layer.

      Wicked. I now have my player, badddies, joypad, velocity of player and statically placed action-based baddies moving in set patterns.

      I have collision working with a contact class and so I am good to start making my first level with treasure, help and HUD updates etc.

      I have also completed the menu framework with layer mutiplexing.

      In the end most of my code has come from the test suite and some tips for the usual suspects.

      I find most of my problem now are understanding more of object-c and xcode features.

      Cheers Paul.

  13. Steve Robinson says:

    Apologies, Jason, my bad!

    Any ideas on how do I stop the baddies from moving position with the player. I seem to solve one problem and create another.

    Does you main GameLayer contain all the children? Including the TileMap, Payer and Baddies or do you put baddies on a hidden layer and show then when you move the timeMap position?

    I can’t seem to get player to move yet baddies sat at correct positions.

    • paulsondev says:

      quick answer…

      I have a class for my level which creates a parallax node. I then add the background as a child….the tilemap as a child…then the sprites as a child….this means that the baddies (sprites) would move with the map.

      Then the player is the only thing that has a force applied to it so it would tricker the parallax node to move…which bring all the off-screen thing into view…map and baddies.

      So in order for this to work properly you just have to update the player to stay in the centre of the screen and any movement moves everything else.

      I think that may of sounded more complicated then it is…but I hope that helps a little.

      • Steve Robinson says:

        My problem, my main problem which has me stumped is this.

        My baddies start off roaming too and from points at a specific location not visible on the screen. When the player moves due to force (Box2D LinerVelocity) The body of the baddie follows the players box2d body during world step? I want the body to stay static where the baddie is located.

        Do you remove the baddies body and re-create every time the screen is moved?

        =================== Code =================

        – (void)spawnEnemy {

        baddie = [CCSprite spriteWithFile:@”enemy.png”];
        baddie.position = ccp(100, 100);
        baddie.tag = 2;

        id actionMove = [CCMoveBy actionWithDuration:3 position:ccp(-100,0)];
        //id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:@selector(spriteDone:)];
        [baddie runAction:[CCRepeatForever actionWithAction:[CCSequence actions:actionMove,[actionMove reverse],nil]]];

        _baddieBody = [self addBoxBodyForSprite:baddie];
        [map addChild:baddie z:0 tag:2];

        }

      • Steve Robinson says:

        ========= Code of the adding of a baddie body ========
        – (b2Body *)addBoxBodyForSprite:(CCSprite *)sprite {

        b2BodyDef spriteBodyDef;
        //spriteBodyDef.type = b2_dynamicBody;
        spriteBodyDef.position.Set(sprite.position.x/PTM_RATIO, sprite.position.y/PTM_RATIO);
        spriteBodyDef.userData = sprite;
        b2Body *spriteBody = _world->CreateBody(&spriteBodyDef);

        b2PolygonShape spriteShape;
        spriteShape.SetAsBox(sprite.contentSize.width/PTM_RATIO/2,
        sprite.contentSize.height/PTM_RATIO/2);

        b2FixtureDef spriteShapeDef;
        spriteShapeDef.shape = &spriteShape;
        spriteShapeDef.density = 30.0;
        spriteShapeDef.isSensor = true;
        spriteShapeDef.friction = 0.1f;
        spriteShapeDef.restitution = 1.0f;
        spriteBody->CreateFixture(&spriteShapeDef);
        return spriteBody;
        }

      • paulsondev says:

        Here is a great Tutorial for scrolling tilemap in 2d game. Might be useful.
        2d-scrolling-game-with-cocos2d-tilemap-with-zoom

  14. Steve Robinson says:

    I use this code ie the baddie’s box2d body follows the baddie sprite, but seems to add a small offset and of get out of sync with player? Any ideas of a better way?

    [node setPosition:newPos]; //Set new position of TileMap

    int32 velocityIterations = 8;
    int32 positionIterations = 1;

    _world->Step(delta,velocityIterations,positionIterations);
    for(b2Body *b = _world->GetBodyList(); b; b=b->GetNext()) {
    if (b->GetUserData() != NULL) {
    CCSprite *sprite = (CCSprite *)b->GetUserData();
    if (sprite.tag == kTagPlayer1) {
    //NSLog(@”Processing Player∫”);
    if (joypadMoving) {

    b->SetLinearVelocity(b2Vec2 (velX,velY));
    }else {
    velX =0;
    velY =0;
    b->SetLinearVelocity(b2Vec2 (velX,velY));
    }

    sprite.position = CGPointMake(b->GetPosition().x*PTM_RATIO, b->GetPosition().y*PTM_RATIO);

    }

    if (sprite.tag == kTagWalkBaddie) {

    //NSLog(@”Processing Baddie∫”);
    b2Vec2 b2Position = b2Vec2((sprite.position.x/PTM_RATIO),(sprite.position.y/PTM_RATIO));
    float32 b2Angle = 0;
    b->SetTransform(b2Position, b2Angle);

    }

    }

    }

  15. Billy says:

    I have very important question…im still begining im 13 and i need help ok here goes…

    i went on after the tutorial 2 adding enemys im making the game much longer (just changeing the number of tiles) but i need help

    i want to make multiple levels like in the planet one i think its called also how do i add slight gravity to the “ball.png” image?? i need help and would very much so appreciate it agian i have only been doing iphone programming for mabye 2 month and have just started any prgramming and one else in my town or any were that i know of does this and i need help…And if you need to email me or anything i will just level ur email and i will email you
    thanks a bunch!!

    • paulsondev says:

      Well to answer your first question about levels….
      There is a bunch of different ways to do it and it entirely depends on how you game would be set up. My game take the player back to a menu to select level so I just simply change the tilemap depending on what level they choose. If your game will send the player to the next level automatically then I think you would want to create separate classes for each level. Like I said there are many different ways to do it and I only really have experience doing it my way.
      For your second question on gravity…..you would need to use a physics framework like Box2D. The tutorial 1 and 2 do not have that implemented but it is not hard to do once you have an understanding of Box2D.

      I know that the answers don’t help a hole lot but it is necessary to first get a good understanding of the frameworks by doing some reading on apple’s dev site and Box2D site. There are so many different ways to do things and it all depends on what type of game play you want. So having an understanding is key to making your choices for coding.

      • Billy says:

        Thanks for your tutorials there AMAZING (and the first ones that worked any do you have any good website that has VIDEO lessons on box2d or cocos2d because i learn better by seeing a video not reading so ya do u have any website suggestions??

      • paulsondev says:

        I think the best for video tutorials would be 71 squared…although its not for cocos2d but great for iphone games and beginners. Here is the link.

        71squared

  16. paulsondev says:

    Yes I use box2d. Everything is box2d except the tilemap and background.

  17. Valerio De Angelis says:

    Hello,

    Thanks for the tutorial. It really helps making sense of tiled maps.

    I’m struggling with removing tiles attached to body when collisions happen.

    I’m using Box2D to detect collisions. I created a body for tiles with which a ball needs to collide (think classic block game). I can detect the collision.

    The problem is that in the body object I don’t see a clean way to store a reference to the Tile I need to remove. I could use userData but I’ve other bodies that use userData to reference the Sprite attached to the body and I’d rather not mix up types of objects referenced by userData. Too much potential for exceptions.

    Also I need to store in the body the tile location. I could create a sprite for each tile for which I create a body but that seems wastful.

    Any idea? As you are using Box2D and tileMap did you run across this problem?

    Thanks

  18. Pingback: Parallax Node & Fade-in-out Sound di Cocos2D 1.9.1 « Heru Prasetia B'loGs

  19. RobertKreed says:

    hey great tutorials I gave both 1 and 2 5 out of 5, I loved it, showed new ways to do them that actually took less time then all the other methods I’ve found so far! I have one question though, how would you make it to where the Flowers Respawn after a set amount of time? I keep looking around for the answer and i can’t seem to find it. if it was a sprite I don’t think it would be to hard to implement but since its dealing with the collectible items found on the Tile set and a layer I think that would be slightly harder to do. any advice?

    • PaulsonApps says:

      Hey thank you…the respawn of flowers would be easy.

      Once the flower is collected just set in scheduled call to a method which recreates a sprite in that location. You have to pass a attribute with it to tell the grid location on the tiledmap.

      That should do it for re-spawning the flowers.

      • RobertKreed says:

        I’ve been trying that, I found some guy trying to do the same thing but he’s got about as far as i have.

        [self schedule:@selector(respawnFlower:) interval:2];

        -(void)respawnFlower:(ccTime)dt {

        }

        the only problem I’m having is the attribute that I have to pass in order to tell where to put it.

  20. RobertKreed says:

    Also on your source Code, Its not showing the baddies at all. the game runs fine but the Enemies are not spawning at all.

  21. Eric says:

    That’s awesome! You really helps me a lot!

  22. itsafeaturedev says:

    I was wondering if you could help, i have tried creating a larger tilemap but when i move the ball to the right of the screen it wont scroll any further, can you tell me where this is configured, its been driving me mad for hours lol

    • itsafeaturedev says:

      Ignore that i think i figured it out by changing this value from 160 to 320

      if (newPos.x > 0 || newPos.x 0 || newPos.y < -320) {
      newPos.y = currentPos.y;
      mapMoving = NO;
      } else {
      mapMoving = YES;
      }

  23. david says:

    Hey, the tutorials are the best ive come across. thanks alot!!

    i really need your help if possible, im an absolute newbie at coding and making games. I manage to get the game to run minus the baddies, however soon as i start to try using my own tile map it builds with no errors but the game only manages to get to the cocos2d screen and no game… any ideas?

    thanks

  24. Hello there! This is my first visit to your blog!
    We are a group of volunteers and starting a new project in a
    community in the same niche. Your blog provided us valuable information to work on.
    You have done a extraordinary job!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: