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

Previous: http://www.cocos2d-x.org/forums/6/topics/51141

7.Score indicator:
    Type these codes before ‘HelloWorld’ class declaration in the ‘HelloWorldScene.h’, we are going to make a score indicator.

class HelloWorldHud : public cocos2d::Layer
{
public:
    void numCollectedChanged(int numCollected);
    virtual bool init();
    CREATE_FUNC(HelloWorldHud);

    cocos2d::LabelTTF *label;
};

    Type these inside the ‘HelloWorld’ class declaration.

......
Private:
......
int _numCollected;
static HelloWorldHud *_hud;
......

    In the ‘HelloWorldScene.cpp’,
    Type these at the top of file:

HelloWorldHud *HelloWorld::_hud = NULL;

    Add to the HelloWorld::createScene() method, right before the return

......
auto hud = HelloWorldHud::create();
_hud = hud;

scene->addChild(hud);
......
Add inside setPlayerPosition, in the case where a tile is collectable
......
this->_numCollected++;
this->_hud->numCollectedChanged(_numCollected);
......

    Now add those method:

bool HelloWorldHud::init()
{
    if (!Layer::init())
    {
        return false;
    }

    auto visibleSize = Director::getInstance()->getVisibleSize();
    label = LabelTTF::create("0", "fonts/Marker Felt.ttf", 18.0f, Size(50, 20), TextHAlignment::RIGHT);
    label->setColor(Color3B(0, 0, 0));
    int margin = 10;
    label->setPosition(visibleSize.width - (label->getDimensions().width / 2) - margin,
        label->getDimensions().height / 2 + margin);
    this->addChild(label);

    return true;
}

void HelloWorldHud::numCollectedChanged(int numCollected)
{
    char showStr[20];
    sprintf(showStr, "%d", numCollected);
    label->setString(showStr);
}

    It is easy to understand that we make a ‘LabelTTF’ to create the number we want. (We set the value ‘0’, the font, the size, the color, and the position.)
When the vegetable has been eaten by our sprite, the number will be plus 1.
Image Title

8.Music & Sounds:
There is no doubt that it will be very boring if there is no music at all. So we are going to make some funny.
    Add these two lines in the ‘HelloWorldScene. cpp’ (When something involves with the music, we should have the ‘SimpleAudioEngine.h’, and the CocosDenshion is the music function in the Cocos2d engine.)

#include "SimpleAudioEngine.h"
using namespace CocosDenshion;

bool HelloWorld::init()
{
......
SimpleAudioEngine::getInstance()->preloadEffect("error.mp3");
SimpleAudioEngine::getInstance()->preloadEffect("item.mp3");
SimpleAudioEngine::getInstance()->preloadEffect("step.mp3");

// I make this effect ’wade.mp3’ for fun. You can try to do it yourself, or simply delete them.
SimpleAudioEngine::getInstance()->preloadEffect("wade.mp3");
SimpleAudioEngine::getInstance()->playBackgroundMusic("background.mp3");
SimpleAudioEngine::getInstance()->setBackgroundMusicVolume(0.1);
......
}

(Notice that it is ‘playBackgroundMusic’, not ‘preloadBackgoundMusic’.)

// In case for collidable tile
SimpleAudioEngine::getInstance()->playEffect("error.mp3");

// In case of collectable tile
SimpleAudioEngine::getInstance()->playEffect("item.mp3");

// Right before setting player position
SimpleAudioEngine::getInstance()->playEffect("step.mp3");

// I make this effect for fun. You can try to do it yourself, or simply delete them.
SimpleAudioEngine::getInstance()->playEffect("wade.mp3");

Oh~ It’s hard to show you this result by using picture.
Image Title

9.Add Enemy:
    Maybe you still remember how to create our sprite, the character. But we will make it some different to build multiple enemies. We still do it on the ‘Object-Player’ layer. Set the values as the picture shown (The name, the property name, and the property value. You can have different value, if you are going to have different type of enemy.):
Image Title

