cocos2d-x案例开发大全 几何跳跃源码解析及交叉编译再现

来源:互联网 发布:苹果随机抽奖软件 编辑:程序博客网 时间:2024/06/08 06:37

注:前面部分对于各个类的介绍主要来自原书,此次总结主要是对于游戏总体的运行逻辑以及cocos2d常用知识在该游戏中的一些应用的总结,

对于后面游戏的逻辑并没有涉及到!


一、总体介绍各个类
1.布景相关的类

1.1 场景管理类 GameSceneManager

该类的主要作用是管理各个场景。在整个游戏中其实它会先调用createScene()方法创建第一个场景,并实现从当前场景跳转到其它场景,从而贯穿整个游戏。

1.2 设置音乐和音效布景类 MusicLayer

该类的作用很明显了,就是对游戏中使用的音乐和音效的设置。

1.3 选择游戏关卡布景类 LeverLayer

该类的主要作用是对游戏关卡进行选择,在进入游戏场景时会通过保存好的所选的关卡索引进入相应关卡的游戏界面。

1.4 游戏关卡一布景类 GameLayer

该场景就是根据所选关卡(方块跳跃和综合跳跃)进入相应游戏的场景,也就是真正玩游戏的场景。

1.5 游戏关卡二布景类 FlyLaer

该场景就是根据所选关卡(飞行跳跃)进入相应游戏的场景,也就是真正玩游戏的场景。



2.管理相关的类

2.1 常量相关的类 Constant

声明一些静态的常量,其他的类通过引入该常量文件来访问游戏的常量,方便数据的管理和修改。

2.2 音乐管理类 MusicManager

将所有关于音乐和音效的代码都集中在此类中,方便对音乐方面的管理和调用,大大加强了开发效率。

2.3 粒子系统管理类 ParticleSystemHelp

将所有关于粒子系统的代码都集中在此类中,方便对粒子系统的管理和调用,大大加强了开发效率。

2.4 精灵管理类 SpriteManager

主要负责精灵的创建和一些关于精灵的功能方法。

3.辅助相关的类

3.1 暂停类 PauseCode

3.2 欢迎布景的辅助类 MenuLayerHelp

主要功能是初始化MenuLayer类所需的精灵以及实现单击精灵执行相应的功能方法。

3.3 选择方块布景的辅助类 ChoiceCubeLayer

主要功能是初始化ChoiceCubeLayer类所需的精灵以及实现单击精灵执行相应功能方法。

3.4 设置音乐和音效的辅助类 MusicLayerHelp

主要功能是初始化MusicLayer类所需的精灵以及实现单击精灵执行相应功能方法。

3.5 选择关卡布景的辅助类 LevelLayerHelp

主要功能是初始化LevelLayer类所需的精灵以及实现单击精灵执行相应功能方法。



4.物体相关的类

4.1 跳跃方块类 JumpCube

主要功能是对跳跃方块进行封装。

4.2 飞行器类 FlyObject

主要功能是对飞行器进行封装。

4.3 障碍物类 Barrier

主要功能是对障碍物进行封装,其中有两个自定义的子类,分别是TriangleBarrier类和RectBarrier类。


整个游戏源码解析:


注:因为知识面有限,有些地方笔者可能也不清楚代码的具体作用和实现原理,可能会避开不讲,怕误导。


AppDelegate::applicationDidFinishLaunching(),该方法是程序准备完成,游戏启动的入口函数。


1.先获取导演类的单例,然后通过导演类的单例获取GLViewImpl对象,如果不存在(glview为空),就重新(create())创建一个。


2.setOpenGLView(pEGLView)之后,调用setDesignResolutionSize()函数,进行自动适配屏幕分辨率设置。


屏幕设置的相关函数:


