第一章 cocos基础介绍

来源:互联网 发布:关口知宏《结》 编辑:程序博客网 时间:2024/05/16 05:03

1.1 历史介绍

Ricardo2008年的时候发布cocos2d-iPhone的引擎。cocos2d-x是由王哲在2010年引进的,它的前身是cocos-ios,但是不兼容其他的平台。Cocos在国内游戏份额是70%,国外20%cocos向下兼容一直做得不好,即使两个版本发布的很近,也有很多的细节是不可以在低版本上运行的。

由于游戏的生命周期很短,开发周期也很短,对代码的要求不高,有更多写代码的机会,所以适合新手进入。游戏需要建立面向对象的概念,Cocos2d-x是基于C++写的,里面都是一堆的类库。

为何都是类库,有的称为库,有的称为框架,有的称为引擎?因为C语言库,只是使用库中的函数等等;但是qt框架,可以继承类库,在类的基础上增加一些特殊的功能;cocos2d-x游戏引擎是按照游戏设计的要求顺序的调用这些资源,比如定时器定时发送图片。cocos2dx封装了OpenGL的图形接口,本质是一个图形引擎。游戏要具有简单,耐玩和虐心等特点。

1.2 开发环境搭建

Windows平台下,直接将压缩包解压就好,解压之后将_MACOSX删除,需要安装pathon(默认安装就ok)才可以创建工程。创建工程需要从终端运行一个的脚本,路径是cocos2d-x-2.2.3\tools\project-creator\

然后create_project.py -project  -package  -language  。包名称对于Android来说有用,Android下面project没有用,创建之后生成一个项目,项目下面的classes目录存储的是和平台无关的代码。之后再vs里面打开这个项目,编译这个项目,第一次花费一段时间,编译之后就可以运行了。

1.3 helloWorld代码分析

生成的win32代码是用WindowsAPI写的,main函数封装为_tWinMainAppDelegate定义代理对象(应用程序app),CCEGLView 创建窗口,设置窗 口的属性,之后执行应用程序的runrun不是用app调用的,CCApplication::sharedApplication()->run()。貌似没有使用定义的代理对象,其实在定义代理对象的时候,调用基类CCApplication的构造函数,在基类中定义了一个静态指针变量(因为是单例),在构造函数中用这个成员变量保存this指针,然后调用成员函数sharedApplication返回那个变量,也就是this指针。在run中调用正在执行的那个对象的虚方法applicationDidFinishLaunching,其实游戏真正是从这里开始的。这里用到了代理AppDelegate,代理类是private的继承于AppAplication,这样代理不会知道太多的被代理的信息,而CCApplication继承于CCApplicationProtocolAppAplication中放入了很多跨平台的代码,AppDelegate实现CCApplicationProtocol中定义的虚接口。在cocos中经常会用到代理。

1.4 游戏架构

director->scene->layer->spritemenulable.

导演类CCDirector ,推动游戏的发展,切换场景,运行场景,一个导演同一时间只能运行一个场景。

场景CCScene抽象一个独立游戏逻辑,每一个关卡为一个场景,就像话剧用的画幕一样,也是渲染树的根节点。

CCLayer 将精灵分类,划分层次,舞台有多层画布。在2.x中,层还有一个很重要的功能,接收触摸消息,只有它可以接收触摸,但是3.0的话就有很多可以接收摸。

精灵CCSprite抽象了一个可见的游戏元素,一般是图片。

cocos的类构造和初始化是用create函数,没有在构造函数和析构函数中写代码。cocos中定义一个宏函数CREATE_FUNCclass),是为了简化代码,其实里面调用了initautorelease函数。将来写类的时候,需要包含cocos2d.h头文件,使用命名空间USING_NS_CC,添加init函数,在init中调用父类中的init,一般都是返回true。在类定义时候添加CREATE_FUNCcreate函数用到了工厂模式,只能用于不带参数的create。在layer中定义scene函数,在这个函数中创建一个场景,然后创建层,之后加入到场景中。Cocos创建对象一般不使用new,而是使用create方法。Cocos的二段初始化,init是业务相关的初始化,构造函数中语言层次的初始化(基本不使用)。

1.5 锚点

