Weitere ähnliche Inhalte
Ähnlich wie ㉕cocos2dを覚えよう!初級編③ (15)
Mehr von Nishida Kansuke (20)
Kürzlich hochgeladen (11)
㉕cocos2dを覚えよう!初級編③
- 2. 動作環境
• Mac OS X 10.8 Mountain Lion
• xcode 4.5.2
• cocos2d for iPhone 2.0
http://www.cocos2d-iphone.org/
- 4. もくじ
• cocos2dの基本
• Sceneの構成要素
• 忍ベーダー
• 仮想スティック
• 忍者の移動
- 6. cocos2dについて
• オープンソース+無料で商用利用可能
• 2Dに特化
• 物理エンジン搭載(box2d,chipmunk)
• 効果音やBGMの再生も可能
• OpenGL利用で高速描画
• Objective-Cで書かれている
- 10. cocos2dの基礎知識
• CCSprite
– 回転、拡大、縮小、傾斜、透過
• CCAnimation
– ぱらぱら漫画のような、画像切り替え
• CCAction
– キャラクターに任意の動きを設定可能
– イベント処理
(CCSendMessage、CCCallFunc)
- 11. cocos2dの基礎知識
• CCTMXTiledMap
– タイルマップの表示
• CCParticleSystem
– パーティクルの表示
• CCSpriteBatchNode
– スプライトをまとめて管理
• SimpleAudioEngine
– 効果音、BGMを簡単に再生
- 16. Layerの中にはいろいろおける
CCSprite、CCMenu、CCLabelBMFont、
CCSpriteBatchNode
などを置くことができる
- 17. LayerとSprite
• Layer
• Sprite(手裏剣1)
• Sprite(手裏剣2)
• Sprite(手裏剣3)
• Sprite(忍者)
レイヤーの中に、スプライトを置くことが
できる
- 19. LayerとSpriteBatchNodeとSprite
• Layer
• BatchNode
• Sprite(手裏剣1)
• Sprite(手裏剣2)
• Sprite(手裏剣3)
• BatchNode
• Sprite(忍者)
レイヤーの中に、バッチノードをおいて、そ
の中に、スプライトを置く
バッチノードの中には、その中に含まれてい
るスプライトしかおけない
- 23. 4inch対応
• 今回は画面上部の見
える部分を変更する
ことで対応します
• スコアなどの文字は、
画面の高さをもとに
表示して、画面内に
収まるようにします。
• 忍ベーダーや手裏剣
は、4inchの座標で計
算します。3.5inchでも
得ない画面外の部分
でも処理を行います。
- 26. メインscene
• フロントlayer
– スコア
• スティックlayer
– 左右のボタン
• メインlayer
– READY? 、START!
– ゲームオーバー
– 忍ベーダー、手裏剣
– 忍者
– 点線、床
• 背景layer
– 背景画像
- 28. 音楽素材について①
• 音楽素材については、PANICPUMPKIN様
のご好意により、使用させていただいてい
ます。
• http://panicpumpkin.omiki.com/
• ゲームBGMに特化したサイトなのでおす
すめ!(曲数も多いです)
• 利用報告、 著作表記、リンクなどの明記
不要で商用利用可能の音楽素材を多数公
開されています。
- 33. 普通のボタンとの違い
• 普通のボタンは、おし
て離した時にイベント
が起きる
• コントローラーのボタ
ンは、押した時にON、
離した時にOFFになる
- 34. moveイベント
• ONになったあと、指を
移動してボタン外に出
たらOFFになる。
• 指を移動して、移動先
がボタンだったらONに
なる
- 35. マルチタッチ
• 両手を使うため、マル
チタッチに対応する
• 複数の指で同じボタン
が押された時も考慮す
る
• ボタンが押された時に
UITouchを配列に記録し
ておき、すべての指が
離れたらOFFにする
- 38. GameData.m
-‐
(id)init{
if((self
=
[super
init])){
self.stickArrayL
=
[NSMutableArray
array];
self.stickArrayR
=
[NSMutableArray
array];
[self
resetScore];
}
return
self;
}
-‐(void)resetStickArray{
[self.stickArrayL
removeAllObjects];
[self.stickArrayR
removeAllObjects];
}
- 40. AppDelegate.m
-‐
(BOOL)application:(UIApplication
*)application
didFinishLaunchingWithOptions:(NSDictionary
*)launchOptions
{
:
//
マルチタッチを有効にする
[glView
setMultipleTouchEnabled:YES];
return
YES;
}
- 42. StickLayer.m①
-‐(void)initLayer{
[[CCSpriteFrameCache
sharedSpriteFrameCache]
addSpriteFramesWithFile:@"NInvadersResource.plist"];
CCSpriteBatchNode
*ninvadersBatchNode
=
[CCSpriteBatchNode
batchNodeWithFile:@"NInvadersResource.pvr.ccz"
capacity:100];
[self
addChild:ninvadersBatchNode
z:OBJECT_STICK
tag:OBJECT_STICK];
- 43. StickLayer.m②
CCSprite
*sp;
sp
=
[CCSprite
spriteWithSpriteFrameName:@"button_off.png"];
sp.position
=
ccp(42,
92);
[ninvadersBatchNode
addChild:sp
z:SPRITE_STICK_L_OFF
tag:SPRITE_STICK_L_OFF];
sp
=
[CCSprite
spriteWithSpriteFrameName:@"button_on.png"];
sp.position
=
ccp(42,
92);
sp.visible
=
NO;
[ninvadersBatchNode
addChild:sp
z:SPRITE_STICK_L_ON
tag:SPRITE_STICK_L_ON];
- 44. StickLayer.m③
sp
=
[CCSprite
spriteWithSpriteFrameName:@"button_off.png"];
sp.position
=
ccp(320
-‐
42,
92);
[ninvadersBatchNode
addChild:sp
z:SPRITE_STICK_R_OFF
tag:SPRITE_STICK_R_OFF];
sp
=
[CCSprite
spriteWithSpriteFrameName:@"button_on.png"];
sp.position
=
ccp(320
-‐
42,
92);
sp.visible
=
NO;
[ninvadersBatchNode
addChild:sp
z:SPRITE_STICK_R_ON
tag:SPRITE_STICK_R_ON];
}
- 46. StickLayer.m
-‐
(id)init{
self
=
[[super
init]
autorelease];
if
(self)
{
//
イベントの無効/有効
self.isTouchEnabled
=
YES;
self.isAccelerometerEnabled
=
NO;
//
変数
GameData
*gameData
=
[GameData
getInstance];
[gameData
resetStickArray];
//レイヤーの初期化
[self
initLayer];
}
return
self;
}
- 47. タッチイベント
• タッチされたら、タッチ座標を取得
• タッチ座標がボタンの位置だったら
– UITouchを保存する
– ボタンが押されたことにする
– ONのボタンを表示する(今回は、OFFのボタ
ンを非表示にしなくてもいいデザインなので、
OFFボタンはそのまま)
- 48. StickLayer.m①
-‐(void)ccTouchesBegan:(NSSet
*)touches
withEvent:(UIEvent
*)event
{
CCSpriteBatchNode
*ninvadersBatchNode
=
(CCSpriteBatchNode*)[self
getChildByTag:OBJECT_STICK];
GameData
*gameData
=
[GameData
getInstance];
for(UITouch*
touch
in
touches){
CGPoint
touchPoint
=
[touch
locationInView:[touch
view]];
touchPoint
=
[[CCDirector
sharedDirector]
convertToGL:touchPoint];
CCSprite
*sp_off_l
=
(CCSprite*)[ninvadersBatchNode
getChildByTag:SPRITE_STICK_L_OFF];
CCSprite
*sp_on_l
=
(CCSprite*)[ninvadersBatchNode
getChildByTag:SPRITE_STICK_L_ON];
if(CGRectContainsPoint(sp_off_l.boundingBox,
touchPoint)){
[gameData.stickArrayL
addObject:touch];
sp_on_l.visible
=
YES;
self.isL
=
TRUE;
}
- 49. StickLayer.m②
CCSprite
*sp_off_r
=
(CCSprite*)[ninvadersBatchNode
getChildByTag:SPRITE_STICK_R_OFF];
CCSprite
*sp_on_r
=
(CCSprite*)[ninvadersBatchNode
getChildByTag:SPRITE_STICK_R_ON];
if(CGRectContainsPoint(sp_off_r.boundingBox,
touchPoint)){
[gameData.stickArrayR
addObject:touch];
sp_on_r.visible
=
YES;
self.isR
=
TRUE;
}
}
}
- 50. TIPS①
• touchesの中に複数のタッチイベントが
入っているので、1個ずつ処理を行う
– for(UITouch*
touch
in
touches){
– }
• touch
座標を、cocos2dの座標に変換する
– CGPoint
touchPoint
=
[touch
locationInView:
[touch
view]];
– touchPoint
=
[[CCDirector
sharedDirector]
convertToGL:touchPoint];
- 54. StickLayer.m②
for(UITouch*
touch
in
touches){
CGPoint
touchPoint
=
[touch
locationInView:[touch
view]];
touchPoint
=
[[CCDirector
sharedDirector]
convertToGL:touchPoint];
CCSprite
*sp_on_l
=
(CCSprite*)[ninvadersBatchNode
getChildByTag:SPRITE_STICK_L_ON];
[gameData.stickArrayL
removeObject:touch];
if([gameData.stickArrayL
count]
==
0){
sp_on_l.visible
=
NO;
self.isL
=
FALSE;
}
- 55. StickLayer.m③
CCSprite
*sp_on_r
=
(CCSprite*)[ninvadersBatchNode
getChildByTag:SPRITE_STICK_R_ON];
[gameData.stickArrayR
removeObject:touch];
if([gameData.stickArrayR
count]
==
0){
sp_on_r.visible
=
NO;
self.isR
=
FALSE;
}
}
}
- 61. 忍者の仕様
• ボタンがおされてい
るあいだ移動する
• 移動中は、アニメー
ションする
• ボタンを離すと手裏
剣をなげるために、
上を向く
- 64. MainLayer.m
//
忍者
CCSpriteBatchNode
*gameBatchNode
=
(CCSpriteBatchNode*)[self
getChildByTag:OBJECT_GAME];
self.ninja
=
[[[Ninja
alloc]
init]autorelease];
self.ninja.mainScene
=
(MainScene*)[self
parent];
[gameBatchNode
addChild:self.ninja.sprite
z:SPRITE_GAME_NINJYA
tag:SPRITE_GAME_NINJYA];
- 68. Ninja.m
if(self.mainScene.stickLayer.isL){
if(self.way
!=
NINJYA_WAY_LEFT){
[self.sprite
stopAllActions];
NSMutableArray
*animFrames
=
[NSMutableArray
array];
[animFrames
addObject:[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:@"ninjya_l.png"]];
[animFrames
addObject:[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:@"ninjya_l2.png"]];
CCAnimation
*animation
=
[CCAnimation
animationWithSpriteFrames:animFrames
delay:0.2f];
id
repeatAnim
=
[CCRepeatForever
actionWithAction:[CCAnimate
actionWithAnimation:animation]];
[self.sprite
runAction:repeatAnim];
self.way
=
NINJYA_WAY_LEFT;
}
self.waitCount
=
0;
x
=
x
-‐
dt
*
NINJA_SPEED;
}
- 71. Ninja.m
else{
[self.sprite
stopAllActions];
if(self.way
==
NINJYA_WAY_LEFT){
CCSpriteFrame
*sf
=
[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:@"ninjya_l.png"];
[self.sprite
setDisplayFrame:sf];
}else
if(self.way
==
NINJYA_WAY_RIGHT){
CCSpriteFrame
*sf
=
[[CCSpriteFrameCache
sharedSpriteFrameCache]
spriteFrameByName:@"ninjya_r.png"];
[self.sprite
setDisplayFrame:sf];
}
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;
}
}
- 74. Ninja.m
float
xx
=
self.sprite.position.x
+
x;
if(xx
<
30){
xx
=
30;
}else
if(xx
>
(320
-‐
30)){
xx
=
(320
-‐
30);
}
self.sprite.position
=
ccp(xx,
self.sprite.position.y);