[Tutorial Series] Use the Cocos2d-x-3.0 game engine. Write a Tile Map Game.(part03)

Previous: hhttp://www.cocos2d-x.org/forums/6/topics/51024
6.Collision detected
    Since our sprite can move everywhere, you must be very exciting. There is also something strange. Probably you already notice that. The sprite we had made can through everywhere. So we will make it more realistic.
Image Title
Through the house

    Go back to the Tiled Map editor. Press the ‘New Tileset’ menu and open the new material we are going to use. Right-click the red one, and set the new property for it. (Pay attention to the upper and lower case. It may do some trickery.)
Image Title
    Now create a new layer, and name it ‘blockage01’. (Or whatever you like, just remember the name.) Paint those red rectangle on the map to mark the area where our sprite can not move through.
Image Title

    Now, you probably already know what we are going to do! When we are coding we can make the program detect this red rectangle tile and know its property—the ‘Blockage’ is true. (Be wary about whether it’s ‘true’ or ‘True’, it will matter.) Make these area can be through or not.
    Return back to the VC. This time I sure you know where to put these exactly.
    In the ‘HelloWorldScene.h’:

cocos2d::TMXLayer *_blockage;

    In the ‘HelloWorldScene.cpp’:

_blockage = _tileMap->layerNamed("Blockage01");

    But this time we will set these red tiles to be invisible.

_blockage->setVisible(false);

    Add a new method to calculate the tiles’ coordinate

class HelloWorld : public cocos2d::Layer
{
public:
......
cocos2d::Point tileCoordForPosition(cocos2d::Point position);
......
}

    In the ‘HelloWorldScene.cpp’:

Point HelloWorld::tileCoordForPosition(Point position)
{
	int x = position.x / _tileMap->getTileSize().width;
	int y = ((_tileMap->getMapSize().height * _tileMap->getTileSize().height) - position.y) / _tileMap->getTileSize().height;
	return Point(x, y);
}

    The original coordinate is on the upper-left corner. So you probably will be confused about the mathematical formula.
Image Title
The original coordinate

    We replace the code in the ‘void HelloWorldPlayerPosition(Point position)’

void HelloWorld::setPlayerPosition(Point position)
{
    Point tileCoord = this->tileCoordForPosition(position);
    int tileGid = _blockage->getTileGIDAt(tileCoord);
    if (tileGid) {
        auto properties = _tileMap->getPropertiesForGID(tileGid).asValueMap();
        if (!properties.empty()) {
            auto collision = properties["Blockage”].asString();
            if ("True" == collision) {
                return;
            }
        }
    }
    _player->setPosition(position);
}

    We convert our sprite’s coordinate into the tiles’ coordinate. Then use the method ‘getTileGIDAt’ to get the specified position’s GID. Then use the GID to check the tiles’ property and decide whether it can be go through. (We will add more function in the ‘void HelloWorld::setPlayerPosition(Point position)’ later.)

    Try your game. This time the sprite won’t go through the area that you already blockade. And the red tiles won’t be seen since we already set them invisible.

Image Title
Blockage

    Open up a new tile map material and create a new layer in the Tile Map editor. (I name the new layer ‘Foreground01’) And do some farming…on the ‘Foreground01’ layer. Use the green tiles we already met and paint them verdant on the ‘Blockage01’ layer (Yes, the ‘Blockage01’, not the ‘Foreground01’ we created before.)

Image Title
    Set the new property for the green tiles like we did to the red ones.
Image Title
New property

    In the ‘HelloWorldScene.h’:

cocos2d::TMXLayer *_foreground;

    In the ‘HelloWorldScene.cpp’:

_foreground = _tileMap->getLayer("Foreground01");

    Add these code to the ‘void HelloWorld::setPlayerPosition(Point position)’

auto collectable = properties["Collectable"].asString();
if ("True" == collectable) {
    _blockage->removeTileAt(tileCoord);
_foreground->removeTileAt(tileCoord);

_player->setPosition(position);  
}

Our sprite is truly an herbivore.
Image Title
Herbivore

To be continue…

Next: http://www.cocos2d-x.org/forums/6/topics/51363


05.png (144.6 KB)


06.png (7.9 KB)


07.png (220.7 KB)


00.png (158.1 KB)


01.png (14.4 KB)


02.png (547.4 KB)


03.png (54.3 KB)


04.png (493.5 KB)

2 Likes

cool you tutorial

Thank you so much! I want the characters to move smoothly in the map, rather than moving in each square as all over again. EX: tank game

hey bro, appreciate this tutorial. you’re awesome. But, this part is confusing me. Can you break it down to more comprehensible bits? arent we suppose to do farming on the Foreground01 layer? why are we placing green tiles(collectible property) on the “blockage01” layer?

do you just paste this inside " void HelloWorld::setPlayerPosition(Point position)" or do you specifically paste it inside this condition:

if (tileGid) {
auto properties = _tileMap->getPropertiesForGID(tileGid).asValueMap();
if (!properties.empty()) {
auto collision = properties[“Blockage”].asString();
if (“true” == collision) {return;}
}
}

please be specific, Im a noob :smiley:

nevermind, got it working

hey @Suigintou

I found an issue with tilemap.
whenever I try getTileGIDAt it always returns 0.

which prevents me from proceeding further.
However I found a workaround here -
http://forum.spritebuilder.com/t/collision-detection-with-tilemap-problem/10535/3

I am wondering what happened to the main approach
How did it worked for you.
If didn’t then what workaround did you implement to it… !! :smile:

@reyanthonyrenacia have you managed to make it work… !!
did the default worked for you… !!
or did you make any changes to it.

Regards,
Pabitra

@pabitrapadhy: I had a similar issue, and then realized that it did not always return 0. The calculations of tile was wrong and thus it hit empty spaces all the time, and empty spaces in the blocking-layer are 0. This was due to some calculation needed on ios retina (used in my emulator). I hade to divide tileSize height and width with CC_CONTENT_SCALE_FACTOR() to get the correct tiles.