`
fireDragonpzy
  • 浏览: 462780 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

《Learn IPhone and iPad Cocos2d Game Delevopment》第6章

阅读更多
一、 CCSpriteBatchNode

在屏幕上贴图时,图形硬件需要经过准备、渲染、清除等步骤。每次贴图都会重复这个过程。如果图形硬件能事先知道有一组拥有相同纹理的Sprite需要渲染,则这个过程会被简化。比如,一组Sprite的准备和清除动作总共只需要执行一次。

下图的例子使用了CCSpriteBacthNode。屏幕上同时有几百颗子弹飞过。如果一次只渲染一颗,那么帧率马上降到85%。使用CCSpriteBatchNode,可以避免这种情况:



 

通常我们这样创建一个CCSprite:

CCSprite* sprite=[CCSprite spriteWithFile:@”bullet.png”];

[self addChild:sprite];

而使用CCSpriteBatchNode 则需要修改为:

CCSpriteBatchNode* batch=[CCSpriteBatchNode batchNodeWithFile:@”bullet.png”];

[self addChild:batch];

for(int i=0;i<100;i++){

CCSprite* sprite=[CCSprite spriteWithFile:@”bullet.png”];

[batch addChild:bullet];

}

注意,CCSpriteBatchNode需要一个图片文件名作为参数,哪怕它根本用不着这个图片(进行显示)。可以把它看做是一个Layer,你可以用它来加入一些CCSprite节点。由于它使用了一个图片文件作为构造参数,所以在后面加入的CCSprite中必须使用相同的文件作为构造参数,否则会导致如下错误:

SpriteBatches[13879:207] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'CCSprite is not using the same texture id'

当采用相同纹理的CCSpite越多,则采用CCSpriteBatchNode的好处越明显。

但这有一个限制,所有的CCSprite节点都会位于同一个Z坐标(深度)上。如果子弹是“击穿”敌人并向后飞,你得使用两个Z轴不同的CCSpriteBatchNode。

另外一个限制是,CCSpriteBatchNode和加入其中的CCSprite必须使用相同的贴图。这一点在使用Texture Atlas时尤其显得重要。一个Texture Atlas可以画多个不同的图片,并且这些图片使用同一个CCSpriteBatchNode,以提高渲染速度。

Z轴的问题可以通过指定CCSpriteBatchNode中单个CCSprite的Z值来解决。如果你所有的图片都放到了一个Texture Atlas(纹理集),则你完全可以只使用一个CCSpriteBatchNode。

把CCSpriteBatchNode看成一个简单的CCLayer,它只接受使用相同图片的CCSprite,这样,你就知道怎么用它了。

在下面代码中,隐藏有一个致命的陷阱:

-(id)init{

    If ((self = [super initWithFile:@"ship.png"])) {

[self scheduleUpdate];

    }

    return self;

}

由于-(id)init方法是默认的初始化方法,它会被其他初始化方法比如initWithFile调用。 在-(id)init方法中调用了[super initWithFile…]方法,[super initWithFile…]会调用[super init], 该类覆盖了-(id)init方法,于是又会调用-(id)init方法,无限循环。

解决办法是修改方法名,比如修改为-(id)initWithShipImage。

这个教训告诉我们,在默认初始化方法-(id)init中,除了[super init]之外,永远不要调用其他东西(其他的初始化方法)。如果你必须在初始化方法中调用[super initWith…]方法,你应当把方法名命名为initWith…。

二、示例代码

1、ship类

#import <Foundation/Foundation.h>
#import "cocos2d.h"
 
@interface Ship : CCSprite
{
}
 
+( id ) ship;
 
@end
#import "Ship.h"
#import "Bullet.h"
#import "GameScene.h"
 
@interface Ship (PrivateMethods)
-( id ) initWithShipImage;
@end
 
 
@implementation Ship
 
+( id ) ship
{
return [[[ self alloc ] initWithShipImage ] autorelease ];
}
 
-( id ) initWithShipImage
{
if (( self = [ super initWithFile : @"ship.png" ]))
{
[ self scheduleUpdate ];
}
return self ;
}
 
-( void ) dealloc
{
[ super dealloc ];
}
 
-( void ) update:( ccTime )delta
{
[[ GameScene sharedGameScene ] shootBulletFromShip : self ];
}
 
@end
 
ship类很简单,除了update方法。该方法调用了GameScene的shootBulletFromShip方法外([GameScene shareGameScene]实际上只是获取GameScene 的单实例)。

2、GameScene类

#import <Foundation/Foundation.h>
#import "cocos2d.h"
 
#import "Ship.h"
 
typedef enum
{
GameSceneNodeTagBullet = 1 ,
GameSceneNodeTagBulletSpriteBatch ,
} GameSceneNodeTags;
 
@interface GameScene : CCLayer
{
int nextInactiveBullet ;
}
 
+( id ) scene;
+( GameScene *) sharedGameScene;
 
-( void ) shootBulletFromShip:( Ship *)ship;
 
@property ( readonly ) CCSpriteBatchNode* bulletSpriteBatch;
 
@end
#import "GameScene.h"
#import "Ship.h"
#import "Bullet.h"
 
@interface GameScene (PrivateMethods)
-( void ) countBullets:( ccTime )delta;
@end
 
@implementation GameScene
 
static GameScene* instanceOfGameScene;
+( GameScene *) sharedGameScene
{
NSAssert ( instanceOfGameScene != nil , @"GameScene instance not yet initialized!" );
return instanceOfGameScene ;
}
 
+( id ) scene
{
CCScene *scene = [ CCScene node ];
GameScene *layer = [ GameScene node ];
[scene addChild : layer];
return scene;
}
 
-( id ) init
{
if (( self = [ super init ]))
{
instanceOfGameScene = self ;
CGSize screenSize = [[ CCDirector sharedDirector ] winSize ];
CCColorLayer * colorLayer = [ CCColorLayer layerWithColor : ccc4 ( 255 , 255 , 255 , 255 )];
[ self addChild :colorLayer z :- 1 ];
CCSprite * background = [ CCSprite spriteWithFile : @"background.png" ];
background. position = CGPointMake (screenSize. width / 2 , screenSize. height / 2 );
[ self addChild :background];
Ship * ship = [ Ship ship ];
ship. position = CGPointMake (ship. texture . contentSize . width / 2 , screenSize. height / 2 );
[ self addChild :ship];
CCSpriteBatchNode * batch = [ CCSpriteBatchNode batchNodeWithFile : @"bullet.png" ];
[ self addChild :batch z : 1 tag : GameSceneNodeTagBulletSpriteBatch ];
 
for ( int i = 0 ; i < 400 ; i++)
{
Bullet * bullet = [ Bullet bullet ];
bullet. visible = NO ;
[batch addChild :bullet];
}
[ self schedule : @selector ( countBullets :) interval : 3 ];
}
return self ;
}
 
-( void ) dealloc
{
instanceOfGameScene = nil ;
// don't forget to call "super dealloc"
[ super dealloc ];
}
 
-( void ) countBullets:( ccTime )delta
{
CCLOG ( @"Number of active Bullets: %i" , [ self . bulletSpriteBatch . children count ]);
}
 
-( CCSpriteBatchNode *) bulletSpriteBatch
{
CCNode * node = [ self getChildByTag : GameSceneNodeTagBulletSpriteBatch ];
NSAssert ([node isKindOfClass :[ CCSpriteBatchNode class ]], @"not a CCSpriteBatchNode" );
return ( CCSpriteBatchNode *)node;
}
 
-( void ) shootBulletFromShip:( Ship *)ship
{
CCArray * bullets = [ self . bulletSpriteBatch children ];
CCNode * node = [bullets objectAtIndex : nextInactiveBullet ];
NSAssert ([node isKindOfClass :[ Bullet class ]], @"not a bullet!" );
Bullet * bullet = ( Bullet *)node;
[bullet shootBulletFromShip :ship];
nextInactiveBullet ++;
if ( nextInactiveBullet >= [bullets count ])
{
nextInactiveBullet = 0 ;
}
}
 
@end
现在你应该看到了,在init方法中使用CCSpriteBatchNode加入了400颗子弹(被设置为不可见了)。然后在接下来的shootBulletFromShip方法(在ship的update方法中调用)中,依次调用每一颗子弹的shootBulletFromShip方法。

3、Bullet类

#import <Foundation/Foundation.h>
#import "cocos2d.h"
 
#import "Ship.h"
 
@interface Bullet : CCSprite
{
CGPoint velocity ;
float outsideScreen ;
}
 
@property ( readwrite , nonatomic ) CGPoint velocity;
 
+( id ) bullet;
 
-( void ) shootBulletFromShip:( Ship *)ship;
 
@end
#import "Bullet.h"
 
 
@interface Bullet (PrivateMethods)
-( id ) initWithBulletImage;
@end
 
 
@implementation Bullet
 
@synthesize velocity;
 
+( id ) bullet
{
return [[[ self alloc ] initWithBulletImage ] autorelease ];
}
 
-( id ) initWithBulletImage
{
if (( self = [ super initWithFile : @"bullet.png" ]))
{
}
return self ;
}
 
-( void ) dealloc
{
[ super dealloc ];
}
 
// Re-Uses the bullet
-( void ) shootBulletFromShip:( Ship *)ship
{
float spread = ( CCRANDOM_0_1 () - 0.5f ) * 0.5f ;
velocity = CGPointMake ( 1 , spread);
outsideScreen = [[ CCDirector sharedDirector ] winSize ]. width ;
self . position = CGPointMake (ship. position . x + ship. contentSize . width * 0.5f , ship. position . y );
self . visible = YES ;
[ self scheduleUpdate ];
}
 
-( void ) update:( ccTime )delta
{
self . position = ccpAdd ( self . position , velocity );
if ( self . position . x > outsideScreen )
{
self . visible = NO ;
[ self unscheduleAllSelectors ];
}
}
@end
shootBulletFromShip方法实现了子弹的射击。Spread变量计算了一个扩散值,使从飞船中射出的子弹有1/2的机率会向上/下两边扩散。Velocity是一个每帧移动的位置偏移量。然后设置子弹的初始位置位于飞船右边。在把子弹可视状态设置为显示后,调度运行update方法(每帧调用一次)。

在update方法中,让子弹移动velocity的偏移量。这种方式,比CCMoveXX方法效率更高一些。而且这里用了一个技巧,当子弹飞出屏幕后,我们并没有立即将Bullet对象清除(为了节省资源),而是子弹设置为不可视缓存起来,方便再次使用以提高程序性能。出于这个原因,我们在GameScene类中设计了一个nextInactiveBullet变量,以此来记录已经使用掉(射出去)的子弹(设置为可视的子弹)。等所有子弹都射出去以后,nextInactiveBullet重置为0。

三、增加角色动画

以下代码为ship对象增加角色动画。Ship对象的角色动画是5张连续的帧图像,以表现飞船尾部不断喷射并变化的火焰。

-( id ) initWithShipImage
{
if (( self = [ super initWithFile : @"ship.png" ]))
{
// 把5张图片装入动画帧数组
NSMutableArray * frames = [ NSMutableArray arrayWithCapacity : 5 ];
for ( int i = 0 ; i < 5 ; i++)
{
NSString * file = [ NSString stringWithFormat : @"ship-anim%i.png" , i];
// 使用贴图缓存构造2D贴图
CCTexture2D * texture = [[ CCTextureCache sharedTextureCache ] addImage :file];
CGSize texSize = texture. contentSize ;
CGRect texRect = CGRectMake ( 0 , 0 , texSize. width , texSize. height );
// 用2D贴图构造动画帧
CCSpriteFrame * frame = [ CCSpriteFrame frameWithTexture :texture rect :texRect offset : CGPointZero ];
// 把动画帧放入数组
[frames addObject :frame];
}
// 用动画帧数组构造动画对象,帧率:0.08秒/帧,标识名:move
CCAnimation * anim = [ CCAnimation animationWithName : @"move" delay : 0.08f frames :frames];
// 如果你把anim存储到CCSprite,则可以通过名称move来访问CCAnimation
//[self addAnimation:anim];
// 构造Action:无限重复
CCAnimate * animate = [ CCAnimate actionWithAnimation :anim];
CCRepeatForever * repeat = [ CCRepeatForever actionWithAction :animate];
[ self runAction :repeat];
[ self scheduleUpdate ];
}
return self ;
}
为求简便,上面的代码我们也可以封装为一个新的类别Category。

1、类别Animation Helper

利用OC中的Category,我们可以扩展CCAnimation类。Category提供了一种不需要修改类的源代码即可为类增加新方法的途径(有点象AOP?),但它不能增加新的成员变量。下面的代码为CCAnimation增加了一个Category,名为Helper(新建Class,名为CCAnimationHelper.h):

#import <Foundation/Foundation.h>
#import "cocos2d.h"
 
@interface CCAnimation (Helper)
 
+( CCAnimation *) animationWithFile:( NSString *) name frameCount:( int )frameCount delay:( float ) delay ;
+( CCAnimation *) animationWithFrame:( NSString *)frame frameCount:( int )frameCount delay:( float ) delay ;
 
@end
#import "CCAnimationHelper.h"
 
@implementation CCAnimation (Helper)
 
// 通过图片文件名创建CCAnimation对象 .
+( CCAnimation *) animationWithFile:( NSString *) name frameCount:( int )frameCount delay:( float ) delay
{
// 把前面的代码移到这里来了
NSMutableArray * frames = [ NSMutableArray arrayWithCapacity :frameCount];
for ( int i = 0 ; i < frameCount; i++)
{
NSString * file = [ NSString stringWithFormat : @"%@%i.png" , name , i];
CCTexture2D * texture = [[ CCTextureCache sharedTextureCache ] addImage :file];
 
CGSize texSize = texture. contentSize ;
CGRect texRect = CGRectMake ( 0 , 0 , texSize. width , texSize. height );
CCSpriteFrame * frame = [ CCSpriteFrame frameWithTexture :texture rect :texRect offset : CGPointZero ];
[ frames addObject :frame];
}
return [ CCAnimation animationWithName : name delay : delay frames : frames ];
}
 
// 通过 sprite frames 创建CCAnimation .
+( CCAnimation *) animationWithFrame:( NSString *)frame frameCount:( int )frameCount delay:( float ) delay
{
// 未实现
return nil ;
}
@end
现住,在Ship类的初始化方法里,可以通过CCAnimation的类别Helper这样简单地创建动画对象了:

-( id ) initWithShipImage
{
if (( self = [ super initWithFile : @"ship.png" ]))
{
// 使用类别Helper来创建动画对象
CCAnimation * anim = [ CCAnimation animationWithFile : @"ship-anim" frameCount : 5 delay : 0.08f ];
// 创建Action:无限循环播放动画
CCAnimate * animate = [ CCAnimate actionWithAnimation :anim];
CCRepeatForever * repeat = [ CCRepeatForever actionWithAction :animate];
[ self runAction :repeat];
[ self scheduleUpdate ];
}
return self ;
}
四、 Texture Atlas 贴图集(或译作纹理集)

1、定义

贴图集Texture Atlas仅仅是一张大的贴图。通过使用CCSpriteBatchNode,你可以一次性渲染所有的图片。使用Texture Atlas不但节约了内存也提升了性能。

贴图的大小(宽和高)总是2的n次方——例如1024*128或256*512。由于这个规则,贴图尺寸有时候是大于图片的实际尺寸的。例如,图片大小140*600,当加载到内存时,贴图尺寸是256*1024。这显然是一种内存浪费,尤其是你有几个这样的单独的Texture时。

因此有了Texture Atlas的概念。它是一张包含了多个图片的图片,并且它的尺寸已经是对齐的。所谓对齐,即是根据前面提到的那个规则,指它的长和宽都已经是2的n次方。贴图集每一个角色帧(sprite frame)都定义为贴图集中的一部分(一个矩形区域)。这些角色帧的CGrect则定义在单独的一个.plist文件里。这样cocos2d就可以从一张大的贴图集中单独渲染某个指定的角色帧。

2、Zwoptex

Zwoptex是一个2D贴图工具,付费版需要$24.95。有一个7天的试用版,下载地址http://zwoptexapp.com 。但Zwoptex提供了一个flash版,没有时间限制:http://zwoptexapp.com/flashwersion ,也基本够用(仅仅有一些限制,比如2048*2048贴图限制,角色旋转等)。

如果你不想试用Zwoptex,那么有一个可以替换的工具是TexturePacker:

http://texturepacker.com/

这里以Zwoptex 0.3b7版本为例(这个是免费版)。打开Zwoptex,默认是一个叫做Untitled的空白画布。选择菜单:Sprite Sheet ——>Import Sprites,会弹出文件选择对话框,选择你需要的角色帧图片文件,点击import,于是所有的图片会导入到Zwoptex。

 

选择菜单:Sprite Sheet——>Settings,会弹出布局窗口:



 

你可以更改设置,包括画布大小,排序规则、行间距、列间距等,目的是用最小的贴图集容纳全部所需的图片。然后点击save去应用。

注意,除非单独为3GS、iPad和iPhone4开发,否则不要使用2048*2048的画布尺寸,因为老的型号最大只支持1024*1024。

改变画布大小时要当心,因为有时候图片会叠在一起——由于空间不足。

建议不要手动更改图片(如移动、旋转),因为这个版本并不支持,它是自动布局的。

Zwoptex会自动截掉图片中透明边沿,所以本来一样大小的图片在Zwoptex中会显得大小不一。



 

不用担心,cocos2d会自动计算这些误差并正确显示(不用担心,这些数据都记载在.plist里)。

点击File——>save菜单,编辑结果保存为.zss文件格式(Zwoptex格式)。

点击Sprite Sheet——>Export——>Texture,编辑结果保存为.png格式。

点击Sprite Sheet——>Export——>Cordinates,编辑结果保存为.plist格式。

后两者,正是cocos2d所需要的。

3、Cocos2d中使用贴图集

首先,将Zwoptex生成的.png和.plist文件加入到项目的Resource组中。然后在代码中使用贴图集:

-( id ) initWithShipImage
{
// 用CCSpriteFrameCache加载贴图集,用.plist文件而不是.png文件做参数
CCSpriteFrameCache * frameCache = [ CCSpriteFrameCache sharedSpriteFrameCache ];
[frameCache addSpriteFramesWithFile : @"ship-and-bullet.plist" ];
 
// 从贴图集中加载名为ship.png的sprite,注意ship.png是.plist中定义的key,而不是真正意义的文件名
if (( self = [ super initWithSpriteFrameName : @"ship.png" ]))
{
// 从贴图集中加载sprite帧,注意用.plist中的key值做参数而非文件名
NSMutableArray* frames = [NSMutableArray arrayWithCapacity : 5 ];
for ( int i = 0 ; i < 5 ; i ++)
{
NSString* file = [NSString stringWithFormat: @"ship-anim%i.png" , i ];
CCSpriteFrame * frame = [frameCache spriteFrameByName :file];
[frames addObject :frame];
}
CCAnimation * anim = [ CCAnimation animationWithName : @"move" delay : 0.08f frames :frames];
CCAnimate * animate = [ CCAnimate actionWithAnimation :anim];
CCRepeatForever * repeat = [ CCRepeatForever actionWithAction :animate];
[ self runAction :repeat];
[ self scheduleUpdate ];
}
return self ;
}
[CCSpriteFrameCache sharedSpriteFrameCache]是一个单例对象,其 addSpriteFramesWithFile 方法用于加载贴图集(需要以.plist文件名作为参数)。对于大文件贴图集(超过512*512),加载过程可能会花费数秒,应当在游戏开始前就加载。

CCSprite的initWithSpriteFrameName方法可以从贴图集中获取贴图,并设置Sprite的显示图片,但它需要以贴图集(.plist)中的帧名(framename,实际上是<frames>中的一个<key>)为参数。

当然,如果要从贴图集中得到一个帧,可以用CCSpriteFrameCache的spriteFrameByName方法。这同样需要用贴图集中的帧名为参数。

如果你加载了多个贴图集,但只要名为ship.png的帧只有1个,那么cocos2d就可以找到正确贴图的。

 
其他代码没有任何改变。但出现了一个奇怪的现象:飞船的位置莫名其妙地向屏幕中心靠近了一点,尽管不是很明显。这个问题很容易解决,之前Ship的初始化代码是这样的:

Ship * ship = [ Ship ship ];
ship. position = CGPointMake (ship. texture . contentSize . width / 2 , screenSize. height / 2 );
[ self addChild :ship];
 

这个地方需要改变:

ship. position = CGPointMake (ship. contentSize . width / 2 , screenSize. height / 2 );
问题解决了。导致这个现象的原因是,ship对象的texture的contentSize要比ship对象的contentSize大(Ship的Texture现在用的是贴图集——具体说就是 ship-and-bullet.png 这张图,尺寸为256*256,而原来的ship.png才128*64)。

4、修改CCAnimation类别Helper

现在是实现类别Helper中的animationWithFrame方法的时候了:

+( CCAnimation *) animationWithFrame:(NSString*)frame frameCount:( int )frameCount delay:( float ) delay
{
// 构造一个frame数组
NSMutableArray* frames = [NSMutableArray arrayWithCapacity :frameCount];
// 通过CCSpriteFrameCache从贴图集中加载frame,并将frame加到数组中
for ( int i = 0 ; i < frameCount; i ++)
{
NSString* file = [NSString stringWithFormat: @"%@%i.png" , frame, i ];
CCSpriteFrameCache * frameCache = [ CCSpriteFrameCache sharedSpriteFrameCache ];
CCSpriteFrame * frame = [frameCache spriteFrameByName :file];
[ frames addObject :frame];
}
// 用frame数组构建animation对象并返回
return [ CCAnimation animationWithName :frame delay : delay frames : frames ];
}
现在,可以修改ship类中initWithShipImage方法,把CCAnimation的初始化修改为:

CCAnimation * anim = [ CCAnimation animationWithFrame : @"ship-anim" frameCount : 5 delay : 0.08f ];
 

5、弱水三千,只取一瓢饮

只要你愿意,你可以把所有游戏图片都加到一个贴图集里。用3个1024*1024的贴图集跟用20个更小的贴图集效率更高。

对于程序员而言,应当把代码“分离”成不同的逻辑组件。于此不同,对于贴图集来说,我们的目标就是尽可能多地把图片放到一个贴图集里,尽可能降低内存空间的浪费。

用一个贴图集放入玩家图片,用另外的贴图集放怪物A、B、C的图片——这好像更符合逻辑些,但这仅仅有助于你有大量的图片,而且每次你只是有选择地加载一部分图片的时候。

当你的图片只需要3-4个1024*1024贴图集的时候,你应当把所有图片只放在这些贴图集里进行预加载。这需要12-16MB的内存。程序代码和其他资源如音频则不会占用这么多内存,你可以把这些贴图集都保留在内存,这样哪怕只有128MB RAM的老IOS设备也可以承受。

如果超过这个内存,就应该采取特别的策略了。比如,可以把游戏图片进行分类,并且只在当前地图中加载必要的贴图集。这可以减少地图加载时的延时。

因为cocos2d会自动缓存所有图片,需要一种卸载贴图的机制。绝大部分情况下你可以使用cocos2d提供的:

[[CCSpriteFrameCache sharedSpriteFrameCache]removeUnusedSpriteFrames];

[[CCTextureCache sharedTextureCache] removeUnusedTextures];

显然应当在某些贴图不再使用的时候调用这些方法。比如转场景完成后。游戏正在进行时就不行了。注意,仅仅在新场景初始化结束后,前面的场景才会被 deallocated 。意即在一个 Scenen 的初始化方法中你不能调用 removeUnusedxxx 方法——除非你在两个 scene 转换中使用了第 5 章的 LoadingScene 类,这样你要扩展 LoadingScene 使它在加载新场景替时 remove 所有未使用的贴图。

如果要绝对清除所有内存中的贴图以加载新的贴图,应当使用:

[CCSpriteFrameCache purgeSharedSpriteFrameCache];

[CCTextureCache purgeSharedTextureCache];


摘自:http://blog.csdn.net/kmyhy/article/details/6387190
分享到:
评论

相关推荐

    Learn iPhone and iPad cocos2d Game Development中文版全集

    《Learn iPhone and iPad cocos2d Game Development中文版全集》是一部深入浅出的教程,旨在帮助读者掌握在iOS平台上使用cocos2d框架开发游戏的技能。cocos2d是一款强大的2D游戏开发库,特别适合于iPhone和iPad应用...

    Learn iPhone and iPad Cocos2D Game Developmentn中文版

    《Learn iPhone and iPad Cocos2D Game Development》中文版是一本专为苹果移动平台开发者设计的游戏开发教程。Cocos2D是一款广泛使用的2D游戏引擎,尤其在iOS平台上备受青睐,因为它提供了强大的图形渲染能力、丰富...

    Learn iPhone and iPad Cocos2D Game Development(中文版)

    01 介绍cocos2d 02 开始学习 03 基础知识 04 你的第一个游戏 05 游戏构成要素 06 深入了解精灵 07 横向滚屏射击游戏 08 完成滚屏射击游戏 09 粒子效果 10 瓷砖地图基础知识 11 45度角瓷砖地图 12 物理引擎 13 弹球...

    Learn iPhone and iPad Cocos2D Game Development

    Learn iPhone and iPad Cocos2D Game Development provides a rock-solid introduction to the cocos2d iPhone game engine and related tools. It focuses on the process of creating several games made entirely...

    Learn iPhone and iPad Cocos2D Game Development 前三章中文翻译

    《Learn iPhone and iPad Cocos2D Game Development》是一本专为苹果移动设备(iPhone和iPad)游戏开发设计的教程书籍,其前三章的中文翻译为我们提供了初步了解Cocos2D框架的基础知识。Cocos2D是一款强大的开源游戏...

    Learn iPhone and iPad Cocos2D Game 原文及译文

    《Learn iPhone and iPad Cocos2D Game》是针对初学者的一本优秀教程,旨在帮助读者掌握使用Cocos2D框架创建iOS游戏的基础知识。Cocos2D是一个强大的、开源的游戏开发框架,它允许开发者用Objective-C语言编写游戏,...

    Learn iPhone and iPad Cocos2D Game

    《Learn iPhone and iPad Cocos2D Game Development》是一本专为iOS游戏开发爱好者和专业人士编写的英文原版书籍,旨在帮助读者深入理解如何利用Cocos2D框架创建高性能、交互性强的游戏。Cocos2D是一个广泛使用的...

    苹果IOS平台游戏设计教程Learn iPhone and iPad Cocos2D Game Development

    《苹果IOS平台游戏设计教程:Learn iPhone and iPad Cocos2D Game Development》是一本专为开发者准备的指南,旨在帮助他们掌握在iOS平台上利用Cocos2D框架开发游戏的技能。Cocos2D是一个强大的2D游戏开发库,特别...

    Learn iPhone and iPad Cocos2D Game Development中文版(13章全)

    《Learn iPhone and iPad Cocos2D Game Development中文版》是一本深入浅出的教程,旨在帮助读者掌握在iOS平台上使用Cocos2D框架进行游戏开发的技术。Cocos2D是一款强大的2D游戏引擎,尤其适合Objective-C编程语言的...

    learn iphone and ipad cocos2d game development 中英双版

    learn iphone and ipad cocos2d game development 是一本出色的讲解cocos2d的书籍,本人整理了其中英文版本与大家分享。

    Learn iPhone and iPad Cocos2D Game Development 前4、5、6章中文翻译

    《Learn iPhone and iPad Cocos2D Game Development》是一本专为iOS平台上的游戏开发而设计的教程,尤其针对使用Cocos2D框架进行游戏开发的初学者和中级开发者。Cocos2D是一款强大的2D游戏引擎,广泛应用于iPhone和...

    Learn iPhone and iPad Cocos2D Game Development源码二

    在本资源中,“Learn iPhone and iPad Cocos2D Game Development源码二”是一个关于使用Cocos2D游戏引擎开发iOS游戏的实践教程。Cocos2D是一个流行的游戏开发框架,适用于iPhone、iPad以及Mac平台,它允许开发者用...

    中文pdf-Learn iphone and ipad cocos2d game development

    本教程《Learn iPhone and iPad Cocos2d Game Development》深入浅出地介绍了如何利用Cocos2d引擎创建令人惊叹的游戏。Cocos2d为iOS游戏提供了丰富的功能和强大的性能,包括2D渲染、动画系统、物理引擎支持、用户...

    pdf-Learn iphone and ipad cocos2d game development中文版

    《Learn iPhone and iPad Cocos2D Game Development》是一本针对初学者和有一定基础的开发者设计的书籍,专注于利用Cocos2D框架进行iOS平台的游戏开发。Cocos2D是一款广泛应用于2D游戏、动态图形和应用程序开发的...

    Learn iPhone and iPad Cocos2D Game Development中英文版

    《Learn iPhone and iPad Cocos2D Game Development》是一本专为开发者设计的指南,旨在帮助他们掌握使用Cocos2D框架进行iOS游戏开发的技术。Cocos2D是一款强大的开源游戏引擎,尤其适合初学者和有经验的开发者进行2...

    Learn iPhone and iPad cocos2d Game Development 中文翻译版

    《Learn iPhone and iPad cocos2d Game Development》中文翻译版是一本专门为希望在iPhone和iPad上进行游戏开发的开发者量身定制的指南。cocos2d是一个开源的游戏开发框架,它基于Objective-C,使得iOS游戏开发变得...

Global site tag (gtag.js) - Google Analytics