今回でこの連載も最終回となる、最後にサウンド再生、残りタイム表示と、ゲームがタイトル画面とゲーム画面のフローでループできるよう実装して、ゲーム部分の仕上げをしたいと思う。
サウンドの再生
まずはサウンドの再生から実装していこう。ゲーム中ではSE(サウンドエフェクト)とBGMの2つを鳴らすが、それぞれ必要なフレームワークをプロジェクトに追加する必要がある。AudioToolboxとAVFoundationの2つのフレームワークを追加しよう。
| 図1:フレームワークの追加(クリックで拡大) |
そして、GameController.h に以下のようにサウンド用のプロパティーを追加しておく。
@interface GameController : NSObject {
GameBoardView *gameView;
GamePieceView *pieceView; //うさぎ
GamePieceView *enemyView; //オオカミ
int carotCount;
BOOL isGameClear;
//サウンド
NSMutableArray* seArray; //SEの配列
AVAudioPlayer* bgmPlayer; //BGM再生クラス
}
SEの再生
まずSEを再生しよう。サウンドデータを作りプロジェクトに追加する必要がある、本来はシーンごとにSEを用意するのだが今回は1つのSEを鳴らすようにする。iOSでは .aif / .wav / .mp3 などの一般的なフォーマットを再生することができるが、今回は se00.caf というコア・オーディオというフォーマットのサウンドファイルを使用することにする。コア・オーディオファイルについては後ほど説明する。
SEは再生用のクラスとそのインスタンス作り、それで再生を行う。以下がSE再生用のクラスになる。
<クラス定義>
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioServices.h>
@interface SoundEffect : NSObject {
SystemSoundID soundID;
}
- (id)initWithContentsOfFile:(NSString *)path;
- (void)play;
@end
<クラス実装部>
#import "SoundEffect.h"
@implementation SoundEffect
- (id)initWithContentsOfFile:(NSString *)path {
self = [super init];
if (self != nil) {
NSURL *aFileURL = [NSURL fileURLWithPath:path isDirectory:NO];
AudioServicesCreateSystemSoundID((CFURLRef)aFileURL, &soundID);
}
return self;
}
-(void)dealloc {
AudioServicesDisposeSystemSoundID(soundID);
[super dealloc];
}
-(void)play {
AudioServicesPlaySystemSound(soundID);
}
@end
GameControllerクラスの初期化時に以下のコードを追加して SoundEffectのインスタンスを配列の保持しておく。
// SE
seArray = [[NSMutableArray array] retain];
NSString* path;
SoundEffect* se;
path = [[NSBundle mainBundle] pathForResource:@"se00" ofType:@"aif"];
se = [[[SoundEffect alloc] initWithContentsOfFile:path] autorelease];
[seArray addObject:se];
SoundEffectクラスはサウンドデータのパスから SystemSoundID を得て、SystemSoundIDを使ってサウンドを再生する。SystemSoundIDの定義は以下のようになっている、ただの整数値だ。配列に入れて使用したいので、このようにクラス化している。
<SystemSoundID定義>
typedef UInt32 SystemSoundID;
オオカミが攻撃を開始する時にSEを再生してみよう。今回は1つだけだが、複数のSEを使う場合は別にSE番号などを定義しておけばいいだろう。その番号で配列から SoundEffect を取り出して、playメソッドで再生する。
-(void) gamePieceCAMoveStart:(GamePieceView*)piece Position:(CGPoint)pt {
//オオカミが攻撃開始
if(piece.type==TYPE_WLOF && piece.state==STATE_ATTACK){
// SE再生
SoundEffect* se = [seArray objectAtIndex:0];
[se play];
//隣のマス目にいる
if([self nearPlayerPieceAngle:piece]!=MOVANGL_NON){
if( pieceView.state!=STATE_DAMAGE && pieceView.state!=STATE_DEAD ){
pieceView.state = STATE_DAMAGE;
if(pieceView.life <= 0){
piece.state = STATE_STAY;
}
}
}
}
//うさぎが移動開始
if( piece.type==TYPE_RABBIT ){
[enemyView moveWith:piece.tile];
}
}
- この記事のキーワード
