20150303084414283.jpg

     《王国保卫战》是一款经典的塔防游戏,我们今天就以这款游戏为例,看一下cocos2dx的设计。

      

       修改AppDelegate中内容,将setDesignResolutionSize中改为

1
(960, 640, ResolutionPolicy::FIXED_HEIGHT)

保持传入的设计分辨率高度不变,根据屏幕分辨率修正设计分辨率的宽度。

通过:

1
2
auto scene = WelcomeScene::createScene();  
director->runWithScene(scene);

来启动新的场景,进入开始游戏界面。

首先是Kingdom Rush的LOGO以及该LOGO的动画

加载资源文件xx.plist

1
SpriteFrameCache::getInstance()->addSpriteFramesWithFile("mainmenu_spritesheet_32_1-hd.plist");

添加背景图片

1
2
3
4
5
6
7
8
//从SpriteFrameCache中加载图片  
auto sprite_background = Sprite::createWithSpriteFrameName("mainmenu_bg.png");  
   
//设置位置  
sprite_background->setPosition(Point(visibleSize.width/2,visibleSize.height/2));  
 
//添加背景,Zorder设置为-1为此场景最底层  
addChild(sprite_background,-1);

然后添加kingdom Rush Logo

1
2
3
4
5
6
7
8
9
10
sprite_Logo = Sprite::createWithSpriteFrameName("logo.png");  
 
//计算Logo图应该在的位置  
point_Logo.x = visibleSize.width/2,visibleSize.height;  
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就显示在了背景图片之上,初始大小为0.2倍,给它设置一个ScaleTo的动画例如ScaleTo::create(0.5,1.5,1.5),然后播放即可。

在LOGO缩放动画完成后,会有Kingdom从左到右闪烁的动画,通过查看原游戏资源图片发现这是一个帧动画,每一帧的图片已经保存在plist当中,通过播放帧动画即可实现效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//从资源中加图片,设置位置  
auto sprite = Sprite::createWithSpriteFrameName("logo_brillo_0001.png");  
   
sprite->setPosition(point_Logo);  
//生成帧动画  
//参见http://www.cnblogs.com/onlycxue/p/3509610.html  
SpriteFrame* frame = NULL;  
Vector<SpriteFrame*> aFrames(20);  
   
for (int len = 1;len <= 21; len++)  
{  
      frame = SpriteFrameCache::getInstance()->spriteFrameByName(String::createWithFormat("logo_brillo_00d.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缩放动画完成之后链接上帧动画,达到原有游戏效果。


接下来是开始按键的生成以及动画。

20150303090242195.jpg

Cocos2d-x中,可以采用MenuItemSprite来定义一个精灵按键,方便设置按键效果以及监听。

本文采用给Sprite添加监听的方式来实现一个按键,首先是加载资源图片,在上述动画序列Sequence的最后再添加一个开始按键的下移动画MoveTo即可实现,代码略。

创建一个监听

1
auto button_Start_listener = EventListenerTouchOneByOne::create();

设置onTouchBegan即点击后的相应

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 = Rect(0+40, 0+30, size.width-80, size.height/3 +15);  
  //当点击坐标在区域内时  
  if (rect.containsPoint(locationInNode))  
  {    
    //改变Button式样达到点击效果  
    target->setDisplayFrame(SpriteFrameCache::getInstance()->spriteFrameByName("menu_startchain_0002.png"));            
    return true;    
  }    
  return false;    
};

因为点击整个场景的所有精灵时,都会依次执行所有的EventListenerTouchOneByOne,所以需要在onTouchBegan中加入对点击区域的判断,以此来判断是否点击在所需精灵中,rect即精灵所在区域,这里对原有精灵的rect进行了修正,即去掉START按键中链子以及其他的部分,当点击是,改变改精灵的图片,达到点击效果。

设置点击后释放动作监听

1
2
3
4
5
6
7
button_Start_listener->onTouchEnded = [&](Touch* touch, Event* event){  
  auto target = static_cast<Sprite*>(event->getCurrentTarget());  
  static_cast<Sprite*>(event->getCurrentTarget())->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后,隐藏,然后将开始游戏菜单上移。

20150303092402989.jpg

三个“NEW GAME”的背景图片是一个SPRITE,"CLOSE"按键设置监听方式与上述开始按键类似,也可使用MenuItemSprite方式,当点击开始按键后,给这些精灵添加MoveTo动画,移动到场景上。

“NEW GAME”采用新建一个自定义精灵的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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;  
};

首先我们自定义一个创建方法

1
2
0