參考書目:Learning Cocos2D
這次要學的就是製作無限大的關卡。首先會放入一些雲朵,以隨機的速度從右邊移動到左邊,當雲朵移動到左邊螢幕外面時,他們會被重置到右邊的螢幕外面,讓雲朵一再的出現。其實這種方法跟射擊類遊戲很像,也可以運用在射擊類遊戲之中。
首先製作interface檔(iOS/Cocoa Touch/Objective-C class):
變數scrollingBatchNode是為了把雲朵等都放進去,避免呼叫太多的OpenGL ES渲染。再來換處理他的實作檔:
首先在實作檔中建立PlatformScrollingLayer的category,然後實作init方法,首先啟動觸碰,創造靜態背景,依照設備不同選取不同的捲動atlas,然後加入雲朵,建立icon,最後回傳self。
再來創造背景:
這也是很簡單,再來創造雲朵:
首先定一個參數,0到5,來將雲朵的sprite檔案名稱叫出來,然後用叫出來的檔案名稱呼叫雲朵的Sprite,再將這些Sprite放到Batch node裡面去,最後是將雲朵的sprite重新設定位置。
再來是建立重新設定雲朵的方法:
首先是取得螢幕大小,將參數存到CCNode變數中,然後取得雲朵的寬度。再來是將雲朵設在螢幕的右邊畫面外再外移一個雲朵寬加上1單位,y位置是透過隨機數目去除螢幕高度得到的結果,然後將雲朵重新設在新的x和y。再來是使用兩個常數(可以放在實作檔的最上面):
本來我是想直接用數字就好,但這樣不好理解,所以保持原來的寫法,一個是雲朵移動最大的時間,一個是最小的時間,if迴圈是處理如果算出來的值太小的話,就以最小時間為主。
然後要設定雲朵移動的方向,所以將螢幕大小的寬度乘上負一,再減去一單位,這樣雲朵就會往左邊移動,然後就用這個CG位置來製作雲朵移動的動畫,分成moveAciton和resetAction,一個是移動,一個是重置,最後讓雲朵去執行這個動畫。然後計算新的z值,這要稍微說明一下。
雲朵最大的移動期間是10,如果這雲朵的移動期間是2,那他新的z值就是10-2=8,如果另一個雲朵移動期間是7,那他新的z值就是10-7=3,這是什麼意思呢?移動越快的(移動期間越短的)以視差來說,就應該安排在離使用者比較近的位置,這表示他的z值要大,反之,移動越慢的,要越遠離使用者。
再來,建立init方法:
這一次我把它放在離左邊螢幕比較近的地方。這邊要說明一下nextZValue是什麼。這是要把icon放在所有雲朵的上面,他首先對scrollingBatchNode要求他所有的children的CCArray,然後計算CCArray裡面有多少的元素。這樣的話,不論雲朵有多少個,都可以動態地獲得一個z值保持icon在所有雲朵的上面。
最後是加上觸控方法:
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation =
[[CCDirector sharedDirector] convertToGL:touchLocation];
//touchLocation = [self convertToNodeSpace:touchLocation];
id moveIcon = [CCMoveTo actionWithDuration:1.0f position:touchLocation];
[icon runAction:moveIcon];
}
}
再來就是要建立Scene(iOS/Cocoa touch/Objective-C class):
#import "CCScene.h"
#import "cocos2d.h"
#import "PlatformScrollingLayer.h"
@interface PlatformScene : CCScene
@end
然後在實作檔中建立init方法:
-(id) init {
self = [super init];
if (self != nil) {
PlatformScrollingLayer *scrollingLayer = [PlatformScrollingLayer node];
[self addChild:scrollingLayer];
}
return self;
}
接著就編譯吧,你應該會看到icon在空中飛,然後可以按一下讓他移動。
朝著射擊遊戲邁進吧!
接著我想再追加一點功能,讓它變成更具體的射擊遊戲,請在PlatformScrollingLayer.m中加上此功能:
-(void) shootBullets {
CGSize screenSize = [CCDirector sharedDirector].winSize;
CCSprite *fakeBullet = [CCSprite spriteWithFile:@"Icon-Small.png"];
CGSize bulletSize = [fakeBullet boundingBox].size;
CGPoint bulletLocation = icon.position;
fakeBullet.position = bulletLocation;
[self addChild:fakeBullet z:10 tag:kBullet];
float targetLocation = screenSize.width + bulletSize.width + 1;
id shootAction = [CCMoveTo actionWithDuration:1.5f position:ccp(targetLocation, bulletLocation.y)];
[fakeBullet runAction:shootAction];
}
然後在init裡面追加有塗顏色的那一行:
[self createIcon];
[self schedule:@selector(shootBullets) interval:1];
注意,如果你不是把這code寫在[self createIcon];之後的話,你會發現編譯時,子彈會從左下角射出,由此你可以知道icon的預設位置其實是在螢幕的左下角。
既然有update,就當然不能忘了增加update方法給它呼叫:
-(void) update:(ccTime *) dt {
}
空空如也的update方法。
現在編譯看看,有沒有發現它在發射小圖示?雖然目前使用的方法還很粗糙,但提供給各位作個參考,今後會繼續更新和追加!
這次要學的就是製作無限大的關卡。首先會放入一些雲朵,以隨機的速度從右邊移動到左邊,當雲朵移動到左邊螢幕外面時,他們會被重置到右邊的螢幕外面,讓雲朵一再的出現。其實這種方法跟射擊類遊戲很像,也可以運用在射擊類遊戲之中。
開始
首先製作interface檔(iOS/Cocoa Touch/Objective-C class):
#import "CCLayer.h"
#import "cocos2d.h"
@interface PlatformScrollingLayer : CCLayer{
CCSpriteBatchNode *scrollingBatchNode;
}
@end
變數scrollingBatchNode是為了把雲朵等都放進去,避免呼叫太多的OpenGL ES渲染。再來換處理他的實作檔:
#import "PlatformScrollingLayer.h"
@interface PlatformScrollingLayer (PrivateMethod)
-(void)resetCloudWithCloud:(id) node;
-(void)createCloud;
-(void)createIcon; //createVikingAndPlateform
-(void)createStaticBackground;
@end
@implementation PlatformScrollingLayer
-(id) init {
self = [super init];
if (self != nil) {
srandom(time(NULL));
self.isTouchEnabled = YES;
[self createStaticBackground];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:@"ScrollingCloudsTextureAtlas.plist"];
scrollingBatchNode = [CCSpriteBatchNode
batchNodeWithFile:@"ScrollingCloudsTextureAtlas.png"];
}else {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:@"ScrollingCloudsTextureAtlasiPhone.plist"];
scrollingBatchNode = [CCSpriteBatchNode
batchNodeWithFile:@"ScrollingCloudsTextureAtlasiPhone.png"];
}
[self addChild:scrollingBatchNode];
for (int x = 0; x < 25; x++) {
[self createCloud];
}
[self createIcon];
}
return self;
}
@end
首先在實作檔中建立PlatformScrollingLayer的category,然後實作init方法,首先啟動觸碰,創造靜態背景,依照設備不同選取不同的捲動atlas,然後加入雲朵,建立icon,最後回傳self。
再來創造背景:
-(void)createStaticBackground {
CGSize screenSize = [CCDirector sharedDirector].winSize;
CCSprite *background;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
background = [CCSprite spriteWithFile:@"tiles_grad_bkgrnd.png"];
}else {
background = [CCSprite spriteWithFile:@"tiles_grad_bkgrndiPhone.png"];
}
[background setPosition:ccp(screenSize.width/2.0f, screenSize.height/2.0f)];
[self addChild:background];
}
這也是很簡單,再來創造雲朵:
-(void) createCloud {
int cloudToDraw = random() % 6;
NSString *cloudFileName = [NSString stringWithFormat:@"tiles_cloud%d.png", cloudToDraw];
CCSprite *cloudSprite = [CCSprite spriteWithSpriteFrameName:cloudFileName];
[scrollingBatchNode addChild:cloudSprite];
[self resetCloudWithCloud:cloudSprite];
}
首先定一個參數,0到5,來將雲朵的sprite檔案名稱叫出來,然後用叫出來的檔案名稱呼叫雲朵的Sprite,再將這些Sprite放到Batch node裡面去,最後是將雲朵的sprite重新設定位置。
再來是建立重新設定雲朵的方法:
-(void)resetCloudWithNode:(id)node {
CGSize screenSize = [CCDirector sharedDirector].winSize;
CCNode *cloud = (CCNode *) node;
float xOffSet = [cloud boundingBox].size.width;
int xPosition = screenSize.width + 1 + xOffSet;
int yPosition = random() % (int) screenSize.height;
[cloud setPosition:ccp(xPosition, yPosition)];
int moveDuration = random() % kMaxCloudMoveDuration;
if (moveDuration < kMinCloudMoveDuration) {
moveDuration = kMinCloudMoveDuration;
}
float offScreenXPosition = (xOffSet * -1) -1;
id moveAction = [CCMoveTo actionWithDuration:moveDuration
position:ccp(offScreenXPosition, [cloud position].y)];
id resetAction = [CCCallFuncN actionWithTarget:self selector:@selector(resetCloudWithNode:)];
id sequenceAction = [CCSequence actions:moveAction, resetAction, nil];
[cloud runAction:sequenceAction];
int newZOrder = kMaxCloudMoveDuration - moveDuration;
[scrollingBatchNode reorderChild:cloud z:newZOrder];
}
首先是取得螢幕大小,將參數存到CCNode變數中,然後取得雲朵的寬度。再來是將雲朵設在螢幕的右邊畫面外再外移一個雲朵寬加上1單位,y位置是透過隨機數目去除螢幕高度得到的結果,然後將雲朵重新設在新的x和y。再來是使用兩個常數(可以放在實作檔的最上面):
#define kMaxCloudMoveDuration 10
#define kMinCloudMoveDuration 1
本來我是想直接用數字就好,但這樣不好理解,所以保持原來的寫法,一個是雲朵移動最大的時間,一個是最小的時間,if迴圈是處理如果算出來的值太小的話,就以最小時間為主。
然後要設定雲朵移動的方向,所以將螢幕大小的寬度乘上負一,再減去一單位,這樣雲朵就會往左邊移動,然後就用這個CG位置來製作雲朵移動的動畫,分成moveAciton和resetAction,一個是移動,一個是重置,最後讓雲朵去執行這個動畫。然後計算新的z值,這要稍微說明一下。
雲朵最大的移動期間是10,如果這雲朵的移動期間是2,那他新的z值就是10-2=8,如果另一個雲朵移動期間是7,那他新的z值就是10-7=3,這是什麼意思呢?移動越快的(移動期間越短的)以視差來說,就應該安排在離使用者比較近的位置,這表示他的z值要大,反之,移動越慢的,要越遠離使用者。
再來,建立init方法:
-(void) createIcon {
CGSize screenSize = [CCDirector sharedDirector].winSize;
int nextZValue = [scrollingBatchNode children].count + 1;
icon = [CCSprite spriteWithFile:@"Icon-Small-50.png"];
icon.position = ccp(20, screenSize.height/2.0f);
[self addChild:icon z:nextZValue];
}
CGSize screenSize = [CCDirector sharedDirector].winSize;
int nextZValue = [scrollingBatchNode children].count + 1;
icon = [CCSprite spriteWithFile:@"Icon-Small-50.png"];
icon.position = ccp(20, screenSize.height/2.0f);
[self addChild:icon z:nextZValue];
}
這一次我把它放在離左邊螢幕比較近的地方。這邊要說明一下nextZValue是什麼。這是要把icon放在所有雲朵的上面,他首先對scrollingBatchNode要求他所有的children的CCArray,然後計算CCArray裡面有多少的元素。這樣的話,不論雲朵有多少個,都可以動態地獲得一個z值保持icon在所有雲朵的上面。
最後是加上觸控方法:
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInView:[touch view]];
touchLocation =
[[CCDirector sharedDirector] convertToGL:touchLocation];
//touchLocation = [self convertToNodeSpace:touchLocation];
id moveIcon = [CCMoveTo actionWithDuration:1.0f position:touchLocation];
[icon runAction:moveIcon];
}
}
建立Scene
再來就是要建立Scene(iOS/Cocoa touch/Objective-C class):
#import "CCScene.h"
#import "cocos2d.h"
#import "PlatformScrollingLayer.h"
@interface PlatformScene : CCScene
@end
然後在實作檔中建立init方法:
-(id) init {
self = [super init];
if (self != nil) {
PlatformScrollingLayer *scrollingLayer = [PlatformScrollingLayer node];
[self addChild:scrollingLayer];
}
return self;
}
接著就編譯吧,你應該會看到icon在空中飛,然後可以按一下讓他移動。
朝著射擊遊戲邁進吧!
接著我想再追加一點功能,讓它變成更具體的射擊遊戲,請在PlatformScrollingLayer.m中加上此功能:
-(void) shootBullets {
CGSize screenSize = [CCDirector sharedDirector].winSize;
CCSprite *fakeBullet = [CCSprite spriteWithFile:@"Icon-Small.png"];
CGSize bulletSize = [fakeBullet boundingBox].size;
CGPoint bulletLocation = icon.position;
fakeBullet.position = bulletLocation;
[self addChild:fakeBullet z:10 tag:kBullet];
float targetLocation = screenSize.width + bulletSize.width + 1;
id shootAction = [CCMoveTo actionWithDuration:1.5f position:ccp(targetLocation, bulletLocation.y)];
[fakeBullet runAction:shootAction];
}
然後在init裡面追加有塗顏色的那一行:
[self createIcon];
[self schedule:@selector(shootBullets) interval:1];
注意,如果你不是把這code寫在[self createIcon];之後的話,你會發現編譯時,子彈會從左下角射出,由此你可以知道icon的預設位置其實是在螢幕的左下角。
既然有update,就當然不能忘了增加update方法給它呼叫:
-(void) update:(ccTime *) dt {
}
空空如也的update方法。
現在編譯看看,有沒有發現它在發射小圖示?雖然目前使用的方法還很粗糙,但提供給各位作個參考,今後會繼續更新和追加!
留言
張貼留言