塔防游戏《王国保卫战》教程:开始界面
《王国保卫战》是一款经典的塔防游戏,今天我们以这款游戏为例,探讨 Cocos2d-x 的设计。
1. 修改 AppDelegate 内容
首先,我们需要修改 AppDelegate 中的内容,将 setDesignResolutionSize 进行调整,保持传入的设计分辨率高度不变,根据屏幕分辨率修正设计分辨率的宽度。代码如下:
setDesignResolutionSize(960, 640, ResolutionPolicy::FIXED_HEIGHT);
然后,通过以下代码启动新的场景,进入开始游戏界面:
auto scene = WelcomeScene::createScene();
director->runWithScene(scene);
2. 开始界面元素构建
2.1 加载资源与添加背景图片
首先加载资源文件 xx.plist,使用以下代码:
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("mainmenu_spritesheet_32_1-hd.plist");
接着添加背景图片,从 SpriteFrameCache 中加载图片,设置位置并添加到场景中,Zorder 设置为 -1 使其位于场景最底层:
auto sprite_background = Sprite::createWithSpriteFrameName("mainmenu_bg.png");
sprite_background->setPosition(Point(visibleSize.width/2, visibleSize.height/2));
addChild(sprite_background, -1);
2.2 添加 Kingdom Rush Logo 及动画
添加 Logo 并计算其应在的位置,设置初始大小:
auto sprite_Logo = Sprite::createWithSpriteFrameName("logo.png");
Point point_Logo;
point_Logo.x = visibleSize.width/2;
point_Logo.y = visibleSize.height - (sprite_Logo->getContentSize().height/2);
sprite_Logo->setScale(0.2f);
sprite_Logo->setPosition(point_Logo);
addChild(sprite_Logo, 1);
给 Logo 设置一个 ScaleTo 的动画,例如 ScaleTo::create(0.5, 1.5, 1.5),然后播放该动画。
在 Logo 缩放动画完成后,会有 Kingdom 从左到右闪烁的动画。这是一个帧动画,每一帧的图片已保存在 plist 中,通过以下代码实现:
auto sprite = Sprite::createWithSpriteFrameName("logo_brillo_0001.png");
sprite->setPosition(point_Logo);
SpriteFrame* frame = NULL;
Vector<SpriteFrame*> aFrames(20);
for (int len = 1; len <= 21; len++) {
frame = SpriteFrameCache::getInstance()->spriteFrameByName(String::createWithFormat("logo_brillo_%04d.png", len)->getCString());
if (frame != nullptr) {
aFrames.pushBack(frame);
}
}
addChild(sprite, 2);
auto animation = Animation::createWithSpriteFrames(aFrames, 0.1f);
sprite->runAction(RepeatForever::create(Animate::create(animation)));
使用 RepeatForever::create 创建一个不间断播放的动画,放置在 Logo 上覆盖,完成动画效果。
创建一个动画序列 Sequence,在序列中加入 Logo 的缩放动画和帧动画,可在 Logo 缩放动画完成之后链接上帧动画,达到原有游戏效果。
2.3 开始按键的生成及动画
在 Cocos2d-x 中,可采用 MenuItemSprite 来定义一个精灵按键,方便设置按键效果以及监听。本文采用给 Sprite 添加监听的方式来实现一个按键。
首先加载资源图片,在上述动画序列 Sequence 的最后再添加一个开始按键的下移动画 MoveTo 即可实现,代码略。
创建一个监听:
auto button_Start_listener = EventListenerTouchOneByOne::create();
设置 onTouchBegan 即点击后的响应:
button_Start_listener->onTouchBegan = [&](Touch* touch, Event* event) {
auto target = static_cast<Sprite*>(event->getCurrentTarget());
Point locationInNode = target->convertTouchToNodeSpace(touch);
Size size = target->getContentSize();
Rect rect = Rect(0 + 40, 0 + 30, size.width - 80, size.height/3 + 15);
if (rect.containsPoint(locationInNode)) {
target->setDisplayFrame(SpriteFrameCache::getInstance()->spriteFrameByName("menu_startchain_0002.png"));
return true;
}
return false;
};
因为点击整个场景的所有精灵时,都会依次执行所有的 EventListenerTouchOneByOne,所以需要在 onTouchBegan 中加入对点击区域的判断,以此来判断是否点击在所需精灵中,这里对原有精灵的 rect 进行了修正,去掉 START 按键中链子以及其他的部分,当点击时,改变该精灵的图片,达到点击效果。
设置点击后释放动作监听:
button_Start_listener->onTouchEnded = [&](Touch* touch, Event* event) {
auto target = static_cast<Sprite*>(event->getCurrentTarget());
target->setDisplayFrame(SpriteFrameCache::getInstance()->spriteFrameByName("menu_startchain_0001.png"));
button_Start->runAction(MoveTo::create(0.3f, Point(point_Logo.x, point_Logo.y)));
button_Start->setVisible(false);
setSaveMenuVisible();
};
点击后开始按键 MoveTo 到 Logo 后,隐藏,然后将开始游戏菜单上移。
2.4 其他元素处理
三个 “NEW GAME” 的背景图片是一个 SPRITE,“CLOSE” 按键设置监听方式与上述开始按键类似,也可使用 MenuItemSprite 方式,当点击开始按键后,给这些精灵添加 MoveTo 动画,移动到场景上。
“NEW GAME” 采用新建一个自定义精灵的方式,定义如下:
class SlotMenu : public Sprite {
public:
SlotMenu();
~SlotMenu();
virtual bool initWithNum(int num);
CREATE_FUNC(SlotMenu);
void button_Savelot_Delete_callback(Ref* pSender);
void conform_delete(Ref* pSender);
void cancel_delete(Ref* pSender);
void createNewGame();
static SlotMenu* createMenu(int num);
protected:
Label* label_hint;
MenuItemSprite* button_Savelot_Delete;
Sprite* savelot;
};
首先自定义一个创建方法,后续可根据需求进一步完善其功能。
通过以上步骤,我们完成了《王国保卫战》开始界面的设计与实现,包括背景、Logo、动画以及各种按键的处理。更多关于帧动画的详细内容可参考 http://www.cnblogs.com/onlycxue/p/3509610.html。