cocos2d-x 2.x打飞机(三)

1.2 方案

首先在上一个案例飞机大战的项目中增加一个敌人类Enemy,继承至CCNode,该类定义如下方法和属性:

static Enemy* createEnemy(EnemyType type, float m_speed);

CCSize getShowContentSize();

CCRect getCollisionArea()获取敌人的碰撞区域;

void hurt(int hurtnum);

int m_hp;

float m_speed;

CCSprite *m_showSprite;

bool initEnemy(EnemyType type, float m_speed);

void move();

void remove()。

敌人飞机所拥有的功能和Plane类类似,依次实现敌人飞机的移动、获取碰撞区域等方法。hurt方法实现是被子弹击中后的效果。

道具和子弹一样拥有自己的速度、碰撞区域等所以将道具也封装成一个类,在飞机大战的项目中增加一个道具类Star,继承至CCNode,该类定义如下方法和属性:

CREATE_FUNC(Star);

CCSize getShouContentSize();

CCRect getCollisionArea();

void willRemove();

CC_SYNTHESIZE(bool, m_isWillRemove, IsWillRemove);

CCSprite *m_showSprite;

float m_speed;

bool init();

void move();

void remove()。

最后在精灵层中添加敌人和道具,然后进行子弹和敌人飞机的碰撞检测、玩家飞机和道具的碰撞检测,并实现相应的业务逻辑。

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建敌人类

首先在上一个案例飞机大战的项目中增加一个敌人类Enemy,继承至CCNode,代码如下所示:

    
    
    
    
  1. typedef enum {
  2. TYPE_1,
  3. TYPE_2,
  4. TYPE_3,
  5. TYPE_4,
  6. TYPE_COUNT
  7. }EnemyType;
  8. class Enemy : public CCNode {
  9. public:
  10. static Enemy* createEnemy(EnemyType type, float m_speed);
  11. CCSize getShowContentSize();
  12. //获取敌人的碰撞区域
  13. CCRect getCollisionArea();
  14. //伤害
  15. void hurt(int hurtnum);
  16. private:
  17. int m_hp;
  18. float m_speed;
  19. CCSprite *m_showSprite;
  20. bool initEnemy(EnemyType type, float m_speed);
  21. void move();
  22. void remove();
  23. };

其次实现敌人的创建方法和初始化方法,代码如下所示:

    
    
    
    
  1. Enemy* Enemy::createEnemy(EnemyType type, float speed) {
  2. Enemy *enemy = new Enemy;
  3. if (enemy && enemy->initEnemy(type, speed)) {
  4. enemy->autorelease();
  5. return enemy;
  6. }
  7. CC_SAFE_DELETE(enemy);
  8. return NULL;
  9. }

然后实现敌人的初始化方法initEnemy,在初始化方法中开启定时器调实现敌人的移动,代码如下所示:

    
    
    
    
  1. bool Enemy::initEnemy(EnemyType type, float speed) {
  2. if(!CCNode::init()) return false;
  3. const char* imageName;
  4. switch ((int)type) {
  5. case TYPE_1:
  6. imageName = "enem1.png";
  7. m_hp = 5;
  8. break;
  9. case TYPE_2:
  10. imageName = "enem2.png";
  11. m_hp = 10;
  12. break;
  13. case TYPE_3:
  14. imageName = "enem3.png";
  15. m_hp = 15;
  16. break;
  17. case TYPE_4:
  18. imageName = "enem4.png";
  19. m_hp = 20;
  20. break;
  21. }
  22. m_showSprite = CCSprite::create(imageName);
  23. this->addChild(m_showSprite);
  24. m_speed = speed;
  25. this->schedule(schedule_selector(Enemy::move));
  26. return true;
  27. }

接着实现定时器的回调方法move,实现敌人的移动,代码如下所示:

    
    
    
    
  1. void Enemy::move() {
  2. this->setPositionY(this->getPositionY() - m_speed);
  3. if (this->getPositionY() <= - m_showSprite->getContentSize().height * 0.5) {
  4. this->remove();
  5. }
  6. }

