読者です 読者をやめる 読者になる 読者になる

夏までにiPhone アプリつくってみっか!

趣味でiPhone/Androidアプリを開発し、日々勉強した事を書いています。オープンワールド系レースゲームをUnityで開発中です。

【cocos2d】全てのSEをピタッと止める

cocos2d TravelShooting JP

ゲームにポーズ機能をしばらく前に付けましたが、ポーズした時に鳴っているSEがすぐに鳴り止まず、弾の発射音や爆発音が後を引くのがずっと気になっていました。
BGMはSimpleAudioEngineのpauseBackgroundMusicで一時停止できますが、エフェクトの方はどのエフェクトを止めるのかsoundIDという物を指定する必要があります。
SimpleAudioEngineを使って普通にSEを鳴らすときにはsoundIDあまり意識しないのですが、以前同時発声数を減らしてSEのキレを良くするクラスを作っていたので、これを拡張して全SEを一瞬で停止するstopAllEffects機能を追加しました。
SEのキレを良くする方法につきましてはこちらをご参照ください。

【cocos2d】あえて同時発声を制限してキレのいいSEを鳴らす - 夏までにiPhone アプリつくってみっか!

改良したソースはこちら。

ヘッダファイル

#import <Foundation/Foundation.h>
#import "cocos2d.h"

@interface SEManager : NSObject {
    
}

+ (SEManager *)sharedManager;
- (void)playSE:(NSString *)filename keyword:(NSString *)keyword;
- (void)playSE:(NSString *)filename keyword:(NSString *)keyword pitch:(Float32)pitch pan:(Float32)pan gain:(Float32)gain;
- (void)stopAllEffects;

@end

メインファイル

#import "SEManager.h"
#import "SimpleAudioEngine.h"


@implementation SEManager {
    NSMutableDictionary* _IDTable;
}

+ (SEManager *)sharedManager
{
    static SEManager* sharedInstance = nil;
    if (!sharedInstance) {
        sharedInstance = [[self alloc] init];
    }
    return sharedInstance;
}

- (id)init
{
    if ((self = [super init])) {
        _IDTable = [NSMutableDictionary dictionary];
    }
    return self;
}

- (void)playSE:(NSString *)filename keyword:(NSString *)keyword
{
    id IDObject = _IDTable[keyword];
    if (IDObject) {
        [[SimpleAudioEngine sharedEngine] stopEffect:[IDObject integerValue]];
    }
    ALuint soundID = [[SimpleAudioEngine sharedEngine] playEffect:filename];
    _IDTable[keyword] = @(soundID);
}

- (void)playSE:(NSString *)filename keyword:(NSString *)keyword pitch:(Float32)pitch pan:(Float32)pan gain:(Float32)gain
{
    id IDObject = _IDTable[keyword];
    if (IDObject) {
        [[SimpleAudioEngine sharedEngine] stopEffect:[IDObject integerValue]];
    }
    ALuint soundID = [[SimpleAudioEngine sharedEngine] playEffect:filename pitch:pitch pan:pan gain:gain];
    _IDTable[keyword] = @(soundID);
}

- (void)stopAllEffects
{
    for (id key in _IDTable) {
        ALuint soundID = [_IDTable[key] integerValue];
        [[SimpleAudioEngine sharedEngine] stopEffect:soundID];
    }
}

@end

現在鳴っているsoundIDを記憶しているNSMutableDictionaryから全てのsoundIDを読み出してstopEffectに渡しています。
また、ついでに他のメソッドもモダンな記述方法に直してみました。
Objective-Cっぽさが薄まって読みやすくなったと思います。