1.cocos2d-iphone环境搭建
第一步:下载cocos2d-iphone最新版本;地址:http://code.google.com/p/cocos2d-iphone/downloads/list (当前最新2.1-beta)
第二步:下载完成之后解压;
第三步:启动终端;
第四步:先利用cd命令进入cocos2d引擎文件夹,然后“./install-templates.sh -u”命令开始安装cocos2d
http://blog.csdn.net/kepoon/article/details/7634013
工程目录介绍:
预编译前缀头文件 “HelloWorld_prefix.pch”头文件的作用是给编译过程加速。把不常变化的框架(Frameworks)头文件添加到前缀头文件(prefix header)中。这样在编译的时候,框架的代码会被预先编译,所有的类都将可以使用这些头文件。不幸的是,这样做也有一个缺点:如果前缀头文件里其中一个头文件 发生了变化,你的所有代码将会重新编译。这就是为什么应该只添加那些极 少或者从来都不变化的头文件到前缀头文件中。cocos2d.h头文件可以被添加到前缀头文件中,因为它很少改变。,即使只为了不再需要在其他源代码里写 #import “cocos2d.h”, 也是值得一开始就在前缀头文件里写进 cocos2d.h 的。
#ifdef __OBJC__
#import
#import
#import "cocos2d.h"
#endif
任何在 AppDelegate 的 dealloc 方法中设置的断点都不起作用!这是正常的。当iOS 关闭一个程序时,它只是简单的把内存清空,以加快关闭的速度。这也是为什么 AppDelegate 的 dealloc 方法中的任何代码都不会被运行。并不需要 动调用 dealloc 方法以“解决这个问题”。如果确实需要在程序关闭之前在 AppDelegate 中运行代码,你可以在 applicationWillTerminate 方法中运行代码。如果目标 iOS 是 4 或者更高的版本,应该使用
applicationDidEnterBackground。
2.cocos2d-iPhone
http://www.cocos2d-iphone.org/
【cocos2d书籍翻译-更新结束】《Learn iPhone and iPad Cocos2D Game Development》
http://blog.csdn.net/a287971/article/details/7631684
http://www.cocoachina.com/bbs/simple/?t55155.html
http://cocos2d-central.com/files/file/2-source-code-for-the-learn-iphone-and-ipad-cocos2d-game-development-book/
《Learn iPhone and iPad Cocos2D Game Development》
3.cocos2d介绍
一部分人感觉 iOS 设备更 加适合 2D 游戏。一般来说2D游戏更容易开发,也更容易让人理解。而且很多时候2D游戏对硬件的要求更小,这样就允许创建更生动和拥有更多细节的游戏图形。
自带物理引擎:
cocos2d 整合了两套物理引擎。一套叫 Chipmunk,另一套叫 Box2d。它们的功能基本相同,最大的区别是编写它们所使用的编程语言:Chipmunk 是用 C 写的, Box2d 是用 C++写的。对大多数开发者来说, Box2d 是比较好的选择,它面向对象的特性也更容易和 Objective-C 整合在一 起。
隐藏了OpenGL ES 技术复杂度
游戏开发者喜欢 cocos2d 的一个原因是它隐藏了底端的 OpenGL ES 代码。同时,cocos2d 允许你自由的在任何时间为任意游戏对象添加你自己的 OpenGL ES 代码。还可以添加一些 Cocoa Touch 的用户界面元素到程序中。大多数 cocos2d 游戏中的图形由简单的 Sprite 类利用图片文件生成。一 个 Sprite 就是一个贴图。可以通过改变 CCSprite 类的 Objective-C 属性来 改变这个贴图的大小,旋转和颜色。不需要关心这些效果是怎样用 OpenGL ES 代码来实现的。
仍需要一些编程知识:
需要编程知识
虽然其他的一些 iOS 游戏引擎,比如 Unity, iTorque 和 Shiva 专注于提供工具和流程以降低对编程知识的要求。但是使用那些工具的同时,你也牺牲了灵活性,当然还有钞票。
使用一些工具
学习一些与cocos2d配合使用的工具,比如Zwoptex和Particle Designer。 没有这些工具,你只能成为“半个”cocos2d开发者。这些工具可以帮助你制作 日益复杂的游戏。
4.动画间隔(Animation Interval)
iOS设备不支持超过60帧每秒的帧率,它的屏幕刷新率被锁定在60帧每秒(Hz)。
动画间隔决定了cocos2d更新屏幕的频率。游戏不保证从始至终都达到60帧每秒的帧率。实际上,保持游戏运行在一个高的帧率上是我们的责任。在某些时候,把帧率设为30帧每秒可能更合适。对于那些很复杂的游戏,它们 的帧率可能在30和60帧每秒之间上下浮动的很厉害,设置一个低一点的帧率会 对这样的游戏有所帮助。当设置了一个低一点的帧率,而且游戏可以稳定的 保持在这个帧率,用户的体验会比使用一个高一些但是不稳定的帧率要好很多。
iOS 应用属于用户界面驱动类型的程序,它需要发送和接收很多的事件。通常在游戏编程中不会发送和接收很多的事件,并且会让很多对象决定如何响应事件。因为提高运行效率和降低用户输入延迟的原因,游戏引擎常常联系的很紧密。很多工作会在循环和更新方法中完成。这些方法要么是每一帧都调用,要么是在特定的时间点调用。
iOS设备使用的ARM CPU不支持直接在硬件上做除法, 乘法一般会快一些。虽然有时效果并不明显,但是养成这个习惯很有好处。
在一定的数量级内,分成两个循环所带来的额外系统开销是可以忽略不计的。
5. 所有节点的基类都是CCNode类。它包含了位置信息,但是没有显示信息。它定义了许多除显示节点外的通用的属性和方法。
所有节点都有一个共同的父类:CCNode。它是一个抽象类,没有视觉表现。它定义了许多除显示节点外的通用的属性和方法。除了场景本身,每一个节点只有一个父节点,但是可以有任意数量的子节点。
CCNode,CCScene和CCLayer这些类是没有视觉表现的。它们是在内部作为场景图的抽象概念来使用的。CCSprite是具有视觉表现的节点。
对一个节点施加的影响将会影响到它的所有子节点。但是有时候这也会产生混淆,因为像位置和旋转都是相对于 父节点来说的。
CCNode类实现了所有添加,获取和删除子节点的方法,addChild中的z参数决定了节点的绘制顺序。拥有最小z值的节点会首先被绘制; 拥有最大z值的节点最后一个被绘制。如果多个节点拥有相同的z值,他们的绘 制顺序将由他们的添加顺序来决定。这个规则只适用于像sprites有视觉表现的节点。
6.CCDirector:导演,CCDirector类,简称Director(导演),是cocos2d游戏引擎的核心。很多cocos2d的初始化过程包含了 [CCDirector sharedDirector]的调用。
Director是一个单例:它保存着 cocos2d的全局配置设定,同时管理着cocos2d的场景。
Director的主要用处如下:
(1). 访问和改变场景
(2). 访问cocos2d的配置细节
(3). 访问视图(OpenGL,UIView,UIWindow)
(4). 暂停,恢复和结束游戏
(5). 在UIKit和OpenGL之间转换坐标
7.CCScene:场景图(The Scene Graph) ,场景层级。
CCScene是一个抽象的概念,它的功能是根据像素坐标把物体放置在场景里相应的地方,任何cocos2d场景都会用一个CCScene作为父对象。
层次结构:在游戏场景图中,在最上面放置场景节点(MyScene),通常跟着的是一个层节点(CCLayer)。在cocos2d里,层节点的作用是接收触摸和加速计的输入。在CCLayer下一层的是游戏的组成要素,它们大多数是精灵(sprite)节点。
CCScene对象总是场景图里面的第一个节点。通常CCScene的子节点都是继承自 CCLayer。CCLayer包含了各个游戏对象。因为大多数情况下场景对象本身不包 含任何游戏相关的代码,而且很少被子类化,所以它一般都是在CCLayer对象里 通过+(id)scene这个静态方法来创建的。
CCScene只是一个抽象的概念,默认的设置场景的方法是在类里面使用 一个静态初始化方法(static initializer)+(id) scene。几乎在任何情况 下,CCScene都是在这里创建和使用的。以下是一个通用的+(id) scene方法:
+(id) scene {
CCScene *scene = [CCScene node];
id node = [HelloWorld node];
[scene addChild:node];
return scene;
}
第一个创建场景的地方是在AppDelegate中aplicationDidFinishLaunching方法
结束处,用Director的runWithScene方法开始运行第一个场景:
[[CCDirector sharedDirector] runWithScene:[HelloWorld scene]];
在其它情况下,用replaceScene方法来替换已有的场景:
[[CCDirector sharedDirector] replaceScene:[HelloWorld scene]];
用以下代码在任意一个地方显示“设置场景”:
[[CCDirector sharedDirector] pushScene:[Settings scene]];
如果身处“设置场景”,但又想关闭“设置场景”时,可以调用popScene,会回到之前还保留在内存里的场景:
[[CCDirector sharedDirector] popScene];
8.CCLayer: 有时候在同一个场景里你需要多个CCLayer。
CCLayer类本身并不做什么,它的功能是允许触摸和加速计的输入。大多数游戏会接受基本的触摸输入,CCLayer通常是第一个被加入CCScene的类。
和场景一样,层没有大小的概念。层是一个组织的概念。对一个层使用动作,那么所有在这个层上的物体都会同时受到影响,比一个一个操作更有效率。
用层和使用其它的节点一样,并不会因为使用多个层而降低运行效率。如果层接收触摸或者加速计事件的话就不一样了。因为接收处理外来事件很耗费资源。所以不应该使用很多接收外来事件的层。比较好的处理方式是只使用一个层来接收和处理事件。如果需要的话,这个层应该通过转发事件的方式来通知其它节点或类。
CCLayer最典型的应用是把各个节点组织起来,还有接 收触摸输入和加速计输入的信息 - 前提是上述接收功能已被启用。
设置isTouchEnabled为YES来让层接收触摸事件。
CCLayer接收触摸事件:
一旦启用isTouchEnabled属性,许多与接收触摸输入相关的方法将会开始被调用:
当手指首次触摸到屏幕时调用的方法:
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent*)event
手指在屏幕上移动时调用的方法:
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent*)event
当手指从屏幕上提起时调用的方法:
-(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent*)event
当触摸事件被取消时调用的方法:
-(void) ccTouchesCancelled:(NSSet *)touches withEvent:(UIEvent*)event
取消事件的情况很少发生,所以在大多数情况下它的行为和触摸结束时相同。
触摸事件由Cocoa Touch API接收,触摸的位置必须被转换为OpenGL的坐标
-(CGPoint) locationFromTouches:(NSSet *)touches
{
UITouch *touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView: [touch view]];
return [[CCDirector sharedDirector] convertToGL:touchLocation];
}
接收加速计事件:和触摸输入一样,加速计必须在启用以后才能接收加速计事件: self.isAccelerometerEnabled = YES; 层里面要加入一个特定的方法来接收加速计事件: -(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
CCLOG(@"acceleration: x:%f / y:%f / z:%f", acceleration.x, acceleration.y,
acceleration.z);
}
在处理加速计事件的代码中,改变速度变量的值间接更新主角精灵的位置,而不是直接更新主角精灵。
OS设备使用的ARM CPU不支持直接在硬件上做除法, 乘法一般会快一些。
10.schedule,预约信息:其实就是Objective-C里面的每隔一段时间调用一次方法。 比如,在其中处理碰撞测试。
CCNode可以[self scheduleUpdate]来预定信息,
-(void) update:(ccTime)delta
{
// 此方法每一帧都会被调用
}
delta参数表示的是此方法的上一次调用到现在所经过的时间。
停止节点的所有选择器:
[self unscheduleAllSelectors];
停止某个指定的选择器:
[self unschedule:@selector(updateTenTimesPerSecond:)];
停止对当前方法的预约
// 用_cmd关键词停止当前方法的预定
-(void) irregularUpdate:(ccTime)delta
{
// 首先,停止方法调用的预定 [self unschedule:_cmd];
// 这里我们用随机数来决定下次调用此方法需要经过的时间 float nextUpdate = CCRANDOM_0_1() * 10;
// 然后用_cmd来代替选择器,用新的时间间隔来重新预定方法调用
[self schedule:_cmd interval:nextUpdate];
}
scheduleUpdate不能被单独取消,它只能随unscheduleAllSelectors一起取消。
11.CCTransitionScene: 所有过渡效果的类都继承自CCTransitionScene。在游戏里不是每个过渡效果都很有用,即使它们看起来很好看。玩家们最关心的是过渡的速度。设置过渡效果的时间不要超过一秒,或者干脆完全不用。
14.CSprite:CCSprite是最常用到的类
生成 精灵最简单的方法是把图片文件加载进CCTexture2D材质里面,然后将它赋给精灵。
精灵中图片的中心点和精灵的左下角位置是一致的。生成的精灵被放 置在(0,0)点,也就是屏幕的左下角。将贴图的中心点和精灵的左下角位置设为一致有很大的好处,一旦开始使用精灵的旋转或缩放属性,精灵的中心点将会保持在它的位置上。
得到图片大小最简单的方法就是生成一个临时CCSprite精灵。
15.定位点
每个节点都有一个定位点 anchorPoint,它定义的是贴图相对于节点位置(position)的向左向下的偏移,通过把贴图的宽和高乘以定位点来得到贴图的偏移值。但是只有当此节点拥有贴图时,这个定位点才有用。
默认anchorPoint属性设置为(0.5,0.5)或者贴图尺寸的一半。它是 一个抽象的因素,一个乘数,而不是一个特定的像素尺寸。如果设置anchorPoint为(0,0)的,实际上是把贴图的左下角同节点的位置对齐了。但不要在cocos2d里面这样做。这样做会引起很多麻烦,包括旋转和缩放,父节点和子节点之间的相对位置,还有距离测试和碰撞测试。要保证anchorPoint在贴图的中央。
如果anchorPoint的点的值为负值则图片在position的右上,正值时图片在position的左下。当anchorPoint保存默认值(0.5,0.5)时,position就是图片的中心点了。
position:节点的左下点,原点。
定位点anchorPoint默认值是两个0.5,可理解为本来精灵和其图片重合,但故意默认为两个0.5,使精灵向右上移动了一半的位置。
精灵的position是精灵的左下角,同时是其中的图片的中心点,这有个好处是精灵基于这个点旋转或缩放时,我们看到图片的中心点没有移动。旋转在物理世界中常见,基于位置的碰撞检测可能也已经适应了0.5。
可能只需要在操作sprite时需要有时特殊调整定位点。
如果没有设置position,position默认值是(0,0)
16.贴图大小 :即一张资源图片的实际尺寸
目前可用于iOS设备的贴图尺寸必须符合“2的n次方”规定,所以贴图的宽和高必须是2,4,8,16,32,64,128,256,512,1024,在第三代设备上可以达到2048像素。
假设图片尺寸是260x260,用 的是32位颜色。在内存里,贴图本来只占279KB左右的空间,但是现在却使用了 整整1MB,这是因为iOS设备要求任何贴图的尺寸必须符 合“2的n次方”规定。260x260像素的贴图到了iOS设备中以后,系统会自动生 成一张与260x260尺寸最相近的符合“2的n次方”规定的图片(一张512x512像 素的图片),以便于把原贴图放进这个符合规定的“容器”中。而这张512x512 像素的图片占用了1MB的内存空间。
纹理贴图集是一张包含多个图片的大图片,同时这张大图片满足“2的n次方规则”。每一张包含于纹理贴图集中的图片都有一个精灵帧(sprite frame),这些帧用于定义各个图片在纹理贴图集中所处的各个长方形区域。精灵帧就是一个CGRect结构,定义了各个图片在纹理贴图集上所处的位置。这些精灵帧保存在一个单独的.plist文件中,cocos2d可以利用这个文件渲染纹理贴图集中指定的图片。这样避免了多张不符合规定的图片对内存的浪费。
[player texture].contentSize是精灵纹理的内容尺寸,即图片尺寸。因为纹理尺寸的大小只能是 2 的方幂,但实际的图像尺寸可能会比纹理尺寸小。例如,如果原始图像的尺寸为 100×100 像素,那么纹理尺寸就是 128×128 像素。纹理的 contentSize 属性会返回原始图像的尺寸,也就是 100×100 像素。 大部分情况下,处理的都是内容尺寸而不是纹理尺寸,因为纹理可能是包含多个图像的纹理图册。
有时利用一个临时的精灵来得到图片的大小
CCSprite* tempSpider = [CCSprite spriteWithFile:@"spider.png"];
float imageWidth = [tempSpider texture].contentSize.width;
17.CCLabel,CCLabelTTF,CCLabelLatlas,CCLabelbmFont
以下代码会生成 一个CCLabel对象用于显示文字:
CCLabel* label = [CCLabel labelWithString:@"text" fontName:@"AppleGothic"
fontSize:32];
[self addChild:label];
从生成文字的内部原理来说,TrueType字体被用于CCTexture2D贴图上渲染出文字。因为每次文字改变都会导致系统重新渲染一遍,非常耗时,,所以不应该经常改变文字。
[label setString:@"new text"];
可以通过改变anchorPoint属性将文字居左,居右,置顶或者放置在底部。
// 使用实例:将标签放置在屏幕右上角
// 标签文字延展到左下方,并且在屏幕上总是可见
CGSize size = [[CCDirector sharedDirector] winSize];
label.position = CGPointMake(size.width, size.height);
label.anchorPoint = CGPointMake(1, 1);
CCLabelBMFont* scoreLabel = [CCLabelBMFont labelWithString:@"0" fntFile:@"bitmapfont.fnt"];
创建bitmap字体文件,使用工具Hiero,它是一个免费的Java Web程序,在这里找到它:http://slick.cokeandcode.com/demos/hiero.jnlp
需要添加bitmapfont.fnt和配套的bitmapfont.png文件。
更新的
http://www.google.fr/url?sa=t&source=web&cd=2&ved=0CCgQFjAB&url=http%3A%2F%2Fn4te.com%2Fhiero%2Fhiero.jnlp&rct=j&q=hiero%20lion%20font&ei=ryJuTq3VK8SF-wat9qjmBA&usg=AFQjCNH9b2dk-gQYEHgoQmFkXjiM9wSDEw&sig2=1plodsazWJVULDNRiLEWUA
BMFont是个Windows程序,在这里下载BMFont: http://www.angelcode.com/products/bmfont/
如果用CCBitmapFontAtlas,CCLabelBMFont显示的文字不存在于.fnt文件中,它们将不会被显示,字母区别大小写。
www.71squared.com发布了一款可以替代Hiero的工具:Glyph Designer。虽然该工具是收费的,不过物有所值。 在http://glyphdesigner.71squared.com可以下载Glyph Designer的试用版本
18.CCMenu
需要一些可以让用户进行操作的按钮,使用CCMenu类来生成菜单。CCMenu只支持 CCMenuItem节点作为它的子节点。
19.CCAction
动作是用于在节点上运行某些“动作”的轻量级类。可以通过动作让节点移 动,旋转,缩放,着色,淡进淡出和干很多其它的事情。动作可以用于任何节点,可以在精灵,标签,甚至菜单或者整个场景中使用它们。
cocos2d的动作可以分为两种类型。一种是“即时动作”,它的效果和设定节点属性一样,例如设定visible或flipX属性。另一种是“时间间隔动作”,这种动作在一段时间之内发生,例如上述代码的移动动作。不需要在这两种动作完成以后将它们从内存里清理出去,cocos2d会自动释放动作所占用的内存。
一些动作类型:重复动作,舒缓动作,动作序列,即时动作。
当一个物体需要经常改变它的速度或方向时(每秒钟好几次),选择动作来移动它就不是个好选择了。因为动作是设计用于存在时间相对较长的物体的,所以频繁的生成动作会增加系统分配和释放内存的开销,降低程序运行效率。
CCBlink
CCMoveTo
CCCallFuncN:
CCCallFunc:使用CCCallFunc的结果是sender为nil,CCCallFunc不会将 sender参数传进来。
CCMoveBy
CCSequence
CCRepeatForever
CCEaseIn
CCRotateBy
CCScaleTo
-(void) stopActionByTag:(NSInteger)aTag;
-(CCAction*) runAction:(CCAction*) action;
当一个物体需要经常改变它的速度或方向时(每秒钟好几次),选择动作来移动它就不是个好选择了。因为动作是设计用于存在时间相对较长的物体的,所以频繁的生成动作会增加系统分配和释放内存的开销,降低程序运行效率。如果你不为动作的运行留出时间的话,动作根本就不会起作用,若在每一帧里都用新的动作去替换旧的动作时,新动作不会产生作用,新动作没有时间去替换旧的动作。
20.CCArray
它和苹果官方的NSMutableArray类似,但是运行效率更高。 CCArray类实现了NSArray和NSMutableArray的子集,并且添加一些从NSArray初 始化到CCArray的新方法。CCArray通过将数组中的最后一个对象(nil)赋值给删 除的位置,实现了fastRemoveObject和fastRemoveObjectAtIndex两个方法。避 免了复制部份数组的内存。这让删除数组中的元素变的更快,不过这也意味着 CCArray中的对象会改变位置。
如果程序依赖于指定的对象排列次序,就不要使用fastRemoveObject这类方法。
如果不是绝对必要,不要在for或者其它循环里的条件判断中调用方法,这样可以节省几个CPU循环。
21. CCLOG
CCLOG宏将苹果的 NSLog 方法进行了封装,所以 CCLOG 只在调试构建时会被编译,在发布构建时会被删除。建议在使用 NSLog 的地方用 CCLOG 代替,因为日志只是给自己看的。NSLog 会让发布的游戏变慢,因为它即使在发布构建里也会运行!
即使一条 NSLog 或者 CCLOG 也会让 Debugger Console 的窗口填满日志信息,导致程序运行速度变慢。如果觉得游戏在调试构建中的运行性能很差,应该看一下 Debugger Console 里面是不是有多余的日志活动。从 Xcode 的 Run 菜单里,选择 Console 以显示 Debugger Console 窗口。
两个构建配置(build configurations): 调试(Debug)和发布(Release)。他们之间的主要区别是:只有在调试时, 某些函数,比如 CCLOG,才会编译和被游戏代码所使用。这是影响调试和发布构 建两个配置之间影响运行性能最主要的因素。
22.。以下是一些最常用到的cocos2d 单例类和访问它们的方法:
CCActionManager* sharedManager = [CCActionManager sharedManager];
CCDirector* sharedDirector = [CCDirector sharedDirector];
CCSpriteFrameCache* sharedCache = [CCSpriteFrameCache sharedSpriteFrameCache];
CCTextureCache* sharedTexCache = [CCTextureCache sharedTextureCache];
CCTouchDispatcher* sharedDispatcher = [CCTouchDispatcher sharedDispatcher];
CDAudioManager* sharedManager = [CDAudioManager sharedManager]; SimpleAudioEngine* sharedEngine = [SimpleAudioEngine sharedEngine];
在创建任何一个单例类之前,要考虑是否真的需要单例,是否需求会在不久的将来改变。
23.一些数学函数
ccpDistance:float actualDistance = ccpDistance(player.position, spider.position);
ccpMult 乘法
ccpAdd
ccpSub 减法
可以在cocos2d的Xcode项目中 的cocos2d/Support组,找到CGPointExtension文件,里面有很多有用的数学函 数。
24.示例
如何使用cocos2d制作类似Scott Pilgrim的2D横版格斗过关游戏part2(翻译)
http://blog.sina.com.cn/s/blog_4b55f6860101aaav.html
如何设计开发iPhone塔防游戏2-月黑之时
http://article.ityran.com/archives/879
25.
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
//screen coordinate, screen topleft (0,0)
CGPoint po=[touch locationInView:[touch view]];
//screen coordinate, screen bottomleft (0,0)
CGPoint touchLocation = [[CCDirector sharedDirector] convertToGL:po];
//NodeSpace coordinate, NodeSpace bottomleft (0,0)
CCTMXTiledMap* map;
CGPoint touchLocation = [map convertTouchToNodeSpace:touch];
}
}