3.0中有以下相关接口(参考自:http://blog.sina.com.cn/s/blog_923fdd9b0101g4i3.html):
Director::getInstance()->getOpenGLView()->setDesignResolutionSize() //设计分辨率大小及模式 


setDesignResolutionSize(DW, DH, resolutionPolicy) 有三个参数,设计分辨率宽,设计分辨率高,分辨率策略。


适配策略ResolutionPolicy,作为一个枚举类型,包括了如下方案:


enum class ResolutionPolicy
{
 
      EXACT_FIT,
 
    NO_BORDER,
 
    SHOW_ALL,
  
    FIXED_HEIGHT,
 
    FIXED_WIDTH,
 
    UNKNOWN,
};


其中的各个配置参数的配置含义如下:
EXACT_FIT:图片在选定的区域全部可见,图片显示可能会被压缩或者拉伸,不再保持原来的纵横比。


NO_BORDER:图片在特定的区域全部可见,不会扭曲,但可能会被剪裁,维持原来的纵横比。


SHOW_ALL:图片在特定的区域全部可见,不会扭曲,维持原来的纵横比,但可能显示边界。


FIXED_HEIGHT:固定高度,修改内部画布的宽度已适应设备的纵横比。不会扭曲。


FIXED_WIDTH:固定宽度,修改内部画布的高度已适应设备的纵横比。不会扭曲。




Director::getInstance()->setContentScaleFactor() //内容缩放因子 


决定了图片显示到屏幕的缩放因子,但是这个接口的参数不是通过资源图片的宽、高比屏幕宽、高得来。Cocos2d-x引擎设计试图屏蔽游戏开发者直接去关注屏幕,


所以这个因子是资源宽、高比设计分辨率宽、高。setContentScaleFactor()通常有两个方式来设置参数。RH/DH或RW/DW,不同的因子选择有不同的缩放负作用。


3.接下来看这两行代码:
GameSceneManager* gsm = new GameSceneManager();
        gsm->createScene(); //跌换到欢迎场景显示


new一个GameSceneManager类的对象,返回一个指针,将该指针赋值给gsm,然后调用createScene()方法创建第一个场景,从这里开始,其实整个游戏就已经被带动起来了。


3.1 void GameSceneManager::createScene()


1)调用MusicManager::loadMusic()(静态方法)加载背景音乐。


2)Scene* gameScene = Scene::create();//创建一个场景对象(返回一个 autorelease 的场景对象。)


3)MenuLayer* layer =  MenuLayer::create();//创建一个欢迎布景对象


这里说下MenuLayer::create方法以及init方法的调用和关系。

定位MenuLayer::create() 方法,指向 CREATE_FUNC(MenuLayer),再跟踪进去看,此宏定义了一个静态函数create():


#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \




{ \
    __TYPE__ *pRet = new(std::nothrow) __TYPE__(); \
   


if (pRet && pRet->init()) \
 
  
{ \
        
pRet->autorelease(); \


        
return pRet; \
    

} \
    


else \
 
   
{ \
   
     
delete pRet; \
        


pRet = nullptr; \
        


return nullptr; \
   
} \


       
}


将__TYPE__替换成MenuLayer,该方法先new一个MenuLayer对象,如果对象创建成功,调用init()(在这里对该方法对父类的init进行了重写)方法,调用成功后调用autorelease()对对象进行托管。


4)前面说过在MenuLayer::create()中会调用init()方法,看下重写的init方法做了哪些事。


首先调用了父类的初始化方法——设置节点标签,方便布景之间的查找——new一个SpriteManager对象,我们来看看SpriteManager类的构造函数:


1)SpriteManager(Layer* layerIn),有参构造函数,MenuLayer对象在init中创建SpriteManager对象时将自己(this)作为形参传给了SpriteManager的构造函数


2)调用SpriteBatchNode::create加载一张大图,接下来重要的一步是设置触摸事件。下面介绍下触摸事件的知识:


先看下事件处理机制:事件处理机制一般都有三个重要的角色:事件、事件源和事件处理者。事件源是事件发生的场所,通常就是各个试图或控件;事件处理者是接收事件并进行处理的一段程序。

触摸事件有两个事件监听器:EventListenerTouchOneByOne 表示的是单点触摸;而EventListenerTouchAllAtOnce 表示的就是多点触摸。


EventListenerTouchOneByOne中触摸事件响应属性:


(1)std::function<bool(Touch*, Event*)> onTouchBegan;


当一个手指触摸屏幕时回调该属性所指定的函数。如果函数返回值为true,则可以回调后面的两个属性(onTouchMoved和onTouchEnded)所指定的函数,否则不回调。


