00001 // 00002 // SoundPlayer.m 00003 // MacTrek 00004 // 00005 // Created by Aqua on 03/07/2006. 00006 // Copyright 2006 __MyCompanyName__. 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 subscibeToNotifications]; 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) subscibeToNotifications { 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 } 00067 00068 - (void) unSubscibeToNotifications { 00069 [notificationCenter removeObserver:self name:nil]; // remove myself from all notifications 00070 } 00071 00072 - (void) loadSounds { 00073 00074 SoundEffect *sound; 00075 00076 sound = [[SoundEffect alloc] init]; 00077 [sound loadSoundWithName:@"SoundEffects/cloak"]; 00078 [soundEffects setObject:sound forKey:@"CLOAK_SOUND"]; 00079 sound = [[SoundEffect alloc] init]; 00080 [sound loadSoundWithName:@"SoundEffects/engine"]; 00081 [soundEffects setObject:sound forKey:@"ENGINE_SOUND"]; 00082 sound = [[SoundEffect alloc] init]; 00083 [sound loadSoundWithName:@"SoundEffects/enter_ship"]; 00084 [soundEffects setObject:sound forKey:@"ENTER_SHIP_SOUND"]; // triggerd by GuiManager 00085 sound = [[SoundEffect alloc] init]; 00086 [sound loadSoundWithName:@"SoundEffects/explosion"]; 00087 [soundEffects setObject:sound forKey:@"EXPLOSION_SOUND"]; 00088 sound = [[SoundEffect alloc] init]; 00089 [sound loadSoundWithName:@"SoundEffects/explosion_other"]; 00090 [soundEffects setObject:sound forKey:@"EXPLOSION_OTHER_SOUND"]; 00091 sound = [[SoundEffect alloc] init]; 00092 [sound loadSoundWithName:@"SoundEffects/fire_plasma"]; 00093 [soundEffects setObject:sound forKey:@"FIRE_PLASMA_SOUND"]; 00094 sound = [[SoundEffect alloc] init]; 00095 [sound loadSoundWithName:@"SoundEffects/fire_plasma"]; // use same sound 00096 [soundEffects setObject:sound forKey:@"FIRE_PLASMA_OTHER_SOUND"]; 00097 sound = [[SoundEffect alloc] init]; 00098 [sound loadSoundWithName:@"SoundEffects/fire_torp"]; 00099 [soundEffects setObject:sound forKey:@"FIRE_TORP_SOUND"]; 00100 sound = [[SoundEffect alloc] init]; 00101 [sound loadSoundWithName:@"SoundEffects/fire_torp_other"]; 00102 [soundEffects setObject:sound forKey:@"FIRE_TORP_OTHER_SOUND"]; 00103 sound = [[SoundEffect alloc] init]; 00104 [sound loadSoundWithName:@"SoundEffects/intro"]; 00105 [soundEffects setObject:sound forKey:@"INTRO_SOUND"]; 00106 sound = [[SoundEffect alloc] init]; 00107 [sound loadSoundWithName:@"SoundEffects/message"]; 00108 [soundEffects setObject:sound forKey:@"MESSAGE_SOUND"]; // $$ trigger ? 00109 sound = [[SoundEffect alloc] init]; 00110 [sound loadSoundWithName:@"SoundEffects/fire_phaser"]; 00111 [soundEffects setObject:sound forKey:@"PHASER_SOUND"]; 00112 sound = [[SoundEffect alloc] init]; 00113 [sound loadSoundWithName:@"SoundEffects/fire_phaser_other"]; 00114 [soundEffects setObject:sound forKey:@"PHASER_OTHER_SOUND"]; 00115 sound = [[SoundEffect alloc] init]; 00116 [sound loadSoundWithName:@"SoundEffects/plasma_hit"]; 00117 [soundEffects setObject:sound forKey:@"PLASMA_HIT_SOUND"]; 00118 sound = [[SoundEffect alloc] init]; 00119 [sound loadSoundWithName:@"SoundEffects/red_alert"]; 00120 [soundEffects setObject:sound forKey:@"RED_ALERT_SOUND"]; 00121 sound = [[SoundEffect alloc] init]; 00122 [sound loadSoundWithName:@"SoundEffects/self_destruct"]; 00123 [soundEffects setObject:sound forKey:@"SELF_DESTRUCT_SOUND"]; 00124 sound = [[SoundEffect alloc] init]; 00125 [sound loadSoundWithName:@"SoundEffects/shield_down"]; 00126 [soundEffects setObject:sound forKey:@"SHIELD_DOWN_SOUND"]; 00127 sound = [[SoundEffect alloc] init]; 00128 [sound loadSoundWithName:@"SoundEffects/shield_up"]; 00129 [soundEffects setObject:sound forKey:@"SHIELD_UP_SOUND"]; 00130 sound = [[SoundEffect alloc] init]; 00131 [sound loadSoundWithName:@"SoundEffects/torp_hit"]; 00132 [soundEffects setObject:sound forKey:@"TORP_HIT_SOUND"]; 00133 sound = [[SoundEffect alloc] init]; 00134 [sound loadSoundWithName:@"SoundEffects/uncloak"]; 00135 [soundEffects setObject:sound forKey:@"UNCLOAK_SOUND"]; 00136 sound = [[SoundEffect alloc] init]; 00137 [sound loadSoundWithName:@"SoundEffects/warning"]; // not needed, red alert 00138 [soundEffects setObject:sound forKey:@"WARNING_SOUND"]; // replaced it 00139 00140 // we are done 00141 NSLog(@"SoundPlayer.loadSound done"); 00142 [notificationCenter postNotificationName:@"SP_SOUNDS_CACHED"]; 00143 // play intro sound 00144 [self playSoundEffect:@"INTRO_SOUND"]; 00145 } 00146 00147 - (void) handleSpeedChangeRequest:(NSNumber*)reqSpeed { 00148 00149 int speed = [[universe playerThatIsMe] speed]; 00150 00151 if ((speed == 0) && (reqSpeed > 0)) { // fire up the engines scotty 00152 [self playSoundEffect:@"ENGINE_SOUND"]; 00153 } 00154 } 00155 00156 - (void) handleAlertChanged:(NSNumber*)intAlert { 00157 00158 int newAlertStatus = [intAlert intValue]; 00159 00160 if (newAlertStatus == PLAYER_RED) { 00161 [self playSoundEffect:@"RED_ALERT_SOUND"]; 00162 } 00163 } 00164 00165 - (void) handleCloakChanged:(NSNumber*)boolCloakOn { 00166 00167 bool cloakOn = [boolCloakOn boolValue]; 00168 00169 if (cloakOn) { 00170 [self playSoundEffect:@"CLOAK_SOUND"]; 00171 } else { 00172 [self playSoundEffect:@"UNCLOAK_SOUND"]; 00173 } 00174 } 00175 00176 - (void) playSoundEffect:(NSString*) snd { 00177 SoundEffect *sound = [soundEffects objectForKey:snd]; 00178 if (sound != nil) { 00179 [sound play]; 00180 } else { 00181 NSLog(@"Soundplayer.playSoundEffect no sound for %@", snd); 00182 } 00183 00184 } 00185 00186 - (void) handleSelfDestruct { 00187 [self playSoundEffect:@"SELF_DESTRUCT_SOUND"]; 00188 } 00189 00190 - (void) handleMyPhaser:(Phaser*)Phaser { 00191 [self playSoundEffect:@"PHASER_SOUND"]; 00192 } 00193 00194 - (void) handleShieldsPlayer:(Player*)player { 00195 00196 if (![player isMe]) { 00197 return; // you'll get crazy 00198 } 00199 00200 if ([player flags] & PLAYER_SHIELD) { 00201 [self playSoundEffect:@"SHIELD_UP_SOUND"]; 00202 } else { 00203 [self playSoundEffect:@"SHIELD_DOWN_SOUND"]; 00204 } 00205 00206 } 00207 00208 - (void) handlePlayerExploded:(Player*)player { 00209 if ([player isMe]) { 00210 [self playSoundEffect:@"EXPLOSION_SOUND"]; 00211 } else { 00212 [self playSoundEffect:@"EXPLOSION_OTHER_SOUND"]; 00213 } 00214 } 00215 00216 - (void) handleOtherPhaser:(Phaser*)phaser { 00217 SoundEffect *sound = [soundEffects objectForKey:@"PHASER_OTHER_SOUND"]; 00218 00219 [self playSoundEffect:sound relativeToEntity:[phaser owner]]; 00220 } 00221 00222 - (void) handleMyTorpFired:(Torp*)torp { 00223 [self playSoundEffect:@"FIRE_TORP_SOUND"]; 00224 } 00225 00226 - (void) handleOtherTorpFired:(Torp*)torp { 00227 SoundEffect *sound = [soundEffects objectForKey:@"FIRE_TORP_OTHER_SOUND"]; 00228 00229 [self playSoundEffect:sound relativeToEntity:[torp owner]]; 00230 } 00231 00232 - (void) handleTorpExploded:(Torp*)torp { 00233 SoundEffect *sound = [soundEffects objectForKey:@"TORP_HIT_SOUND"]; 00234 00235 [self playSoundEffect:sound relativeToEntity:torp]; 00236 } 00237 00238 - (void) handleMyPlasmaFired:(Plasma*)plasma { 00239 [self playSoundEffect:@"FIRE_PLASMA_SOUND"]; 00240 } 00241 00242 - (void) handleOtherPlasmaFired:(Plasma*)plasma { 00243 SoundEffect *sound = [soundEffects objectForKey:@"FIRE_PLASMA_OTHER_SOUND"]; 00244 00245 [self playSoundEffect:sound relativeToEntity:[plasma owner]]; 00246 } 00247 00248 - (void) handlePlasmaExploded:(Plasma*)plasma { 00249 SoundEffect *sound = [soundEffects objectForKey:@"PLASMA_HIT_SOUND"]; 00250 00251 [self playSoundEffect:sound relativeToEntity:plasma]; 00252 } 00253 00254 - (void) playSoundEffect:(SoundEffect*)sound relativeToEntity:(Entity*)obj { 00255 float distance = [universe distanceToEntity:obj from:[universe playerThatIsMe]]; 00256 float angle = [universe angleDegBetweenEntity:obj from:[universe playerThatIsMe]]; 00257 00258 [self playSoundEffect:sound atAngle:angle atDistance:distance]; 00259 } 00260 00261 - (void) playSoundEffect:(SoundEffect*)sound atAngle:(float)angle atDistance:(float)distance { 00262 00263 if (sound == nil) { 00264 NSLog(@"Sounplayer.playSoundEffect no sound.."); 00265 return; 00266 } 00267 00268 if (distance > SP_MAX_RANGE) { // prevent negative volume 00269 NSLog(@"Sounplayer.playSoundEffect refuse to play, too far away"); 00270 return; 00271 } 00272 00273 // angle is 0..360, balance is -1 +1 00274 float balance = sin(angle); 00275 00276 // decrease volume with distance at SP_MAX_RANGE = 0 at 0 it is max 00277 float volume = volumeFX - ((volumeFX * distance) / SP_MAX_RANGE); 00278 [sound playWithVolume:volume balance:balance]; 00279 } 00280 00281 @end