就像是船的锚,挂相片的点一样。cocos的原点坐标在左下角。精灵的锚点默认在中心,setAnchorPoint可以修改锚点。锚点影响放置位置,影响缩放(以锚点为基点,四周进行缩放),影响旋转(以中心为圆心旋转)。有一方法可以忽略锚点ignoreAnchorPointForPosition,忽略之后锚点在(0,0)点,层默认是忽略锚点的。不糊了锚点是中心点。锚点的坐标是使用比例。使用getPosition获取的点就是锚点。

背景是有范围的地方,精灵也是有范围的,锚点使用的是相对坐标,代表百分比。每种节点的锚点的默认位置是不一样的。精灵的锚点在中间,层的锚点在左下角,旋转的时候利用锚点来转,设在方便旋转的地方。CCLable锚点在中间,和文字的对齐有关,在左边文字左对齐。

1.6 精灵的创建-众生皆精灵

1.6.1 创建

(1)图片文件:直接使用create,创建的时候可以加参数CCRectMake(),截取图片的大小。

(2)纹理:在内存中的图片,相同图片占用一个内存,可以节约内存,但是在3.x中,通过图片创建精灵,也不会浪费内存。纹理创建需要CCTextureCache(单例),使用的是缓冲,这个时候会用到CCTexture2D,之后使用创建createWithTexture

(3)帧:提取图片中的一部分,类是CCSpriteFrame。可以通过纹理或者图片来创建帧。使用createWithSpriteFramecreateWithSpriteFrameName创建,CCSpriteFrameCache来加载图片。当导入精灵的图片路径错误的时候,会出现一个空白区域。TexturePackerGUI工具会生成plite文件

1.6.2 动作

定义一个CCMoveby对象,然后让精灵调用runAction方法就动起来了。类CCMoveto是绝对路径,CCMoveby是相对路径。还有CCJumpByCCFadeIn等等。

1.6.3 动画

每隔一段时间显示一副图片,使用类CCAnimation,使用之前需要定义一个CCArray,之后用路径/文件名构造一个CCSpriteFrame,然后添加到数组中。创建CCAnimation的时候不可以使用create,会造成内存访问出错,需要createWithSpriteFrame。之后通过CCAnimation构造一个CCAnimate,最后调用runAction就是一幅幅的画面了。为了看到效果增加一个CCRepeatForever,可以一直循环显示。

1.6.4 骨骼动画

精灵套着精灵,小精灵也在执行动作,类同人体的骨骼。

1.6.5批处理精灵

相同的精灵加载到一份到内存,就是一个精灵,节约内存,比如子弹的加载,因为如果加载过多的话,渲染很慢。CCSpriteBatchNode来创建批处理精灵,宏CCRANDOM_0_1产生随机数[0,1]之间。

1.6.6粒子效果

很多精灵按照某种轨迹运行。CCParticleFire火的粒子效果,CCParticalGalaxy银河效果,粒子有好多参数需要设置,也可以定义自己的粒子,调效果的时候很难,可以使用开源库来实现。可以使用粒子编辑器生成plite文件。CCParticleSyatemQuad来加载plite文件。

通常对于多个图片,一般是将多个图片放到一个图片中,需要提供一个.plist格式的文件来切割,否则需要自己来切割,plistXML文件,对应一个字典。这样的话,就需要将合图的帧加载到内存中,用到CCSpriteFrameCache,然后再把缓冲中的帧找出来放到数组中,构造CCSpriteFrame的时候,使用spriteFrameByName

缓冲:可以理解为道具,放到内存中。例如纹理缓冲(是单例,只加载一次)、帧缓冲(单例)。舞台、导演、CCApplication也都是单例。所以添加的主要就是精灵。 

1.7 游戏优化

FPS:frame pre second左下角显示状态,电影一秒24帧。当在场景中添加上万个sprite的时候,游戏运行很卡。Cocos基本的数据结构是渲染树,就是每一帧都会遍历这个树,底层使用OpenGL绘制场景,一般是用framebuf保存像素点,cocosOpenGL的基础上又封装了一层接口。CCNode 是所有Cocos类的基类,addChild就是向树中添加子节点。优化的原理是,同样的图片使用CCBatchNode渲染一次,然后将图片贴到那个node上,生成一个精灵。多张不同的图片,使用TexturePackage生成plist格式文件,然后使用CCSpriteFrameCache,然后将那副大图片渲染,之后使用就一样了。

1.8坐标体系

设置颜色CCLayerColorCCLayerGradient(颜色渐变)。坐标体系代表的是一个标准。OpenGL的坐标体系的原点是左下角,屏幕坐标体系原点是左上角。GetLocation获取的是世界坐标,GetLocationInView获取的是本地坐标,使用ConverToUIconvertToGL可以实现两者的转换。

