ゲームの演出

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;
「ゲームの演出」サンプルプログラム



