ゲームの演出

2011年5月27日(金)
北村 真二

Core Animationを使ったエフェクトクラス

次にCore Animationを使ったエフェクトを追加して行ってみよう。まずはウサギがオオカミに攻撃された時のマークを付けてみる。第5回で紹介したようなマークをあらかじめKeynoteで作っておこう。これをウサギのダメージアニメーション開始時に表示する。

図2:ウサギ攻撃されるエフェクト

エフェクトのための新しいクラスを追加しよう。以下がそのインターフェースだ。このオブジェクトはキャラクターのサブビューとして設定して使う。

@interface EffectView : UIView {
  BOOL		isLoop;
  BOOL		isFinishDelete;
  BOOL		isOpacity;
  BOOL		isPosition;
  BOOL		isBounds;
}
@property (nonatomic, assign) BOOL isLoop;
@property (nonatomic, assign) BOOL isFinishDelete;
- (id)initWith:(UIImage*)image;
- (void)setAnimePosition:(CGPoint)toPoint Duration:(CGFloat)dur;
- (void)setAnimeOpacityFrom:(CGFloat)opa1 To:(CGFloat)opa2 Duration:(CGFloat)dur;
- (void)setAnimeBoundsScaleFrom:(CGFloat)scl1 To:(CGFloat)scl2 Duration:(CGFloat)dur;
@end

クラスには初期化メソッドとこのビュー自身をCore Animationを使ってアニメーションさせるためのメソッドが3つある。それぞれ位置、透明度、サイズをアニメーションさせるメソッドだ。以下が初期化メソッドになる。

- (id)initWith:(UIImage*)image {
    CGRect	rect = CGRectMake(0, 0, image.size.width, image.size.height);
    if (self = [super initWithFrame:rect]) {
        self.layer.contents = (id)image.CGImage;
        isLoop = NO;
        isFinishDelete = YES;
    }
    return self;
}

引数として渡されたUIImageをレイヤーのコンテンツとして設定し、削除のためのフラグisFinishDeleteを立てる、isFinishDeleteが YES の場合、アニメーションが終了したら自分自身を削除する。isLoopが NO ならループ再生する。

以下が透明値をアニメーションさせるメソッドだ。引数に開始値と終わり値、アニメーションの時間を渡す。他の2つもアニメーションさせるプロパティーが違うだけでやっていることは同じだ。

//透明度のアニメーション
- (void)setAnimeOpacityFrom:(CGFloat)opa1 To:(CGFloat)opa2 Duration:(CGFloat)dur {
    //透明値のアニメーションを作成
    CABasicAnimation*	opacity = [CABasicAnimation animationWithKeyPath:@"opacity"];
    //透明値の開始と終わりを設定
    opacity.fromValue = [NSNumber numberWithFloat:opa1];
    opacity.toValue = [NSNumber numberWithFloat:opa2];
    opacity.delegate = self;	//デリゲート
    opacity.duration = dur;	//アニメーションの時間
    opacity.autoreverses = isLoop;	// YESならアニメーションを繰り返す
    if( isLoop )
        opacity.repeatCount = 10000;	// 繰り返し回数
    // アニメーション設定
    [self.layer addAnimation:opacity forKey:@"animateOpacity"];
    isOpacity = YES;
    self.layer.opacity = opa2;
}

そして、アニメーション終了時に呼ばれるデリゲートメソッドで全てのアニメーションの再生が終了し、削除のためのフラグが YES なら自分自身を親ビューから削除する。

- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
  if(isOpacity)
     isOpacity = NO;
  if(isPosition)
     isPosition = NO;
  if(isBounds)
     isBounds = NO;
  if( isOpacity==NO && isPosition==NO && isBounds==NO && isFinishDelete )
      [self removeFromSuperview];
}

ダメージエフェクト

以下が実際の使用例だ。GamePieceViewの setState: で、ステータスがダメージに変わる時にEffectViewをキャラクターに設定している。エフェクト用のビューを作成した後、サイズと透明のアニメーションを0.2秒で設定している。これで「攻撃されたマーク」が0.2秒かけて1.2倍になりながら透明になって消えて行く、そして消えた後、エフェクト用のビューは自分自身を削除して解放される。

case STATE_DAMAGE:	//ダメージ
{
  efView =  autorelease];
  [self addSubview:efView];
  efView.center = CGPointMake(24, 0);
  [efView setAnimeBoundsScaleFrom:1.0 To:1.2 Duration:0.2];
  [efView setAnimeOpacityFrom:1.0 To:0.0 Duration:0.2];
  efView=nil;
  
  ~略~
}break;

眠りエフェクト

次にキャラクターの状態変化が視覚的に分かるようなエフェクトを追加してみよう。オオカミは最初、眠った状態で配置されている。この時にマンガでよくあるような吹き出しを表示する。

図3:オオカミ眠りエフェクト

以下がその設定部分のコードだ。ここでは efView.isFinishDelete に NO を設定しているので、アニメーション終了後も削除されること無くループ再生される。

  case STATE_SLEEP:			//眠り
  {
      imageIndex = MOVANGL_SLEEP;
      efView = ;
      efView.isFinishDelete = NO;
      [self addSubview:efView];
      [efView release];
      efView.center = CGPointMake(40, 0);
      [efView setAnimeBoundsScaleFrom:1.0 To:1.2 Duration:1.5];
  }break;
  • 「ゲームの演出」サンプルプログラム

STUDIO SHIN

家庭用ゲームの企画開発、Mac OS / iOSアプリの開発を主な生業とする。
20年ほど前から家庭用ゲーム開発に携わりファミコンからDS、PSP、Wiiまで幅広く開発。15年前からMac OS Xアプリケーションを開発「DotShotX」「GIFQuickMaker」などを公開。iPhoneアプリ「将棋盤」「DotTouch」「Rabbit Maze」などを開発。開発アプリはアップルのApp Storeで公開中。

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています