公众号推荐
微信公众号搜"智元新知" 关注 微信扫一扫可直接关注哦!
三、第一个cocos2d程序的代码分析
转自MJ老师:http://blog.csdn.net/q199109106q/article/details/8591706
在第一讲 中已经新建了第一个 cocos2d程序,运行效果 如下:
在这 讲中我们来分析下里面的代码 ,了解cocos2d的工作原理,看看屏幕上的这个"Hello World"是如何显示 出来的。
这是HelloWorld项目的代码 结构:
下面,我们开始分析项目中的这些源文件 :
从程序的入口点开始
这么多源文件 在这里 ,究竟先看哪个呢?有些人可能会先挑内容 少的来看,觉得这样就可以轻松解决 掉一个 源文件 了,其实这是不对的,这样看起来更加是一头雾水,根本搞不清楚每个源文件 之间的 联系。正确的做法应该是从程序的入口开始看起,慢慢理顺各个源文件 之间的 关系。
有过iOS开发经验的朋友都知道,一个 iOS程序的入口是main函数 ,这个main函数 存在于main.m中。打开main.m文件 ,看看main函数 的内容 :
int main( int argc, char *argv[]){
NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];
intretVal=UIApplicationMain(argc,argv,nil,@ "AppDelegate" );
[poolrelease];
returnretVal;
}
重点是这句代码 :UIApplicationMain(argc,@"AppDelegate"),UIApplicationMain函数 会根据第4个参数传入的类名创建一个 应用程序的代理对象,这里创建的是AppDelegate对象,因此AppDelegate对象就是整个应用程序的代理。
那应用程序的代理有什么作用呢?
UIApplicationMain函数 创建好应用程序的代理之后,会开启事件循环,一旦监听到系统事件,就会通知 代理对象,并调用 代理对象相关的生命周期方法 来处理事件。比如:
* ios设备的内存极其优先,如果一个 应用程序占用了太多内存,操作系统会发出内存警告,在应用程序接收到这个事件后它会调用 代理的applicationDidReceiveMemoryWarning方法 ,代理在这 个方法 内可以进行释放内存的操作以防止操作系统强制终止应用程序的运行
* 当应用程序成功加载完毕后,会调用 代理的application:didFinishLaunchingWithOptions:方法 ,一般会在这 个方法 里面初始化应用程序的第一个 界面
AppDelegate解读
从上面的分析可知,一般会在AppDelegate的application:didFinishLaunchingWithOptions:方法 中初始化应用程序的第一个 界面,是的,开发者会在该方法 中添加 cocos2d的所有初始化代码
打开AppDelegate.m,查看application:didFinishLaunchingWithOptions:方法
提示 :我在这 个方法 里面加了相应的中文 注释
-( void )applicationDidFinishLaunching:(UIApplication*)application
{
window=[[UIWindowalloc]initWithFrame:[[UIScreenmainScreen]bounds]];
if(![CCDirectorsetDirectorType:kCCDirectorTypedis playLink])
[CCDirectorsetDirectorType:kCCDirectorTypeDefault];
//获取 CCDirector的单例对象
CCDirector*director=[CCDirectorsharedDirector];
//初始化控制器
viewController=[[RootViewControlleralloc]initWithNibName:nilbundle:nil];
viewController.wantsFullScreenLayout=YES;
//创建一个 视图对象
EAGLView*glView=[EAGLViewviewWithFrame:[windowbounds]
pixelFormat:kEAGLColorFormatRGB565
depthFormat:0 ];
//关联这个视图对象到CCDirector
[directorseto penGLView:glView];
//设置屏幕方向
#if GAME_AUTOROTATION==kGameAutorotationUIViewController
//如果是使用UIViewController来实现旋转,就设置竖屏
[directorsetDeviceOrientation:kCCDeviceOrientationPortrait];
#else
//其他情况,就设置横屏
[directorsetDeviceOrientation:kCCDeviceOrientationLandscapeLeft];
#endif
//设置刷新间隔时间
[directorsetAnimationInterval:1.0 / 60 ];
//设置是否要显示 FPS
[directorsetdis playFPS:YES];
//设置控制器的视图
[viewControllersetView:glView];
//添加 控制器的视图到window中
[windowaddSubview:viewController.view];
//显示 window
[windowmakeKeyAndVisible];
//设置纹理格式
[CCTexture2DsetDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
//消除启动时的闪烁
[selfremoveStartupFlicker];
//设置第一个 显示 的屏幕
[[CCDirectorsharedDirector]runWithScene:[HelloWorldLayerscene]];
}
看完这个方法 后,你可能会一头雾水,看到一大堆没见过的API,这些就是cocos2d的API。
1.UIKit与OpenGL
这么多看不懂的代码 ,该怎么解读呢?有些人可能会硬着头皮一行一行按顺序往下解读,这样往往是事倍功半。
一般是先找自己能够看懂的代码 ,比如这几句:
//设置控制器的视图
[viewControllersetView:glView];
//添加 控制器的视图到window中
[windowaddSubview:viewController.view];
//显示 window
[windowmakeKeyAndVisible];
可以看出,屏幕
上显示 的内容 就是这个glView视图,这个glView是EAGLView类
型的:
0];
cocos2d利用OpenGL将内容 都渲染到了这个glView上,最后呈现到屏幕上给用户 看。因此,cocos2d的本质是在UIKit和OpenGL之间进行了转换。
2.CCDirector
cocos2d中以节点(CCNode)为基本元素,整个游戏都是由节点构成的,其实一个 很重要的节点元素就是场景(CCScene类,继承自CCNode),一个 游戏里面可能有很多个场景,比如闯关游戏,可以一个 关卡就是一个 场景,一个 游戏设置界面也可以是一个 场景。怎样才能正常显示 一个 场景呢?那么就需要CCDirector这个类,没有CCDirector,就不能显示 场景。
CCDirector类是整个cocos2d游戏引擎的核心,全局只有一个 实例,通过[CCDirector sharedDirector]可以获取 这个单例对象。
//获取 CCDirector的单例对象
CCDirector*director=[CCDirectorsharedDirector];
CCDirector的主要用途:
* 运行、替换、推入和弹出场景(即场景过渡)
* 访问正在运行的场景
* 暂停、恢复、终止游戏
* 在UIKit和OpengGL之间转换坐标
* 获取 窗口的尺寸
下面这句代码 非常关键:
[directorseto penGLView:glView];
给CCDirector设置视图后,CCDirector才知道场景(CCScene)上的内容 要渲染到哪个视图上面。因此,说CCDirector是UIKit和OpenGL之间的 桥梁,一点也不为过
cocos2d提供了4种类型的CCDirector,不同类型的CCDirector有不同的更新游戏状态的方式,这些更新方式会对游戏的性能 、与UIKit视图的兼容性产生很大影响。
下面这句代码 就是设置CCDirector的类型:
//设置CCDirector的类型,如果iOS<3.1,就不支持 kCCDirectorTypedis playLink,使用kCCDirectorTypeDefault
if (![CCDirectorsetDirectorType:kCCDirectorTypedis playLink])
[CCDirectorsetDirectorType:kCCDirectorTypeDefault];
可以供设置的4种CCDirector:
kCCDirectorTypeNSTimer \ kCCDirectorTypeDefault
最慢
kCCDirectorTypeMainLoop
比NSTimer快,但是与UIKit视图存在兼容性问题
kCCDirectorTypeThreadMainLoop
比NSTimer快,但是与UIKit视图存在兼容性问题
kCCDirectorTypedis playLink
最快,最实用,但iOS版本至少是3.1
3.设置屏幕方向
通过CCDirector来设置屏幕方向
//设置屏幕方向
ifGAME_AUTOROTATION==kGameAutorotationUIViewController
//如果是使用UIViewController来实现旋转,就设置竖屏
[directorsetDeviceOrientation:kCCDeviceOrientationPortrait];
else
//其他情况,就设置横屏
[directorsetDeviceOrientation:kCCDeviceOrientationLandscapeLeft];
#endif
GAME_AUTOROTATION是一个 宏定义,可以用来判断设备对旋转的支持 情况,iOS第1和2代设备上面的旋转是十分耗性能 的,但从iOS第3代设备开始,可以使用UIViewController来轻松实现自动 旋转。
下面列出设备支持 的所有方向:
kCCDeviceOrientationPortrait
kCCDeviceOrientationPortraitUpsideDown
kCCDeviceOrientationLandscapeLeft
kCCDeviceOrientationLandscapeRight
4.设置游戏帧率
大家都知道,游戏界面上的内容 是需要经常刷新的,比如一个 子弹打出去,需要经常刷新子弹的位置。刷新速度就取决于游戏帧率。
[directorsetAnimationInterval: 60 ];
这里设置的1.0/60并不是指游戏帧率,是指刷帧的时间间隔,即屏幕连续2次刷新之间的 时间间隔:1.0/60秒。换算一下,可以得出游戏帧率为60fps(frame per seconds,帧/秒),即1秒钟刷新60帧。当然,如果游戏比较复杂,cpu /GPU需要画大于1.0/60秒的时间来刷新屏幕,就无法保证游戏始终保持60fps的刷新速度,会造成帧率不稳定。如果游戏的帧率发生大幅度波动,会造成时快时慢的效果 ,会严重降低玩家的用户 体验,因此,复杂游戏的帧率不用设置得太高,最好设置为30fps。
注意:由于设备的限制,在iOS设备上的帧率不能大于60fps。如果强迫cocos2d以大于60fps的帧率进行渲染,很有可能会反而使帧率降低。因此,要想达到最快的渲染速度,使用60fps的帧率即可。
5.显示 游戏帧率
[directorsetdis playFPS:YES];
设置了显示 帧率后,屏幕左下角显示 的数字就是游戏的帧率,当前是59.9fps。
cocos2d会隔一段时间就更新这个数值,通过修改 ccConfig .h的CC_DIRECTOR_FPS_INTERVAL值可以调整刷新数值的时间间隔,默 认是0.1,即1秒钟更新10次。ccConfig .h在项目的libs/cocos2d文件 夹中。
#ifndefCC_DIRECTOR_FPS_INTERVAL
#defineCC_DIRECTOR_FPS_INTERVAL(0 .1f)
#endif
6.设置游戏的第一个 场景
[[CCDirectorsharedDirector]runWithScene:[HelloWorldLayerscene]];
这里调用 CCDirector的runWithScene:方法 来设置游戏的第一个 场景,这个场景对象是通过[HelloWorldLayer scene]这个静态方法 创建。
因此,需要搞清楚屏幕上显示 的"Hello World"是怎么弄出来的,还得查看HelloWorldLayer这个类
7.在发出内存警告时释放资源
void)applicationDidReceiveMemoryWarning:(UIApplication*)application{
[[CCDirectorsharedDirector]purgeCachedData];
}
HelloWorldLayer解读
打开HelloWorldLayer.h,可以发现HelloWorldLayer继承了ccl ayer,意为图层
@interfaceHelloWorldLayer:ccl ayer
}
//returnsaCCScenethatcontainstheHelloWorldLayerastheonlychild
+(CCScene*)scene;
@end
那之前看到的场景(CCScene)和图层(ccl ayer)究竟有什么联系呢?
下面我先详细阐述场景(CCScene)和图层(ccl ayer)之间的 关系:
一个 游戏里面可能有很多个场景,比如闯关游戏,可以一个 关卡就是一个 场景,一个 游戏设置界面也可以是一个 场景。一个 场景里面又可以包含多个图层。
拿捕鱼达人来说,下面列出捕鱼达人中的4个场景:
可以看出,不同的业务逻辑就放在不同的场景中。但是,如果一个 场景过于复杂,场景里面又可以分出多个图层(ccl ayer)。
比如场景4中的捕鱼界面,根据图层的功能 ,大致可以分为3个图层:
1> 底部 的Background Layer是背景层,用来显示 背景图片
2> 中间的 Game Layer是游戏层,用来显示 游戏中的精灵(CCSprite,可以用来表示游戏中的人物、道具等),这里的鱼就是精灵
3> 顶部的UI DOM Menu是菜单 层,用来显示 一些菜单 按钮、控制按钮
再查看HelloWorldLayer.m中scene方法 的实现
+(CCScene*)scene
//创建一个 场景对象
CCScene*scene=[CCScenenode];
//创建一个 图层对象
HelloWorldLayer*layer=[HelloWorldLayernode];
//添加 图层到场景中
[sceneaddChild:layer];
//返回场景
returnscene;
}
CCScene和ccl ayer都继承自CCNode,可以通过CCNode的+(id) node方法 快速 创建一个 自动 释放的对象。
这里使用[CCScene node]创建了一个 CCScene对象,使用[HelloWorldLayer node]创建了一个 HelloWorldLayer对象。
最后通过[scene addChild: layer]将图层layer添加 到场景scene中,可以看出layer是scene的一个 子节点。实际上addChild:方法 也是属于CCNode的,可以看出每个CCNode都有自己的子节点。
那"Hello World"这段文字 是怎么显示 到屏幕上的呢?看看HelloWorldLayer的init方法
-(id)init
//alwayscall"super"init
//Applerecommendstore-assign"self"withthe"super"returnvalue
if((self=[ super init])){
//createandinitializeaLabel
ccl abelTTF*label=[ccl abelTTFlabelWithString:@"HelloWorld" fontName:@ "MarkerFelt" fontSize: 64 ];
//askdirectorthethewindowsize
CGSizesize=[[CCDirectorsharedDirector]winSize];
//positionthelabelonthecenterofthescreen
label.position=ccp(size.width/2 ,size.height/ 2 );
//addthelabelasachildtothisLayer
[selfaddChild:label];
}
returnself;
}
首先初始化了一个 ccl abelTTF标签 对象,标签 显示 的文字 为"Hello World",使用Marker Felt字体,字体大小为64,ccl abelTTF继承自CCSprite,属于精灵,CCSprite又继承自CCNode。
ccl abelTTF*label=[ccl abelTTFlabelWithString:@"HelloWorld" fontName:@ "MarkerFelt" fontSize: 64 ];
接着获取 屏幕的宽度和高度
CGSizesize=[[CCDirectorsharedDirector]winSize];
设置标签 在父节点中的位置(默 认情况下,精灵的中心点会在position属性 所指定的位置上)
label.position=ccp(size.width/ 2 );
cpp其实是个宏定
义
#defineccp(__X__,__Y__)CGPointMake(__X__,__Y__)
最后添加 标签 到图层中
[selfaddChild:label];
就这样,"Hello World"就显示 到我们的屏幕上 了
分析可得,我们这个游戏里面存在着3个节点:
CCScene里面有个ccl ayer,ccl ayer里面有个ccl abelTTF
总结
说了这么多内容 ,最后做个大总结:
1.要想利用cocos2d在屏幕上显示 点东西,就必须使用CCDirector运行一个 场景(CCScene),比如
[[CCDirectorsharedDirector]runWithScene:[HelloWorldLayerscene]];
2.场景(CCScene)可以添加 多个图层(ccl ayer),每个图层又可以添加 其他子节点,比如精灵(CCSprite)
3.cocos2d会利用OpenGL将场景(CCScene)中的所有内容 渲染到UIKit视图上(这里用的是EAGLView),EAGLView被添加 到UIWindow中,最终显示 在屏幕上
4.大部分情况下,都是直接面向cocos2d进行开发,即直接用cocos2d的CCSprite、ccl ayer、CCScene等类进行开发,不需要关心OpenGL与UIKit之间的 转换
5.cocos2d的基本元素是节点(CCNode),屏幕上的任何东西都可以称之为节点,像我们常用的CCSprite、ccl ayer、CCScene,都是CCNode的子类,因此,它们都是节点。一个 节点又可以包含多个子节点
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。
相关推荐
本文实践自 RayWenderlich、Ali Hafizji 的文章《How To Create Dynamic Textures with CCRenderTexture in Cocos2D 2.X》,文中使用Cocos2D,我在这里使用Cocos2D-x 2.1.4进行学习和移植。在这篇文章,将会学习到如何创建实时纹理、如何用Gimp创建无缝拼接纹
Cocos-code-ide使用入门学习地点:杭州滨江邮箱:appdevzw@163.com微信公众号:HopToad 欢迎转载,转载标注出处:http://blog.csdn.netotbaron/article/details/424343991. 软件准备 下载地址:http://cn.cocos2d-x.org/download 2. 简介2.1 引用C
第一次開始用手游引擎挺激动!!!进入正题。下载资源1:从Cocos2D-x官网上下载,进入网页http://www.cocos2d-x.org/download,点击Cocos2d-x以下的Download v3.0,保存到自定义的文件夹2:从python官网上下载。进入网页https://www.python.org/downloads/,我当前下载的是3.4.0(当前最新
Cocos2d-x是一款强大的基于OpenGLES的跨平台游戏开发引擎,易学易用,支持多种智能移动平台。官网地址:http://cocos2d-x.org/当前版本:2.0 有很多的学习资料,在这里我只做为自己的笔记记录下来,错误之处还请指出。在VisualStudio2008平台的编译:1.下载当前稳
1. 来源 QuickV3sample项目中的2048样例游戏,以及最近《最强大脑》娱乐节目。将2048改造成一款挑战玩家对数字记忆的小游戏。邮箱:appdevzw@163.com微信公众号:HopToadAPK下载地址:http://download.csdn.net/detailotbaron/8446223源码下载地址:http://download.csdn.net/
Cocos2d-x3.x已经支持使用CMake来进行构建了,这里尝试以QtCreatorIDE来进行CMake构建。Cocos2d-x3.X地址:https://github.com/cocos2d/cocos2d-x1.打开QtCreator,菜单栏→"打开文件或项目...",打开cocos2d-x目录下的CMakeLists.txt文件;2.弹出CMake向导,如下图所示:设置
下载地址:链接:https://pan.baidu.com/s/1IkQsMU6NoERAAQLcCUMcXQ提取码:p1pb下载完成后,解压进入build目录使用vs2013打开工程设置平台工具集,打开设置界面设置: 点击开始编译等待编译结束编译成功在build文件下会出现一个新文件夹Debug.win32,里面就是编译
分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net前言上次用象棋演示了cocos2dx的基本用法,但是对cocos2dx并没有作深入的讨论,这次以超级马里奥的源代码为线索,我们一起来学习超级马里奥的实
1. 圆形音量button事实上作者的本意应该是叫做“电位计button”。可是我觉得它和我们的圆形音量button非常像,所以就这么叫它吧~先看效果:好了,不多解释,本篇到此为止。(旁白: 噗。就这样结束了?)啊才怪~我们来看看代码:[cpp] viewplaincopyprint?CCContro
原文链接:http://www.cnblogs.com/physwf/archive/2013/04/26/3043912.html为了进一步深入学习贯彻Cocos2d,我们将自己写一个场景类,但我们不会走的太远,凡是都要循序渐进,哪怕只前进一点点,那也至少是前进了,总比贪多嚼不烂一头雾水的好。在上一节中我们建