(2)std::function<bool(Touch*, Event*)> onTouchMoved;


当一个手指在屏幕移动时回调该属性所指定的函数。

(3)std::function<bool(Touch*, Event*)> onTouchEnded;


当一个手指离开屏幕时回调该属性所指定的函数。


(4)std::function<bool(Touch*, Event*)> onTouchCancelled;


当单点触摸事件被取消时回调该属性所指定的函数。


EventListenerTouchAllAtOnce中触摸事件响应属性:


(1)std::function<void(const std::vector<Touch*>&, Event*)> onTouchesBegan;


(2)std::function<void(const std::vector<Touch*>&, Event*)> onTouchesMoved;

(3)std::function<void(const std::vector<Touch*>&, Event*)>> onTouchesEnded;


(4)std::function<void(const std::vector<Touch*>&, Event*)>> onTouchesCancelled;


通过该游戏的例子源码来分析单点触摸事件:


首先使用EventListenerTouchOneByOne::create()创建单独触摸事件监听对象listenerTouch,设置是否下传触摸(setSwallowTouches(true) true不向下触摸,简单点来说,比如有两个sprite ,A和 B,A在上B在下(位置重叠),


触摸A的时候,B不会受到影响,反之false,向下传递触摸,触摸A也等于触摸了B),然后分别设置它的listenerTouch->onTouchBegan、listenerTouch->onTouchMoved、listenerTouch->onTouchEnded


、listenerTouch->onTouchCancelled属性,其中CC_CALLBACK_2宏定义绑定了回调函数。看看回调函数里做了哪些事:


        1)myOnTouchBegan(Touch *touch, Event *event):获取事件所绑定的触摸对象并将其转化为精灵类型——获取当前坐标(getLocationInView()是获得UI坐标,getLocation()获得的是OpenGL坐标)


接下来就应该是创建触摸对象并将触摸对象添加到监听器中去。这里游戏的作者并没有先创建触摸对象,而是把触摸对象添加到监听器这一动作封装成


独立的方法SpriteManager::AddEventListenerSprite(Sprite* sp)。接下来,我看看都有哪些触摸对象。



SpriteManager类的构造函数执行结束之后init()方法接着new一个MenuLayerHelp对象,继续执行MenuLayerHelp类的构造函数:此构造函数只初始化了Layer和SpriteManager的属性,初始值分别是MenuLayer本身和MenuLayer的SpriteManager属性。


SpriteManager类的构造函数执行完之后,调用mlh->initCreateSprite()方法,进入游戏看到的所有触摸对象均在这里被创建,创建方法是利用MenuLayerHelp类中自定义的initCreateSprite()方法创建的,创建后分别设置成触摸监听对象。



5)MenuLayer::create()中调用init()方法结束后,游戏会根据相应的触摸事件调用相应的代码,下面来详细看看每个触摸事件所调用的代码:


先复习下指针数组和数组指针的概念:


指针数组:array of pointers,即用于存储指针的数组,也就是数组元素都是指针


数组指针:a pointer to an array,即指向数组的指针


还要注意的是他们用法的区别,下面举例说明。


int* a[4]     指针数组     


                  表示:数组a中的元素都为int型指针    


                  元素表示:*a[i]   *(a[i])是一样的,因为[]优先级高于*


int (*a)[4]   数组指针     


                  表示:指向数组a的指针


                  元素表示:(*a)[i]  


(1)刚进入欢迎界面看到的布景的标签是INDEX_MENULAYER(this->setTag(INDEX_MENULAYER)),所以首次触摸时会执行:(MenuLayer*)(layer))->mlh->JudgeSp(sp)


。。。接下来就是根据触摸对象跳转到相应的场景了


顺序动作(Sequnce)可以顺序得一个接着一个运行内部动作序列。


RemoveSelf动作用来删除执行动作的节点。


(2)当布景的标签是INDEX_LEVELLAYER,执行:(LevelLayer*)(layer))->llh->JudgeSp(sp)


。。。往后都是根据对应的标签转到对应的游戏场景,对于后面的游戏场景及场景中实现的逻辑在这就不做解释了。

0 0
原创粉丝点击