前言
做了以下优化
- 击败敌人概率掉落金币
- 建筑消耗金币
- 技能充能
- 技能释放
金币掉落
金币类
将两种金币(掉落的和固定位置上的)写在了一个类里
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;
}
}
}
}
技能会从舞台上方下降到塔防区的随机位置