世界坐标是绝对坐标;本地坐标是以父类为基点定义的坐标,加载的时候是本地坐标,窗口重合的时候两种坐标是一样的。convertToNodeSpace转换为本地坐标,转换世界坐标的时候需要使用父类convertToWorldSpace。使用本地坐标其实就是递归的过程,让游戏更好理解,写代码不用更多的考虑逻辑。

坐标系统,每一个节点都有自己的坐标体系,窗口的原点是左下角,layer默认和窗口是一样大的。坐标的转换,世界坐标体系和节点坐标体系。spriteboundingBox返回我们可以看到的外切矩形,然后观察是否点击在这个矩形中。转换的时候node->convertToNodeSpace将世界坐标转换为节点坐标,转换之前需要获取这个节点的父节点,然后才可以根据这个父节点进行节点的坐标转换。

1.9 CCNode类详解

CCNode是游戏中最重要的对象,在 cocos2dx ,任何可见的或不可见的游戏对象都是一个节点,节点有以下特点:是一个容器,可以包含任意多个其它节点;可以执行一个行为(CCAction);可以执行一定时的任务回调;拥有坐标变换(transform)信息,如 postion,scale,rotation 等;由于一个节点可以添加任意个子节点,所有的节点 组成一个树状结构,完成了渲染功能,一个节点只能拥有一个父节点。

CCNode的父节点是CCObjectcocos所有类的基类。CCObject和内存管理、回调函数有关。

CCNode有一系列的成员函数:setZOrder设置层次关系,setScale设置缩放,setSkewX设置扭曲,扭曲90度就看不见了,setContentSize设置内容的大小,内容不会因为扭曲,缩放而改变,boundingBox一旦形状发生内容就变化,setVisible设置是否可见,setRotation旋转,旋转90度就看不见了,180°什么也不发生,旋转和扭曲差不多;setOrderOfArrival一般系统来管理,setGLServerStatus设置GL的参数,addChild的时候可以设置一个tag,以后方便查找,setGrid设置格子效果,setShadeProgramOpenGL的范围;getCamera获取视角;isRuning查看是否运行起来;onEnter场景的初始化;onExit场景结束;transform变换;坐标的转换函数。

1.10 人机交互

触摸(CCTouch)开始时调用setTouchEnable打开触摸开关,然后设置setTouchMode(单点或者多点)。在类中需要添加虚函数ccTouchBegan,参数决定消息是否时候往下传递;ccTouchEnded触摸结束的时候调用;ccTouchMoved移动的时候调用,有帧循环累积效应,只要按下就一直调用,调用的频率是帧的间隔,使用CCLog打印信息,也可以实现拖动;ccTouchCanclled一般是电话打入的时候导致触摸终止。这几个函数的第二个参数是用在苹果上的。getLocation是获取坐标点,getDelta获取差值,就是触摸移动相邻点的差值。拖着飞机跑,在ccTouchMoved中处理,当点击的点位于飞机的boundingBox时候就重新设置坐标(当前坐标+getDelta),让飞机跑不出去,设置飞机的锚点在窗口的一定范围内。boundingBox是轮廓(缩放)的大小,contentSize表示真实大小,碰撞检测的时候使用boundingBox

触摸有优先级(默认是0,数字越小优先级越高),优先级相同的层触摸回调都会被回调,哪个先回调不清楚,一般是在上层的调用;如果有优先级高的层截获消息(并且优先级高的层ccTouchBegan返回true),优先级低的不会获得到消息。单点触控的多点触控,因为调用的是相同的move函数,getID来获取是哪一个点触控。多点触控:实现两只手的缩放功能,使用的函数也不一样,用CCSet集合来保存这些点。然后使用迭代器来访问,用的场景比较少。一个都不能死就是多点触控。

触摸使用了消息分发原理,触摸将消息压到一个栈中,然后将消息分给相应的进程,然后相应的进程来处理。同样也使用了代理。addTargetedDelegate的第三个参数用于是否吞噬消息,接收触摸的先后顺序是和渲染的顺序是不一样的。 

键盘处理:主要指Android的返回键和菜单键,keyBackClickedkeyMenuClicked

摇一摇:setAccelerometerEnable重力感应,调用didAccelerate

0 0
原创粉丝点击