『cocos2dで作るiPhone&iPadゲームプログラミング』のメモ

書籍読んだメモ

なんか細かいの

  • /cocos2d Sources/ というグループには cocos2dゲームエンジンを構成するすべてのファイルが含まれている。
  • コンパイル済みのプレフィックスヘッダー ****_prefix.pch ビルド時間を短縮するために使ったりする
  • ccConfig.h : CC_DIRECTOR_FPS_INTERVALFPS 表示頻度を変えられる。デフォルトは 1.0 / 10
  • purge, purgeCachedDataメソッド 使用していないテクスチャのメモリなどを解放する。アプリケーションの使用メモリが多くなったときに起動させる。purge よりも purgeCachedData のほうが削減量が多い??

cocos2d のシングルトンクラス

// MyManager クラスとシングルトンとして実装する
static MyManager *sharedManager = nil;
+ (MyManager *) sharedManager {
  if ( sharedManager == nil ) {
    sharedManager = [[MyManager alloc] init];
  }
  return sharedManager;
}

cocos2d のシングルトンクラス

  • CCActionManager
  • CCDirector
  • CCSpriteFrameCache
  • CCTextureCache
  • CCTouchDispatcher
  • CDAudioManager
  • SimpleAudioEngine

Director

  • シーンへのアクセス
  • cocos2d の設定情報へのアクセス
  • ビュー(OpenGL, UIView, UIWindow)へのアクセス
  • ゲームの一時停止、再開、終了
  • UIKit および OpenGL 座標の変換

ディレクターの種類はいくつかあって、デフォルトは CCDirectorDisplayLink が使われている。 cocos2d-x の場合はどうなっているんだろうなぁ…?

CCNode

CCLayer, CCScene, CCSprite などの親クラスとなる、すべてのノードのベースクラス。 このクラスはビジュアル表現を持たない抽象クラスであり、 すべてのノードに共通するプロパティとメソッドをすべて定義します。

/**
 - ノードを操作する
 */
// 新しいノードを作成する:
CCNode *childNode = [CCNode node];
// 新しいノードを子として追加する:
[myNodeaddChild:childNode z:0 tag:123];
// 子ノードを取得する:
CCNode *retrievedNode = [myNode getChildByTag:123];
// タグを使って子ノードを削除する:cleanupは実行中のアクションも全て停止させる
[myNode removeChildByTag:123 cleanup:YES];
// ノードのポインタを取得している場合に、そのノードを削除する:
[myNode removeChild:retrievedNode];
// ノードのすべての子を削除する
[myNode removeAllChildrenWithCleanup:YES];
// 親ノード(myNode) を削除する
[myNode removeFromParentAndCleanup:YES];

/**
 - アクションを操作する
 */
// アクションを宣言する:
CCAction *action = [CCBlink ationWithDuration:10 blinks:20];
action.tag = 234; // アクションとノードのタグは競合しない
// アクションを実行してノードを点滅させる
[myNode runAction:action];
// あとからアクションにアクセスする必要がある場合に、そのタグを使ってアクションを取得する
CCAction *retrievedAction = [myNode getActionByTag:234];
// タグを使ってアクションを停止する
[myNode stopActionByTag:234];
// ポインタを使ってアクションを停止する
[myNode stopAction:action];
// このノードで実行中のアクションをすべて停止する
[myNode stopAllActions];

