cocos2D 程序代码分析 3
来源:互联网 发布:儿童英语网络课程好吗 编辑:程序博客网 时间:2024/06/06 11:41
在第一讲中已经新建了第一个cocos2d程序,运行效果如下:
在这讲中我们来分析下里面的代码,了解cocos2d的工作原理,看看屏幕上的这个"Hello World"是如何显示出来的。
这是HelloWorld项目的代码结构:
下面,我们开始分析项目中的这些源文件:
从程序的入口点开始
这么多源文件在这里,究竟先看哪个呢?有些人可能会先挑内容少的来看,觉得这样就可以轻松解决掉一个源文件了,其实这是不对的,这样看起来更加是一头雾水,根本搞不清楚每个源文件之间的联系。正确的做法应该是从程序的入口开始看起,慢慢理顺各个源文件之间的关系。
有过iOS开发经验的朋友都知道,一个iOS程序的入口是main函数,这个main函数存在于main.m中。打开main.m文件,看看main函数的内容:
重点是这句代码:UIApplicationMain(argc, argv, nil, @"AppDelegate"),UIApplicationMain函数会根据第4个参数传入的类名创建一个应用程序的代理对象,这里创建的是AppDelegate对象,因此AppDelegate对象就是整个应用程序的代理。
那应用程序的代理有什么作用呢?
UIApplicationMain函数创建好应用程序的代理之后,会开启事件循环,一旦监听到系统事件,就会通知代理对象,并调用代理对象相关的生命周期方法来处理事件。比如:
* ios设备的内存极其优先,如果一个应用程序占用了太多内存,操作系统会发出内存警告,在应用程序接收到这个事件后它会调用代理的applicationDidReceiveMemoryWarning方法,代理在这个方法内可以进行释放内存的操作以防止操作系统强制终止应用程序的运行
* 当应用程序成功加载完毕后,会调用代理的application:didFinishLaunchingWithOptions:方法,一般会在这个方法里面初始化应用程序的第一个界面
AppDelegate解读
从上面的分析可知,一般会在AppDelegate的application:didFinishLaunchingWithOptions:方法中初始化应用程序的第一个界面,是的,开发者会在该方法中添加cocos2d的所有初始化代码
打开AppDelegate.m,查看application:didFinishLaunchingWithOptions:方法
提示:我在这个方法里面加了相应的中文注释
看完这个方法后,你可能会一头雾水,看到一大堆没见过的API,这些就是cocos2d的API。
1.UIKit与OpenGL
这么多看不懂的代码,该怎么解读呢?有些人可能会硬着头皮一行一行按顺序往下解读,这样往往是事倍功半。
一般是先找自己能够看懂的代码,比如这几句:
可以看出,屏幕上显示的内容就是这个glView视图,这个glView是EAGLView类型的:cocos2d利用OpenGL将内容都渲染到了这个glView上,最后呈现到屏幕上给用户看。因此,cocos2d的本质是在UIKit和OpenGL之间进行了转换。2.CCDirector
cocos2d中以节点(CCNode)为基本元素,整个游戏都是由节点构成的,其实一个很重要的节点元素就是场景(CCScene类,继承自CCNode),一个游戏里面可能有很多个场景,比如闯关游戏,可以一个关卡就是一个场景,一个游戏设置界面也可以是一个场景。怎样才能正常显示一个场景呢?那么就需要CCDirector这个类,没有CCDirector,就不能显示场景。
CCDirector类是整个cocos2d游戏引擎的核心,全局只有一个实例,通过[CCDirector sharedDirector]可以获取这个单例对象。
CCDirector的主要用途:
* 运行、替换、推入和弹出场景(即场景过渡)
* 访问正在运行的场景
* 暂停、恢复、终止游戏
* 在UIKit和OpengGL之间转换坐标
* 获取窗口的尺寸
下面这句代码非常关键:
给CCDirector设置视图后,CCDirector才知道场景(CCScene)上的内容要渲染到哪个视图上面。因此,说CCDirector是UIKit和OpenGL之间的桥梁,一点也不为过
cocos2d提供了4种类型的CCDirector,不同类型的CCDirector有不同的更新游戏状态的方式,这些更新方式会对游戏的性能、与UIKit视图的兼容性产生很大影响。
下面这句代码就是设置CCDirector的类型:
可以供设置的4种CCDirector:kCCDirectorTypeNSTimer \ kCCDirectorTypeDefault最慢kCCDirectorTypeMainLoop比NSTimer快,但是与UIKit视图存在兼容性问题kCCDirectorTypeThreadMainLoop比NSTimer快,但是与UIKit视图存在兼容性问题kCCDirectorTypeDisplayLink最快,最实用,但iOS版本至少是3.13.设置屏幕方向
通过CCDirector来设置屏幕方向
下面列出设备支持的所有方向:
kCCDeviceOrientationPortraitkCCDeviceOrientationPortraitUpsideDownkCCDeviceOrientationLandscapeLeftkCCDeviceOrientationLandscapeRight
4.设置游戏帧率
大家都知道,游戏界面上的内容是需要经常刷新的,比如一个子弹打出去,需要经常刷新子弹的位置。刷新速度就取决于游戏帧率。
注意:由于设备的限制,在iOS设备上的帧率不能大于60fps。如果强迫cocos2d以大于60fps的帧率进行渲染,很有可能会反而使帧率降低。因此,要想达到最快的渲染速度,使用60fps的帧率即可。
5.显示游戏帧率
设置了显示帧率后,屏幕左下角显示的数字就是游戏的帧率,当前是59.9fps。cocos2d会隔一段时间就更新这个数值,通过修改ccConfig.h的CC_DIRECTOR_FPS_INTERVAL值可以调整刷新数值的时间间隔,默认是0.1,即1秒钟更新10次。ccConfig.h在项目的libs/cocos2d文件夹中。
6.设置游戏的第一个场景
这里调用CCDirector的runWithScene:方法来设置游戏的第一个场景,这个场景对象是通过[HelloWorldLayer scene]这个静态方法创建。因此,需要搞清楚屏幕上显示的"Hello World"是怎么弄出来的,还得查看HelloWorldLayer这个类
7.在发出内存警告时释放资源
HelloWorldLayer解读
打开HelloWorldLayer.h,可以发现HelloWorldLayer继承了CCLayer,意为图层
那之前看到的场景(CCScene)和图层(CCLayer)究竟有什么联系呢?
下面我先详细阐述场景(CCScene)和图层(CCLayer)之间的关系:
一个游戏里面可能有很多个场景,比如闯关游戏,可以一个关卡就是一个场景,一个游戏设置界面也可以是一个场景。一个场景里面又可以包含多个图层。
拿捕鱼达人来说,下面列出捕鱼达人中的4个场景:
场景1场景2
场景3场景4
可以看出,不同的业务逻辑就放在不同的场景中。但是,如果一个场景过于复杂,场景里面又可以分出多个图层(CCLayer)。
比如场景4中的捕鱼界面,根据图层的功能,大致可以分为3个图层:
1> 底部的Background Layer是背景层,用来显示背景图片
2> 中间的Game Layer是游戏层,用来显示游戏中的精灵(CCSprite,可以用来表示游戏中的人物、道具等),这里的鱼就是精灵
3> 顶部的UI DOM Menu是菜单层,用来显示一些菜单按钮、控制按钮
再查看HelloWorldLayer.m中scene方法的实现
CCScene和CCLayer都继承自CCNode,可以通过CCNode的+(id) node方法快速创建一个自动释放的对象。这里使用[CCScene node]创建了一个CCScene对象,使用[HelloWorldLayer node]创建了一个HelloWorldLayer对象。
最后通过[scene addChild: layer]将图层layer添加到场景scene中,可以看出layer是scene的一个子节点。实际上addChild:方法也是属于CCNode的,可以看出每个CCNode都有自己的子节点。
就这样,"Hello World"就显示到我们的屏幕上了
分析可得,我们这个游戏里面存在着3个节点:
CCScene里面有个CCLayer,CClayer里面有个CCLabelTTF
总结
说了这么多内容,最后做个大总结:
1.要想利用cocos2d在屏幕上显示点东西,就必须使用CCDirector运行一个场景(CCScene),比如
2.场景(CCScene)可以添加多个图层(CCLayer),每个图层又可以添加其他子节点,比如精灵(CCSprite)
3.cocos2d会利用OpenGL将场景(CCScene)中的所有内容渲染到UIKit视图上(这里用的是EAGLView),EAGLView被添加到UIWindow中,最终显示在屏幕上
4.大部分情况下,都是直接面向cocos2d进行开发,即直接用cocos2d的CCSprite、CCLayer、CCScene等类进行开发,不需要关心OpenGL与UIKit之间的转换
5.cocos2d的基本元素是节点(CCNode),屏幕上的任何东西都可以称之为节点,像我们常用的CCSprite、CCLayer、CCScene,都是CCNode的子类,因此,它们都是节点。一个节点又可以包含多个子节点
- cocos2D 程序代码分析 3
- cocos2d-x加入控制台程序代码
- Andorid Launcher程序代码分析
- Andorid Launcher程序代码分析
- Andorid Launcher程序代码分析
- Andorid Launcher程序代码分析
- 分析netcat程序代码
- Andorid Launcher程序代码分析
- C语言程序代码分析
- Andorid Launcher程序代码分析
- Andorid Launcher程序代码分析
- Andorid Launcher程序代码分析
- Andorid Launcher程序代码分析
- 分析netcat程序代码
- C程序代码分析
- 2.用户程序代码分析
- DrawTools绘图程序代码分析
- 汇编语言秒表程序代码分析(21)
- 【Android】退出多个Activity方法(四)
- js判断变量是否是数组(跨浏览器和ECMA)
- springboot+EHcache 实现文章浏览量的缓存和超时更新
- 微信硬件开发系列教程AA1
- C/C++疑问之为何一般采用循环队列而不是顺序队列
- cocos2D 程序代码分析 3
- jquery选中option的方法
- Tomcat 8080端口被占用(命令解决)
- git clone命令详解
- 搭建ZABBIX监控
- 自动建立swap分区脚本
- 使用cxf发布rest服务接口,和spring的整合
- maven上传私有jar包到本地私服仓库,私服使用nexus repository manager 3.3
- PAT1046