cocos2dx - 制作纵版射击游戏:喵星战争 (二)

注:本教程主要来自《Cocos2D-x权威指南》满硕泉著 机械工业出版社,如需要更详细的内容,请支持并购买正版实体书籍

2013/10/28 更新

在上一个教程里,我们完成了搭建游戏的基本场景GameMain,接下来我们可以开始在这个场景里添砖加瓦了,本节里会讲解怎么添加一个打飞机游戏的主角,以及一些主角的基本功能实现。

主角小猫的定义以及实现

首先创建一个类文件GameObjHero.h/GameObjHero.cpp,在GameObjHero.h里面,如下初始化定义我们的主角类

 1 #include "cocos2d.h"
 2 
 3 using namespace cocos2d;
 4 
 5 class GameObjHero : public CCNode, public CCTargetedTouchDelegate
 6 {
 7 public:
 8     // memeory control
 9     GameObjHero(void);
10     virtual ~GameObjHero(void);
11     
12     // if we need to add a CCNode object into a scene
13     // need to redefine onEnter and onExit method to customize our object
14     virtual void onEnter();
15     virtual void onExit();
16 };
17 
18 GameObjHero Class
GameObjHero.h

因为我们的主角是一个需要画在屏幕上的对象,且可被玩家通过触摸而控制,所以主角类继承自CCNode和CCTargetedTouchDelegate类,前者为主角类提供生成对象的基础,后者为主角类提供处理触摸的方法。而在我们的初始定义里,为了提供一个较为清晰的思路,一开始并没有添加太多其他实现用途的参数或者函数,而是简单的加入了四个基本函数

GameObjHero(void);          //构造函数
virtual ~GameOjbHero(void); //析构函数
virtual void onEnter();     //重定义进入CCNode的对象函数
virtual void onExit();      //重定义离开CCNode的对象函数

这是我们这个主角类的根基,在实现好这四个函数的继承上我们再添加其他更多的主角类特征,接下来在GameObjHero.cpp里对这主角类进行初步实现

 1 #include "GameObjHero.h"
 2 
 3 GameObjHero::GameObjHero()
 4 {}
 5 
 6 GameObjHero::~GameObjHero()
 7 {}
 8 
 9 void GameObjHero::onEnter()
10 {
11     CCNode::onEnter();
12     
13     this -> setContentSize(CCSizeMake(85, 90)); // 85, 90 is the size of catBody1.png
14     CCDirector * pDirector = CCDirector::sharedDirector();
15 
16     // mainbody animation           
17     CCSprite * mainsprite = CCSprite::create("catBody1.png");
18     CCAnimation * ani = CCAnimation::create();
19     ani -> addSpriteFrameWithFileName("catBody1.png");
20     ani -> addSpriteFrameWithFileName("catBody2-4.png");
21     ani -> addSpriteFrameWithFileName("catBody3.png");
22     ani -> addSpriteFrameWithFileName("catBody2-4.png");
23     ani -> setDelayPerUnit(0.1f);
24     ani -> setRestoreOriginalFrame(true);
25     mainsprite -> runAction(CCRepeatForever::create(CCAnimate::create(ani)));
26     addChild(mainsprite);
27     
28     // tail animation
29     CCSprite * tail = CCSprite::create("catTail.png");
30     tail -> setAnchorPoint(ccp(0.5, 1));
31     tail -> setPosition(ccp(-5, -29)); // this position is inside a 85 x 90 content
32     tail -> setScale(0.5);
33     tail -> setRotation(20);
34     tail -> runAction(CCRepeatForever::create((CCActionInterval *) CCSequence::create(CCRotateBy::create(0.5, -40), CCRotateBy::create(0.5, 40), NULL)));
35     addChild(tail);
36 }
37 
38 void GameObjHero::onExit()
39 {
40     CCNode::onExit();
41 }
GameObjHero.cpp

 在onEnter()函数里,主要实现了主角小猫的三个部分

1. 对象大小,主角是一个宽85,高90的对象

2. 主角主体,以catBody1.png为初始帧循环播放动作的CCSprite对象

3. 主角尾巴,以catTail.png为贴图,(0.5,1)为旋转点循环旋转20°动作的CCSprite对象

在完成了这些基础后,我们就可以尝试将我们的主角小猫放到主场景里面看看效果了。

在GameScene.h中加入GameObjHero.h头文件,并添加一个private参数hero

#include "GameObjHero.h"

// in class GameMain: public CCLayer, add below
   private:
       GameObjHero * hero;

在GameScene.cpp的bool GameMain::init()函数里加入生成hero对象的部分

// build the hero
    hero = new GameObjHero();
    hero -> setPosition(ccp(size.width/2, -50));
    hero -> setScale(0.5);
    addChild(hero, 2, 1); // hero's zOrder is 2, tag is 1
    hero -> runAction(CCMoveBy::create(0.5, ccp(0, 150)));

运行程序,这个时候我们就能看到我们的小猫出现在游戏场景上了

PS:这里有一个要注意的地方,传统飞机游戏都是用竖屏玩的,但是这个时候我们运行游戏还是显示的横屏,要更改这个很简单,在项目的ios目录下找到RootViewController.mm, 将里面的supportedInterfaceOrientations返回参数改为UIInterfaceOrientationMaskPortrait就可以了,具体如下