スケジュールされたメッセージ

  • scheduleUpdateupdate:(ccTime)delta を使用する。
    または schedule:(SEL)selector で任意のセレクタをスケジュールに登録できる

  • _cmd キーワードは現在のメソッドを表すもの
    _cmd キーワードを使うと間違ったセレクタをスケジュール/スケジュール解除してしまうという最悪の事態を避けることができる。

    // たとえばあるメソッドを色々な感覚で呼び出す必要がある場合…
    - (void) scheduleUpdates {
    // 最初の update を通常通りにスケジュールする
    [self schedule:@selector(irregularUpdate:) interval:1];
    }
    
    - (void) irregularUpdate:(ccTime)delta {
    // まず、メソッドのスケジュールを解除する
    [self unschedule:_cmd]:
    
    // 実際には、メソッドを次に呼び出すタイミングをランダムに決めるのではなく
    // 何らかのロジックを使うものとする
    float nextUpdate = CCRANDOM_0_1() * 10;
    
    // _cmd をセレクタとして使うことで
    // 新しい間隔でメソッドをスケジュールする
    [self schedule:_cmd interval:nextUpdate];

更新の優先順位

// ノードA
- (void) scheduleUpdates {
  // [self scheduleUpdateWithPriority:0] と等価
  [self scheduleUpdate];
}

// ノードB
- (void) scheduleUpdates {
  [self scheduleUpdateWithPriority:1];
}

// ノードC
- (void) scheduleUpdates {
  [self scheduleUpdateWithPriority:-1];
}

数値の低い順番に実行される。

この場合は C -> A -> B の順番に実行される。

シーンとレイヤー

CCNode と同様に、CCScene クラスと CCLayer クラスはビジュアル表現を持たず、シーングラフの出発点と成る抽象概念として内部で使われます。シーングラフは常に CCScene クラスから派生したオブジェクトとなります。そして CCLayer クラスは、一般にノードをグループにまとめるために使われるほか、タッチ入力と加速度センサー入力を有効にしている場合は、それを受け取るために使われます。

CCLayer

シーンと同様にレイヤーにも大きさはありません。レイヤーは主にグループ化の概念です。たとえば、レイヤでアクションを使うと、そのアクションはレイヤのすべてのオブジェクトに影響を与えます。

タッチ座標を OpenGL 座標に変換する

// このメソッドはシングルタッチのみに対応
- (CGPoint) locationFromTouches:(NSSet *)touches {
  UITouch *touch = [touches anyObject];
  CGPoint touchLocation = [touch locationInView] [touch view]];
  return [[CCDirector sharedDirector] convertToGL: touchLocation];
}

加速度センサーイベントの受け取り

タッチ入力と同様に加速度センサーイベントを受け取るためには、加速度センサーを明示的に有効にしなければなりません。

self.isAccelerometerEnabled = YES;

この場合も、加速度センサーイベントを受け取るレイヤに追加されるメソッドがあります。

- (void) accelerometer:(UIAccelerometer *)accelerometer
         didAccelerate:(UIAcceleration *)acceleration {
  CCLOG(@"acceleration: x:%f / y:%f / z:%f,
        acceleration.x, acceleration.y, acceleration.z);
}

acceleration パラメータを使って、3つの方向のいずれかの加速度を判断できます。

テクスチャのサイズについて

iPhone 3GS 以降の PowerVR SGX 搭載デバイスでは、OpenGL ES 1.1/2.0 ともに2の累乗でないサイズのテクスチャを読み込むことができる extension が有効になっている。

cocos2d では ccConfig.hCC_TEXTURE_NPOT_SUPPORT で読みこんだPNGなどを2の累乗でないサイズで扱う。

メニュー

CCMenuItemFont, CCMenuItemSprite, CCMenuItemToggle

サンプルのコピペ

