欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Cocos2d開發(fā)系列(四)

系統(tǒng) 2163 0

Learn IPhone and iPad Cocos2d Game Delevopment》的第5章。

一、使用多場景

很少有游戲只有一個場景。這個例子是這個樣子的: Cocos2d開發(fā)系列(四)

這個 Scene中用到了兩個Layer,一個Layer位于屏幕上方,標(biāo)有”Here be your Game Scores etc“字樣的標(biāo)簽,用于模擬游戲菜單。一個Layer位于屏幕下方,一塊綠色的草地上有一些隨機游動的蜘蛛和怪物,模擬了游戲的場景。

1、加入新場景

一個場景是一個 Scene類。加入新場景就是加入更多的Scene類。

有趣的是場景之間的切換。使用 [CCDirector replaceScene]方法轉(zhuǎn)場時,CCNode有3個方法會被調(diào)用:OnEnter、OnExit、 onEnterTransitionDidFinish。

覆蓋這 3個方法時要牢記,始終要調(diào)用super的方法,避免程序的異常(比如內(nèi)存泄露或場景不響應(yīng)用戶動作)。

-(void) onEnter {

// node的 init 方法后調(diào)用.

// 如果使用 CCTransitionScene方法,在轉(zhuǎn)場開始后調(diào)用.

[super onEnter];

}

-(void ) onEnterTransitionDidFinish {

// onEnter方法后調(diào)用.

// 如果使用 CCTransitionScene方法,在轉(zhuǎn)場結(jié)束后調(diào)用.

[super onEnterTransitionDidFinish];

}

-(void) onExit

{

// node的 dealloc 方法前調(diào)用.

// 如果使用CCTransitionScene方法, 在轉(zhuǎn)場結(jié)束時調(diào)用.

[super onExit];

}

當(dāng)場景變化時,有時候需要讓某個 node干點什么,這時這3個方法就派上用場了。

與在 node的init方法和dealloc方法中做同樣的事情不同,在onEnter方法執(zhí)行時,場景已經(jīng)初始化了;而在onExit方法中,場景的node仍然是存在的。

這樣,在進(jìn)行轉(zhuǎn)場時,你就可以暫停動畫或隱藏用戶界面元素,一直到轉(zhuǎn)場完成。這些方法調(diào)用的先后順序如下(使用 replaceScene 方法):

1. 第2個場景的 scene 方法

2. 第2個場景的 init 方法

3. 第2個場景的 onEnter 方法

4. 轉(zhuǎn)場

5. 第1個場景的 onExit 方法

6. 第2個場景的 onEnterTransitionDidFinish 方法

7. 第1個場景的 dealloc 方法

二、請稍候??

切換場景時,如果場景的加載是一個比較耗時的工作,有必要用一個類似“ Loading,please waiting…”的場景來過渡一下。用于在轉(zhuǎn)場時過渡的場景是一個“輕量級”的Scene類,可以顯示一些簡單的提示內(nèi)容:

typedef enum

{

TargetSceneINVALID = 0 ,

TargetSceneFirstScene,

TargetSceneOtherScene,

TargetSceneMAX,

} TargetScenes;

@interface LoadingScene : CCScene

{

TargetScenes targetScene_;

}

+( id ) sceneWithTargetScene:(TargetScenes)targetScene;

-( id ) initWithTargetScene:(TargetScenes)targetScene;

@end

#import "LoadingScene.h"

#import "FirstScene.h"

#import "OtherScene.h"

@interface LoadingScene (PrivateMethods)

-( void ) update:(ccTime)delta;

@end

@implementation LoadingScene

+( id ) sceneWithTargetScene:(TargetScenes)targetScene;

{

return [[[ self alloc] initWithTargetScene:targetScene] autorelease];

}

-( id ) initWithTargetScene:(TargetScenes)targetScene

{

if (( self = [ super init]))

{

targetScene_ = targetScene;

CCLabel* label = [CCLabel labelWithString: @"Loading ..." fontName: @"Marker Felt" fontSize: 64 ];

CGSize size = [[CCDirector sharedDirector] winSize];

label.position = CGPointMake(size.width / 2 , size.height / 2 );

[ self addChild:label];

[ self scheduleUpdate];

}

return self ;

}

-( void ) update:(ccTime)delta

{

[ self unscheduleAllSelectors];

switch (targetScene_)

{

case TargetSceneFirstScene:

[[CCDirector sharedDirector] replaceScene:[FirstScene scene]];

break ;

case TargetSceneOtherScene:

[[CCDirector sharedDirector] replaceScene:[OtherScene scene]];

break ;

default :

// NSStringFromSelector(_cmd) 打印方法名

NSAssert2( nil , @"%@: unsupported TargetScene %i" , NSStringFromSelector( _cmd ), targetScene_);

break ;

}

}

