Más contenido relacionado
La actualidad más candente (20)
Similar a ㉖cocos2dを覚えよう! (7)
Más de Nishida Kansuke (20)
㉖cocos2dを覚えよう!
- 2. 動作環境
• Mac OS X 10.8 Mountain Lion
• xcode 4.5.2
• cocos2d for iPhone 2.0
http://www.cocos2d-iphone.org/
- 4. もくじ
• 忍ベーダー
• 敵の移動
• 手裏剣
• 当たり判定
• 点数の増加とレベル
• 改造してみよう!
- 7. 4inch対応
• 今回は画面上部の見え
る部分を変更すること
で対応します
• スコアなどの文字は、
画面の高さをもとに表
示して、画面内に収ま
るようにします。
• 忍ベーダーや手裏剣は、
4inchの座標で計算しま
す。3.5inchでも得ない
画面外の部分でも処理
を行います。
- 10. メインscene
• フロントlayer
– スコア
• スティックlayer
– 左右のボタン
• メインlayer
– READY? 、START!
– ゲームオーバー
– 忍ベーダー、手裏剣
– 忍者
– 点線、床
• 背景layer
– 背景画像
- 12. 音楽素材について①
• 音楽素材については、PANICPUMPKIN様
のご好意により、使用させていただいてい
ます。
• http://panicpumpkin.omiki.com/
• ゲームBGMに特化したサイトなのでおす
すめ!(曲数も多いです)
• 利用報告、 著作表記、リンクなどの明記
不要で商用利用可能の音楽素材を多数公
開されています。
- 16. Invader.h
@interface Invader : NSObject{
}
@property float score;
@property float speed;
@property float minX;
@property float maxX;
@property int life;
@property (nonatomic, retain) CCSprite *sprite;
@property (nonatomic, retain) MainLayer *mainLayer;
-(BOOL)damage:(int)pow;
-(BOOL)tick:(ccTime)dt;
@end
- 17. Invader.h
@interface Invader : NSObject{
}
@property float score;
@property float speed;
@property float minX;
@property float maxX;
@property int life;
@property (nonatomic, retain) CCSprite *sprite;
@property (nonatomic, retain) MainLayer *mainLayer;
-(BOOL)damage:(int)pow;
-(BOOL)tick:(ccTime)dt;
@end
- 18. Invader.m①
- (id)init{
if((self = [super init])){
self.sprite = [CCSprite spriteWithSpriteFrameName:@"vader.png"];
GameData *gameData = [GameData getInstance];
self.sprite.scale = (CCRANDOM_0_1() * (gameData.invaderScaleMax -
gameData.invaderScaleMin)) + gameData.invaderScaleMin;
self.minX = self.sprite.boundingBox.size.width / 2;
self.maxX = 320 - (self.sprite.boundingBox.size.width / 2);
- 19. Invader.m②
float ex = (CCRANDOM_0_1() * (self.maxX - self.minX)) + self.minX;
float ey = 568 + (self.sprite.boundingBox.size.height / 2);
self.sprite.position = ccp(ex, ey);
self.speed = gameData.invaderSpeed / self.sprite.scale;
self.life = (int)(self.sprite.scale * MIN_LIFE);
self.score = self.life;
[self animeStart];
}
return self;
}
- 22. Invader.m③
-(void)animeStart{
[self.sprite stopAllActions];
NSMutableArray *animFrames = [NSMutableArray array];
[animFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:@"vader.png"]];
[animFrames addObject:[[CCSpriteFrameCache sharedSpriteFrameCache]
spriteFrameByName:@"vader2.png"]];
CCAnimation *animation = [CCAnimation
animationWithSpriteFrames:animFrames delay:0.2f];
id repeatAnim = [CCRepeatForever actionWithAction:[CCAnimate
actionWithAnimation:animation]];
[self.sprite runAction:repeatAnim];
}
- 25. MainLayer.m①
// 敵を出す
self.invaderDelayCount += dt;
if(gameData.invaderDelayMax <= self.invaderDelayCount){
self.invaderDelayCount = 0;
Invader *invader = [[[Invader alloc] init] autorelease];
CCSpriteBatchNode *gameBatchNode = (CCSpriteBatchNode*)
[self getChildByTag:OBJECT_GAME];
[gameBatchNode addChild:invader.sprite
z:SPRITE_GAME_ENEMY tag:SPRITE_GAME_ENEMY];
[self.invaderArray addObject:invader];
}
- 28. invader.m
-(BOOL)tick:(ccTime)dt{
float x = self.sprite.position.x;
float y = self.sprite.position.y - (self.speed * dt);
self.sprite.position = ccp(x, y);
// 侵略判定
float dy = self.sprite.position.y -
(self.sprite.boundingBox.size.height / 2);
if(dy <= GAMEOVER_LINE){
return YES;
}
return NO;
}
- 32. MainLayer.m①
-(void)shotAction:(CGPoint)startPos{
if([self.smallShotArray count] >= SHOT_MAX){
return;
}
CCSprite *sp = [CCSprite spriteWithSpriteFrameName:@"shot1.png"];
sp.position = ccp(startPos.x, startPos.y + 24.0f + 20.0f);
CCSpriteBatchNode *gameBatchNode = (CCSpriteBatchNode*)[self getChildByTag:OBJECT_GAME];
[gameBatchNode addChild:sp z:SPRITE_GAME_SHOT];
NSMutableArray* actions = [NSMutableArray array];
[actions addObject:[CCSpawn actions:
[CCMoveTo actionWithDuration:2.0f position:ccp(sp.position.x, 500)],
[CCSequence actions:
[CCRotateBy actionWithDuration:0.5f angle:360],
[CCRotateBy actionWithDuration:0.5f angle:360],
[CCRotateBy actionWithDuration:0.5f angle:360],
[CCRotateBy actionWithDuration:0.5f angle:360],
nil],
nil]];
- 33. MainLayer.m②
[actions addObject:[CCCallFuncN actionWithTarget:self
selector:@selector(shotActionEnd:)]];
id action;
action = [CCSequence actionWithArray:actions];
[sp runAction:action];
[self.smallShotArray addObject:sp];
}
-(void)shotActionEnd:(id)node{
[self.smallShotArray removeObject:node];
[node removeFromParentAndCleanup:YES];
}
- 35. Ninja.m
self.waitCount += dt;
if(self.way != NINJYA_WAY_UP && self.waitCount >=
NINJA_UP_DELAY){
self.waitCount = 0;
CCSpriteFrame *sf = [[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:@"ninjya_u.png"];
[self.sprite setDisplayFrame:sf];
self.way = NINJYA_WAY_UP;
}
if(self.way == NINJYA_WAY_UP && self.waitCount >=
SHOT_DELAY){
self.waitCount = 0;
[self.mainScene.mainLayer
shotAction:self.sprite.position];
}
- 39. MainLayer.m①
//
弾の処理
NSMutableArray
*delShotSpriteArray
=
[NSMutableArray
array];
NSMutableArray
*delInvaderArray
=
[NSMutableArray
array];
for(CCSprite
*shotSprite
in
self.smallShotArray){
BOOL
isDelShot
=
NO;
//
攻撃
for
(Invader
*invader
in
self.invaderArray)
{
//
if(CGRectIntersectsRect(shotSprite.boundingBox,
invader.sprite.boundingBox)){
if(CGRectContainsPoint(invader.sprite.boundingBox,
shotSprite.position)){
BOOL
isDel
=
[invader
damage:SHOT_SMALL_POW];
if(isDel){
CCParticleSystem
*
ps
=
[CCParticleSystemQuad
particleWithFile:@"fire.plist"];
ps.position
=
invader.sprite.position;
ps.scale
=
invader.sprite.scale
*
0.5f;
ps.autoRemoveOnFinish
=
YES;
[self
addChild:ps
z:SPRITE_GAME_PARTICLE];
- 40. MainLayer.m②
[delInvaderArray
addObject:invader];
[invader.sprite
removeFromParentAndCleanup:YES];
[[SimpleAudioEngine
sharedEngine]playEffect:@"xout.caf"];
}else{
[[SimpleAudioEngine
sharedEngine]playEffect:@"xhit.caf"];
}
isDelShot
=
YES;
}
}
[self.invaderArray
removeObjectsInArray:delInvaderArray];
[delInvaderArray
removeAllObjects];
//
弾を削除
if(isDelShot){
[delShotSpriteArray
addObject:shotSprite];
[shotSprite
removeFromParentAndCleanup:YES];
}
}
[self.smallShotArray
removeObjectsInArray:delShotSpriteArray];
- 41. かいせつ①
• 今回は、手裏剣の中心が忍ベーダーの当た
り判定に入っているかどうかで判定!
CGRectContainsPointを使う。
• 当たり判定については、見た目に自然にな
るように判定方法を考えよう!
• 手裏剣があたったら、忍ベーダーにダメー
ジを与える!
- 42. かいせつ②
• 忍ベーダーが消滅したら消滅処理!パー
ティクルを表示する!
• ps.autoRemoveOnFinish = YES;を忘れ
ずに!これをYESにすると、パーティクル
消滅後自動的に終了処理が行われる!
• ループ中の配列から値を消去するには、
removeObjectsInArrayを使おう!
- 44. Invader.m
-(BOOL)damage:(int)pow{
self.life -= pow;
self.sprite.position = ccp(self.sprite.position.x, self.sprite.position.y +
32.0f);
CCSpriteFrame *sf = [[CCSpriteFrameCache
sharedSpriteFrameCache] spriteFrameByName:@"vader_hit.png"];
[self.sprite setDisplayFrame:sf];
if(self.life <= 0){
GameData *gameData = [GameData getInstance];
[gameData addScore:self.score];
return YES;
}
return NO;
}
- 48. GameData.m
-(void)resetScore{
self.score = 0;
self.exp = 0;
self.level = 1;
self.invaderScaleMin = 1.0f;
self.invaderScaleMax = 1.0f;
self.invaderDelayMax = 2.0f;
self.invaderSpeed = 90;
}
-(void)addScore:(int)point{
self.score += point;
self.exp++;
if(self.level < (self.exp / 10)){
self.level++;
self.invaderScaleMax += 0.3f;
self.invaderDelayMax -= 0.25f;
self.invaderSpeed += 5;
}
}