ゲームの演出

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

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

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

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

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

01@interface EffectView : UIView {
02  BOOL      isLoop;
03  BOOL      isFinishDelete;
04  BOOL      isOpacity;
05  BOOL      isPosition;
06  BOOL      isBounds;
07}
08@property (nonatomic, assign) BOOL isLoop;
09@property (nonatomic, assign) BOOL isFinishDelete;
10- (id)initWith:(UIImage*)image;
11- (void)setAnimePosition:(CGPoint)toPoint Duration:(CGFloat)dur;
12- (void)setAnimeOpacityFrom:(CGFloat)opa1 To:(CGFloat)opa2 Duration:(CGFloat)dur;
13- (void)setAnimeBoundsScaleFrom:(CGFloat)scl1 To:(CGFloat)scl2 Duration:(CGFloat)dur;
14@end

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

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

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

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

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

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

01- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag {
02  if(isOpacity)
03     isOpacity = NO;
04  if(isPosition)
05     isPosition = NO;
06  if(isBounds)
07     isBounds = NO;
08  if( isOpacity==NO && isPosition==NO && isBounds==NO && isFinishDelete )
09      [self removeFromSuperview];
10}

ダメージエフェクト

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

01case STATE_DAMAGE:  //ダメージ
02{
03  efView =  autorelease];
04  [self addSubview:efView];
05  efView.center = CGPointMake(24, 0);
06  [efView setAnimeBoundsScaleFrom:1.0 To:1.2 Duration:0.2];
07  [efView setAnimeOpacityFrom:1.0 To:0.0 Duration:0.2];
08  efView=nil;
09   
10  ~略~
11}break;

眠りエフェクト

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

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

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

01case STATE_SLEEP:         //眠り
02{
03    imageIndex = MOVANGL_SLEEP;
04    efView = ;
05    efView.isFinishDelete = NO;
06    [self addSubview:efView];
07    [efView release];
08    efView.center = CGPointMake(40, 0);
09    [efView setAnimeBoundsScaleFrom:1.0 To:1.2 Duration:1.5];
10}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メルマガ会員のサービス内容を見る

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