-( void ) dealloc

{

CCLOG( @"%@: %@" , NSStringFromSelector( _cmd ), self );

[ super dealloc];

}

@end

首先,定義了一個枚舉。這個技巧使 LoadingScene 能用于多個場景的轉(zhuǎn)場,而不是固定地只能在某個場景的切換時使用。繼續(xù)擴展這個枚舉的成員,使 LoadingScene 能適用與更多目標(biāo) Scene 的轉(zhuǎn)場。

sceneWithTargetScene 方法中返回了一個 autorelease 的對象。在 coco2d 自己的類中也是一樣的,你要記住在每個靜態(tài)的初始化方法中使用 autorelease

方法中,構(gòu)造了一個 CCLabel ,然后調(diào)用 scheduleUpdate 方法。 scheduleUpdate 方法會在下一個時間(約一幀)后調(diào)用 update 方法。在 update 方法中,我們根據(jù) sceneWithTargetScene 方法中指定的枚舉參數(shù),切換到另一個 scene 。在這個 scene 的加載完成之前, LoadingScene 會一直顯示并且凍結(jié)用戶的事件響應(yīng)。

我們不能直接在初始化方法 initWithTargetScene 中直接切換 scene ,這會導(dǎo)致程序崩潰。記住,在一個 Node 還在初始化的時候,千萬不要在這個 scene 上調(diào)用 CCDirector replaceScene 方法。

LoadingScene 的使用很簡單,跟一般的 scene 一樣:

CCScene * newScene = [ LoadingScene sceneWithTargetScene : TargetSceneFirstScene ];

[[ CCDirector sharedDirector ] replaceScene :newScene];

三、使用 Layer

Layer類似Photoshop中層的概念,在一個scene中可以有多個Layer:

typedef enum

{

LayerTagGameLayer ,

LayerTagUILayer ,

} MultiLayerSceneTags;

typedef enum

{

ActionTagGameLayerMovesBack ,

ActionTagGameLayerRotates ,

} MultiLayerSceneActionTags;

@class GameLayer ;

@class UserInterfaceLayer ;

@interface MultiLayerScene : CCLayer

{

bool isTouchForUserInterface ;

}

+( MultiLayerScene *) sharedLayer;

@property ( readonly ) GameLayer* gameLayer;

@property ( readonly ) UserInterfaceLayer* uiLayer;

+( CGPoint ) locationFromTouch:( UITouch *)touch;

+( CGPoint ) locationFromTouches:( NSSet *)touches;

+( id ) scene;

@end

@implementation MultiLayerScene

static MultiLayerScene* multiLayerSceneInstance;

+( MultiLayerScene *) sharedLayer

{

NSAssert ( multiLayerSceneInstance != nil , @"MultiLayerScene not available!" );

return multiLayerSceneInstance ;

}

-( GameLayer *) gameLayer

{

CCNode * layer = [ self getChildByTag : LayerTagGameLayer ];

NSAssert ([layer isKindOfClass :[ GameLayer class ]], @"%@: not a GameLayer!" , NSStringFromSelector ( _cmd ));

return ( GameLayer *)layer;

}

-( UserInterfaceLayer *) uiLayer

{

CCNode * layer = [[ MultiLayerScene sharedLayer ] getChildByTag : LayerTagUILayer ];

NSAssert ([layer isKindOfClass :[ UserInterfaceLayer class ]], @"%@: not a UserInterfaceLayer!" , NSStringFromSelector ( _cmd ));

return ( UserInterfaceLayer *)layer;

}

+( CGPoint ) locationFromTouch:( UITouch *)touch

{

CGPoint touchLocation = [touch locationInView : [touch view ]];

return [[ CCDirector sharedDirector ] convertToGL :touchLocation];

}

+( CGPoint ) locationFromTouches:( NSSet *)touches

{

return [ self locationFromTouch :[touches anyObject ]];

}

+( id ) scene

{

CCScene * scene = [ CCScene node ];

MultiLayerScene * layer = [ MultiLayerScene node ];

[scene addChild :layer];

return scene;

}

-( id ) init

{

if (( self = [ super init ]))

{

NSAssert ( multiLayerSceneInstance == nil , @"another MultiLayerScene is already in use!" );

multiLayerSceneInstance = self ;

GameLayer * gameLayer = [ GameLayer node ];

[ self addChild : gameLayer z : 1 tag : LayerTagGameLayer ];

UserInterfaceLayer * uiLayer = [ UserInterfaceLayer node ];

[ self addChild : uiLayer z : 2 tag : LayerTagUILayer ];

}

return self ;

}

-( void ) dealloc

{

CCLOG ( @"%@: %@" , NSStringFromSelector ( _cmd ), self );

[ super dealloc ];

}

@end

MultiLayerScene 中使用了多個 Layer: 一個 GameLayer h 和一個 UserInterfaceLayer

MultiLayerScene 使用了靜態(tài)成員 multiLayerSceneInstance 來實現(xiàn)單例。 MultiLayerScene也是一個Layer,其node方法實際上調(diào)用的是實例化方法init——在其中,我們加入了兩個Layer,分別用兩個枚舉 LayerTagGameLayer LayerTagUILayer 來檢索 , 如屬性方法 gameLayer和uiLayer所示。

uiLayer是一個UserInterfaceLayer,用來和用戶交互,在這里實際上是在屏幕上方放置一個菜單,可以把游戲的一些統(tǒng)計數(shù)字比如:積分、生命值放在這里:

typedef enum

{

UILayerTagFrameSprite ,

} UserInterfaceLayerTags;

@interface UserInterfaceLayer : CCLayer

{

}

-( bool ) isTouchForMe:( CGPoint )touchLocation;

@end

@implementation UserInterfaceLayer

-( id ) init

{

if (( self = [ super init ]))

{

CGSize screenSize = [[ CCDirector sharedDirector ] winSize ];

CCSprite * uiframe = [ CCSprite spriteWithFile : @"ui-frame.png" ];

uiframe. position = CGPointMake ( 0 , screenSize. height );

uiframe. anchorPoint = CGPointMake ( 0 , 1 );

[ self addChild :uiframe z : 0 tag : UILayerTagFrameSprite ];

// Label模擬UI控件( 這個Label沒有什么作用,僅僅是演示) .

CCLabel * label = [ CCLabel labelWithString : @"Here be your Game Scores etc" fontName : @"Courier" fontSize : 22 ];

label. color = ccBLACK ;

label. position = CGPointMake (screenSize. width / 2 , screenSize. height );

label. anchorPoint = CGPointMake ( 0.5f , 1 );

[ self addChild :label];

self . isTouchEnabled = YES ;

}

return self ;

}

-( void ) dealloc

{

CCLOG ( @"%@: %@" , NSStringFromSelector ( _cmd ), self );

[ super dealloc ];

}

-( void ) registerWithTouchDispatcher

{

[[ CCTouchDispatcher sharedDispatcher ] addTargetedDelegate : self priority :- 1 swallowsTouches : YES ];

}

// 判斷觸摸是否位于有效范圍內(nèi) .

-( bool ) isTouchForMe:( CGPoint )touchLocation

{

CCNode * node = [ self getChildByTag : UILayerTagFrameSprite ];

return CGRectContainsPoint ([node boundingBox ], touchLocation);

}

-( BOOL ) ccTouchBegan:( UITouch *)touch withEvent:( UIEvent *)event

{

CGPoint location = [ MultiLayerScene locationFromTouch :touch];

bool isTouchHandled = [ self isTouchForMe :location];

if (isTouchHandled)

{

// 顏色改變?yōu)榧t色,表示接收到觸摸事件 .

CCNode * node = [ self getChildByTag : UILayerTagFrameSprite ];

NSAssert ([node isKindOfClass :[ CCSprite class ]], @"node is not a CCSprite" );

(( CCSprite *)node). color = ccRED ;

// Action: 旋轉(zhuǎn) +縮放 .

CCRotateBy * rotate = [ CCRotateBy actionWithDuration : 4 angle : 360 ];

CCScaleTo * scaleDown = [ CCScaleTo actionWithDuration : 2 scale : 0 ];

CCScaleTo * scaleUp = [ CCScaleTo actionWithDuration : 2 scale : 1 ];

CCSequence * sequence = [ CCSequence actions :scaleDown, scaleUp, nil ];

sequence. tag = ActionTagGameLayerRotates ;

GameLayer * gameLayer = [ MultiLayerScene sharedLayer ]. gameLayer ;

// 重置 GameLayer 屬性 , 以便每次動畫都是以相同的狀態(tài)開始

[gameLayer stopActionByTag : ActionTagGameLayerRotates ];

[gameLayer setRotation : 0 ];

[gameLayer setScale : 1 ];

// 運行動畫

[gameLayer runAction :rotate];

[gameLayer runAction :sequence];

}

return isTouchHandled;

}

