Cocos2D-X Tile Map Tutorial: Part 1

Learn how to make a simple tile-based cross platform game in this Cocos2D-X tile map tutorial! By Jorge Jordán.

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Making the Ninja Move

This is a good start, but your ninja is just sitting there! And that’s not very ninja-like.

You will make the ninja move simply by moving him in the direction the user taps. Add the following code to the public section of HelloWorldScene.h:

void registerWithTouchDispatcher();
    
void setPlayerPosition(CCPoint position);
   
bool ccTouchBegan(CCTouch *touch, CCEvent *event);

void ccTouchEnded(CCTouch *touch, CCEvent *event);

Then open HelloWorldScene.cpp and add this to init, just before return true:

this->setTouchEnabled(true);

This sets the layer to be touch enabled so it pays attention to touch events. Next add these methods to the bottom of the file:

#pragma mark - handle touches

void HelloWorld::registerWithTouchDispatcher() {
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}

bool HelloWorld::ccTouchBegan(CCTouch *touch, CCEvent *event)
{
    return true;
}

void HelloWorld::setPlayerPosition(CCPoint position) {
    _player->setPosition(position);
}

void HelloWorld::ccTouchEnded(CCTouch *touch, CCEvent *event)
{
    CCPoint touchLocation = touch->getLocationInView();
    touchLocation = CCDirector::sharedDirector()->convertToGL(touchLocation);
    touchLocation = this->convertToNodeSpace(touchLocation);
    
    CCPoint playerPos = _player->getPosition();
    CCPoint diff = ccpSub(touchLocation, playerPos);
    
    if ( abs(diff.x) > abs(diff.y) ) {
        if (diff.x > 0) {
            playerPos.x += _tileMap->getTileSize().width;
        } else {
            playerPos.x -= _tileMap->getTileSize().width;
        }
    } else {
        if (diff.y > 0) {
            playerPos.y += _tileMap->getTileSize().height;
        } else {
            playerPos.y -= _tileMap->getTileSize().height;
        }
    }
        
    // safety check on the bounds of the map
    if (playerPos.x <= (_tileMap->getMapSize().width * _tileMap->getTileSize().width) &&
        playerPos.y <= (_tileMap->getMapSize().height * _tileMap->getTileSize().height) &&
        playerPos.y >= 0 &&
        playerPos.x >= 0 )
    {
        this->setPlayerPosition(playerPos);
    }
    
    this->setViewPointCenter(_player->getPosition());
}

Here you override the registerWithTouchDispatcher method to register yourself to handle targed touch events. This will result in ccTouchBegan/ccTouchEnded methods being called (singular case), instead of ccTouchesBegan/ccTouchesEnded methods (plural case).

You may wonder what’s the difference between the singular case and the plural case. In this case it doesn’t matter either way. However, I wanted to introduce everyone to this method in case you hadn’t seen it already, because it has two significant advantages (these are listed verbatim from the cocos2D-X source):

  • “You don’t need to deal with NSSets, the dispatcher does the job of splitting them. You get exactly one UITouch per call.”
  • “You can *claim* a UITouch by returning YES in ccTouchBegan. Updates of claimed touches are sent only to the delegate(s) that claimed them. So if you get a move/ended/cancelled update you’re sure it’s your touch. This frees you from doing a lot of checks when doing multi-touch.”

Anyway, inside your ccTouchEnded location, you convert the location to view coordinates and then to GL coordinates as usual. What is new is you call this->convertToNodeSpace(touchLocation).
This is because the touch location will give you coordinates for where the user tapped inside the viewport (for example 100,100). But you might have scrolled the map a good bit so that it actually matches up to (800,800) for example. So calling this method offsets the touch based on how you have moved the layer.

Next, you figure out the difference between the touch and the player position. You have to choose a direction based on the touch, so first you decide whether to move up/down or side to side based on whichever is the greatest distance away. Then you just see if it’s positive or negative to move up or down.

You adjust the player position accordingly, and then set the viewpoint center to be the player position, which you already wrote in the last section!

Note you have to add a safety check to make sure you’re not moving your player off the map as well!

So Build and Run the project and try it out! You should now be able to tap the screen to move the ninja around.

The Ninja can run

Where To Go From Here?

That’s all for this part of the tutorial. At this point you should know the basics about creating maps and importing them into your game.

Here’s a sample project with the code you’ve developed so far.

In the part 2 of the tutorial you will learn how to add collision detection into the map to prevent your ninja from happily walking through the walls!

Jorge Jordán

Contributors

Jorge Jordán

Author

Over 300 content creators. Join our team.