上一篇我们添加了一只飞动的猪,它过的很安逸,这样不好,会越来越胖,到时候就飞不起来了。现在来添加子弹吧,让它受受jing。
首先添加一个子弹类Bullet:
bullet.h
typedef enum
{
 DIR_UP = 0,
 DIR_DOWN,
 DIR_LEFT,
 DIR_RIGHT
}BULLET_DIR;

class Bullet : public cocos2d::Sprite
{
public:
 Bullet();
 ~Bullet();

 virtual bool init();

 CC_SYNTHESIZE_READONLY(int, _speed_x, _speed_x);
 CC_SYNTHESIZE_READONLY(int, _speed_y, _speed_y);

 CREATE_FUNC(Bullet);

};

子弹是会运动的,所以它有两个属性,代表在x和y方向的速度。BULLET_DIR枚举表示子弹的运动方向。Bullet的init函数实现:

bool Bullet::init()
{
 bool ret = false;
 do {
  CC_BREAK_IF(!this->initWithSpriteFrameName("bullet_1.png"));

  auto visibleSize = Director::getInstance()->getVisibleSize();
  auto origin = Director::getInstance()->getVisibleOrigin();

  const int direction = abs(rand() % 4);
  const int speedUnit = 4;
  float x = 0, y = 0;
  Size bullet_show_size = this->getDisplayFrame()->getRect().size;
  //子弹从屏幕四个方向飞入
  switch(direction) {
   case DIR_UP:
   {
    x = abs(rand()%(int)visibleSize.width);
    y = visibleSize.height - bullet_show_size.height;
    _speed_x = rand()%speedUnit;
    _speed_y = (abs(rand()%speedUnit + 1)) * (-1);
    break;
   }

   case DIR_DOWN:
   {
    x = abs(rand()%(int)visibleSize.width);
    y = bullet_show_size.height;
    _speed_x = rand()%speedUnit;
    _speed_y = abs(rand()%speedUnit+1);
    break;
   }

   case DIR_LEFT:
   {
    x = bullet_show_size.width;
    y = abs(rand()%(int)visibleSize.height);
    _speed_x = abs(rand()%speedUnit + 1);
    _speed_y = rand()%speedUnit;
    break;
   }

   case DIR_RIGHT:
   {
    x = visibleSize.width - bullet_show_size.width;
    y = abs(rand()%(int)visibleSize.height);
    _speed_x = abs(rand()%speedUnit + 1) * (-1);
    _speed_y = rand()%speedUnit;
    break;
   }
  }

  this->setPosition(Point(origin.x + x, origin.y + y));

  auto self_anim = createAnimation("bullet_%d.png", 4, 10);
  this->runAction(RepeatForever::create(Animate::create(self_anim)));

  ret = true;
 }while(0);

 return ret;
}

这里让子弹随机的从屏幕的四个方向飞入,每个子弹的速度都是取随机值,同时根据方向确定速度值。
在GameScene.h中添加:

void createBullet(float dt);
void updateBullet(float dt);

cocos2d::Rect _screenRect;
cocos2d::Array *_bullets;
cocos2d::SpriteBatchNode* _spriteBatch;

_bullets用来存放屏幕上的子弹,因为子弹数目很多,图片用TexturePacker打包的,所以为了提高渲染效率,这里使用_spriteBatch进行批处理。因为子弹是随机生成的,所以我们需要添加两个函数:createBullet(创建子弹)和updateBullet(更新子弹的位置),这两个函数需要在游戏的每一帧都执行。同时还需要对子弹进行检测,如果子弹飞出屏幕就移除它,_screenRect表示屏幕这个矩形区域。
在GameScene.cpp的init函数中添加:

_screenRect = Rect(0, 0, _screenSize.width, _screenSize.height);

SpriteFrameCache::getInstance()->addSpriteFramesWithFile("resources.plist");
_spriteBatch = SpriteBatchNode::create("resources.png");
this->addChild(_spriteBatch);

_bullets = Array::create();
_bullets->retain();

this->schedule(schedule_selector(GameScene::createBullet));
this->schedule(schedule_selector(GameScene::updateBullet));

这里做一些初始化工作。
接着实现createBullet函数:

void GameScene::createBullet( float dt )
{
 int maxBulletNum = 10;
 if (_bullets->count() >= maxBulletNum)
 {
  return;
 }

 Bullet* bullet = Bullet::create();
 bullet->setScale(0.5f);
 _spriteBatch->addChild(bullet);
 _bullets->addObject(bullet);
}

暂时指定最多出现10颗子弹,太多了怕吓坏它。
updateBullet函数:

void GameScene::updateBullet(float dt)
{
 Array *toDestroy = Array::create();

 Object *bulletObj = NULL;
 CCARRAY_FOREACH(_bullets, bulletObj)
 {
  Bullet *bullet = (Bullet*)bulletObj;
  Point position = bullet->getPosition();
  Point new_pos = Point(position.x + bullet->get_speed_x(), position.y + bullet->get_speed_y());

  if(!_screenRect.containsPoint(new_pos)) {
   bullet->setVisible(false);
   _spriteBatch->removeChild(bullet, true);
   toDestroy->addObject(bullet);
  }else {
   bullet->setPosition(new_pos);
  }

 }

 if(toDestroy->count() > 0) {
  _bullets->removeObjectsInArray(toDestroy);
 }

}

是根据子弹在x和y方向的速度周期性更新子弹的位置,如果子弹不在屏幕内则删除它。

cocos2d-x手游性能优化总结

近段时间在使用cocos2d-x开发2D手游,技术方案使用的是cocos2d-x+lua,因为游戏使用的是cocos2d-x 2.1.5版本,有些优化方案在最新版的cocos2d-x版本已经实现...

阅读全文

cocos2dx-html5 实现网页版flappy bird游戏

我也是第一次使用cocos2d_html5,对js和html5也不熟,看引擎自带的例子和引擎源码,边学边做,如果使用过cocos2d-x的话,完成这个游戏还是十分简单的。游戏体...

阅读全文

【cocos2d-x开发实战 特训99-终结篇】移植到android平台和添加admob广告

上一篇已经完成特性99在win32平台下的开发,现在把它移植到android上,首先修改Android.mk文件,内容如下: LOCAL_PATH := $(call my-dir) include $(CLEAR_...

阅读全文

1 条评论

欢迎留言