-( void ) ccTouchEnded:( UITouch *)touch withEvent:( UIEvent *)event

{

CCNode * node = [ self getChildByTag : UILayerTagFrameSprite ];

NSAssert ([node isKindOfClass :[ CCSprite class ]], @"node is not a CCSprite" );

// 色彩復(fù)原

(( CCSprite *)node). color = ccWHITE ;

}

@end

為了保證 uiLayer總是第一個收到touch事件,我們在 registerWithTouchDispatcher 方法中使用-1的priority。并且用 isTouchForMe 方法檢測touch是否處于Layer的范圍內(nèi)。如果在,touchBegan方法返回YES,表示“吃掉” touch事件(即不會傳遞到下一個Layer處理);否則,返回NO,傳遞給下一個Layer(GameLayer)處理。

而在 GameLayer中, registerWithTouchDispatcher 的priority是0

以下是 GameLayer代碼:

@interface GameLayer : CCLayer

{

CGPoint gameLayerPosition ;

CGPoint lastTouchLocation ;

}

@end

@interface GameLayer (PrivateMethods)

-( void ) addRandomThings;

@end

@implementation GameLayer

-( id ) init

{

if (( self = [ super init ]))

{

self . isTouchEnabled = YES ;

gameLayerPosition = self . position ;

CGSize screenSize = [[ CCDirector sharedDirector ] winSize ];

CCSprite * background = [ CCSprite spriteWithFile : @"grass.png" ];

background. position = CGPointMake (screenSize. width / 2 , screenSize. height / 2 );

[ self addChild :background];

CCLabel * label = [ CCLabel labelWithString : @"GameLayer" fontName : @"Marker Felt" fontSize : 44 ];

label. color = ccBLACK ;

label. position = CGPointMake (screenSize. width / 2 , screenSize. height / 2 );

label. anchorPoint = CGPointMake ( 0.5f , 1 );

[ self addChild :label];

[ self addRandomThings ];

self . isTouchEnabled = YES ;

}

return self ;

}

// node加上一個MoveBy的動作(其實就是在圍繞一個方框在繞圈)

-( void ) runRandomMoveSequence:( CCNode *)node

{

float duration = CCRANDOM_0_1 () * 5 + 1 ;

CCMoveBy * move1 = [ CCMoveBy actionWithDuration :duration position : CGPointMake (- 180 , 0 )];

CCMoveBy * move2 = [ CCMoveBy actionWithDuration :duration position : CGPointMake ( 0 , - 180 )];

CCMoveBy * move3 = [ CCMoveBy actionWithDuration :duration position : CGPointMake ( 180 , 0 )];

CCMoveBy * move4 = [ CCMoveBy actionWithDuration :duration position : CGPointMake ( 0 , 180 )];

CCSequence * sequence = [ CCSequence actions :move1, move2, move3, move4, nil ];

CCRepeatForever * repeat = [ CCRepeatForever actionWithAction :sequence];

[node runAction :repeat];

}

// 模擬一些游戲?qū)ο? ,為每個對象加上一些動作(繞圈) .

-( void ) addRandomThings

{

CGSize screenSize = [[ CCDirector sharedDirector ] winSize ];

for ( int i = 0 ; i < 4 ; i++)

{

CCSprite * firething = [ CCSprite spriteWithFile : @"firething.png" ];

firething. position = CGPointMake ( CCRANDOM_0_1 () * screenSize. width , CCRANDOM_0_1 () * screenSize. height );

[ self addChild :firething];

[ self runRandomMoveSequence :firething];

}

for ( int i = 0 ; i < 10 ; i++)

{

CCSprite * spider = [ CCSprite spriteWithFile : @"spider.png" ];

spider. position = CGPointMake ( CCRANDOM_0_1 () * screenSize. width , CCRANDOM_0_1 () * screenSize. height );

[ self addChild :spider];

[ self runRandomMoveSequence :spider];

}

}

-( void ) dealloc

{

CCLOG ( @"%@: %@" , NSStringFromSelector ( _cmd ), self );

// don't forget to call "super dealloc"

[ super dealloc ];

}

-( void ) registerWithTouchDispatcher

{

[[ CCTouchDispatcher sharedDispatcher ] addTargetedDelegate : self priority : 0 swallowsTouches : YES ];

}

-( BOOL ) ccTouchBegan:( UITouch *)touch withEvent:( UIEvent *)event

{

// 記錄開始touch時的位置 .

lastTouchLocation = [ MultiLayerScene locationFromTouch :touch];

// 先停止上一次動作,以免對本次拖動產(chǎn)生干擾 .

[ self stopActionByTag : ActionTagGameLayerMovesBack ];

// 吃掉所有 touche

return YES ;

}

