大熊貓豬·侯佩原創或翻譯作品.歡迎轉載,轉載請注明出處.
如果覺得寫的不好請告訴我,如果覺得不錯請多多支持點贊.謝謝! hopy ;)
通用的星星類已經完成了,下面我們來實現具體的變長和縮短道具.
我們想實現如下功能:在掉落變長星之後,如果反彈棒接到它,則使反彈棒的長度變為原先的2倍.
看似很簡單,但實際有一個問題.你不能僅僅延長反彈棒精靈紋理的長度,因為你在這個游戲中使用的是物理引擎,反彈棒的物理對象的大小是不可以在游戲運行中隨意變化的.
所以我們需要想辦法延長反彈棒的物理大小,當然同時也要延長其精靈幀的大小,這樣才能相互配合達到逼真的延長效果.
這裡本貓使用偷梁換柱的方法,用Ai制作一個延長後的反彈棒,並調整它的物理對象適應新的長度,然後在反彈棒需要變長時,用新長棒代替原來的短棒.
首先用Ai制作一個長的反彈棒.然後在SpriteBuilder中創建一個StickLonger.ccb文件,設置好其物理對象的邊界:
回到Xcode中,在Stick類的接口文件中添加一個新屬性:
+(instancetype)stickLonger;
在Stick.m中實現該類方法:
+(instancetype)stickLonger{
Stick *stick = (Stick*)[CCBReader load:@Elements/StickLonger];
stick.name = @stickLonger;
return stick;
}
可以看到除了stick對象發生了變化,其名稱也和普通的stick有所區別.
回到GameScene.m中在小球與磚塊的碰撞處理中添加以下一句:
[Star spawnStar:(Brick*)brick];
接著我們要處理星星和反彈棒接觸時的事件:
-(BOOL)ccPhysicsCollisionBegin:(CCPhysicsCollisionPair *)pair star:(CCNode *)star
stick:(CCNode *)stick{
//star形狀是五角星,可能會在短時間內多次發生碰撞;但在star已經由第一次碰撞時刪除掉從而導致star為nil
//所以這裡要確保star不為nil.
//star刪除也不能保證其一定為nil,所以增加判斷其parent是否為nil.(2015-11-09 2006)
StarType starType;
@synchronized(self){
if (!star || !star.parent) {
return YES;
}
starType = ((Star*)star).starType;
[star removeFromParentAndCleanup:YES];
}
switch (starType) {
case starTypeStickLonger:
@synchronized(self){
[self scheduleBlock:^(CCTimer *timer){
[Star doStickLongerWork:self.stickInGameScene];
} delay:0];
}
break;
case starTypeUnknown:
case starTypeMax:
NSAssert(NO, @error star type!);
break;
default:
break;
}
return YES;
}
為什麼其中使用了同步偽指令呢?因為其中的代碼會改變GameScene中反彈棒的狀態,而該狀態在GameScene中也可能同時被改變,所以我們需要將其做同步處理.
最後我們在Star類中添加doStickLongerWork方法:
+(void)doStickLongerWork:(Stick *)stick{
GameScene *gameScene = [GameScene sharedGameScene];
CCPhysicsNode *physicsWorld = (CCPhysicsNode*)stick.parent;
@synchronized(gameScene){
if ([stick.name isEqualToString:@stickLonger]) {
return;
}
if ([stick.name isEqualToString:@stickShorter]) {
Stick *stickNormal = [Stick stickNormal];
stickNormal.position = stick.position;
[stick removeFromParent];
//[physicsWorld removeChild:stick cleanup:YES];
[physicsWorld addChild:stickNormal];
gameScene.stickInGameScene = stickNormal;
return;
}
}
CGPoint position = stick.position;
__block Stick *stickLonger;
@synchronized(gameScene){
stickLonger = [Stick stickLonger];
//[physicsWorld removeChild:stick cleanup:YES];
[stick removeFromParent];
stickLonger.position = position;
[physicsWorld addChild:stickLonger];
stickLonger.visible = NO;
gameScene.stickInGameScene = stickLonger;
CCSprite *stickNode = (CCSprite*)[CCBReader load:@Elements/StickNode];
stickNode.position = stickLonger.position;
[gameScene addChild:stickNode z:50];
CCActionScaleTo *longerAction = [CCActionScaleTo actionWithDuration:0.4f scaleX:2.0f scaleY:1.0f];
CCActionCallBlock *blk = [CCActionCallBlock actionWithBlock:^{
[stickNode removeFromParent];
stickLonger.visible = YES;
}];
CCActionSequence *seq = [CCActionSequence actions:longerAction,blk,nil];
[stickNode runAction:seq];
}
[stickLonger scheduleBlock:^(CCTimer *timer){
@synchronized(gameScene){
Stick *stickNormal = [Stick stickNormal];
stickNormal.position = stickLonger.position;
[stickLonger removeFromParent];
[physicsWorld addChild:stickNormal];
gameScene.stickInGameScene = stickNormal;
}
} delay:10];
}
你看到以上方法的第一感覺估計是:好長啊!其實內容很好理解,基本上它做了如下幾件事:
如果反彈棒已經變長了,則啥也不做返回 如果反彈棒處在變短狀態,則恢復其原本大小.這裡考慮到了其他可能改變反彈棒的疊加效果.在反彈棒變短的代碼邏輯中,我們同樣會考慮到這一點. 創建一個變長的反彈棒對象,但暫時將其隱藏,因為我們還想實現一個反彈棒由短變長的動畫效果.因為這個動畫很短,所以不會影響用戶的操控.如果你希望更完美的實現用戶操控的連續性,你可以將反彈棒的觸摸處理臨時”嫁接”到這個臨時對象上,當然是有點麻煩,篇幅原因,這裡只是點到為止. 在10秒之後將反彈棒恢復為原來大小變長道具制作完畢,我們現在編譯運行app,看一下效果: