diff --git a/dat/outfit.xml b/dat/outfit.xml index 4572c21..edcb74e 100644 --- a/dat/outfit.xml +++ b/dat/outfit.xml @@ -53,7 +53,7 @@ mass - laser + mass ExpS 1100 650 @@ -144,7 +144,7 @@ neutron - laser + neutron ExpS 400 650 @@ -262,6 +262,7 @@ 30 + afterburner 100 50 50 @@ -280,6 +281,7 @@ 50 + afterburner 185 100 85 diff --git a/src/input.c b/src/input.c index 158fb80..012bfc2 100644 --- a/src/input.c +++ b/src/input.c @@ -37,7 +37,6 @@ unsigned int input_afterburnSensibility = 500; // ms between taps to afterburn. // From player.c extern double player_turn; -extern double player_acc; extern unsigned int player_target; // Grabbed from main.c extern int show_fps; @@ -144,22 +143,19 @@ static void input_key(int keynum, double value, int abs) { // Accelerating. if(INGAME() && KEY("accel")) { - if(abs)player_acc = value; + if(abs)player_accel(value); else { // Prevent it from getting stuck. - if(value == KEY_PRESS) player_acc = 1.; - else if(value == KEY_RELEASE) player_acc = 0.; + if(value == KEY_PRESS) player_accel(1.); + else if(value == KEY_RELEASE) player_accelOver(); } // Double tap accel = afterburn! t = SDL_GetTicks(); - if((value == KEY_PRESS) && (t-input_accelLast <= input_afterburnSensibility)) { + if((value == KEY_PRESS) && (t-input_accelLast <= input_afterburnSensibility)) player_afterburn(); - } else if((value == KEY_RELEASE) && player_isFlag(PLAYER_AFTERBURNER)) player_afterburnOver(); - else - player_acc = ABS(player_acc); // Make sure value is sane. if(value == KEY_PRESS) input_accelLast = t; } diff --git a/src/music.c b/src/music.c index 4356c88..5ee2238 100644 --- a/src/music.c +++ b/src/music.c @@ -10,15 +10,21 @@ #define MUSIC_STOPPED (1<<1) #define MUSIC_PLAYING (1<<2) -#define MUSIC_KILL (1<<9) -#define music_is(f) (music_state & f) -#define music_set(f) (music_state |= f) -#define music_rm(f) (music_state ^= f) +#define MUSIC_KILL (1<<9) +#define music_is(f) (music_state & f) +#define music_set(f) (music_state |= f) +#define music_rm(f) (music_state ^= f) -#define MUSIC_PREFIX "../snd/music/" -#define MUSIC_SUFFIX ".ogg" +#define MUSIC_PREFIX "../snd/music/" +#define MUSIC_SUFFIX ".ogg" -#define BUFFER_SIZE (4096 * 8) +#define BUFFER_SIZE (4096 * 8) + +#define soundLock() SDL_mutexP(sound_lock) +#define soundUnlock() SDL_mutexV(sound_lock) + +#define musicLock() SDL_mutexP(music_vorbis_lock) +#define musicUnlock() SDL_mutexV(music_vorbis_lock) // Gobal sound mutex. extern SDL_mutex* sound_lock; @@ -81,8 +87,8 @@ int music_thread(void* unused) { else { music_rm(MUSIC_STOPPED); - SDL_mutexP(music_vorbis_lock); // Lock the mutex. - SDL_mutexP(sound_lock); + musicLock(); // Lock the mutex. + soundLock(); // Start playing current song. active = 0; // Load first buffer. @@ -96,12 +102,12 @@ int music_thread(void* unused) { if(stream_loadBuffer(music_buffer[active])) music_rm(MUSIC_PLAYING); alSourceQueueBuffers(music_source, 1, &music_buffer[active]); - SDL_mutexV(sound_lock); + soundUnlock(); active = 0; } while(music_is(MUSIC_PLAYING)) { - SDL_mutexP(sound_lock); + soundLock(); alGetSourcei(music_source, AL_BUFFERS_PROCESSED, &stat); if(stat > 0) { @@ -112,17 +118,17 @@ int music_thread(void* unused) { active = 1 - active; } - SDL_mutexV(sound_lock); + soundUnlock(); SDL_Delay(0); } - SDL_mutexP(sound_lock); + soundLock(); alSourceStop(music_source); alSourceUnqueueBuffers(music_source, 2, music_buffer); - SDL_mutexV(sound_lock); - SDL_mutexV(music_vorbis_lock); + soundUnlock(); + musicUnlock(); } music_set(MUSIC_STOPPED); SDL_Delay(0); // We must not kill resources. @@ -171,7 +177,7 @@ int music_init(void) { music_vorbis_lock = SDL_CreateMutex(); music_vorbis.file.end = 0; // Indication that it's not loaded.. - SDL_mutexP(sound_lock); + soundLock(); alGenBuffers(2, music_buffer); alGenSources(1, &music_source); @@ -179,7 +185,7 @@ int music_init(void) { alSourcef(music_source, AL_ROLLOFF_FACTOR, 0.); alSourcei(music_source, AL_SOURCE_RELATIVE, AL_TRUE); - SDL_mutexV(sound_lock); + soundUnlock(); return 0; } @@ -209,7 +215,7 @@ static int music_loadOGG(const char* filename) { // Free currently loaded ogg. music_free(); - SDL_mutexP(music_vorbis_lock); + musicLock(); // Load the new ogg. pack_open(&music_vorbis.file, DATA, filename); @@ -219,7 +225,8 @@ static int music_loadOGG(const char* filename) { if(music_vorbis.info->channels == 1) music_vorbis.format = AL_FORMAT_MONO16; else music_vorbis.format = AL_FORMAT_STEREO16; - SDL_mutexV(music_vorbis_lock); + musicUnlock(); + return 0; } @@ -259,7 +266,7 @@ static int music_find(void) { } static void music_free(void) { - SDL_mutexP(music_vorbis_lock); + musicLock(); if(music_vorbis.file.end != 0) { ov_clear(&music_vorbis.stream); @@ -267,7 +274,7 @@ static void music_free(void) { music_vorbis.file.end = 0; // Somewhat ended. } - SDL_mutexV(music_vorbis_lock); + musicUnlock(); } void music_volume(const double vol) { @@ -281,9 +288,9 @@ void music_volume(const double vol) { // Only needed if playing! if(music_set(MUSIC_PLAYING)) { - SDL_mutexP(sound_lock); + soundLock(); alSourcef(music_source, AL_GAIN, fvol); - SDL_mutexV(sound_lock); + soundUnlock(); } } diff --git a/src/outfit.c b/src/outfit.c index fb2a6e6..cdf106e 100644 --- a/src/outfit.c +++ b/src/outfit.c @@ -376,6 +376,8 @@ static void outfit_parseSAfterburner(Outfit* tmp, const xmlNodePtr parent) { do { xmlr_float(node, "rumble", tmp->u.afb.rumble); + if(xml_isNode(node, "sound")) + tmp->u.afb.sound = sound_get(xml_get(node)); if(xml_isNode(node, "thrust_perc")) tmp->u.afb.thrust_perc = 1. + xml_getFloat(node)/100.; xmlr_float(node, "thrust_abs", tmp->u.afb.thrust_abs); diff --git a/src/outfit.h b/src/outfit.h index 0ff45d0..fce8b2a 100644 --- a/src/outfit.h +++ b/src/outfit.h @@ -105,6 +105,7 @@ typedef struct Outfit_ { } mod; struct { // Afterburner. double rumble; // Percent of rumble. + ALuint sound; // Sound of the afterburner. double thrust_perc, thrust_abs; // Percent and absolute thrust bonus. double speed_perc, speed_abs; // Percent and absolute speed bonus. double energy; // Energy used while active. diff --git a/src/player.c b/src/player.c index 1b1c734..e8f543e 100644 --- a/src/player.c +++ b/src/player.c @@ -36,25 +36,30 @@ // Player stuff. Pilot* player = NULL; // extern in pilot.h -static Ship* player_ship = NULL; // Temp ship to hold when naming it. -// More hacks. +static Ship* player_ship = NULL; // Temp ship to hold when naming it. +static alVoice* player_voice = NULL; // Player's voice. static double player_px, player_py, player_vx, player_vy, player_dir; -static int player_credits = 0; // Temp hack. +static int player_credits = 0; // Temp hack. + // Player pilot stack - Ships she owns. static Pilot** player_stack = NULL; -static char** player_lstack = NULL; // Names of the planet the ships are at. +static char** player_lstack = NULL; // Names of the planet the ships are at. static int player_nstack = 0; + // Player global properties. -char* player_name = NULL; // Player name. -int player_crating = 0; // Ze rating. -unsigned int player_flags = 0; // Player flags. +char* player_name = NULL; // Player name. +int player_crating = 0; // Ze rating. +unsigned int player_flags = 0; // Player flags. + // Input.c -double player_turn = 0.; // Turn velocity from input. -double player_acc = 0.; // Accel velocity from input. +double player_turn = 0.; // Turn velocity from input. +static double player_acc = 0.; // Accel velocity from input. unsigned int player_target = PLAYER_ID; // Targetted pilot. + // Internal -int planet_target = -1; // Targetted planet. -int hyperspace_target = -1; // Target hyperspace route. +int planet_target = -1; // Targetted planet. +int hyperspace_target = -1; // Target hyperspace route. + // For death etc. static unsigned int player_timer = 0; static Vec2 player_cam; @@ -133,21 +138,31 @@ extern void weapon_minimap(const double res, extern void planets_minimap(const double res, const double w, const double h, const RadarShape shape); // space.c // Internal. + +// Creation. static void player_newMake(void); static void player_newShipMake(char* name); +// Sound. +static void player_initSound(void); +static void player_playSound(ALuint sound, int once); +static void player_stopSound(void); +// Gui. static void rect_parse(const xmlNodePtr parent, double* x, double* y, double* w, double* h); static int gui_parse(const xmlNodePtr parent, const char* name); static void gui_renderPilot(const Pilot* p); static void gui_renderBar(const glColour* c, const Rect* r, const double w); +// Save/Load. static int player_saveShip(xmlTextWriterPtr writer, Pilot* ship, char* loc); static int player_parse(xmlNodePtr parent); static int player_parseDone(xmlNodePtr parent); static int player_parseShip(xmlNodePtr parent, int is_player); + // Externed. void player_dead(void); void player_destroyed(void); int player_save(xmlTextWriterPtr writer); +int player_load(xmlNodePtr parent); // Prompt player name. void player_new(void) { @@ -158,6 +173,9 @@ void player_new(void) { vectnull(&player_cam); gl_bindCamera(&player_cam); + // Setup sound. + player_initSound(); + // Cleanup player stuff if we'll be re-creating. player_cleanup(); @@ -300,9 +318,11 @@ static void player_newShipMake(char* name) { // In case we're respawning. player_rmFlag(PLAYER_CREATING); + // Hackish position setting. vect_cset(&vp, player_px, player_py); vect_cset(&vv, player_vx, player_vy); + // Create the player. pilot_create(player_ship, name, faction_get("Player"), NULL, player_dir, &vp, &vv, PILOT_PLAYER); @@ -382,6 +402,27 @@ void player_cleanup(void) { } } +// Initializes the player sound. +static void player_initSound(void) { + if(player_voice == NULL) { + player_voice = sound_addVoice(0, // Max priority. + 0., 0., 0., 0., 0., // No properties. + VOICE_LOOPING | VOICE_STATIC); + } +} + +// Play a sound. +static void player_playSound(ALuint sound, int once) { + unsigned int flags = VOICE_STATIC; + + if(once == 0) flags |= VOICE_LOOPING; + voice_buffer(player_voice, sound, flags); +} + +static void player_stopSound(void) { + voice_stop(player_voice); +} + void player_message(const char* fmt, ...) { va_list ap; int i; @@ -1335,6 +1376,7 @@ void player_afterburn(void) { player_setFlag(PLAYER_AFTERBURNER); pilot_setFlag(player, PILOT_AFTERBURNER); spfx_shake(player->afterburner->outfit->u.afb.rumble * SHAKE_MAX); + player_playSound(player->afterburner->outfit->u.afb.sound, 0); } } @@ -1342,9 +1384,21 @@ void player_afterburnOver(void) { if(player->afterburner != NULL) { player_rmFlag(PLAYER_AFTERBURNER); pilot_rmFlag(player, PILOT_AFTERBURNER); + player_stopSound(); } } +// Start accelerating. +void player_accel(double acc) { + player_acc = acc; + //player_playSound(player->ship->sound, 0); +} + +void player_accelOver(void) { + player_acc = 0; + //player_stopSound(); +} + // Take a screenshot. static int screenshot_cur = 0; void player_screenshot(void) { @@ -1619,6 +1673,10 @@ static int player_parse(xmlNodePtr parent) { // Initialize the system. space_init(planet_getSystem(planet)); + map_clear(); // Sets the map up. + + // Initialize the sound. + player_initSound(); return 0; } diff --git a/src/player.h b/src/player.h index 175a55b..fb05af5 100644 --- a/src/player.h +++ b/src/player.h @@ -73,4 +73,6 @@ void player_jump(void); void player_screenshot(void); void player_afterburn(void); void player_afterburnOver(void); +void player_accel(double acc); +void player_accelOver(void); diff --git a/src/sound.c b/src/sound.c index 313bfb2..b670639 100644 --- a/src/sound.c +++ b/src/sound.c @@ -52,6 +52,9 @@ #define SOUND_PREFIX "../snd/sounds/" #define SOUND_SUFFIX ".wav" +#define soundLock() SDL_mutexP(sound_lock) +#define soundUnlock() SDL_mutexV(sound_lock) + // Give the buffers a name. typedef struct alSound_ { char* name; // Buffers name. @@ -112,7 +115,7 @@ static int voice_getSource(alVoice* voc); static void voice_init(alVoice* voice); static int voice_play(alVoice* voice); static void voice_rm(alVoice* prev, alVoice* voice); -static void voice_parseFlags(alVoice* voice, const int flags); +static void voice_parseFlags(alVoice* voice, const unsigned int flags); int sound_init(void) { int mem, ret = 0; @@ -122,8 +125,8 @@ int sound_init(void) { // We'll need a mutex. sound_lock = SDL_CreateMutex(); + soundLock(); - SDL_mutexP(sound_lock); const ALchar* device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); // Open the default device. al_device = alcOpenDevice(NULL); @@ -158,7 +161,7 @@ int sound_init(void) { alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); // We can unlock now. - SDL_mutexV(sound_lock); + soundUnlock(); // Start the music server. music_init(); @@ -201,7 +204,7 @@ snderr_ctx: alcCloseDevice(al_device); snderr_dev: al_device = NULL; - SDL_mutexV(sound_lock); + soundUnlock(); SDL_DestroyMutex(sound_lock); sound_lock = NULL; ERR("Sound failed to initialize."); @@ -237,7 +240,7 @@ void sound_exit(void) { alDeleteSources(source_nstack, source_stack); if(sound_lock) { - SDL_mutexP(sound_lock); + soundLock(); if(al_context) { alcMakeContextCurrent(NULL); @@ -245,7 +248,7 @@ void sound_exit(void) { } if(al_device) alcCloseDevice(al_device); - SDL_mutexV(sound_lock); + soundUnlock(); SDL_DestroyMutex(sound_lock); } } @@ -324,7 +327,7 @@ static int sound_load(ALuint* buffer, char* filename) { // Get the file data buffer from the packfile. wavdata = pack_readfile(DATA, filename, &size); - SDL_mutexP(sound_lock); + soundLock(); // Bind to OpenAL buffer. alGenBuffers(1, buffer); @@ -336,7 +339,7 @@ static int sound_load(ALuint* buffer, char* filename) { return 0; } - SDL_mutexV(sound_lock); + soundUnlock(); // Finish up. free(wavdata); @@ -346,13 +349,13 @@ static int sound_load(ALuint* buffer, char* filename) { static void sound_free(alSound* snd) { if(sound_lock) return; - SDL_mutexP(sound_lock); + soundLock(); // Free the stuff. if(snd->name) free(snd->name); alDeleteBuffers(1, &snd->buffer); - SDL_mutexV(sound_lock); + soundUnlock(); } // Update the sounds and prioritize them. @@ -363,7 +366,7 @@ void sound_update(void) { if(sound_lock == NULL) return; // Sound system is off. if(voice_start == NULL) return; // No voices. - SDL_mutexP(sound_lock); + soundLock(); // Update sound. prev = NULL; @@ -386,8 +389,8 @@ void sound_update(void) { voice_rm(prev, voice); voice = next; } while(voice != NULL); - - SDL_mutexV(sound_lock); + + soundUnlock(); } // Remove a voice. @@ -429,7 +432,7 @@ static int voice_getSource(alVoice* voc) { ret = 0; // Default return. - SDL_mutexP(sound_lock); + soundLock(); // Try and grab a source. if(source_nstack > 0) { // We have the source. @@ -441,7 +444,8 @@ static int voice_getSource(alVoice* voc) { ret = voice_play(voc); } else voc->source = 0; - SDL_mutexV(sound_lock); + + soundUnlock(); return ret; } @@ -453,7 +457,6 @@ static void voice_init(alVoice* voice) { alSourcef(voice->source, AL_MAX_DISTANCE, SOUND_MAX_DIST); alSourcef(voice->source, AL_REFERENCE_DISTANCE, SOUND_REFERENCE_DIST); - alSourcei(voice->source, AL_SOURCE_RELATIVE, AL_FALSE); alSourcef(voice->source, AL_GAIN, svolume); alSource3f(voice->source, AL_POSITION, voice->px, voice->py, 0.); //alSource3f(voice->source, AL_VELOCITY, voice->vx, voice->vy, 0.); @@ -465,7 +468,7 @@ static void voice_init(alVoice* voice) { // Create a dynamic moving piece. alVoice* sound_addVoice(int priority, double px, double py, - double vx, double vy, const ALuint buffer, const int flags) { + double vx, double vy, const ALuint buffer, const unsigned int flags) { (void)vx; (void)vy; @@ -506,6 +509,7 @@ alVoice* sound_addVoice(int priority, double px, double py, return voc; } +// Delete the voice. void sound_delVoice(alVoice* voice) { if(sound_lock == NULL) return; @@ -526,31 +530,48 @@ void voice_update(alVoice* voice, double px, double py, double vx, double vy) { } // Changes the voice's buffer. -void voice_buffer(alVoice* voice, const ALuint buffer, const int flags) { +void voice_buffer(alVoice* voice, const ALuint buffer, const unsigned int flags) { voice->buffer = buffer; voice_parseFlags(voice, flags); // Start playing. - SDL_mutexP(sound_lock); + soundLock(); voice_play(voice); - SDL_mutexV(sound_lock); + soundUnlock(); +} + +// Stop playing sound. +void voice_stop(alVoice* voice) { + soundLock(); + if(voice->source != 0) + alSourceStop(voice->source); + soundUnlock(); } // Handle flags. -static void voice_parseFlags(alVoice* voice, const int flags) { +static void voice_parseFlags(alVoice* voice, const unsigned int flags) { voice->flags = 0; // Defaults. // Looping. if(flags & VOICE_LOOPING) voice_set(voice, VOICE_LOOPING); + + if(flags & VOICE_STATIC) + alSourcei(voice->source, AL_SOURCE_RELATIVE, AL_TRUE); + else + alSourcei(voice->source, AL_SOURCE_RELATIVE, AL_FALSE); } // Make a voice play. Must lock before calling. static int voice_play(alVoice* voice) { ALenum err; + ALint stat; // Must have buffer. if(voice->buffer != 0) { + alGetSourcei(voice->source, AL_SOURCE_STATE, &stat); + if(stat == AL_PLAYING) + alSourceStop(voice->source); // Set buffer. alSourcei(voice->source, AL_BUFFER, voice->buffer); @@ -570,7 +591,7 @@ void sound_listener(double dir, double px, double py, double vx, double vy) { if(sound_lock == NULL) return; - SDL_mutexP(sound_lock); + soundLock(); // Set orientation. ALfloat ori[] = { 0., 0., 0., 0., 0., 1. }; @@ -580,6 +601,6 @@ void sound_listener(double dir, double px, double py, double vx, double vy) { alListener3f(AL_POSITION, px, py, 1.); //alListener3f(AL_VELOCITY, vx, vy, 0.); - SDL_mutexV(sound_lock); + soundUnlock(); } diff --git a/src/sound.h b/src/sound.h index 9ef5a53..942c205 100644 --- a/src/sound.h +++ b/src/sound.h @@ -2,7 +2,8 @@ #include #include "physics.h" -#define VOICE_LOOPING (1<<10) +#define VOICE_LOOPING (1<<10) // Voice loops. +#define VOICE_STATIC (1<<11) // Voice isn't relative. struct alVoice; typedef struct alVoice alVoice; @@ -18,12 +19,13 @@ void sound_volume(const double vol); // Voice manipulation function. alVoice* sound_addVoice(int priority, double px, double py, - double vx, double vy, const ALuint buffer, const int flags); + double vx, double vy, const ALuint buffer, const unsigned int flags); void sound_delVoice(alVoice* voice); // Delete voice. void voice_update(alVoice* voice, double px, double py, double vx, double vy); -void voice_buffer(alVoice* voice, const ALuint buffer, const int flags); +void voice_buffer(alVoice* voice, const ALuint buffer, const unsigned int flags); +void voice_stop(alVoice* voice); // Listener manipulation. void sound_listener(double dir, double px, double py, double vx, double vy);