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

|
図2:ウサギ攻撃されるエフェクト |
エフェクトのための新しいクラスを追加しよう。以下がそのインターフェースだ。このオブジェクトはキャラクターのサブビューとして設定して使う。
01 | @interface EffectView : UIView { |
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; |
クラスには初期化メソッドとこのビュー自身を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; |
引数として渡されたUIImageをレイヤーのコンテンツとして設定し、削除のためのフラグisFinishDeleteを立てる、isFinishDeleteが YES の場合、アニメーションが終了したら自分自身を削除する。isLoopが NO ならループ再生する。
以下が透明値をアニメーションさせるメソッドだ。引数に開始値と終わり値、アニメーションの時間を渡す。他の2つもアニメーションさせるプロパティーが違うだけでやっていることは同じだ。
02 | - (void)setAnimeOpacityFrom:(CGFloat)opa1 To:(CGFloat)opa2 Duration:(CGFloat)dur { |
04 | CABasicAnimation* opacity = [CABasicAnimation animationWithKeyPath:@"opacity"]; |
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ならアニメーションを繰り返す |
12 | opacity.repeatCount = 10000; // 繰り返し回数 |
14 | [self.layer addAnimation:opacity forKey:@"animateOpacity"]; |
16 | self.layer.opacity = opa2; |
そして、アニメーション終了時に呼ばれるデリゲートメソッドで全てのアニメーションの再生が終了し、削除のためのフラグが YES なら自分自身を親ビューから削除する。
01 | - (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag { |
08 | if( isOpacity==NO && isPosition==NO && isBounds==NO && isFinishDelete ) |
09 | [self removeFromSuperview]; |
ダメージエフェクト
以下が実際の使用例だ。GamePieceViewの setState: で、ステータスがダメージに変わる時にEffectViewをキャラクターに設定している。エフェクト用のビューを作成した後、サイズと透明のアニメーションを0.2秒で設定している。これで「攻撃されたマーク」が0.2秒かけて1.2倍になりながら透明になって消えて行く、そして消えた後、エフェクト用のビューは自分自身を削除して解放される。
01 | case STATE_DAMAGE: //ダメージ |
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]; |
眠りエフェクト
次にキャラクターの状態変化が視覚的に分かるようなエフェクトを追加してみよう。オオカミは最初、眠った状態で配置されている。この時にマンガでよくあるような吹き出しを表示する。

|
図3:オオカミ眠りエフェクト |
以下がその設定部分のコードだ。ここでは efView.isFinishDelete に NO を設定しているので、アニメーション終了後も削除されること無くループ再生される。
03 | imageIndex = MOVANGL_SLEEP; |
05 | efView.isFinishDelete = NO; |
06 | [self addSubview:efView]; |
08 | efView.center = CGPointMake(40, 0); |
09 | [efView setAnimeBoundsScaleFrom:1.0 To:1.2 Duration:1.5]; |