再实现敌人移除的方法和伤害的方法,在敌人被移除之前会有闪烁的粒子效果,代码如下所示:

    
    
    
    
  1. //敌人移除的方法
  2. void Enemy::remove() {
  3. SpriteLayer *layer = (SpriteLayer*)this->getParent();
  4. layer->getEnemys()->removeObject(this);
  5. this->removeFromParent();
  6. }
  7. //被子弹击中的效果
  8. void Enemy::hurt(int hurtnum) {
  9. m_hp -= hurtnum;
  10. if (m_hp <= 0) {
  11. CCParticleSystemQuad *particle = CCParticleSystemQuad::create("particle_boom.plist");
  12. SpriteLayer *layer = (SpriteLayer*)this->getParent();
  13. layer->addChild(particle);
  14. particle->setPosition(this->getPosition());
  15. //粒子生命结束后自动释放
  16. particle->setAutoRemoveOnFinish(true);
  17. this->remove();
  18. }else {
  19. m_showSprite->stopActionByTag(100);
  20. CCBlink *blink = CCBlink::create(0.8, 3);
  21. blink->setTag(100);
  22. m_showSprite->runAction(blink);
  23. }
  24. }

最后实现获取敌人碰撞区域的方法getCollisionArea,代码如下所示:

    
    
    
    
  1. //获取敌人的碰撞区域
  2. CCRect Enemy::getCollisionArea() {
  3. CCRect rect = m_showSprite->boundingBox();
  4. //飞机节点坐标系下矩形原点位置
  5. CCPoint origin_sprite = rect.origin;
  6. //屏幕坐标系下的原点位置(由于精灵层没有改变过位置,所以现在精灵层的坐标系和屏幕坐标系是吻合)
  7. CCPoint origin = this->convertToWorldSpace(origin_sprite);
  8. return CCRectMake(origin.x, origin.y, rect.size.width, rect.size.height);
  9. }

步骤二:创建道具类

由于道具和子弹一样拥有自己的速度、碰撞区域等所以将道具也封装成一个类,创建一个道具类Star,继承至CCNode,代码如下所示:

    
    
    
    
  1. class Star : public CCNode {
  2. public:
  3. CREATE_FUNC(Star);
  4. CCSize getShouContentSize();
  5. //获取星星的碰撞区域
  6. CCRect getCollisionArea();
  7. //将要移除的方法(做动画)
  8. void willRemove();
  9. //是否将要移除
  10. CC_SYNTHESIZE(bool, m_isWillRemove, IsWillRemove);
  11. private:
  12. CCSprite *m_showSprite;
  13. float m_speed;
  14. bool init();
  15. void move();
  16. void remove();
  17. };

然后依次实现道具的初始化方法init,代码如下所示:

    
    
    
    
  1. bool Star::init() {
  2. if (!CCNode::init()) return false;
  3. m_speed = 10;
  4. m_isWillRemove = false;
  5. m_showSprite = CCSprite::create("star.png");
  6. this->addChild(m_showSprite);
  7. this->schedule(schedule_selector(Star::move));
  8. return true;
  9. }

接下来实现道具移动的方法move,以及获取道具碰撞区域的方法,代码如下所示:

    
    
    
    
  1. //道具移动的方法
  2. void Star::move() {
  3. this->setPositionY(this->getPositionY() - m_speed);
  4. if (this->getPositionY() <= -m_showSprite->getContentSize().height * 0.5) {
  5. this->remove();
  6. }
  7. }
  8. //获取星星的碰撞区域
  9. CCRect Star::getCollisionArea() {
  10. CCRect rect = m_showSprite->boundingBox();
  11. //星星节点坐标系下矩形原点位置
  12. CCPoint origin_sprite = rect.origin;
  13. //屏幕坐标系下的原点位置(由于精灵层没有改变过位置,所以现在精灵层的坐标系和屏幕坐标系是吻合)
  14. CCPoint origin = this->convertToWorldSpace(origin_sprite);
  15. return CCRectMake(origin.x, origin.y, rect.size.width, rect.size.height);
  16. }

最后实现道具移除的方法remove以及移除之前的动画方法willRemove,代码如下所示:

    
    
    
    
  1. //将要移除的方法(做动画)
  2. void Star::willRemove() {
  3. m_isWillRemove = true;
  4. //停止星星的移动
  5. this->unschedule(schedule_selector(Star::move));
  6. CCAnimation *animation = CCAnimation::create();
  7. //
  8. for (int i = 0; i < 4; i++) {
  9. CCSpriteFrame *frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("eat_item%d.png", i)->getCString());
  10. animation->addSpriteFrame(frame);
  11. }
  12. animation->setDelayPerUnit(0.05);
  13. CCAnimate *animate = CCAnimate::create(animation);
  14. CCCallFunc *callFunc =CCCallFunc::create(this, callfunc_selector(Star::remove));
  15. CCSequence *seq = CCSequence::create(animate, callFunc,NULL);
  16. m_showSprite->runAction(seq);
  17. }
  18. //移除
  19. void Star::remove(){
  20. SpriteLayer *layer = (SpriteLayer*)this->getParent();
  21. layer->getStars()->removeObject(this);
  22. this->removeFromParent();
  23. }

