Cocos2dx 3.2 横版过关游戏Brave学习笔记(八)

作者: douxt

好长时间没更新了,这次准备加入敌人的攻击,将敌人波数设置为三波,最后一波会有个小boss。
打完第三波就会出现胜利画面。如果玩家死亡就出现失败界面。

这里采用比较简单的方法控制敌人,即每隔一段时间,让敌人进行攻击,如果不在范围内,则向玩家移动。
在MainScene的init中:

    this->schedule(schedule_selector(MainScene::enemyMove), 3);

这里是每隔3秒让敌人进行一次动作。

用到的函数:

void MainScene::enemyMove(float dt)
{
    for(auto enemy: _enemys)
    {
        if("dead" != enemy->getState()&&_player && "dead" != _player->getState())
        {
            if(_player->isInRange(enemy))
            {
                if("attacking" != enemy->getState())
                {
                    enemy->attack();
                    _player->beHit(enemy->getAttack());
                    this->updateHealth();
                }
            }else
            {
                enemy->walkTo(_player->getBestAttackPosition(enemy->getPosition()));
            }
        }
    }

}

还增加了更新玩家血量的代码,具体可以下载源代码参考。

然后玩家会死亡,对象会被释放,之前没考虑这个情况,所以很可能会出现指针指向无效对象的情况,以前用到_player的地方需要添加相应的检查。

在MainScene中增加变量记录关卡总数和当前关卡,两个vector来记录每一关每个怪的类型和位置:

    int _maxLevel;
    int _level;
    std::vector<std::vector<Player::PlayerType>> _enemyTypes;
    std::vector<std::vector<Vec2>> _enemyPositions;

并在initLevel中进行初始化:

void MainScene::initLevel()
{
    _level = 0;
    _maxLevel = 2;
    std::vector<Player::PlayerType> types;
    types.push_back(Player::ENEMY1);
    types.push_back(Player::ENEMY2);
    _enemyTypes.push_back(types);

    types.clear();
    types.push_back(Player::ENEMY1);
    types.push_back(Player::ENEMY2);
    types.push_back(Player::ENEMY2);
    _enemyTypes.push_back(types);

    types.clear();
    types.push_back(Player::ENEMY1);
    types.push_back(Player::ENEMY1);
    types.push_back(Player::ENEMY2);
    types.push_back(Player::BOSS);
    _enemyTypes.push_back(types);

    std::vector<Vec2> positions;
    positions.push_back(VisibleRect::center());
    positions.push_back(VisibleRect::right() - Vec2(200, 0));
    _enemyPositions.push_back(positions);

    positions.clear();
    positions.push_back(VisibleRect::center());
    positions.push_back(VisibleRect::right() - Vec2(200, 0) + Vec2(0, 200));
    positions.push_back(VisibleRect::right() - Vec2(200, 0) - Vec2(0, 200));
    _enemyPositions.push_back(positions);

    positions.clear();
    positions.push_back(VisibleRect::center() + Vec2(0, 200));
    positions.push_back(VisibleRect::center() - Vec2(0, 200));
    positions.push_back(VisibleRect::right() - Vec2(200, 0) + Vec2(0, 200));
    positions.push_back(VisibleRect::right() - Vec2(200, 0) - Vec2(0, 200));
    _enemyPositions.push_back(positions);

}

然后将addEnemy替换为新的函数:

void MainScene::addEnemyByLevel(int level)
{
    if(level > _maxLevel)
    {
        return;
    }

    auto types = _enemyTypes[level];
    auto positions = _enemyPositions[level];

    for(int ii=0; ii< types.size();ii++)
    {
        addOneEnemy(types[ii], positions[ii]);
    }
}

注意,Player中的类型中添加了一个新类型Boss。然后还需要增加变量来记录关卡总数目,目前的关卡等。
如果玩家死亡,弹出一个新界面,提示玩家游戏结束,并有一个按钮可以返回开始场景。
如果打完第三波,也会弹出类似界面,提示玩家胜利。

void MainScene::enemyDead(Ref* obj)
{
    auto player= dynamic_cast<Player*>(obj);
    if(Player::PlayerType::PLAYER == player->getPlayerType())
    {
        _player = nullptr;
        auto layer = GameOverLayer::create();
        layer->setText("You Died!");
        this->addChild(layer,10000);
    }
    else
    {
        _enemys.eraseObject(player,true);
        log("onEnemyDead:%d", _enemys.size());
        if(_enemys.size() == 0)
        {
            if(_level == 2)
            {
                auto layer = GameOverLayer::create();
                layer->setText("You Win!");
                this->addChild(layer,10000);
                return;
            }
            showNextLevelItem();
        }
    }
}

新增加了一个GameOverLayer。

代码提交了一下,名称为:"add enemy attack, boss, lose if die, win if clear level."




有些地方不太流畅,感觉判断触摸敌人的那块需要改进。 代码应该还存在着不少不完善的地方,希望发现的人能帮忙指出,谢谢!

标签: none

?>