<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                《Learn IPhone andiPad Cocos2d Game Delevopment》的第5章。 ## 一、使用多場景 很少有游戲只有一個場景。這個例子是這個樣子的:![](https://box.kancloud.cn/2016-05-04_572a0b97c29b4.gif) 這個Scene中用到了兩個Layer,一個Layer位于屏幕上方,標有”Herebe your Game Scores etc“字樣的標簽,用于模擬游戲菜單。一個Layer位于屏幕下方,一塊綠色的草地上有一些隨機游動的蜘蛛和怪物,模擬了游戲的場景。 1、加入新場景 一個場景是一個Scene類。加入新場景就是加入更多的Scene類。 有趣的是場景之間的切換。使用[CCDirectorreplaceScene]方法轉場時,CCNode有3個方法會被調用:OnEnter、OnExit、onEnterTransitionDidFinish。 覆蓋這3個方法時要牢記,始終要調用super的方法,避免程序的異常(比如內存泄露或場景不響應用戶動作)。 ~~~ -(void)onEnter { // node的 init方法后調用. // 如果使用CCTransitionScene方法,在轉場開始后調用. [superonEnter]; } -(void )onEnterTransitionDidFinish { // onEnter方法后調用. // 如果使用CCTransitionScene方法,在轉場結束后調用. [superonEnterTransitionDidFinish]; } -(void)onExit { // node的dealloc 方法前調用. // 如果使用CCTransitionScene方法,在轉場結束時調用. [superonExit]; } ~~~ 當場景變化時,有時候需要讓某個node干點什么,這時這3個方法就派上用場了。 與在node的init方法和dealloc方法中做同樣的事情不同,在onEnter方法執行時,場景已經初始化了;而在onExit方法中,場景的node仍然是存在的。 這樣,在進行轉場時,你就可以暫停動畫或隱藏用戶界面元素,一直到轉場完成。這些方法調用的先后順序如下(使用replaceScene 方法): 1. 第2個場景的 scene方法 2. 第2個場景的 init方法 3. 第2個場景的 onEnter方法 4. 轉場 5. 第1個場景的 onExit方法 6. 第2個場景的 onEnterTransitionDidFinish方法 7. 第1個場景的 dealloc方法 ## 二、請稍候?? 切換場景時,如果場景的加載是一個比較耗時的工作,有必要用一個類似“Loading,please waiting…”的場景來過渡一下。用于在轉場時過渡的場景是一個“輕量級”的Scene類,可以顯示一些簡單的提示內容: ~~~ typedefenum { 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 = [CCLabellabelWithString:@"Loading ..." fontName:@"Marker Felt" fontSize:64]; CGSize size = [[CCDirectorsharedDirector] winSize]; label.position =CGPointMake(size.width / 2, size.height / 2); [self addChild:label]; [self scheduleUpdate]; } returnself; } -(void) update:(ccTime)delta { [selfunscheduleAllSelectors]; 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能用于多個場景的轉場,而不是固定地只能在某個場景的切換時使用。繼續擴展這個枚舉的成員,使LoadingScene能適用與更多目標Scene的轉場。 sceneWithTargetScene方法中返回了一個autorelease的對象。在coco2d自己的類中也是一樣的,你要記住在每個靜態的初始化方法中使用autorelease。 在方法中,構造了一個CCLabel,然后調用scheduleUpdate方法。scheduleUpdate方法會在下一個時間(約一幀)后調用update方法。在update方法中,我們根據sceneWithTargetScene方法中指定的枚舉參數,切換到另一個scene。在這個scene的加載完成之前,LoadingScene會一直顯示并且凍結用戶的事件響應。 我們不能直接在初始化方法initWithTargetScene中直接切換scene,這會導致程序崩潰。記住,在一個Node還在初始化的時候,千萬不要在這個scene上調用CCDirector的replaceScene方法。 LoadingScene的使用很簡單,跟一般的scene一樣: ~~~ CCScene* newScene = [LoadingScenesceneWithTargetScene:TargetSceneFirstScene]; [[CCDirectorsharedDirector] replaceScene:newScene]; ~~~ ## 三、使用Layer Layer類似Photoshop中層的概念,在一個scene中可以有多個Layer: ~~~ typedefenum { LayerTagGameLayer, LayerTagUILayer, } MultiLayerSceneTags; typedefenum { ActionTagGameLayerMovesBack, ActionTagGameLayerRotates, }MultiLayerSceneActionTags; @classGameLayer; @classUserInterfaceLayer; @interface MultiLayerScene :CCLayer { boolisTouchForUserInterface; } +(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, @"MultiLayerScenenot available!"); returnmultiLayerSceneInstance; } -(GameLayer*) gameLayer { CCNode* layer = [selfgetChildByTag:LayerTagGameLayer]; NSAssert([layer isKindOfClass:[GameLayerclass]], @"%@: not aGameLayer!", NSStringFromSelector(_cmd)); return (GameLayer*)layer; } -(UserInterfaceLayer*) uiLayer { CCNode* layer = [[MultiLayerScenesharedLayer] getChildByTag:LayerTagUILayer]; NSAssert([layer isKindOfClass:[UserInterfaceLayerclass]], @"%@: not aUserInterfaceLayer!", NSStringFromSelector(_cmd)); return (UserInterfaceLayer*)layer; } +(CGPoint) locationFromTouch:(UITouch*)touch { CGPoint touchLocation = [touchlocationInView: [touch view]]; return [[CCDirectorsharedDirector] convertToGL:touchLocation]; } +(CGPoint) locationFromTouches:(NSSet*)touches { return [selflocationFromTouch:[touches anyObject]]; } +(id) scene { CCScene* scene = [CCScenenode]; MultiLayerScene* layer = [MultiLayerScenenode]; [scene addChild:layer]; return scene; } -(id) init { if ((self = [superinit])) { NSAssert(multiLayerSceneInstance == nil, @"anotherMultiLayerScene is already in use!"); multiLayerSceneInstance = self; GameLayer* gameLayer = [GameLayernode]; [selfaddChild:gameLayerz:1tag:LayerTagGameLayer]; UserInterfaceLayer* uiLayer = [UserInterfaceLayernode]; [selfaddChild:uiLayerz:2tag:LayerTagUILayer]; } returnself; } -(void) dealloc { CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self); [superdealloc]; } @end ~~~ MultiLayerScene 中使用了多個Layer:一個GameLayerh 和一個UserInterfaceLayer 。 MultiLayerScene 使用了靜態成員multiLayerSceneInstance 來實現單例。 MultiLayerScene也是一個Layer,其node方法實際上調用的是實例化方法init——在其中,我們加入了兩個Layer,分別用兩個枚舉LayerTagGameLayer 和LayerTagUILayer 來檢索,如屬性方法gameLayer和uiLayer所示。 uiLayer是一個UserInterfaceLayer,用來和用戶交互,在這里實際上是在屏幕上方放置一個菜單,可以把游戲的一些統計數字比如:積分、生命值放在這里: ~~~ typedefenum { UILayerTagFrameSprite, }UserInterfaceLayerTags; @interface UserInterfaceLayer :CCLayer { } -(bool) isTouchForMe:(CGPoint)touchLocation; @end @implementation UserInterfaceLayer -(id) init { if ((self = [superinit])) { CGSize screenSize = [[CCDirectorsharedDirector] winSize]; CCSprite* uiframe = [CCSpritespriteWithFile:@"ui-frame.png"]; uiframe.position = CGPointMake(0, screenSize.height); uiframe.anchorPoint = CGPointMake(0, 1); [selfaddChild:uiframe z:0tag:UILayerTagFrameSprite]; // 用Label模擬UI控件( 這個Label沒有什么作用,僅僅是演示). CCLabel* label = [CCLabellabelWithString:@"Here be yourGame Scores etc"fontName:@"Courier"fontSize:22]; label.color = ccBLACK; label.position = CGPointMake(screenSize.width / 2, screenSize.height); label.anchorPoint = CGPointMake(0.5f, 1); [selfaddChild:label]; self.isTouchEnabled = YES; } returnself; } -(void) dealloc { CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self); [superdealloc]; } -(void)registerWithTouchDispatcher { [[CCTouchDispatchersharedDispatcher] addTargetedDelegate:selfpriority:-1swallowsTouches:YES]; } // 判斷觸摸是否位于有效范圍內. -(bool) isTouchForMe:(CGPoint)touchLocation { CCNode* node = [selfgetChildByTag:UILayerTagFrameSprite]; returnCGRectContainsPoint([node boundingBox], touchLocation); } -(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event { CGPoint location = [MultiLayerScenelocationFromTouch:touch]; bool isTouchHandled = [selfisTouchForMe:location]; if (isTouchHandled) { // 顏色改變為紅色,表示接收到觸摸事件. CCNode* node = [selfgetChildByTag:UILayerTagFrameSprite]; NSAssert([node isKindOfClass:[CCSpriteclass]], @"node is not a CCSprite"); ((CCSprite*)node).color = ccRED; // Action:旋轉+縮放. CCRotateBy* rotate = [CCRotateByactionWithDuration:4angle:360]; CCScaleTo* scaleDown = [CCScaleToactionWithDuration:2scale:0]; CCScaleTo* scaleUp = [CCScaleToactionWithDuration:2scale:1]; CCSequence* sequence = [CCSequenceactions:scaleDown, scaleUp, nil]; sequence.tag = ActionTagGameLayerRotates; GameLayer* gameLayer = [MultiLayerScenesharedLayer].gameLayer; // 重置GameLayer 屬性,以便每次動畫都是以相同的狀態開始 [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 = [selfgetChildByTag:UILayerTagFrameSprite]; NSAssert([node isKindOfClass:[CCSpriteclass]], @"node is not aCCSprite"); // 色彩復原 ((CCSprite*)node).color = ccWHITE; } @end ? ~~~ 為了保證uiLayer總是第一個收到touch事件,我們在 registerWithTouchDispatcher 方法中使用-1的priority。并且用 isTouchForMe 方法檢測touch是否處于Layer的范圍內。如果在,touchBegan方法返回YES,表示“吃掉”touch事件(即不會傳遞到下一個Layer處理);否則,返回NO,傳遞給下一個Layer(GameLayer)處理。 而在GameLayer中,registerWithTouchDispatcher 的priority是0 以下是GameLayer代碼: ~~~ @interface GameLayer : CCLayer { CGPointgameLayerPosition; CGPointlastTouchLocation; } @end @interface GameLayer(PrivateMethods) -(void) addRandomThings; @end @implementation GameLayer -(id) init { if ((self = [superinit])) { self.isTouchEnabled = YES; gameLayerPosition = self.position; CGSize screenSize = [[CCDirectorsharedDirector] winSize]; CCSprite* background = [CCSpritespriteWithFile:@"grass.png"]; background.position = CGPointMake(screenSize.width / 2, screenSize.height / 2); [selfaddChild:background]; CCLabel* label = [CCLabellabelWithString:@"GameLayer"fontName:@"MarkerFelt"fontSize:44]; label.color = ccBLACK; label.position = CGPointMake(screenSize.width / 2, screenSize.height / 2); label.anchorPoint = CGPointMake(0.5f, 1); [selfaddChild:label]; [selfaddRandomThings]; self.isTouchEnabled = YES; } returnself; } // 為node加上一個MoveBy的動作(其實就是在圍繞一個方框在繞圈) -(void)runRandomMoveSequence:(CCNode*)node { float duration = CCRANDOM_0_1() * 5 + 1; CCMoveBy* move1 = [CCMoveByactionWithDuration:duration position:CGPointMake(-180, 0)]; CCMoveBy* move2 = [CCMoveByactionWithDuration:duration position:CGPointMake(0, -180)]; CCMoveBy* move3 = [CCMoveByactionWithDuration:duration position:CGPointMake(180, 0)]; CCMoveBy* move4 = [CCMoveByactionWithDuration:duration position:CGPointMake(0, 180)]; CCSequence* sequence = [CCSequenceactions:move1, move2, move3,move4, nil]; CCRepeatForever* repeat = [CCRepeatForeveractionWithAction:sequence]; [node runAction:repeat]; } // 模擬一些游戲對象,為每個對象加上一些動作(繞圈). -(void) addRandomThings { CGSize screenSize = [[CCDirectorsharedDirector] winSize]; for (int i = 0; i < 4; i++) { CCSprite* firething = [CCSpritespriteWithFile:@"firething.png"]; firething.position = CGPointMake(CCRANDOM_0_1() * screenSize.width, CCRANDOM_0_1() * screenSize.height); [selfaddChild:firething]; [selfrunRandomMoveSequence:firething]; } for (int i = 0; i < 10; i++) { CCSprite* spider = [CCSpritespriteWithFile:@"spider.png"]; spider.position = CGPointMake(CCRANDOM_0_1() * screenSize.width, CCRANDOM_0_1() * screenSize.height); [selfaddChild:spider]; [selfrunRandomMoveSequence:spider]; } } -(void) dealloc { CCLOG(@"%@: %@", NSStringFromSelector(_cmd), self); //don't forget to call "super dealloc" [superdealloc]; } -(void)registerWithTouchDispatcher { [[CCTouchDispatchersharedDispatcher] addTargetedDelegate:selfpriority:0swallowsTouches:YES]; } -(BOOL) ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event { // 記錄開始touch時的位置. lastTouchLocation = [MultiLayerScenelocationFromTouch:touch]; //先停止上一次動作,以免對本次拖動產生干擾. [selfstopActionByTag:ActionTagGameLayerMovesBack]; //吃掉所有touche returnYES; } -(void) ccTouchMoved:(UITouch*)touch withEvent:(UIEvent *)event { //記錄手指移動的位置 CGPoint currentTouchLocation =[MultiLayerScenelocationFromTouch:touch]; //計算移動的距離 CGPoint moveTo = ccpSub(lastTouchLocation,currentTouchLocation); //上面的計算結果要取反.因為接下來是移動前景,而不是移動背景 moveTo = ccpMult(moveTo,-1); lastTouchLocation =currentTouchLocation; //移動前景——修改Layer的位置,將同時改變Layer所包含的nodeself.position = ccpAdd(self.position, moveTo); } -(void) ccTouchEnded:(UITouch*)touch withEvent:(UIEvent *)event { //最后把Layer的位置復原.Action:移動+漸慢 CCMoveTo* move = [CCMoveToactionWithDuration:1position:gameLayerPosition]; CCEaseIn* ease = [CCEaseInactionWithAction:move rate:0.5f]; ease.tag =ActionTagGameLayerMovesBack; [selfrunAction:ease]; } @end ~~~ 為了讓程序運行起來更有趣,GameLayer中加入了一張青草的背景圖,以及一些游戲對象,并讓這些對象在隨機地移動。這部分內容不是我們關注的,我們需要關注的是幾個touch方法的處理。 1、ccTouchBegan : 由于GameLayer是最后收到touch事件的Layer,我們不需要檢測touch是否在Layer范圍(因為傳給它的都是別的Layer“吃剩下”的touch)。所以GameLayer的touchBegan方法只是簡單的返回YES(“吃掉”所有touch)。 2、ccTouchMoved: 在這里我們計算手指移動的距離,然后讓Layer作反向運動。為什么要作“反向”運動?因為我們想制造一種屏幕隨著手指劃動的感覺,例如: 當手向右劃動時,屏幕也要向右運動。當然,iPhone不可能真的向右運動。要想模擬屏幕向右運動,只需讓游戲畫面向左運動即可。因為當運動物體在向前移動時,如果假設運動物體固定不動,則可以認為是參照物(或背景)在向后運動。 3、ccTouchEnded: 在這里,我們把Layer的位置恢復到原位。 ? ## 四、其他 這一章還討論了很多有用的東西,比如“關卡”。是使用Scene還是Layer作為游戲關卡? 作者還建議在設計Sprite時使用聚合而不要使用繼承。即Sprite設計為不從CCNode繼承,而設計為普通的NSObject子類(在其中聚合了CCNode)。 此外還討論了CCTargetToucheDelegate、CCProgressTimer、CCParallaxNode、vCCRibbon和CCMotionStreak。 這些東西可以豐富我們的理論知識,但沒有必要細讀。 ?
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看