-( void ) ccTouchMoved:( UITouch *)touch withEvent:( UIEvent *)event

{

// 記錄手指移動的位置

CGPoint currentTouchLocation = [ MultiLayerScene locationFromTouch :touch];

// 計算移動的距離

CGPoint moveTo = ccpSub ( lastTouchLocation , currentTouchLocation);

// 上面的計算結(jié)果要取反 .因為接下來是移動前景,而不是移動背景

moveTo = ccpMult (moveTo, - 1 );

lastTouchLocation = currentTouchLocation;

// 移動前景——修改 Layer的位置,將同時改變Layer所包含的node self . position = ccpAdd ( self . position , moveTo);

}

-( void ) ccTouchEnded:( UITouch *)touch withEvent:( UIEvent *)event

{

// 最后把 Layer的位置復(fù)原 .Action: 移動 +漸慢

CCMoveTo * move = [ CCMoveTo actionWithDuration : 1 position : gameLayerPosition ];

CCEaseIn * ease = [ CCEaseIn actionWithAction :move rate : 0.5f ];

ease. tag = ActionTagGameLayerMovesBack ;

[ self runAction :ease];

}

@end

為了讓程序運行起來更有趣, GameLayer中加入了一張青草的背景圖,以及一些游戲?qū)ο螅⒆屵@些對象在隨機地移動。這部分內(nèi)容不是我們關(guān)注的,我們需要關(guān)注的是幾個touch方法的處理。

1、 ccTouchBegan

由于 GameLayer是最后收到touch事件的Layer,我們不需要檢測touch是否在Layer范圍(因為傳給它的都是別的Layer“吃剩下”的touch)。所以GameLayer的touchBegan方法只是簡單的返回YES(“吃掉”所有touch)。

2 ccTouchMoved:

在這里我們計算手指移動的距離,然后讓 Layer作反向運動。為什么要作“反向”運動? 因為我們想制造一種屏幕隨著手指劃動的感覺,例如: 當(dāng)手向右劃動時,屏幕也要向右運動。當(dāng)然,iPhone不可能真的向右運動。要想模擬屏幕向右運動,只需讓游戲畫面向左運動即可。因為當(dāng)運動物體在向前移動時,如果假設(shè)運動物體固定不動,則可以認(rèn)為是參照物(或背景)在向后運動。

3、 ccTouchEnded:

在這里,我們把 Layer的位置恢復(fù)到原位。

四、其他

這一章還討論了很多有用的東西,比如“關(guān)卡”。是使用 Scene還是Layer作為游戲關(guān)卡?

作者還建議在設(shè)計 Sprite時使用聚合而不要使用繼承。即Sprite設(shè)計為不從CCNode繼承,而設(shè)計為普通的NSObject子類(在其中聚合了CCNode)。

此外還討論了 CCTargetToucheDelegate、CCProgressTimer、CCParallaxNode、vCCRibbon和CCMotionStreak。

這些東西可以豐富我們的理論知識,但沒有必要細(xì)讀。

Cocos2d開發(fā)系列(四)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产亚洲情侣一区二区无 | 波多野结衣亚洲 | 欧美激情久久欧美激情 | 懂色一区二区三区免费观看 | 午夜激情av| 午夜精品在线视频 | 天天操天天射天天舔 | 天天色踪合 | 色综合久久中文字幕综合网 | 久久夜色精品国产 | 久草视频在线资源 | 精品免费国产一区二区三区四区介绍 | 夜夜夜操操操 | 欧美在线 | 亚洲 | 天天干天天操天天舔 | 亚洲国产一区二区三区四区色欲 | 耽美男男肉文 | 国产精品福利短视在线播放频 | 亚洲一区二区三区高清 | 久久国产一区 | 色拍拍欧美视频在线看 | 精品无人乱码一区二区三区 | 97精品国产高清在线看入口 | 久久久中文| 91免费看 | 亚洲综合18p | 正在播放国产精品 | 亚洲视频免费在线观看 | 毛片性生活| 九九九国产在线 | 欧洲精品视频完整版在线 | 欧美性一区二区三区 | 久草视频在线免费播放 | 天天影视色香欲综合网老头 | 国产精品久久久久久久午夜 | 色综合天天天天做夜夜夜夜做 | 激情久久av一区av二区av三区 | 午夜资源 | 波多野结衣一区二区三区在线观看 | 一级特色黄大片 | 99国产精品视频免费观看 |