-(void) createMenu:(ccTime)delta
{
  // unschedule the selector, we only want this method to be called once
  [self unschedule:_cmd];

  CGSize size = [[CCDirector sharedDirector] winSize];

  // set CCMenuItemFont default properties
  [CCMenuItemFont setFontName:@"Helvetica-BoldOblique"];
  [CCMenuItemFont setFontSize:40];

  // create a few labels with text and selector
  CCMenuItemFont* item1 = [CCMenuItemFont itemFromString:@"Go Back!" target:self selector:@selector(menuItem1Touched:)];

  // create a menu item using existing sprites
  CCSprite* normal = [CCSprite spriteWithFile:@"Icon.png"];
  normal.color = ccRED;
  CCSprite* selected = [CCSprite spriteWithFile:@"Icon.png"];
  selected.color = ccGREEN;
  CCMenuItemSprite* item2 = [CCMenuItemSprite itemFromNormalSprite:normal selectedSprite:selected target:self selector:@selector(menuItem2Touched:)];

  // create a toggle item using two other menu items (toggle works with images, too)
  [CCMenuItemFont setFontName:@"STHeitiJ-Light"];
  [CCMenuItemFont setFontSize:40];
  CCMenuItemFont* toggleOn = [CCMenuItemFont itemFromString:@"I'm ON!"];
  CCMenuItemFont* toggleOff = [CCMenuItemFont itemFromString:@"I'm OFF!"];
  CCMenuItemToggle* item3 = [CCMenuItemToggle itemWithTarget:self selector:@selector(menuItem3Touched:) items:toggleOn, toggleOff, nil];

  // create the menu using the items
  CCMenu* menu = [CCMenu menuWithItems:item1, item2, item3, nil];
  menu.position = CGPointMake(-(size.width / 2), size.height / 2);
  menu.tag = 100;
  [self addChild:menu];

  // calling one of the align methods is important, otherwise all labels will occupy the same location
  [menu alignItemsVerticallyWithPadding:40];

  // use an action for a neat initial effect - moving the whole menu at once!
  CCMoveTo* move = [CCMoveTo actionWithDuration:3 position:CGPointMake(size.width / 2, size.height / 2)];
  CCEaseElasticOut* ease = [CCEaseElasticOut actionWithAction:move period:0.8f];
  [menu runAction:ease];
}

-(void) menuItem3Touched:(id)sender
{
  // sender is a CCMenuItemToggle in this case
  CCMenuItemToggle* toggleItem = (CCMenuItemToggle*)sender;
  // これで現在選択されている画像が何かを取得できる
  int index = [toggleItem selectedIndex];
  if ( index == 0 ) {
    // 処理を分岐
  } else if ( index == 1 ) {
    // 処理を分岐
  }
  CCLOG(@"item 3 touched: %@ - selected index: %i", sender, index);
}

P88 加速度によりプレーヤーを動かす

加速度を受け取るメソッドでプレーヤの速度を変更する

-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
{
  // These three values control how the player is moved. I call such values "design parameters" as they
  // need to be tweaked a lot and are critical for the game to "feel right".
  // Sometimes, like in the case with deceleration and sensitivity, such values can affect one another.
  // For example if you increase deceleration, the velocity will reach maxSpeed faster while the effect
  // of sensitivity is reduced.

  // this controls how quickly the velocity decelerates (lower = quicker to change direction)
  // どれくらい減速するかを制御する
  // この値が小さいほど向きを素早く変更できる
  float deceleration = 0.4f;
  // this determines how sensitive the accelerometer reacts (higher = more sensitive)
  // 加速度センサーの感度を設定する
  // この値が大きいほど感度が高くなる
  float sensitivity = 6.0f;
  // 最大速度 how fast the velocity can be at most
  float maxVelocity = 100;

  // adjust velocity based on current accelerometer acceleration
  // 現在の加速度センサーの加速ん基づいて速度を調節する
  playerVelocity.x = playerVelocity.x * deceleration + acceleration.x * sensitivity;

  // we must limit the maximum velocity of the player sprite, in both directions (positive & negative values)
  // 画面端の処理
  if (playerVelocity.x > maxVelocity) {
    playerVelocity.x = maxVelocity;
  } else if (playerVelocity.x < -maxVelocity) {
    playerVelocity.x = -maxVelocity;
  }

  // Alternatively, the above if/else if block can be rewritten using fminf and fmaxf more neatly like so:
  // playerVelocity.x = fmaxf(fminf(playerVelocity.x, maxVelocity), -maxVelocity);
}

update: メソッドでプレーヤの位置を速度を利用して変更する。