// Type these code after where we create the player

bool HelloWorld::init()
{
......
	for (auto& eSpawnPoint: objects->getObjects()){
		ValueMap& dict = eSpawnPoint.asValueMap();
		if(dict["Enemy"].asInt() == 1){
			x = dict["x"].asInt();
			y = dict["y"].asInt();
			this->addEnemyAtPos(Point(x, y));
		}
	}......
}

    In the ‘HelloWorldScene.cpp’

void HelloWorld::addEnemyAtPos(Point pos)
{
	auto enemy = Sprite::create("030.png");
	enemy->setPosition(pos);
	enemy->setScale(0.5);

	this->animateEnemy(enemy);
	this->addChild(enemy);

	_enemies.pushBack(enemy);
}

10.Make them move:
    The enemy will chase down our player. Because the player will move at our will, we will make those enemies chase the player automatically. I make them move 10 pixels every 0.3 second.

void HelloWorld::enemyMoveFinished(Object *pSender)
{
    Sprite *enemy = (Sprite *)pSender;

    this->animateEnemy(enemy);
}
void HelloWorld::animateEnemy(Sprite *enemy)
{
    float actualDuration = 0.3f;

    auto position = (_player->getPosition() - enemy->getPosition()).normalize()*10;
    auto actionMove = MoveBy::create(actualDuration, position);
    auto actionMoveDone = CallFuncN::create(CC_CALLBACK_1(HelloWorld::enemyMoveFinished, this));
    enemy->runAction(Sequence::create(actionMove, actionMoveDone, NULL));
}

    The function ‘animateEnemy’ create two ‘action’. The first one makes enemies move 10 pixels every 0.3 second. You can change the value if you like. The other one will call the function ’enemyMoveFinished’. I use the ‘Sequence::create’ to bind them. When the first function finished, the second one be call and start working.

Image Title
    But we want the enemy want the enemies can turn around and face the player.
    Add these to ’void HelloWorld::animateEnemy(Sprite *enemy)’

void HelloWorld::animateEnemy(Sprite *enemy)
{
	auto actionTo1 = RotateTo::create(0, 0, 180);
	auto actionTo2 = RotateTo::create(0, 0, 0);
	auto diff = ccpSub(_player->getPosition(), enemy->getPosition());

    if (diff.x < 0) {
		enemy->runAction(actionTo2);
    }
	if (diff.x > 0) {
		enemy->runAction(actionTo1);
	}
......
float actualDuration = 0.3f;
......
}

Let us see the result:
Image Title

Enemy movement 1 Enemy movement2

To be continue…

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


00.png (251.0 KB)


01.png (496.2 KB)


02.png (111.0 KB)


03.png (579.2 KB)


04.png (163.8 KB)

1 Like

@Suigintou good job ricky! thank u very much

I’m a beginner of C++.
I cannot make the following code execute

*auto position = (_player->getPosition() - enemy->getPosition()).normalize()10;

what does normalize() function do?

normalize makes a Vec2 to length 1
example (8, 6) → (0.8, 0.6)
but it returns void (:зゝ∠)
try this:
auto position = (ninja->getPosition() - enemy->getPosition());
position.normalize();
auto actionMove = MoveBy::create(actualDuration, position.operator*(10));

1 Like

Thanks sbyang.
It working.

This is what you call TUTORIAL!! daym, wish there’s more of this. … @Suigintou please make more tutorials !! Plugin-X, Facebook, Multiplayer, AStar!! :smiley:

I see lots of tutorials that teach you ‘how to display a sprite’ or ‘how to click the screen’, .and you’re left with nothing but impractical game programming LOL. Yours is awesome :smiley:

1 Like

I guess you made lots of requests and he ran away… yes we need more like such tutorials… he is Great except that I can’t understand Japanese…Lol

Hi,
What if I want the enemy to move toward player only when the enemy’s position in visible on screen because your code move enemy to player no matter how far there are from player
thanks

Yours sincerely

Amazin tutorial thank you