步骤三:在精灵层中添加敌人和道具

首先在精灵层类中增加如下属性和方法:

CC_SYNTHESIZE_READONLY(CCArray*, m_stars, Stars)存放道具对象的数组;

CC_SYNTHESIZE_READONLY(CCArray*, m_enemys, Enemys)存放敌人的数组;

void addStar()添加星星的方法;

void addEnemy()添加敌人的方法。

首先在精灵层的初始化方法中设置定时器添加敌人,并且实现定时器的回调方法addEnemy方法,代码如下所示:

    
    
    
    
  1. bool SpriteLayer::initSpriteLayer(int Level) {
  2. if(!CCLayer::init())return false;
  3. //设置随机算子 time(0)当前系统时间
  4. srand(time(0));
  5. this->loadRosources();
  6. m_stars = CCArray::create();
  7. CC_SAFE_RETAIN(m_stars);
  8. m_bullets = CCArray::create();
  9. CC_SAFE_RETAIN(m_bullets);
  10. m_removebullets = CCArray::create();
  11. CC_SAFE_RETAIN(m_removebullets);
  12. m_enemys = CCArray::create();
  13. CC_SAFE_RETAIN(m_enemys);
  14. m_buttle_level = 1;
  15. //创建云池对象
  16. m_cloudPool = CloudPool::creatPool(5);
  17. CC_SAFE_RETAIN(m_cloudPool);
  18. //往精灵层中添加云
  19. this->schedule(schedule_selector(SpriteLayer::addCloud), 2);
  20. //创建玩家飞机
  21. m_plane = Plane::createPlane(0);
  22. this->addChild(m_plane);
  23. m_plane->setPosition(SCREEN_POSITION(0.5, 0.2));
  24. //创建敌机
  25. this->schedule(schedule_selector(SpriteLayer::addEnemy), 2);
  26. //开启触摸
  27. this->setTouchEnabled(true);
  28. //设置触摸模式
  29. this->setTouchMode(kCCTouchesOneByOne);
  30. return true;
  31. }
  32. //添加敌人
  33. void SpriteLayer::addEnemy() {
  34. int type = rand() % TYPE_COUNT;
  35. float speed = rand() % 5 + 3;
  36. Enemy *enemy = Enemy::createEnemy((EnemyType)type, speed);
  37. enemy->setPosition(CCRANDOM_0_1() * SCREEN.width, SCREEN.height + enemy->getShowContentSize().height * 0.5);
  38. this->addChild(enemy);
  39. m_enemys->addObject(enemy);
  40. }

其次在精灵层的初始化方法中设置定时器添加道具,并且实现定时器的回调方法addStar方法,代码如下所示:

    
    
    
    
  1. bool SpriteLayer::initSpriteLayer(int Level) {
  2. if(!CCLayer::init())return false;
  3. //设置随机算子 time(0)当前系统时间
  4. srand(time(0));
  5. this->loadRosources();
  6. m_stars = CCArray::create();
  7. CC_SAFE_RETAIN(m_stars);
  8. m_bullets = CCArray::create();
  9. CC_SAFE_RETAIN(m_bullets);
  10. m_removebullets = CCArray::create();
  11. CC_SAFE_RETAIN(m_removebullets);
  12. m_enemys = CCArray::create();
  13. CC_SAFE_RETAIN(m_enemys);
  14. m_buttle_level = 1;
  15. //创建云池对象
  16. m_cloudPool = CloudPool::creatPool(5);
  17. CC_SAFE_RETAIN(m_cloudPool);
  18. //往精灵层中添加云
  19. this->schedule(schedule_selector(SpriteLayer::addCloud), 2);
  20. //添加星星道具
  21. this->schedule(schedule_selector(SpriteLayer::addStar), 4);
  22. //创建玩家飞机
  23. m_plane = Plane::createPlane(0);
  24. this->addChild(m_plane);
  25. m_plane->setPosition(SCREEN_POSITION(0.5, 0.2));
  26. //创建敌机
  27. this->schedule(schedule_selector(SpriteLayer::addEnemy), 2);
  28. //开启触摸
  29. this->setTouchEnabled(true);
  30. //设置触摸模式
  31. this->setTouchMode(kCCTouchesOneByOne);
  32. return true;
  33. }
  34. //添加星星
  35. void SpriteLayer::addStar() {
  36. Star *star = Star::create();
  37. star->setPosition(CCRANDOM_0_1() * SCREEN.width, SCREEN.height + star->getShouContentSize().height * 0.5);
  38. this->addChild(star);
  39. m_stars->addObject(star);
  40. }

