前言

做了以下优化

  1. 击败敌人概率掉落金币
  2. 建筑消耗金币
  3. 技能充能
  4. 技能释放

金币掉落

金币类

将两种金币(掉落的和固定位置上的)写在了一个类里

class Gold :public Sprite {
public:
    int type = 0;
    vector<Gold*> golds;
    int goldNum = 0;
    void initial(int type);        //-1或1
    void update(float dt);        //固定金币
    void addGold(int);
    void getGoldAnimation();
};
void Gold::initial(int t) {
    type = t;
    if (type == 0) {
        addGold(t);
        AudioEngine::play2d("sound/addgold.mp3");
    } else {
        setPosition(Vec2(GOLD_POS_X, GOLD_POS_Y));
        schedule(schedule_selector(Gold::update));
    }

}
void Gold::update(float dt) {
    for (int i = 0; i < golds.size(); i++) {
        if (i == golds.size()) {
            return;
        }
        if (getBoundingBox().intersectsRect(golds[i]->getBoundingBox())) {
            golds[i]->removeFromParentAndCleanup(true);
            golds.erase(golds.begin() + i);
            i--;
            goldNum++;
            AudioEngine::play2d("sound/getgold.mp3");
            getGoldAnimation();
        }
    }
}
void Gold::addGold(int t) {        //金币生成后移动的动画
    float offsetX = 0;            //x偏移量
    ActionInterval* move1 = MoveBy::create(0.5, Vec2(offsetX, -20));
    ActionInterval* move2 = MoveBy::create(0.5, Vec2(offsetX, 10));
    ActionInterval* move3 = MoveBy::create(0.5, Vec2(offsetX, -10));
    ActionInterval* move4 = MoveBy::create(0.5, Vec2(offsetX, 5));
    ActionInterval* move5 = MoveBy::create(0.5, Vec2(offsetX, -5));
    ActionInterval* move6 = MoveTo::create(1.5, Vec2(GOLD_POS_X, GOLD_POS_Y));
    ActionInterval* move = Sequence::create(move1, move2, move3, move4, move5, move6, NULL);
    runAction(move);
}
void Gold::getGoldAnimation() {        //获得金币的动画(放缩)
    ScaleTo* scale1 = ScaleTo::create(0.3, 1.2);
    ScaleTo* scale2 = ScaleTo::create(0.3, 1.0);
    ActionInterval* scale = Sequence::create(scale1, scale2, NULL);
    runAction(scale);
}

效果

金币消耗

初始化建筑消耗金币的位置

void catTD::initGold() {
    gameGold = Gold::create("gold1.png");
    gameGold->initial(1);
    addChild(gameGold);
    gameGoldNumLabel = LabelAtlas::create("0", "nums.png", 20, 16, '0');
    gameGoldNumLabel->setPosition(GOLD_POS_X + gameGoldNumLabel->getContentSize().width, GOLD_POS_Y - gameGoldNumLabel->getContentSize().height / 2);
    addChild(gameGoldNumLabel);
    for (int i = 0; i < 4; i++) {
        auto gold = Gold::create("gold.png");
        gold->setPosition(100 * i + LEFT_TOWN_X - 10, 15);
        auto label = Label::create();
        label->setPosition(100 * i + LEFT_TOWN_X - 10 + gold->getContentSize().width, 15);
        string s = "  x ";
        label->setString(s.append(to_string(i + 2)));
        label->setColor(Color3B(0, 0, 0));
        addChild(gold);
        addChild(label);
    }
}

判断金币是否足够

bool catTD::catOnTouchBegan(Touch* touch, Event* unused_event) {    //单击事件
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 10; j++) {
            if (townReady != nullptr) {
                if (!rGridArea[i][j].isBuild) {
                    Rect rec = Rect(RIGHT_GRID_CORNER_X + GRID_SIZE * i, RIGHT_GRID_CORNER_Y + GRID_SIZE * j, GRID_SIZE, GRID_SIZE);
                    if (rec.containsPoint(mousePos)) {
                        if (gameGoldNum >= townReady->cost) {        //建筑消耗金币
                            gameGold->goldNum -= townReady->cost;
                            addTown(Pos(i, j), townReady->type);
                            removeChild(townReady);
                            townReady = nullptr;

                        }
                    }
                }
            }
        }
    }
}

技能充能

技能按钮及充能进度

