使用Cocos2d-x-3.0游戏引擎。编写一个瓦片地图游戏 part04

上一篇地址:http://www.cocoachina.com/bbs/read.php?tid=196836&page=1&toread=1#tpc

  1. Score indicator:
    计分器
    在“HelloWorldScene.h”中的“HelloWorld”类声明里编写这些代码,我们要开始制作一个分数指示器。
class HelloWorldHud : public cocos2d::Layer
{
public:
    void numCollectedChanged(int numCollected);
    virtual bool init();
    CREATE_FUNC(HelloWorldHud);

    cocos2d::LabelTTF *label;
};
```

在“HelloWorld”类的声明中编写这些代码。
``````
Private:
``````
int _numCollected;
static HelloWorldHud *_hud;
```

``````


In the ‘HelloWorldScene.cpp’,
Type these at the top of file:
编写在文档的顶部
HelloWorldHud *HelloWorld::_hud = NULL;
```


添加进方法HelloWorld::createScene()中,在return语句之前。
``````
auto hud = HelloWorldHud::create();
_hud = hud;

scene->addChild(hud);
```

``````
添加进方法setPlayerPosition中,在判断瓦片是否可收集的部分
``````
this->_numCollected++;
this->_hud->numCollectedChanged(_numCollected);
```

``````
现在添加这些代码:
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;
    sprintf(showStr, "%d", numCollected);
    label->setString(showStr);
}

```

这很好理解,我们创建了一个“LabelTTF”文本制作出我们要的数字(我们将其值设置为0,设置了字体,大小,颜色,还有位置。)
When the vegetable has been eaten by our sprite, the number will be plus 1.
当蔬菜被我们的精灵吃掉后,数字会增加1
   

8.    Music & Sounds:
音效和声音
毫无疑问,如果没有音乐的话这会非常无聊。所以我们这就要让它非富起来。
添加下面两行进“HelloWorldScene. cpp”(当有些事需要涉及到音效的时候,我们要添加‘SimpleAudioEngine.h’,还有CocosDenshion是Cocos2d引擎里涉及音乐的方法。)
#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’.)
(注意是‘playBackgroundMusic’, 而不是‘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");
```


音效效果用图片似乎不太好展示。
   

9.    Add Enemy:
增加敌人
也许你还记得我们是怎样创建我么你的精灵,人物的。但是我们会把它弄得略有不同以此创建多数的敌人。我们仍然在“Object-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:
让他们动起来
敌人将会追赶我们的玩家。因为玩家将会随我们的想法移动,我们会使得这些敌人自动追赶我们的玩家。我会是他们每0.3秒移动10个像素点。

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));
}
```


这个方法‘animateEnemy’创建了两个“动作”。第一个使敌人没0.3秒移动10像素点。你能改变这个值,如果你想的话。另一个会引用方法’enemyMoveFinished’。我是用了‘Sequence::create’语句是它们绑定在了一起。当地一个方法实现后,第二个将会被引用并开始工作。
  
 

 
但是我们要敌人能够转向并面对玩家。

添加这些代码进’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:
看看结果:
     
Enemy movement 1                     Enemy movement2
 

未完待续~(一日一更)

下一篇地址:http://www.cocoachina.com/bbs/read.php?tid=197315&page=1&toread=1#tpc

没错,还是我啦!

为何我在windows下运行的时候,不播放音乐呢

是所有音效都没正常播放么?还是只有背景音乐?

所有的音效都不能正常播放,我按照楼主的代码写好了,也全部都编译通过了,而且我把所有的.mp3都拷贝到resources文件夹下面了,还自己下载的背景音乐,还将播放音量调到最大,还是啥声音都没有。也没有那几种音效,不知道是哪里的问题,完全是按着楼主的步骤来的。

背景音乐和音效的使用可以看下这篇文章哦。正常调用是不会有什么问题的。

http://blog.csdn.net/jackystudio/article/details/12117827

我把声音代码主要几个截图给你传上来,还有一个我试过可用较小的背景音。如果一切都对但还是没有音效的话,那真是爱莫能助了···

感谢楼主的无私奉献,我已经找到问题了,原来是因为我的.mp3文件太大了,我自己从网上下载的高品质音乐,导致不能播放,换一个小一点的就可以了。还是很喜欢楼主的这一系列教程,对我这种刚入门的人来说确实很有用,即能帮助我理解cocos2dx的运行机制,又不至于迷失在技术的枯燥描述中而倍感沮丧,感谢。:867:

多谢版主的分享,我已经找到问题了。音乐文件不能太大,不然就不能播放,换一个质量低一点的文件小一点的就OK了,虽然我不是很懂这是为什么,但是感觉还是有必要分享出来,帮助后面可能和我同样碰到这个问题的人。

我也感谢您的经验分享。

能否说明一下音乐文件的大小?

如果是这个问题,我试着try一下临界点,同时也找一下原因。:875::875::875:

我用的9.88M的背景音乐就不能播放,然后换成1.30M的就可以正常播放了

打扰下,你对操作Tiled工具的使用很熟悉吗?可否写个详细的操作教程 ,谢谢

大侠,能写个详细使用Tile工具的教程,包含每个步骤过程,图文并茂或是视频教程,谢谢

Label(没TTF)设置颜色无效~~;
计分器如果不放在HelloWorld里面传值用什么呢?感觉做教程还是不要偷懒哦,类堆在一起会带坏小孩子的啊:3:

label->setColor(Color3B(0, 0, 0)); 是这里改颜色···

这里是要新建一个HelloWorldHub类么?

想问几个问题,不知有没人来解答

在“HelloWorldScene.h”中的“HelloWorld”类声明里编写这些代码,我们要开始制作一个分数指示器。
class HelloWorldHud : public cocos2d::Layer
为什么要这样写而不是再建一个类。这算内部类呢还是算继承呢还是算什么?

编写在文档的顶部
HelloWorldHud *HelloWorld::_hud = NULL;
这样写又是什么意义?

即使照着教程抄完了代码,还是云里雾里看不懂

还有,我用楼主提供的音效文件,添加了播放音效的代码后,点调试就自动关掉了

把HelloWorldHud换成HelloWorld试试

这段代码

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

报错

error C2662: “cocos2d::Vec2::normalize”: 不能将“this”指针从“const cocos2d::Vec2”转换为“cocos2d::Vec2 &”

你的能运行吗,上面那个HelloWordHud到底是写嵌套类,还是单独写个类