然后在精灵层的初始化方法中设置定时器添加道具,并且实现定时器的回调方法addStar方法,代码如下所示:

    
    
    
    
  1. bool SpriteLayer::initSpriteLayer(int Level) {
  2. if(!CCLayer::init())return false;
  3. //设置随机算子 time(0)当前系统时间
  4. srand(time(0));
  5. this->loadRosources();
  6. m_stars = CCArray::create();
  7. CC_SAFE_RETAIN(m_stars);
  8. m_bullets = CCArray::create();
  9. CC_SAFE_RETAIN(m_bullets);
  10. m_removebullets = CCArray::create();
  11. CC_SAFE_RETAIN(m_removebullets);
  12. m_enemys = CCArray::create();
  13. CC_SAFE_RETAIN(m_enemys);
  14. m_buttle_level = 1;
  15. //创建云池对象
  16. m_cloudPool = CloudPool::creatPool(5);
  17. CC_SAFE_RETAIN(m_cloudPool);
  18. //往精灵层中添加云
  19. this->schedule(schedule_selector(SpriteLayer::addCloud), 2);
  20. //添加星星道具
  21. this->schedule(schedule_selector(SpriteLayer::addStar), 4);
  22. //创建玩家飞机
  23. m_plane = Plane::createPlane(0);
  24. this->addChild(m_plane);
  25. m_plane->setPosition(SCREEN_POSITION(0.5, 0.2));
  26. //创建敌机
  27. this->schedule(schedule_selector(SpriteLayer::addEnemy), 2);
  28. //开启触摸
  29. this->setTouchEnabled(true);
  30. //设置触摸模式
  31. this->setTouchMode(kCCTouchesOneByOne);
  32. return true;
  33. }
  34. //添加星星
  35. void SpriteLayer::addStar() {
  36. Star *star = Star::create();
  37. star->setPosition(CCRANDOM_0_1() * SCREEN.width, SCREEN.height + star->getShouContentSize().height * 0.5);
  38. this->addChild(star);
  39. m_stars->addObject(star);
  40. }

步骤四:在精灵层中进行碰撞检测

首先在精灵层的初始化方法中设置定时器scheduleUpdate,进行碰撞检测,代码如下所示:

    
    
    
    
  1. bool SpriteLayer::initSpriteLayer(int Level) {
  2. if(!CCLayer::init())return false;
  3. //设置随机算子 time(0)当前系统时间
  4. srand(time(0));
  5. this->loadRosources();
  6. m_stars = CCArray::create();
  7. CC_SAFE_RETAIN(m_stars);
  8. m_bullets = CCArray::create();
  9. CC_SAFE_RETAIN(m_bullets);
  10. m_removebullets = CCArray::create();
  11. CC_SAFE_RETAIN(m_removebullets);
  12. m_enemys = CCArray::create();
  13. CC_SAFE_RETAIN(m_enemys);
  14. m_buttle_level = 1;
  15. //创建云池对象
  16. m_cloudPool = CloudPool::creatPool(5);
  17. CC_SAFE_RETAIN(m_cloudPool);
  18. //往精灵层中添加云
  19. this->schedule(schedule_selector(SpriteLayer::addCloud), 2);
  20. //创建玩家飞机
  21. m_plane = Plane::createPlane(0);
  22. this->addChild(m_plane);
  23. m_plane->setPosition(SCREEN_POSITION(0.5, 0.2));
  24. //创建敌机
  25. this->schedule(schedule_selector(SpriteLayer::addEnemy), 2);
  26. //开启触摸
  27. this->setTouchEnabled(true);
  28. //设置触摸模式
  29. this->setTouchMode(kCCTouchesOneByOne);
  30. //设置定时器检测碰撞
  31. this->scheduleUpdate();
  32. return true;
  33. }

其次实现定时器的回调方法Update,Update方法中需要对道具和飞机的碰撞进行检测以及子弹与敌人的碰撞进行检测,代码如下所示:

    
    
    
    
  1. void SpriteLayer::update(float time) {
  2. //检测玩家飞机是否与星星碰撞
  3. this->planeCollisionStar();
  4. //检测子弹是否与敌人碰撞
  5. this->bulletCollisionEnemy();
  6. //释放子弹
  7. this->removeBullet();
  8. }

