00001 // 00002 // SoundPlayer.m 00003 // MacTrek 00004 // 00005 // Created by Aqua on 03/07/2006. 00006 // Copyright 2006 Luky Soft. All rights reserved. 00007 // 00008 00009 #import "SoundPlayer.h" 00010 00011 Universe *universe; 00012 00013 @implementation SoundPlayer 00014 00015 - (id) init { 00016 self = [super init]; 00017 if (self != nil) { 00018 //soundEffects = [[NSMutableArray alloc] init]; 00019 soundEffects = [[NSMutableDictionary alloc] init]; 00020 universe = [Universe defaultInstance]; 00021 volumeFX = 0.8; 00022 volumeMusic = 0.8; 00023 00024 //[self subscribeToNotifications]; // the gui manager will sub/unsub us 00025 00026 // start caching in the background 00027 [self performSelector:@selector(loadSounds) withObject:nil afterDelay:0.01]; 00028 //[self loadSounds]; // $$seperate thread works not ok? 00029 00030 } 00031 return self; 00032 } 00033 00034 - (void) awakeFromNib { 00035 00036 // hmm not called? 00037 00038 } 00039 00040 - (void) setVolumeFx:(float)vol { 00041 volumeFX = vol; 00042 } 00043 00044 - (void) setVolumeMusic:(float)vol { 00045 volumeMusic = vol; 00046 } 00047 00048 - (void) subscribeToNotifications { 00049 00050 [notificationCenter addObserver:self selector:@selector(handleAlertChanged:) name:@"PL_ALERT_STATUS_CHANGED"]; 00051 [notificationCenter addObserver:self selector:@selector(handleCloakChanged:) name:@"PL_CLOAKING"]; 00052 [notificationCenter addObserver:self selector:@selector(handleCloakChanged:) name:@"PL_UNCLOAKING"]; 00053 [notificationCenter addObserver:self selector:@selector(handleMyPhaser:) name:@"PL_MY_PHASER_FIRING"]; 00054 [notificationCenter addObserver:self selector:@selector(handleOtherPhaser:) name:@"PL_OTHER_PHASER_FIRING"]; 00055 [notificationCenter addObserver:self selector:@selector(handleMyTorpFired:) name:@"PL_TORP_FIRED_BY_ME"]; 00056 [notificationCenter addObserver:self selector:@selector(handleOtherTorpFired:) name:@"PL_TORP_FIRED_BY_OTHER"]; 00057 [notificationCenter addObserver:self selector:@selector(handleTorpExploded:) name:@"PL_TORP_EXPLODED"]; 00058 [notificationCenter addObserver:self selector:@selector(handleMyPlasmaFired:) name:@"PL_PLASMA_FIRED_BY_ME"]; 00059 [notificationCenter addObserver:self selector:@selector(handleOtherPlasmaFired:) name:@"PL_PLASMA_FIRED_BY_OTHER"]; 00060 [notificationCenter addObserver:self selector:@selector(handlePlasmaExploded:) name:@"PL_PLASMA_EXPLODED"]; 00061 [notificationCenter addObserver:self selector:@selector(handlePlayerExploded:) name:@"PL_EXPLODE_PLAYER"]; 00062 [notificationCenter addObserver:self selector:@selector(handleSelfDestruct) name:@"SPW_SELF_DESTRUCT_INITIATED"]; 00063 [notificationCenter addObserver:self selector:@selector(handleShieldsPlayer:) name:@"PL_SHIELD_UP_PLAYER"]; 00064 [notificationCenter addObserver:self selector:@selector(handleShieldsPlayer:) name:@"PL_SHIELD_DOWN_PLAYER"]; 00065 [notificationCenter addObserver:self selector:@selector(handleSpeedChangeRequest:) name:@"COMM_SEND_SPEED_REQ"]; 00066 [notificationCenter addObserver:self selector:@selector(handleMessageSent) name:@"COMM_SEND_MESSAGE"]; 00067 } 00068 00069 - (void) unSubscibeToNotifications { 00070 [notificationCenter removeObserver:self name:nil]; // remove myself from all notifications 00071 } 00072 00073 - (void) loadSounds { 00074 00075 SoundEffect *sound; 00076 00077 sound = [[SoundEffect alloc] init]; 00078 [sound loadSoundWithName:@"SoundEffects/cloak.au"]; 00079 [soundEffects setObject:sound forKey:@"CLOAK_SOUND"]; 00080 sound = [[SoundEffect alloc] init]; 00081 [sound loadSoundWithName:@"SoundEffects/engine.au"]; 00082 [soundEffects setObject:sound forKey:@"ENGINE_SOUND"]; 00083 sound = [[SoundEffect alloc] init]; 00084 [sound loadSoundWithName:@"SoundEffects/enter_ship.au"]; 00085 [soundEffects setObject:sound forKey:@"ENTER_SHIP_SOUND"]; // triggerd by GuiManager 00086 sound = [[SoundEffect alloc] init]; 00087 [sound loadSoundWithName:@"SoundEffects/explosion.au"]; 00088 [soundEffects setObject:sound forKey:@"EXPLOSION_SOUND"]; 00089 sound = [[SoundEffect alloc] init]; 00090 [sound loadSoundWithName:@"SoundEffects/explosion_other.au"]; 00091 [soundEffects setObject:sound forKey:@"EXPLOSION_OTHER_SOUND"]; 00092 sound = [[SoundEffect alloc] init]; 00093 [sound loadSoundWithName:@"SoundEffects/fire_plasma.au"]; 00094 [soundEffects setObject:sound forKey:@"FIRE_PLASMA_SOUND"]; 00095 sound = [[SoundEffect alloc] init]; 00096 [sound loadSoundWithName:@"SoundEffects/fire_plasma.au"]; // use same sound 00097 [soundEffects setObject:sound forKey:@"FIRE_PLASMA_OTHER_SOUND"]; 00098 sound = [[SoundEffect alloc] init]; 00099 [sound loadSoundWithName:@"SoundEffects/fire_torp.au"]; 00100 [soundEffects setObject:sound forKey:@"FIRE_TORP_SOUND"]; 00101 sound = [[SoundEffect alloc] init]; 00102 [sound loadSoundWithName:@"SoundEffects/fire_torp_other.au"]; 00103 [soundEffects setObject:sound forKey:@"FIRE_TORP_OTHER_SOUND"]; 00104 sound = [[SoundEffect alloc] init]; 00105 [sound loadSoundWithName:@"SoundEffects/intro.au"]; 00106 [soundEffects setObject:sound forKey:@"INTRO_SOUND"]; 00107 sound = [[SoundEffect alloc] init]; 00108 [sound loadSoundWithName:@"SoundEffects/message.au"]; 00109 [soundEffects setObject:sound forKey:@"MESSAGE_SOUND"]; 00110 sound = [[SoundEffect alloc] init]; 00111 [sound loadSoundWithName:@"SoundEffects/fire_phaser.au"]; 00112 [soundEffects setObject:sound forKey:@"PHASER_SOUND"]; 00113 sound = [[SoundEffect alloc] init]; 00114 [sound loadSoundWithName:@"SoundEffects/fire_phaser_other.au"]; 00115 [soundEffects setObject:sound forKey:@"PHASER_OTHER_SOUND"]; 00116 sound = [[SoundEffect alloc] init]; 00117 [sound loadSoundWithName:@"SoundEffects/plasma_hit.au"]; 00118 [soundEffects setObject:sound forKey:@"PLASMA_HIT_SOUND"]; 00119 sound = [[SoundEffect alloc] init]; 00120 [sound loadSoundWithName:@"SoundEffects/red_alert.au"]; 00121 [soundEffects setObject:sound forKey:@"RED_ALERT_SOUND"]; 00122 sound = [[SoundEffect alloc] init]; 00123 [sound loadSoundWithName:@"SoundEffects/self_destruct.au"]; 00124 [soundEffects setObject:sound forKey:@"SELF_DESTRUCT_SOUND"]; 00125 sound = [[SoundEffect alloc] init]; 00126 [sound loadSoundWithName:@"SoundEffects/shield_down.au"]; 00127 [soundEffects setObject:sound forKey:@"SHIELD_DOWN_SOUND"]; 00128 sound = [[SoundEffect alloc] init]; 00129 [sound loadSoundWithName:@"SoundEffects/shield_up.au"]; 00130 [soundEffects setObject:sound forKey:@"SHIELD_UP_SOUND"]; 00131 sound = [[SoundEffect alloc] init]; 00132 [sound loadSoundWithName:@"SoundEffects/torp_hit.au"]; 00133 [soundEffects setObject:sound forKey:@"TORP_HIT_SOUND"]; 00134 sound = [[SoundEffect alloc] init]; 00135 [sound loadSoundWithName:@"SoundEffects/uncloak.au"]; 00136 [soundEffects setObject:sound forKey:@"UNCLOAK_SOUND"]; 00137 sound = [[SoundEffect alloc] init]; 00138 [sound loadSoundWithName:@"SoundEffects/warning.au"]; // not needed, red alert 00139 [soundEffects setObject:sound forKey:@"WARNING_SOUND"]; // replaced it 00140 00141 // we are done 00142 NSLog(@"SoundPlayer.loadSound done"); 00143 [notificationCenter postNotificationName:@"SP_SOUNDS_CACHED"]; 00144 } 00145 00146 - (void) handleSpeedChangeRequest:(NSNumber*)reqSpeed { 00147 00148 int speed = [[universe playerThatIsMe] speed]; 00149 00150 if ((speed == 0) && (reqSpeed > 0)) { // fire up the engines scotty 00151 [self playSoundEffect:@"ENGINE_SOUND"]; 00152 } 00153 } 00154 00155 - (void) handleAlertChanged:(NSNumber*)intAlert { 00156 00157 int newAlertStatus = [intAlert intValue]; 00158 00159 if (newAlertStatus == PLAYER_RED) { 00160 [self playSoundEffect:@"RED_ALERT_SOUND"]; 00161 } 00162 } 00163 00164 - (void) handleCloakChanged:(NSNumber*)boolCloakOn { 00165 00166 bool cloakOn = [boolCloakOn boolValue]; 00167 00168 if (cloakOn) { 00169 [self playSoundEffect:@"CLOAK_SOUND"]; 00170 } else { 00171 [self playSoundEffect:@"UNCLOAK_SOUND"]; 00172 } 00173 } 00174 00175 - (void) playSoundEffect:(NSString*) snd { 00176 SoundEffect *sound = [soundEffects objectForKey:snd]; 00177 if (sound != nil) { 00178 [sound play]; 00179 } else { 00180 NSLog(@"Soundplayer.playSoundEffect no sound for %@", snd); 00181 } 00182 00183 } 00184 00185 - (void) handleMessageSent { 00186 [self playSoundEffect:@"MESSAGE_SOUND"]; 00187 } 00188 00189 - (void) handleSelfDestruct { 00190 [self playSoundEffect:@"SELF_DESTRUCT_SOUND"]; 00191 } 00192 00193 - (void) handleMyPhaser:(Phaser*)Phaser { 00194 [self playSoundEffect:@"PHASER_SOUND"]; 00195 } 00196 00197 - (void) handleShieldsPlayer:(Player*)player { 00198 00199 if (![player isMe]) { 00200 return; // you'll get crazy 00201 } 00202 00203 if ([player flags] & PLAYER_SHIELD) { 00204 [self playSoundEffect:@"SHIELD_UP_SOUND"]; 00205 } else { 00206 [self playSoundEffect:@"SHIELD_DOWN_SOUND"]; 00207 } 00208 00209 } 00210 00211 - (void) handlePlayerExploded:(Player*)player { 00212 if ([player isMe]) { 00213 [self playSoundEffect:@"EXPLOSION_SOUND"]; 00214 } else { 00215 [self playSoundEffect:@"EXPLOSION_OTHER_SOUND"]; 00216 } 00217 } 00218 00219 - (void) handleOtherPhaser:(Phaser*)phaser { 00220 SoundEffect *sound = [soundEffects objectForKey:@"PHASER_OTHER_SOUND"]; 00221 00222 [self playSoundEffect:sound relativeToEntity:[phaser owner]]; 00223 } 00224 00225 - (void) handleMyTorpFired:(Torp*)torp { 00226 [self playSoundEffect:@"FIRE_TORP_SOUND"]; 00227 } 00228 00229 - (void) handleOtherTorpFired:(Torp*)torp { 00230 SoundEffect *sound = [soundEffects objectForKey:@"FIRE_TORP_OTHER_SOUND"]; 00231 00232 [self playSoundEffect:sound relativeToEntity:[torp owner]]; 00233 } 00234 00235 - (void) handleTorpExploded:(Torp*)torp { 00236 SoundEffect *sound = [soundEffects objectForKey:@"TORP_HIT_SOUND"]; 00237 00238 [self playSoundEffect:sound relativeToEntity:torp]; 00239 } 00240 00241 - (void) handleMyPlasmaFired:(Plasma*)plasma { 00242 [self playSoundEffect:@"FIRE_PLASMA_SOUND"]; 00243 } 00244 00245 - (void) handleOtherPlasmaFired:(Plasma*)plasma { 00246 SoundEffect *sound = [soundEffects objectForKey:@"FIRE_PLASMA_OTHER_SOUND"]; 00247 00248 [self playSoundEffect:sound relativeToEntity:[plasma owner]]; 00249 } 00250 00251 - (void) handlePlasmaExploded:(Plasma*)plasma { 00252 SoundEffect *sound = [soundEffects objectForKey:@"PLASMA_HIT_SOUND"]; 00253 00254 [self playSoundEffect:sound relativeToEntity:plasma]; 00255 } 00256 00257 - (void) playSoundEffect:(SoundEffect*)sound relativeToEntity:(Entity*)obj { 00258 float distance = [universe distanceToEntity:obj from:[universe playerThatIsMe]]; 00259 float angle = [universe angleDegBetweenEntity:obj from:[universe playerThatIsMe]]; 00260 00261 [self playSoundEffect:sound atAngle:angle atDistance:distance]; 00262 } 00263 00264 - (void) playSoundEffect:(SoundEffect*)sound atAngle:(float)angle atDistance:(float)distance { 00265 00266 if (sound == nil) { 00267 NSLog(@"Sounplayer.playSoundEffect no sound.."); 00268 return; 00269 } 00270 00271 if (distance > SP_MAX_RANGE) { // prevent negative volume 00272 NSLog(@"Sounplayer.playSoundEffect refuse to play, too far away"); 00273 return; 00274 } 00275 00276 // angle is 0..360, balance is -1 +1 00277 float balance = sin(angle); 00278 00279 // decrease volume with distance at SP_MAX_RANGE = 0 at 0 it is max 00280 float volume = volumeFX - ((volumeFX * distance) / SP_MAX_RANGE); 00281 [sound playWithVolume:volume balance:balance]; 00282 } 00283 00284 @end