欢迎光临Software MyZone,有问题可留言或到站点论坛发帖,争取第一时间帮忙解决 || 站点论坛:火龙论坛 || 淘宝小店:应小心的易淘屋 【欢迎大家提建设性意见】

【cocos2d-x开发实战 特训99-part1】添加一只可以拖动的飞猪 转

欢迎热爱编程的朋友们参与到cocos2d-x编程中,为了给大家提供良好的交流环境,网站以开启QQ群
Software MyZone:66202765(群号,欢迎加入,若满,请加1群)
Software MyZone 1群(2dx):286504621
【加群请写:Software MyZone或者是firedragonpzy】
淘宝店:【应小心的易淘屋】初次开店,大家多多支持……
群论坛:火龙论坛正试运营阶段,欢迎大家多提些建设性意见……
摘自:http://codingnow.cn/cocos2d-x/1402.html

周末闲着没事,搞了一个手机版的特训99,这是一款pc上的经典小游戏,就是满大街的“是男人就挺过20s”。游戏比较简单,通过手指拖动飞猪躲避四面八方的子弹,也算是学习cocos2d-x的小demo,主要的小知识点:

1. cocos2d-x实现帧动画
2. 使用Box2D进行碰撞检测
3. 一些粒子特效
4. cocos2d-x 3.0在android平台添加admob广告
5. xml解析和cocos2d-x显示中文
游戏资源是从全民飞机大战中扣出来的。游戏在win32上运行效果图如下:
共三个场景:首页、游戏中、游戏结束。
游戏源码下载地址:http://download.csdn.net/detail/zhoujianghai/7047139

首先切换到cocos2d-x-3.0alpha1\tools\project-creator目录,执行:

python create_project.py -p SuperMan -k com.alexzhou.superman -l cpp
这篇文章我们要实现一只不停飞着的猪,就是咱们的英雄,然后用手指可以拖动它。
创建游戏的主角:飞猪,这里类命名为Plane,因为之前想用飞机素材的,后来发现飞机没有动画图片。飞猪的资源图片如下:

Plane类目前很简单,只有一个init函数,内容如下:

bool Plane::init()
{
 bool ret = false;
 do {
  CC_BREAK_IF(!this->initWithSpriteFrameName("hero_01.png"));
  auto self_anim = createAnimation("hero_%02d.png", 7, 10);
  this->runAction(RepeatForever::create(Animate::create(self_anim)));
  ret = true;
 }while(0);
 return ret;
}

一共7帧,因为第一帧和最后一帧图片是一样的,所以上面只看到六帧。
createAnimation是根据图片名、帧数、每帧时间创建动画的函数,以后的子弹类也用得到,可以抽出来作为一个工具函数使用。

Animation* createAnimation(const char* path, int frame_count, int fps)
{
 Array *frames = Array::createWithCapacity(frame_count);
 for(int i = 1; i < = frame_count; ++ i) {
  const char* img_name = String::createWithFormat(path, i)->getCString();
  
//log("img_name=%s", img_name);
  SpriteFrame *frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(img_name);
  frames->addObject(frame);
 }
 return Animation::createWithSpriteFrames(frames, 1.0 / fps);
}

接下来删除引擎生成的HelloWorldScene.h和cpp文件,创建游戏的主场景GameScene类,前面创建的主角飞猪需要添加到场景中显示。代码如下:

class GameScene: public cocos2d::Layer
{
public:
 GameScene();
 
 virtual ~GameScene();
 
 virtual bool init();
 
 static cocos2d::Scene* scene();
 void onTouchesBegan(const std::vector<cocos2d::touch *>& touches, cocos2d::Event *unused_event);
 void onTouchesMoved(const std::vector</cocos2d::touch><cocos2d::touch *>& touches, cocos2d::Event *unused_event);
 void onTouchesEnded(const std::vector</cocos2d::touch><cocos2d::touch *>& touches, cocos2d::Event *unused_event);
 
CREATE_FUNC(GameScene);
 
private:
 Plane *_plane;
 bool _isFlying;
 cocos2d::Size _screenSize;
};

这里因为需要实现拖动飞猪,所以重写了onTouchesXXX这三个函数。三个变量分别是:飞猪、判断飞猪是否可以移动的变量、屏幕尺寸。
在init函数中添加Plane对象,设置它的坐标:

bool GameScene::init() 
{
 bool bRet = false;
 do
 {
  CC_BREAK_IF(! Layer::init());
  _screenSize = Director::getInstance()->getVisibleSize();
  auto origin = Director::getInstance()->getVisibleOrigin();
 
  SpriteFrameCache::getInstance()->addSpriteFramesWithFile("pig.plist");
 
  _plane = Plane::create();
  _plane->setScale(2.0f);
  _plane->setPosition(Point(origin.x + _screenSize.width / 2, origin.y + _screenSize.height / 2));
  this->addChild(_plane, 100);
 
  auto listener = EventListenerTouchAllAtOnce::create();
  listener->onTouchesBegan = CC_CALLBACK_2(GameScene::onTouchesBegan, this);
  listener->onTouchesMoved = CC_CALLBACK_2(GameScene::onTouchesMoved, this);
  listener->onTouchesEnded = CC_CALLBACK_2(GameScene::onTouchesEnded, this);
  _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
 
  bRet = true;
 }while(0);
 return bRet;
}

cocos2d-x 3.0使用了c++ 11的特性,这里触摸函数使用了bind和function的方式,下面来实现这三个函数:

void GameScene::onTouchesBegan(const vector<touch *>& touches, Event *unused_event)
{
 vector</touch><touch *>::const_iterator touchIter = touches.begin();
 Touch *pTouch = (Touch*)(*touchIter);
 Point location = pTouch->getLocation();
 Rect rect = _plane->getBoundingBox();
 
 if(rect.containsPoint(location))
 {
  _isFlying = true;
 }
}
 
void GameScene::onTouchesMoved(const vector</touch><touch *>& touches, Event *unused_event)
{
 vector</touch><touch *>::const_iterator touchIter = touches.begin();
 Touch *pTouch = (Touch*)(*touchIter);
 Point location = pTouch->getLocation();
 Point start = pTouch->getStartLocation();
 Point direction = (location - start).normalize();
 Rect screen = Rect(0, 0, _screenSize.width, _screenSize.height);
 
 if(_isFlying)
 {
  if(screen.containsPoint(location)) {
   _plane->setPosition(location);
  }
 }
}
 
void GameScene::onTouchesEnded(const vector</touch><touch *>& touches, Event *unused_event)
{
 _isFlying = false;
}

逻辑比较简单,没啥好说的。就是手指拖动飞猪的时候更新飞猪的坐标,然后判断只能在屏幕内拖动飞猪。
最后更新AppDelegate.cpp的代码,在director->setOpenGLView(eglView);后面添加:
eglView->setDesignResolutionSize(720, 1280, ResolutionPolicy::SHOW_ALL);
指定资源的分辨率为720×1280,然后把main.cpp中游戏窗口大小改成(360, 640)。
运行效果如下:

发表评论