然后实现飞机和道具的碰撞方法planeCollisionStar,代码如下所示:

    
    
    
    
  1. //遍历星星是否与飞机产生碰撞
  2. void SpriteLayer::planeCollisionStar() {
  3. for (int i = 0; i < m_stars->count(); i++) {
  4. Star *star = (Star*)m_stars->objectAtIndex(i);
  5. //如果星星不是将要移除的才做碰撞检测
  6. if (!star->getIsWillRemove()) {
  7. if (star->getCollisionArea().intersectsRect(m_plane->getCollisionArea())) {
  8. //星星进入将要销毁的状态
  9. star->willRemove();
  10. //换子弹
  11. if (m_buttle_level < 35) {
  12. m_buttle_level++;
  13. }
  14. }
  15. }
  16. }
  17. }

最后实现子弹和敌人的碰撞方法bulletCollisionEnemy,代码如下所示:

    
    
    
    
  1. //遍历子弹是否与敌人产生碰撞
  2. void SpriteLayer::bulletCollisionEnemy() {
  3. for (int i = 0; i < m_bullets->count(); i ++) {
  4. Bullet *bullet = (Bullet*)m_bullets->objectAtIndex(i);
  5. for (int j = 0; j < m_enemys->count(); j++) {
  6. Enemy *enemy = (Enemy*)m_enemys->objectAtIndex(j);
  7. //isRunning() 如果该节点在父节点中显示 return true
  8. if (bullet->isRunning()) {
  9. //判断子弹是否打中了敌人
  10. if (bullet->getCollisionArea().intersectsRect(enemy->getCollisionArea())) {
  11. //敌人伤害
  12. enemy->hurt(bullet->getAttack());
  13. //子弹销毁
  14. bullet->remove();
  15. }
  16. }
  17. }
  18. }
  19. }

1.4 完整代码

本案例中,SpriteLayer.h文件中的完整代码如下所示:

    
    
    
    
  1. #ifndef __Plane__SpriteLayer__
  2. #define __Plane__SpriteLayer__
  3. #include<stdio.h>
  4. #include "cocos2d.h"
  5. #include "Plane.h"
  6. #include "CloudPool.h"
  7. #include "Bullet.h"
  8. #include "Star.h"
  9. #include "Enemy.h"
  10. USING_NS_CC;
  11. class SpriteLayer : public CCLayer {
  12. public:
  13. ~SpriteLayer();
  14. static SpriteLayer* createSpriteLayer(int Level);
  15. //发射子弹
  16. void shootBullet();
  17. //保存星星的数组
  18. CC_SYNTHESIZE_READONLY(CCArray*, m_stars, Stars);
  19. //保存子弹的数组
  20. CC_SYNTHESIZE_READONLY(CCArray*, m_bullets, Bullets);
  21. //将要移除子弹的数组
  22. CC_SYNTHESIZE_READONLY(CCArray*, m_removebullets, RemoveBullets);
  23. //保存敌人的数组
  24. CC_SYNTHESIZE_READONLY(CCArray*, m_enemys, Enemys);
  25. private:
  26. int m_buttle_level;
  27. //加载资源 (加载plist)
  28. void loadRosources();
  29. Plane *m_plane;
  30. CloudPool *m_cloudPool;
  31. bool initSpriteLayer(int Level);
  32. //添加云
  33. void addCloud();
  34. //添加星星
  35. void addStar();
  36. //添加敌人
  37. void addEnemy();
  38. //遍历星星是否与飞机产生碰撞
  39. void planeCollisionStar();
  40. //遍历子弹是否与敌人产生碰撞
  41. void bulletCollisionEnemy();
  42. CCPoint m_tempTouchPos;
  43. virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
  44. virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
  45. virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
  46. void update(float time);
  47. //移除不需要的子弹
  48. void removeBullet();
  49. };
  50. #endif /* defined(__Plane__SpriteLayer__) */
隐藏