-(void) update:(ccTime)delta
{
  CGPoint pos = player.position;
  pos.x += playerVelocity.x;

  CGSize screenSize = [[CCDirector sharedDirector] winSize];
  float imageWidthHalved = [player texture].contentSize.width * 0.5f;
  float leftBorderLimit = imageWidthHalved;
  float rightBorderLimit = screenSize.width - imageWidthHalved;

  // 画面端の処理
  if (pos.x < leftBorderLimit) {
    pos.x = leftBorderLimit;
    playerVelocity = CGPointZero;
  } else if (pos.x > rightBorderLimit) {
    pos.x = rightBorderLimit;
    playerVelocity = CGPointZero;
  }

  // Alternatively, the above if/else if block can be rewritten using fminf and fmaxf more neatly like so:
  // pos.x = fmaxf(fminf(pos.x, rightBorderLimit), leftBorderLimit);

  player.position = pos;
}

p99 デバッグでのレンダリングメソッド

サンプルのゲームはデバッグでクモ男の当たり判定が出るようになっている。

この当たり判定は、CCNode#draw をオーバーライドして、

OpenGL のプリミティブによって描画している。

// Only draw this debugging information in, well, debug builds.
-(void) draw
{
  // デバッグでのクモ男の当たり判定を表示する部分
#if DEBUG
  // Iterate through all nodes of the layer.
  CCNode* node;
  CCARRAY_FOREACH([self children], node)
  {
    // Make sure the node is a CCSprite and has the right tags.
    if ([node isKindOfClass:[CCSprite class]] && (node.tag == 1 || node.tag == 2))
    {
      // The sprite's collision radius is a percentage of its image width. Use that to draw a circle
      // which represents the sprite's collision radius.
      CCSprite* sprite = (CCSprite*)node;
      float radius = [sprite texture].contentSize.width * 0.4f;
      float angle = 0;
      int numSegments = 10;
      bool drawLineToCenter = NO;

      // GLプリミティブで円を描く
      ccDrawCircle(sprite.position, radius, angle, numSegments, drawLineToCenter);
    }
  }
#endif

  // こちらはクモの糸を描く
  CGSize screenSize = [[CCDirector sharedDirector] winSize];

  // always keep variables you have to calculate only once outside the loop
  float threadCutPosition = screenSize.height * 0.75f;

  // Draw a spider thread using OpenGL
  // CCARRAY_FOREACH is a bit faster than regular for loop
  CCSprite* spider;
  CCARRAY_FOREACH(spiders, spider)
  {
    // only draw thread up to a certain point
    if (spider.position.y > threadCutPosition)
    {
      // vary thread position a little so it looks a bit more dynamic
      // これはクモの糸の揺れを実現しているコード
      float threadX = spider.position.x + (CCRANDOM_0_1() * 2.0f - 1.0f);

      // GLプリミティブで直線を描く
      glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
      ccDrawLine(spider.position, CGPointMake(threadX, screenSize.height));
    }
  }
}

第4章のその他

  • isKindOfClass で正しいクラスかどうかを調べる。
    ただしこの機能は cocos2d-x では現在存在しないらしい。実装できないっぽい。
  • CCNode#numberOfRunningActions == 0 が真ならばアクションは実行されていない。
  • [UIApplication sharedApplication].isAdleTimerDisabled プロパティにより、電源かかってにスリープするのを妨害できる。
  • CCArrayCCARRAY_FOREACH で走査できる。NSArray よりちょっとだけ高速。

アニメーションは CCAnimationCache に登録しておくと便利

  CCAnimation *anim = CCAnimation::animationWithFrames((CCMutableArray<cocos2d::CCSpriteFrame *>) frames, 0.05f);

  // アニメーションを CCAnimationCache に登録
  CCAnimationCache *cache = CCAnimationCache::sharedAnimationCache();
  cache->addAnimation(anim, "AnimationName");

  // CCAnimationCache に登録したアニメーションを取り出す
  CCAnimation *animFromCache = cache->animationByName("AnimationName");

ソフトウェア

  • Seashore : Gimp がベースの画像編集ソフト, Macの場合はGimpよりもこっちのが使いやすそうだな。
  • Zwoptex : http://zwoptexapp.com/flashversion フラッシュバージョンは無料
  • TexturePackerPro : Zwoptex よりこっちのほうが良いらしい。
  • Pixen : opensword.org/Pixen,