// For ios6, use supportedInterfaceOrientations & shouldAutorotate instead
- (NSUInteger) supportedInterfaceOrientations{
#ifdef __IPHONE_6_0
    //return UIInterfaceOrientationMaskLandscape;
    return UIInterfaceOrientationMaskPortrait;
#endif
} 

作为一个飞机游戏的主角,当然要能受到玩家的控制,这里采取了传统的触摸控制来实现这一个功能。

首先加入一个bool变量来判断主角是否被玩家的触摸控制和一个CCPoint变量获得触摸的偏移位置,在GameObjHero类中加入一下public变量

public:
     CCPoint offset;
     bool isControl; 

然后加入一个获取触摸位置的函数和重写五个和触摸相关的函数,同样也是作为public函数使用

// redefine touch method
    bool containsTouchLocation(CCTouch * touch); // 获得触摸的位置,判断是否在控制范围内并返回判断结果
    virtual bool ccTouchBegan(CCTouch * touch, CCEvent * event); // 处理触摸开始时效果的函数
    virtual void ccTouchMoved(CCTouch * touch, CCEvent * event); // 处理触摸移动时效果的函数
    virtual void ccTouchEnded(CCTouch * touch, CCEvent * event); // 处理触摸结束时效果的函数

// Memory control with touchDelegate virtual void touchDelegateRetain(); // 获得触摸delegate virtual void touchDelegateRelease();// 释放触摸delegate

接下来我们看这些函数的具体实现,在GameObjHero.cpp中加入以下函数实现

 1 bool GameObjHero::containsTouchLocation(CCTouch * touch)
 2 {
 3     CCSize size = getContentSize();
 4     CCPoint pos = getPosition();
 5     CCRect pRect = CCRectMake(pos.x - size.width/2, pos.y - size.height/2, size.width, size.height);
 6     
 7     CCPoint location = touch -> getLocationInView();
 8     location = CCDirector::sharedDirector() -> convertToGL(location);
 9     return pRect.containsPoint(location);
10 }
bool containsTouchLocation(CCTouch * touch)

构造一个当前的有效区域,获得触摸位置后,用containsPoint函数判断触摸位置是否在当前的有效区域内。

 1 bool GameObjHero::ccTouchBegan(CCTouch * touch, CCEvent * event)
 2 {
 3     if (!containsTouchLocation(touch)) {
 4         return false;
 5     }
 6     else
 7     {
 8         isControl = true;
 9         CCPoint touchPoint = touch -> getLocationInView();
10         touchPoint = CCDirector::sharedDirector() -> convertToGL(touchPoint);
11         offset.x = touchPoint.x - this -> getPosition().x;
12         offset.y = touchPoint.y - this -> getPosition().y;
13     }
14     return true;
15 }
bool ccTouchBegan(CCTouch * touch, CCEvent * event)

判断触摸点是否在有效区域内,若无效,返回false,否则将isControl赋值为true并获得触摸的偏移位置。

 1 void GameObjHero::ccTouchMoved(CCTouch * touch, CCEvent * event)
 2 {
 3     if (isControl) {
 4         CCPoint touchPoint = touch -> getLocationInView();
 5         touchPoint = CCDirector::sharedDirector() -> convertToGL(touchPoint);
 6         float x = touchPoint.x - offset.x;
 7         float y = touchPoint.y - offset.y;
 8         
 9         this -> setPosition(x, y);
10     }
11 }
void ccTouchMoved(CCTouch * touch, CCEvent * event)

判断isControl是否为true,若为true,则通过偏移变量计算出主角的最新位置并进行设置

1 void GameObjHero::ccTouchEnded(CCTouch * touch, CCEvent * event)
2 {
3     if (isControl) {
4         isControl = false;
5     }
6 }
void ccTouchEnded(CCTouch * touch, CCEvent * event)

判断isControl是否为true,若为true,则将isControl重新赋值为false.

void GameObjHero::touchDelegateRetain()
{
    this -> retain();
}

void GameObjHero::touchDelegateRelease()
{
    this -> release();
}

重写获得与释放触摸delegate函数。

最后记得在onEnter函数中激活触摸功能以及加入两个变量的初始化, 在onExit函数中加入去除触摸delegate

void GameObjHero::onEnter()
{
    // enable touch
    pDirector -> getTouchDispatcher() -> addTargetedDelegate(this, 0, true);
    ......
    // init touch related variable
    offset = ccp(0, 0);
    isControl = false;
    ......
}

void GameObjHero::onExit()
{
    CCDirector * pDirector = CCDirector::sharedDirector();
    pDirector -> getTouchDispatcher() -> removeDelegate(this);
    CCNode::onExit();
}

编译并运行游戏,现在我们可以通过触摸来控制我们的小猫主角了!!

(小猫的实现到这里基本完成了,接下来我要介绍怎么加入飞机游戏里的敌人 - 狗博士,请继续关注)

  

 

 

 

 

posted @ 2013-10-16 20:33  fuutou  阅读(717)  评论(0编辑  收藏  举报