本案例中,SpriteLayer.cpp文件中的完整代码如下所示:

    
    
    
    
  1. #include "SpriteLayer.h"
  2. #include "Tools.h"
  3. #include "Cloud.h"
  4. SpriteLayer::~SpriteLayer() {
  5. CC_SAFE_RELEASE(m_cloudPool);
  6. CC_SAFE_RELEASE(m_stars);
  7. CC_SAFE_RELEASE(m_bullets);
  8. CC_SAFE_RELEASE(m_removebullets);
  9. CC_SAFE_RELEASE(m_enemys);
  10. }
  11. SpriteLayer* SpriteLayer::createSpriteLayer(int Level){
  12. SpriteLayer *layer = new SpriteLayer;
  13. if (layer && layer->initSpriteLayer(Level)) {
  14. layer->autorelease();
  15. return layer;
  16. }
  17. CC_SAFE_DELETE(layer);
  18. return NULL;
  19. }
  20. bool SpriteLayer::initSpriteLayer(int Level) {
  21. if(!CCLayer::init())return false;
  22. //设置随机算子 time(0)当前系统时间
  23. srand(time(0));
  24. this->loadRosources();
  25. m_stars = CCArray::create();
  26. CC_SAFE_RETAIN(m_stars);
  27. m_bullets = CCArray::create();
  28. CC_SAFE_RETAIN(m_bullets);
  29. m_removebullets = CCArray::create();
  30. CC_SAFE_RETAIN(m_removebullets);
  31. m_enemys = CCArray::create();
  32. CC_SAFE_RETAIN(m_enemys);
  33. m_buttle_level = 1;
  34. //创建云池对象
  35. m_cloudPool = CloudPool::creatPool(5);
  36. CC_SAFE_RETAIN(m_cloudPool);
  37. //往精灵层中添加云
  38. this->schedule(schedule_selector(SpriteLayer::addCloud), 2);
  39. //添加星星道具
  40. this->schedule(schedule_selector(SpriteLayer::addStar), 4);
  41. //创建玩家飞机
  42. m_plane = Plane::createPlane(0);
  43. this->addChild(m_plane);
  44. m_plane->setPosition(SCREEN_POSITION(0.5, 0.2));
  45. //创建敌机
  46. this->schedule(schedule_selector(SpriteLayer::addEnemy), 2);
  47. //开启触摸
  48. this->setTouchEnabled(true);
  49. //设置触摸模式
  50. this->setTouchMode(kCCTouchesOneByOne);
  51. this->scheduleUpdate();
  52. return true;
  53. }
  54. void SpriteLayer::loadRosources() {
  55. CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Game/sp_all.plist");
  56. CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Game/bullet_lv.plist");
  57. CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile("Game/effect0.plist");
  58. }
  59. void SpriteLayer::addCloud() {
  60. Cloud *cloud = m_cloudPool->getCloud();
  61. if (cloud) {
  62. this->addChild(cloud);
  63. }
  64. }
  65. //添加星星
  66. void SpriteLayer::addStar() {
  67. Star *star = Star::create();
  68. star->setPosition(CCRANDOM_0_1() * SCREEN.width, SCREEN.height + star->getShouContentSize().height * 0.5);
  69. this->addChild(star);
  70. m_stars->addObject(star);
  71. }
  72. //添加敌人
  73. void SpriteLayer::addEnemy() {
  74. int type = rand() % TYPE_COUNT;
  75. float speed = rand() % 5 + 3;
  76. Enemy *enemy = Enemy::createEnemy((EnemyType)type, speed);
  77. enemy->setPosition(CCRANDOM_0_1() * SCREEN.width, SCREEN.height + enemy->getShowContentSize().height * 0.5);
  78. this->addChild(enemy);
  79. m_enemys->addObject(enemy);
  80. }
  81. bool SpriteLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) {
  82. m_tempTouchPos = pTouch->getLocation();
  83. return true;
  84. }
  85. void SpriteLayer::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) {
  86. // pTouch->getLocation();
  87. // pTouch->getLocationInView();
  88. CCPoint movePoint = pTouch->getLocation() - m_tempTouchPos;
  89. m_plane->setPosition(m_plane->getPosition() + movePoint);
  90. m_tempTouchPos = pTouch->getLocation();
  91. }
  92. void SpriteLayer::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) {}
  93. //发射子弹
  94. void SpriteLayer::shootBullet() {
  95. Bullet *bullet = Bullet::createBullet(m_plane->getPosition(), m_buttle_level);
  96. this->addChild(bullet, -1);
  97. m_bullets->addObject(bullet);
  98. }
  99. //遍历星星是否与飞机产生碰撞
  100. void SpriteLayer::planeCollisionStar() {
  101. for (int i = 0; i < m_stars->count(); i++) {
  102. Star *star = (Star*)m_stars->objectAtIndex(i);
  103. //如果星星 不是将要移除的 才做碰撞检测
  104. if (!star->getIsWillRemove()) {
  105. if (star->getCollisionArea().intersectsRect(m_plane->getCollisionArea())) {
  106. //星星进入将要销毁的状态
  107. star->willRemove();
  108. //换子弹
  109. if (m_buttle_level < 35) {
  110. m_buttle_level++;
  111. }
  112. }
  113. }
  114. }
  115. }
  116. //遍历子弹是否与敌人产生碰撞
  117. void SpriteLayer::bulletCollisionEnemy() {
  118. for (int i = 0; i < m_bullets->count(); i ++) {
  119. Bullet *bullet = (Bullet*)m_bullets->objectAtIndex(i);
  120. for (int j = 0; j < m_enemys->count(); j++) {
  121. Enemy *enemy = (Enemy*)m_enemys->objectAtIndex(j);
  122. //isRunning() 如果该节点在父节点中显示 return true
  123. if (bullet->isRunning()) {
  124. //判断子弹是否打中了敌人
  125. if (bullet->getCollisionArea().intersectsRect(enemy->getCollisionArea())) {
  126. //敌人伤害
  127. enemy->hurt(bullet->getAttack());
  128. //子弹销毁
  129. bullet->remove();
  130. }
  131. }
  132. }
  133. }
  134. }
  135. void SpriteLayer::update(float time) {
  136. //检测玩家飞机是否与星星碰撞
  137. this->planeCollisionStar();
  138. //检测子弹是否与敌人碰撞
  139. this->bulletCollisionEnemy();
  140. //释放子弹
  141. this->removeBullet();
  142. }
  143. //移除不需要的子弹
  144. void SpriteLayer::removeBullet() {
  145. for (int i = 0; i < m_removebullets->count(); i++) {
  146. Bullet *removeBullet = (Bullet*)m_removebullets->objectAtIndex(i);
  147. m_bullets->removeObject(removeBullet);
  148. }
  149. m_removebullets->removeAllObjects();
  150. }