P160,161 テクスチャキャッシュや SpriteFrame のキャッシュの削除

// removeUnused**** で使われていないキャッシュを削除する
[CCSpriteFrameCache sharedSpriteFrameCache] removeUnusedSpriteFrames];
[CCTextureCache sharedTextureCache] removeUnusedTextures];

// purge はすべてのキャッシュを削除する
[[CCSpriteFrameCache sharedSpriteFrameCache] purgeSharedSpriteFrameCache];
[[CCTextureCache sharedTextureCache] purgeSharedTextureCache];

P157 CCSpriteFrame を使ったスプライトの生成方法

-(id) initWithShipImage
{
  // Load the Texture Atlas sprite frames, this also loads the Texture with the same name.
  CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
  [frameCache addSpriteFramesWithFile:@"ship-and-bullet.plist"];

  // Loading the Ship's sprite using a sprite frame name (eg the filename)
  if ((self = [super initWithSpriteFrameName:@"ship.png"]))
  {
    // create an animation object from all the sprite animation frames
    CCAnimation* anim = [CCAnimation animationWithFrame:@"ship-anim" frameCount:5 delay:0.08f];

    // add the animation to the animationCache
    //[[CCAnimationCache sharedAnimationCache] addAnimation:anim name:@"ship-anim"];
    //CCAnimation* shipAnim = [[CCAnimationCache sharedAnimationCache] animationByName:@"ship-anim"];

    // run the animation by using the CCAnimate action
    CCAnimate* animate = [CCAnimate actionWithAnimation:anim];
    CCRepeatForever* repeat = [CCRepeatForever actionWithAction:animate];
    [self runAction:repeat];

    [self scheduleUpdate];
  }
  return self;
}

P149, 159 アニメーションを簡潔に記述するためのヘルパーカテゴリ

ヘッダー

//
//  CCAnimationHelper.h
//  SpriteBatches
//
//  Created by quipu on 11/03/07.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface CCAnimation (Helper)

+(CCAnimation*) animationWithFile:(NSString*)name frameCount:(int)frameCount delay:(float)delay;
+(CCAnimation*) animationWithFrame:(NSString*)frame frameCount:(int)frameCount delay:(float)delay;

@end
//
//  CCAnimationHelper.m
//  SpriteBatches
//
//  Created by quipu on 11/03/07.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "CCAnimationHelper.h"

@implementation CCAnimation (Helper)

// Creates an animation from single files.
+(CCAnimation*) animationWithFile:(NSString*)name frameCount:(int)frameCount delay:(float)delay
{
  // load the animation frames as textures and create the sprite frames
  NSMutableArray* frames = [NSMutableArray arrayWithCapacity:frameCount];
  for (int i = 0; i < frameCount; i++)
  {
    // Assuming all animation files are named "nameX.png" with X being a consecutive number starting with 0.
    NSString* file = [NSString stringWithFormat:@"%@%i.png", name, i];
    CCTexture2D* texture = [[CCTextureCache sharedTextureCache] addImage:file];

    // Assuming that image file animations always use the whole image for each animation frame.
    CGSize texSize = texture.contentSize;
    CGRect texRect = CGRectMake(0, 0, texSize.width, texSize.height);
    CCSpriteFrame* frame = [CCSpriteFrame frameWithTexture:texture rect:texRect];

    [frames addObject:frame];
  }

  // create an animation object from all the sprite animation frames
  return [[[CCAnimation alloc] initWithFrames:frames delay:delay] autorelease];
}