void catTD::addSkillBtns() {
    for (int i = 0; i < 4; i++) {
        auto progress1 = Sprite::create("bar1.png");
        progress1->setPosition(Vec2(LEFT_SKILL_X + 100 * i, 20));
        auto progress2 = Sprite::create("bar3.png");
        ProgressTimer* progress = ProgressTimer::create(progress2);
        progress->setPosition(Vec2(LEFT_SKILL_X + 100 * i, 20));
        progress->setType(ProgressTimer::Type::BAR);
        progress->setMidpoint(Point(0, 0.5));
        progress->setBarChangeRate(Point(1, 0));
        progress->setPercentage(0);
        skillProgress.push_back(progress);
        addChild(progress1);
        addChild(progress);
        stringstream ss;
        ss << "skill" << i << ".png";
        auto skillBtn = Button::create(ss.str());
        skillBtn->setPosition(Vec2(LEFT_SKILL_X + 100 * i, LEFT_SKILL_Y));
        skillBtn->setName(ss.str());
        skillBtns.push_back(skillBtn);
        skillBtn->addTouchEventListener([=](Ref* sender, Widget::TouchEventType type) {
            switch (type) {
                case ui::Widget::TouchEventType::ENDED:
                    if (skillProgress[i]->getPercentage() < 100) {
                    } else {
                        if (skillReady == nullptr) {
                            if (townReady != nullptr) {
                                removeChild(townReady);
                                townReady = nullptr;
                            }
                            int j;
                            for (j = 0; j < 4; j++) {
                                if (skillBtns[j]->getBoundingBox().containsPoint(mousePos)) {        //如果鼠标在按钮内
                                    break;
                                }
                            }
                            stringstream s;
                            s << "skill" << j << ".png";
                            auto skill = Skill::create(s.str().c_str());                //获取第几张图
                            skillReady = skill;
                            skillReady->type = j;
                            addChild(skillReady);
                        } else {
                            removeChild(skillReady);
                            skillReady = nullptr;
                        }
                        skillProgress[i]->setPercentage(0);
                    }
                    break;
            }
        });
        addChild(skillBtn);
    }
}

生成能量

void catTD::addPower(Vec2 pos, int type) {
    stringstream ss;
    ss << "power" << type << ".png";
    auto power = Sprite::create(ss.str().c_str());
    power->setPosition(pos);
    addChild(power);
    ActionInterval* move = MoveTo::create(1.5, Vec2(LEFT_SKILL_X + 100 * type, LEFT_SKILL_Y));
    power->runAction(move);
    skillPowers.push_back(power);
}

判断能量是否移动到技能图案上

void catTD::getPower() {
    for (int j = 0; j < skillPowers.size(); j++) {
        if (j == skillPowers.size()) {
            break;
        }
        for (int i = 0; i < skillBtns.size(); i++) {            //判断是否获取到能量
            if (i == skillBtns.size()) {
                break;
            }
            if (skillPowers[j]->getBoundingBox().intersectsRect(skillBtns[i]->getBoundingBox())) {
                AudioEngine::play2d("sound/bubble.mp3");
                removeChild(skillPowers[j]);
                skillPowers.erase(skillPowers.begin() + j);
                float per = skillProgress[i]->getPercentage() + 5;
                if (per >= 100) {
                    per = 100;
                }
                skillProgress[i]->setPercentage(per);
                j--;
                i--;
                return;
            }
        }
    }
}

让removeRound函数返回消除的数量

int catTD::removeRound(Pos pos) {
    int removeNum = 1;
    int id = pos.x * 10 + pos.y;
    Cat* cat = (Cat*)getChildByName(to_string(id));
    int type = cat->type;
    addPower(cat->getPosition(), type);        //增加能量
    //
    return removeNum;
}

可以根据消除数量播放不同音效

int k = removeRound(pos);
if (k < 3) {
    AudioEngine::play2d("sound/click0.mp3");
} else if (k < 6) {
    AudioEngine::play2d("sound/click1.mp3");
} else {
    AudioEngine::play2d("sound/click2.mp3");
}

效果

技能释放

Skill类

class Skill :public Sprite {
public:
    int type = -1;
    vector<Sprite*> skills;
    void initial(Vec2);        //初始化
    void move();        //移动
};
void Skill::initial(Vec2 pos) {
    setPosition(RIGHT_GRID_CORNER_X + rand() % (GRID_SIZE * 10), WINDOW_HEIGHT);
    move();
}
void Skill::move() {
    ActionInterval* move1 = MoveTo::create(2.0f, Vec2(RIGHT_GRID_CORNER_X + rand() % (GRID_SIZE * 4), RIGHT_GRID_CORNER_Y + rand() % (GRID_SIZE * 10)));
    ActionInterval* move2 = MoveBy::create(1.0f, Vec2(0, 0));
    ActionInterval* move = Sequence::create(move1, move2, NULL);
    move->setTag(0);
    runAction(move);
}

使用技能

void catTD::useSkill(int skillType) {
    stringstream ss;
    ss << "skill" << skillType << ".png";
    for (int i = 0; i < 5; i++) {
        auto skill = Skill::create(ss.str().c_str());
        skill->initial(mousePos);
        addChild(skill);
        skills.push_back(skill);
    }
}

技能是否击中敌人

void catTD::skillAttack() {
    for (int i = 0;; i++) {
        if (i == skills.size()) {
            break;;
        }
        if (skills[i]->getActionByTag(0) == nullptr) {
            removeChild(skills[i]);
            skills.erase(skills.begin() + i);
            i--;
        }
    }
    for (int i = 0;; i++) {
        if (i == skills.size()) {
            break;
        }
        for (int j = 0;; j++) {
            if (j == enemys.size()) {
                break;
            }
            if (skills[i]->getBoundingBox().intersectsRect(enemys[j]->getBoundingBox())) {
                addGold(1, enemys[j]);
                removeChild(enemys[j]);
                enemys.erase(enemys.begin() + j);
                return;
            }
        }
    }
}

技能会从舞台上方下降到塔防区的随机位置

演示

Last modification:July 12th, 2020 at 12:57 am