隐藏

本案例中,Enemy.h文件中的完整代码如下所示:

    
    
    
    
  1. #ifndef __Plane__Enemy__
  2. #define __Plane__Enemy__
  3. #include<stdio.h>
  4. #include "cocos2d.h"
  5. USING_NS_CC;
  6. typedef enum {
  7. TYPE_1,
  8. TYPE_2,
  9. TYPE_3,
  10. TYPE_4,
  11. TYPE_COUNT
  12. }EnemyType;
  13. class Enemy : public CCNode {
  14. public:
  15. static Enemy* createEnemy(EnemyType type, float m_speed);
  16. CCSize getShowContentSize();
  17. //获取敌人的碰撞区域
  18. CCRect getCollisionArea();
  19. //伤害
  20. void hurt(int hurtnum);
  21. private:
  22. int m_hp;
  23. float m_speed;
  24. CCSprite *m_showSprite;
  25. bool initEnemy(EnemyType type, float m_speed);
  26. void move();
  27. void remove();
  28. };
  29. #endif /* defined(__Plane__Enemy__) */
隐藏

本案例中,Enemy.cpp文件中的完整代码如下所示:

    
    
    
    
  1. #include "Enemy.h"
  2. #include "SpriteLayer.h"
  3. Enemy* Enemy::createEnemy(EnemyType type, float speed) {
  4. Enemy *enemy = new Enemy;
  5. if (enemy && enemy->initEnemy(type, speed)) {
  6. enemy->autorelease();
  7. return enemy;
  8. }
  9. CC_SAFE_DELETE(enemy);
  10. return NULL;
  11. }
  12. bool Enemy::initEnemy(EnemyType type, float speed) {
  13. if(!CCNode::init()) return false;
  14. const char* imageName;
  15. switch ((int)type) {
  16. case TYPE_1:
  17. imageName = "enem1.png";
  18. m_hp = 5;
  19. break;
  20. case TYPE_2:
  21. imageName = "enem2.png";
  22. m_hp = 10;
  23. break;
  24. case TYPE_3:
  25. imageName = "enem3.png";
  26. m_hp = 15;
  27. break;
  28. case TYPE_4:
  29. imageName = "enem4.png";
  30. m_hp = 20;
  31. break;
  32. }
  33. m_showSprite = CCSprite::create(imageName);
  34. this->addChild(m_showSprite);
  35. m_speed = speed;
  36. this->schedule(schedule_selector(Enemy::move));
  37. return true;
  38. }
  39. void Enemy::move() {
  40. this->setPositionY(this->getPositionY() - m_speed);
  41. if (this->getPositionY() <= - m_showSprite->getContentSize().height * 0.5) {
  42. this->remove();
  43. }
  44. }
  45. CCSize Enemy::getShowContentSize() {
  46. return m_showSprite->getContentSize();
  47. }
  48. //获取敌人的碰撞区域
  49. CCRect Enemy::getCollisionArea() {
  50. CCRect rect = m_showSprite->boundingBox();
  51. //飞机节点坐标系下 矩形原点位置
  52. CCPoint origin_sprite = rect.origin;
  53. //屏幕坐标系下的原点位置(由于精灵层没有改变过位置,所以现在精灵层的坐标系和屏幕坐标系是吻合)
  54. CCPoint origin = this->convertToWorldSpace(origin_sprite);
  55. return CCRectMake(origin.x, origin.y, rect.size.width, rect.size.height);
  56. }
  57. //伤害
  58. void Enemy::hurt(int hurtnum) {
  59. m_hp -= hurtnum;
  60. if (m_hp <= 0) {
  61. CCParticleSystemQuad *particle = CCParticleSystemQuad::create("particle_boom.plist");
  62. SpriteLayer *layer = (SpriteLayer*)this->getParent();
  63. layer->addChild(particle);
  64. particle->setPosition(this->getPosition());
  65. //粒子生命结束后自动释放
  66. particle->setAutoRemoveOnFinish(true);
  67. this->remove();
  68. }else {
  69. m_showSprite->stopActionByTag(100);
  70. CCBlink *blink = CCBlink::create(0.8, 3);
  71. blink->setTag(100);
  72. m_showSprite->runAction(blink);
  73. }
  74. }
  75. void Enemy::remove() {
  76. SpriteLayer *layer = (SpriteLayer*)this->getParent();
  77. layer->getEnemys()->removeObject(this);
  78. this->removeFromParent();
  79. }