// Creates an animation from sprite frames.
+(CCAnimation*) animationWithFrame:(NSString*)frame frameCount:(int)frameCount delay:(float)delay
{
  // load the ship's animation frames as textures and create a sprite frame
  NSMutableArray* frames = [NSMutableArray arrayWithCapacity:frameCount];
  for (int i = 0; i < frameCount; i++)
  {
    NSString* file = [NSString stringWithFormat:@"%@%i.png", frame, i];
    CCSpriteFrameCache* frameCache = [CCSpriteFrameCache sharedSpriteFrameCache];
    CCSpriteFrame* frame = [frameCache spriteFrameByName:file];
    [frames addObject:frame];
  }

  // return an animation object from all the sprite animation frames
  return [[[CCAnimation alloc] initWithFrames:frames delay:delay] autorelease];
}

@end

CCParallaxNode

  if ((self = [super init]))
  {
    // This adds a solid color background.
    CCLayerColor* colorLayer = [CCLayerColor layerWithColor:ccc4(255, 0, 255, 255)];
    [self addChild:colorLayer z:0];

    CGSize screenSize = [[CCDirector sharedDirector] winSize];

    // Load the sprites for each parallax layer, from background to foreground.
    CCSprite* para1 = [CCSprite spriteWithFile:@"parallax1.png"];
    CCSprite* para2 = [CCSprite spriteWithFile:@"parallax2.png"];
    CCSprite* para3 = [CCSprite spriteWithFile:@"parallax3.png"];
    CCSprite* para4 = [CCSprite spriteWithFile:@"parallax4.png"];

    // Set the correct offsets depending on the screen and image sizes.
    para1.anchorPoint = CGPointMake(0, 1);
    para2.anchorPoint = CGPointMake(0, 1);
    para3.anchorPoint = CGPointMake(0, 0.6f);
    para4.anchorPoint = CGPointMake(0, 0);
    CGPoint topOffset = CGPointMake(0, screenSize.height);
    CGPoint midOffset = CGPointMake(0, screenSize.height / 2);
    CGPoint downOffset = CGPointZero;

    // Create a parallax node and add the sprites to it.
    CCParallaxNode* paraNode = [CCParallaxNode node];
    [paraNode addChild:para1 z:1 parallaxRatio:CGPointMake(0.5f, 0) positionOffset:topOffset];
    [paraNode addChild:para2 z:2 parallaxRatio:CGPointMake(1, 0) positionOffset:topOffset];
    [paraNode addChild:para3 z:4 parallaxRatio:CGPointMake(2, 0) positionOffset:midOffset];
    [paraNode addChild:para4 z:3 parallaxRatio:CGPointMake(3, 0) positionOffset:downOffset];
    [self addChild:paraNode z:0 tag:ParallaxSceneTagParallaxNode];

    // Move the parallax node to show the parallaxing effect.
    CCMoveBy* move1 = [CCMoveBy actionWithDuration:5 position:CGPointMake(-160, 0)];
    CCMoveBy* move2 = [CCMoveBy actionWithDuration:15 position:CGPointMake(160, 0)];
    CCSequence* sequence = [CCSequence actions:move1, move2, nil];
    CCRepeatForever* repeat = [CCRepeatForever actionWithAction:sequence];
    [paraNode runAction:repeat];

CCRibbon

タッチと組み合わせて、リボン状につながった画像を描画する。ちと、重い。イニシャライザもよくわからないものがある… width は意味がないように見える。fade は ソースコード見ても具体的に使っている箇所が見当たらない?

  // イニシャライザ
  // width の設定はいみあるんだろうか… addPointAt:Width: で ポイント設定毎にwidth引数に渡すのであんまり意味ない気がするんだけど…なんか勘違いしてるのかなぁ
  CCRibbon* ribbon = [CCRibbon ribbonWithWidth:320
                                         image:@"spider.png"
                                        length:320
                                         color:ccc4(255, 255, 255, 255)
                                          fade:0.5f];

  // リボンを描画するポイントを追加
  // ccTouchMoved メソッド内などで実行
  [ribbon addPointAt:point width:32];

CCMotionStreak

CCRibbon のラッパー。使い方もCCRibbonと似たようなもん。

[self removeChildByTag:ParallaxSceneTagRibbon cleanup:YES];
CCMotionStreak* streak = [CCMotionStreak streakWithFade:0.9f minSeg:-1 image:@"spider.png" width:32 length:32 color:ccc4(255, 0, 255, 255)];

サンプルについてのメモ

5-10 : CCMotionStreak 7-7 : SneakyInput アナログコントローラー(仮想ジョイパッド) & パララックス背景の独自実装クラス 7-8 : SneakyInput デジタルコントローラー(Dパッド)

P179 テクスチャを繰り返す

GL_REPEAT テクスチャパラメータをつかって、特定の短形領域で繰り返す。パフォーマンスやメモリへのオーバーヘッドを増やすことなく、少なくとも数千ピクセルあるいは数十個のスクリーン領域をこのリピートテクスチャで覆うことができる。ただし、1辺が2の累乗のテクスチャじゃないとダメ。

CGRect repeatRect = CGRectMake(-5000, -5000, 5000, 5000);
CCSprite *sprite = [CCSprite spriteWithFile:@"square.png" rect:repeatRect];
ccTexParams params = {
  GL_LINEAR,
  GL_LINEAR,
  GL_REPEAT,
  GL_REPEAT
};
[sprite.texture setTexParameters:&params];

この場合は、スプライトが占める領域を決定する rect を使ってスプライトを初期化しなければなりません。ccTexParams 構造体は、GL_REPEAT に設定されたラップパラメータで初期化されます。これがなんのことかわからなくても心配入りません。これらの OpenGL パラメータは CCTexture2DsetTexParameters メソッドを使ってスプライトのテクスチャで設定されます。

パーティクルデザイナー

Particle Designer

パーティクルのローディングは時間がかかるためプリロードしたほうがよい。

プリロードする方法は CCParticleSystem オブジェクトを パーティクル用の plist から一度つくる(このオブジェクトは使わないでOK)か、CCTextureCacheシングルトンに使用する画像を読み込んでおく。

ゲームセンターを実装する

LeaderboardAchievements (成績) ・ オンラインマルチプレイヤーなどの機能を使用できる。

Game Centerame Kit API

  • ゲームセンターはiOS4.1 以降のみで利用可能なので4.1以下は条件分岐で弾くこと。
  • ゲームセンターはプレイヤーアカウント・各プレイヤーの友達リスト・リーダーボード・成績を管理/記録するサービス。この情報は Appleのサーバー上にオンラインで保存され、Game Center アプリケーションを通じてアクセスします。
  • Game Kit APIGame Center の機能をプログラムするために使用する。Game Center サーバーにアクセスし、組み込みの Leaderboard ビュー, Achievements ビュー, Matchmaking ビューを表示することができる。その一方で、Game Kit には、Bluetooth や音声チャットなどによるP2Pネットワーキングなど、ゲームセンター以外の機能もある。

プロジェクトの設定

  • Xcode のプロジェクトに正しい Bundle ID を入力する。
  • GameKit.framework をプロジェクトに追加する。(デバイスがゲーセン必須でなければ optional に変更する)

Info.plist : UIRequiredDeviceCapabilytiesgamekit という boolean 型のキーを追加して YES にするとゲームセンターが必須になり、iOS4.1以下のデバイスではアプリを使えなくなる。まぁ大抵のゲームはゲーセン必須では無いので弄る必要はない。この設定を取り消したい場合は gamekit キーごと削除しなければならないので注意が必要。 - Prefix.pch#import <GameKit/GameKit.h> をインポートしておくといいらしいけど cocos2d-x ではどうなるのかしら

サンプルコードのコピペ

#import <Availability.h>

#ifndef __IPHONE_3_0
#warning "This project uses features only available in iPhone SDK 3.0 and later."
#endif

#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#endif

ローカルプレイヤー

Game Center プログラミングの基本概念 : ローカルプレイヤーのみが Leaderboard へのスコアの送信、Archivements への進捗の報告が可能。

Game Center アプリでは最初にローカルプレイヤーの認証を実行する必要がある。この認証に失敗した場合は Game Center サービスのほとんどが利用できない。

Share