隐藏

本案例中,Star.h文件中的完整代码如下所示:

    
    
    
    
  1. #ifndef __Plane__Star__
  2. #define __Plane__Star__
  3. #include<stdio.h>
  4. #include "cocos2d.h"
  5. USING_NS_CC;
  6. class Star : public CCNode {
  7. public:
  8. CREATE_FUNC(Star);
  9. CCSize getShouContentSize();
  10. //获取星星的碰撞区域
  11. CCRect getCollisionArea();
  12. //将要移除的方法 (做动画)
  13. void willRemove();
  14. //是否将要移除
  15. CC_SYNTHESIZE(bool, m_isWillRemove, IsWillRemove);
  16. private:
  17. CCSprite *m_showSprite;
  18. float m_speed;
  19. bool init();
  20. void move();
  21. void remove();
  22. };
  23. #endif /* defined(__Plane__Star__) */
隐藏

本案例中,Star.cpp文件中的完整代码如下所示:

    
    
    
    
  1. #include "Star.h"
  2. #include "SpriteLayer.h"
  3. bool Star::init() {
  4. if (!CCNode::init()) return false;
  5. m_speed = 10;
  6. m_isWillRemove = false;
  7. m_showSprite = CCSprite::create("star.png");
  8. this->addChild(m_showSprite);
  9. this->schedule(schedule_selector(Star::move));
  10. return true;
  11. }
  12. void Star::move() {
  13. this->setPositionY(this->getPositionY() - m_speed);
  14. if (this->getPositionY() <= -m_showSprite->getContentSize().height * 0.5) {
  15. this->remove();
  16. }
  17. }
  18. CCSize Star::getShouContentSize() {
  19. return m_showSprite->getContentSize();
  20. }
  21. //将要移除的方法 (做动画)
  22. void Star::willRemove() {
  23. m_isWillRemove = true;
  24. //停止星星的移动
  25. this->unschedule(schedule_selector(Star::move));
  26. CCAnimation *animation = CCAnimation::create();
  27. //
  28. for (int i = 0; i < 4; i++) {
  29. CCSpriteFrame *frame = CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(CCString::createWithFormat("eat_item%d.png", i)->getCString());
  30. animation->addSpriteFrame(frame);
  31. }
  32. animation->setDelayPerUnit(0.05);
  33. CCAnimate *animate = CCAnimate::create(animation);
  34. CCCallFunc *callFunc =CCCallFunc::create(this, callfunc_selector(Star::remove));
  35. CCSequence *seq = CCSequence::create(animate, callFunc,NULL);
  36. m_showSprite->runAction(seq);
  37. }
  38. //移除
  39. void Star::remove(){
  40. SpriteLayer *layer = (SpriteLayer*)this->getParent();
  41. layer->getStars()->removeObject(this);
  42. this->removeFromParent();
  43. }
  44. //获取星星的碰撞区域
  45. CCRect Star::getCollisionArea() {
  46. CCRect rect = m_showSprite->boundingBox();
  47. //星星节点坐标系下 矩形原点位置
  48. CCPoint origin_sprite = rect.origin;
  49. //屏幕坐标系下的原点位置(由于精灵层没有改变过位置,所以现在精灵层的坐标系和屏幕坐标系是吻合)
  50. CCPoint origin = this->convertToWorldSpace(origin_sprite);
  51. return CCRectMake(origin.x, origin.y, rect.size.width, rect.size.height);
  52. }

你可能感兴趣的:(cocos2d-x)