diff --git a/dat/outfit.xml b/dat/outfit.xml index 29d0901..3dc6234 100644 --- a/dat/outfit.xml +++ b/dat/outfit.xml @@ -8,6 +8,7 @@ </general> <specific type="1"> <gfx>lasergreen</gfx> + <sound>laser</sound> <delay>500</delay> <speed>550</speed> <range>300</range> diff --git a/src/main.c b/src/main.c index 3cc5ea3..8fcd20f 100644 --- a/src/main.c +++ b/src/main.c @@ -111,7 +111,7 @@ int main(int argc, char** argv) { // OpenAL sound. if(sound_init()) WARN("Problem setting up sound!"); music_load("Machina"); - music_play(); + //music_play(); // Input. if((indjoystick >= 0) || (namjoystick != NULL)) { @@ -177,6 +177,8 @@ int main(int argc, char** argv) { input_handle(&event); // handles all the events the player keybinds. } + sound_update(); // Do the sound stuff. + glClear(GL_COLOR_BUFFER_BIT); fps_control(); // Who doesn't love FPS control? diff --git a/src/music.c b/src/music.c index 55ae090..62f97c1 100644 --- a/src/music.c +++ b/src/music.c @@ -153,6 +153,8 @@ void music_exit(void) { for(i = 0; i < nmusic_selection; i++) free(music_selection[i]); free(music_selection); + + SDL_DestroyMutex(music_vorbis_lock); } // Internal music loading ruitines. @@ -220,6 +222,10 @@ static void music_free(void) { SDL_mutexV(music_vorbis_lock); } +void music_volume(const double vol) { + alSourcef(music_source, AL_GAIN, (ALfloat)vol); +} + // Music control functions. void music_load(const char* name) { int i; diff --git a/src/music.h b/src/music.h index 857e93c..96bb65f 100644 --- a/src/music.h +++ b/src/music.h @@ -9,6 +9,7 @@ int music_init(void); void music_exit(void); // Music control. +void music_volume(const double vol); void music_load(const char* name); void music_play(void); void music_stop(void); diff --git a/src/outfit.c b/src/outfit.c index a9dce7c..0a8a49d 100644 --- a/src/outfit.c +++ b/src/outfit.c @@ -105,6 +105,8 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) { snprintf(str, strlen(xml_get(node))+sizeof(OUTFIT_GFX)+4, OUTFIT_GFX"%s.png", xml_get(node)); tmp->gfx_space = gl_newSprite(str, 6, 6); } + else if(xml_isNode(node, "sound")) + tmp->sound = sound_get(xml_get(node)); else if(xml_isNode(node, "damage")) { cur = node->children; do { @@ -116,6 +118,7 @@ static void outfit_parseSWeapon(Outfit* tmp, const xmlNodePtr parent) { #define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name) if(tmp->gfx_space == NULL) WARN("Outfit '%s' missing 'gfx' element", tmp->name); + MELEMENT(tmp->sound, "sound"); MELEMENT(tmp->delay, "delay"); MELEMENT(tmp->speed, "speed"); MELEMENT(tmp->range, "range"); @@ -159,6 +162,8 @@ static void outfit_parseSAmmo(Outfit* tmp, const xmlNodePtr parent) { OUTFIT_GFX"%s.png", xml_get(node)); tmp->gfx_space = gl_newSprite(str, 6, 6); } + else if(xml_isNode(node, "sound")) + tmp->sound = sound_get(xml_get(node)); else if(xml_isNode(node, "damage")) { cur = node->children; do { @@ -170,7 +175,8 @@ static void outfit_parseSAmmo(Outfit* tmp, const xmlNodePtr parent) { #define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name) if(tmp->gfx_space == NULL) WARN("Outfit '%s' missing 'gfx' element", tmp->name); - MELEMENT(tmp->thrust, " thrust"); + MELEMENT(tmp->sound, "sound"); + MELEMENT(tmp->thrust, "thrust"); MELEMENT(tmp->turn, "turn"); MELEMENT(tmp->speed, "speed"); MELEMENT(tmp->range, "duration"); diff --git a/src/outfit.h b/src/outfit.h index 2eceb69..99921de 100644 --- a/src/outfit.h +++ b/src/outfit.h @@ -1,5 +1,6 @@ #pragma once #include "opengl.h" +#include "sound.h" #define outfit_isProp(o,p) ((o)->properties & p) // Property flags. @@ -46,6 +47,7 @@ typedef struct { double damage_armour, damage_shield; // Damage. glTexture* gfx_space; + ALuint sound; // Sound to play. }; struct { // Launcher. //unsigned int delay; // Delay between shots. diff --git a/src/pilot.c b/src/pilot.c index 5ebe951..5d633e2 100644 --- a/src/pilot.c +++ b/src/pilot.c @@ -252,8 +252,12 @@ static void pilot_update(Pilot* pilot, const double dt) { if(!pilot_isFlag(pilot, PILOT_HYPERSPACE) && VMOD(pilot->solid->vel) > pilot->ship->speed) // Should not go faster. - vect_pset(&pilot->solid->vel, VMOD(pilot->solid->vel) - 0.3*pilot->ship->thrust*dt, + vect_pset(&pilot->solid->vel, pilot->ship->speed, VANGLE(pilot->solid->vel)); + + // Update the source. + //alSource3f(pilot->source, AL_POSITION, pilot->solid->pos.x, pilot->solid->pos.y, 0.); + //alSource3f(pilot->source, AL_VELOCITY, pilot->solid->vel.x, pilot->solid->vel.y, 0.); } // Pilot is getting ready or is in, hyperspace. @@ -356,7 +360,12 @@ void pilot_init(Pilot* pilot, Ship* ship, char* name, Faction* faction, AI_Profi } } + // Sound source. + // Eh.... + + // Set flags and functions. if(flags & PILOT_PLAYER) { + //alSourcef(pilot->source, AL_GAIN, 0.); pilot->think = player_think; // Players don't need to thing! :P pilot->render = NULL; // Render will be called from player_think pilot_setFlag(pilot, PILOT_PLAYER); // It's a player! diff --git a/src/pilot.h b/src/pilot.h index 53b8bbd..8d1ff23 100644 --- a/src/pilot.h +++ b/src/pilot.h @@ -4,6 +4,7 @@ #include "ai.h" #include "outfit.h" #include "faction.h" +#include "sound.h" #include "ship.h" #define PLAYER_ID 1 @@ -66,7 +67,11 @@ typedef struct Pilot { PilotOutfit* secondary; // Secondary weapon. PilotOutfit* ammo; // Secondary ammo (if needed). - unsigned int flags; // Used for AI etc. + // Sound source. + ALuint source; + + // Misc. + unsigned int flags; // Used for AI etc. unsigned int ptimer; // Generic timer for internal pilot use. // AI. diff --git a/src/player.c b/src/player.c index 30852a1..7977c98 100644 --- a/src/player.c +++ b/src/player.c @@ -174,7 +174,7 @@ void player_new(void) { d = RNG(0, 359)/180.*M_PI; pilot_create(ship, "Player", faction_get("Player"), NULL, d, &v, NULL, PILOT_PLAYER); - gl_bindCamera(&player->solid->pos); + gl_bindCamera(&player->solid->pos); // Set opengl camers. space_init(system); // Welcome message. @@ -796,6 +796,14 @@ void player_think(Pilot* player) { pilot_shoot(player, player_target, 1); vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir); + + // Set the listener stuff. + ALfloat ori[] = { 0., 0., 0., 0., 0., 1. }; + ori[0] = cos(player->solid->dir); + ori[1] = sin(player->solid->dir); + alListenerfv(AL_ORIENTATION, ori); + alListener3f(AL_POSITION, player->solid->pos.x, player->solid->pos.y, 0.); + alListener3f(AL_VELOCITY, player->solid->vel.x, player->solid->vel.y, 0.); } // Modify the radar resolution. diff --git a/src/ship.c b/src/ship.c index ec9a791..ef96c31 100644 --- a/src/ship.c +++ b/src/ship.c @@ -38,81 +38,83 @@ static Ship* ship_parse(xmlNodePtr parent) { ShipOutfit* otmp, *ocur; char str[PATH_MAX] = "\0"; - xmlChar* xstr; + char* stmp; - tmp->name = (char*)xmlGetProp(parent, (xmlChar*)"name"); + tmp->name = xml_nodeProp(parent, "name"); if(tmp->name == NULL) WARN("Ship in "SHIP_DATA" has invalid or no name"); node = parent->xmlChildrenNode; do { // Load all the data. - if(strcmp((char*)node->name, "GFX")==0) { - snprintf(str, strlen((char*)node->children->content)+sizeof(SHIP_GFX)+sizeof(SHIP_EXT), - SHIP_GFX"%s"SHIP_EXT, (char*)node->children->content); + if(xml_isNode(node,"GFX")) { + snprintf(str, strlen(xml_get(node)) + sizeof(SHIP_GFX) + sizeof(SHIP_EXT), + SHIP_GFX"%s"SHIP_EXT, xml_get(node)); tmp->gfx_space = gl_newSprite(str, 6, 6); // Target. - snprintf(str, strlen((char*)node->children->content)+sizeof(SHIP_GFX)+sizeof(SHIP_TARGET)+sizeof(SHIP_EXT), - SHIP_GFX"%s"SHIP_TARGET SHIP_EXT, (char*)node->children->content); + snprintf(str, strlen(xml_get(node)) + sizeof(SHIP_GFX)+sizeof(SHIP_TARGET)+sizeof(SHIP_EXT), + SHIP_GFX"%s"SHIP_TARGET SHIP_EXT, xml_get(node)); tmp->gfx_target = gl_newImage(str); } - else if(strcmp((char*)node->name, "GUI")==0) - tmp->gui = strdup((char*)node->children->content); - else if(strcmp((char*)node->name, "class")==0) - tmp->class = atoi((char*)node->children->content); - else if(strcmp((char*)node->name, "movement")==0) { + else if(xml_isNode(node, "GUI")) + tmp->gui = strdup(xml_get(node)); + else if(xml_isNode(node, "sound")) + tmp->sound = sound_get(xml_get(node)); + else if(xml_isNode(node, "class")) + tmp->class = atoi(xml_get(node)); + else if(xml_isNode(node, "movement")) { cur = node->children; do { - if(strcmp((char*)cur->name, "thrust")==0) - tmp->thrust = atoi((char*)cur->children->content); - else if(strcmp((char*)cur->name, "turn")==0) - tmp->turn = atoi((char*)cur->children->content); - else if(strcmp((char*)cur->name, "speed")==0) - tmp->speed = atoi((char*)cur->children->content); + if(xml_isNode(cur, "thrust")) + tmp->thrust = xml_getInt(cur); + else if(xml_isNode(cur, "turn")) + tmp->turn = xml_getInt(cur); + else if(xml_isNode(cur, "speed")) + tmp->speed = xml_getInt(cur); } while((cur = cur->next)); } - else if(strcmp((char*)node->name, "health")==0) { + else if(xml_isNode(node, "health")) { cur = node->children; do { - if(strcmp((char*)cur->name, "armour")==0) - tmp->armour = (double)atoi((char*)cur->children->content); - else if(strcmp((char*)cur->name, "shield")==0) - tmp->shield = (double)atoi((char*)cur->children->content); - else if(strcmp((char*)cur->name, "energy")==0) - tmp->energy = (double)atoi((char*)cur->children->content); - else if(strcmp((char*)cur->name, "armour_regen")==0) - tmp->armour_regen = (double)(atoi((char*)cur->children->content))/60.0; - else if(strcmp((char*)cur->name, "shield_regen")==0) - tmp->shield_regen = (double)(atoi((char*)cur->children->content))/60.0; - else if(strcmp((char*)cur->name, "energy_regen")==0) - tmp->energy_regen = (double)(atoi((char*)cur->children->content))/60.0; + if(xml_isNode(cur, "armour")) + tmp->armour = (double)xml_getInt(cur); + else if(xml_isNode(cur, "shield")) + tmp->shield = (double)xml_getInt(cur); + else if(xml_isNode(cur, "energy")) + tmp->energy = (double)xml_getInt(cur); + else if(xml_isNode(cur, "armour_regen")) + tmp->armour_regen = (double)(xml_getInt(cur))/60.0; + else if(xml_isNode(cur, "shield_regen")) + tmp->shield_regen = (double)(xml_getInt(cur))/60.0; + else if(xml_isNode(cur, "energy_regen")) + tmp->energy_regen = (double)(xml_getInt(cur))/60.0; } while((cur = cur->next)); } - else if(strcmp((char*)node->name, "characteristics")==0) { + else if(xml_isNode(node, "characteristics")) { cur = node->children; do { - if(strcmp((char*)cur->name, "crew")==0) - tmp->crew = atoi((char*)cur->children->content); - else if(strcmp((char*)cur->name, "mass")==0) - tmp->mass = (double)atoi((char*)cur->children->content); - else if(strcmp((char*)cur->name, "cap_weapon")==0) - tmp->cap_weapon = atoi((char*)cur->children->content); - else if(strcmp((char*)cur->name, "cap_cargo")==0) - tmp->cap_cargo = atoi((char*)cur->children->content); + if(xml_isNode(cur, "crew")) + tmp->crew = xml_getInt(cur); + else if(xml_isNode(cur, "mass")) + tmp->mass = (double)xml_getInt(cur); + else if(xml_isNode(cur, "cap_weapon")) + tmp->cap_weapon = xml_getInt(cur); + else if(xml_isNode(cur, "cap_cargo")) + tmp->cap_cargo = xml_getInt(cur); } while((cur = cur->next)); } - else if(strcmp((char*)node->name, "outfits")==0) { + else if(xml_isNode(node, "outfits")) { cur = node->children; do { - if(strcmp((char*)cur->name, "outfit")==0) { + if(xml_isNode(cur, "outfit")) { otmp = MALLOC_L(ShipOutfit); - otmp->data = outfit_get((char*)cur->children->content); - xstr = xmlGetProp(cur, (xmlChar*)"quantity"); - if(!xstr) + otmp->data = outfit_get(xml_get(cur)); + stmp = xml_nodeProp(cur, "quantity"); + if(!stmp) WARN("Ship '%s' is missing tag 'quantity for outfit '%s'", tmp->name, otmp->data->name); - otmp->quantity = atoi((char*)xstr); - free(xstr); + otmp->quantity = atoi(stmp); + free(stmp); otmp->next = NULL; if((ocur = tmp->outfit) == NULL) tmp->outfit = otmp; @@ -130,17 +132,18 @@ static Ship* ship_parse(xmlNodePtr parent) { #define MELEMENT(o,s) if(o == 0) WARN("Ship '%s' missing '"s"' element", tmp->name) if(tmp->name == NULL) WARN("Ship '%s' missing 'name' tag", tmp->name); if(tmp->gfx_space == NULL) WARN("Ship '%s' missing 'GFX' element", tmp->name); + if(tmp->gui == NULL) WARN("Ship '%s' missing 'GUI' element", tmp->name); MELEMENT(tmp->thrust, "thrust"); MELEMENT(tmp->turn, "turn"); MELEMENT(tmp->speed, "speed"); - MELEMENT(tmp->crew, "crew"); - MELEMENT(tmp->mass, "mass"); MELEMENT(tmp->armour, "armour"); MELEMENT(tmp->armour_regen, "armour_regen"); MELEMENT(tmp->shield, "shield"); MELEMENT(tmp->shield_regen, "shield_regen"); MELEMENT(tmp->energy, "energy"); MELEMENT(tmp->energy_regen, "energt_regen"); + MELEMENT(tmp->crew, "crew"); + MELEMENT(tmp->mass, "mass"); MELEMENT(tmp->cap_cargo, "cap_cargo"); MELEMENT(tmp->cap_weapon, "cap_weapon"); #undef MELEMENT diff --git a/src/ship.h b/src/ship.h index 0555900..fbfca35 100644 --- a/src/ship.h +++ b/src/ship.h @@ -36,6 +36,9 @@ typedef struct { // GUI interface. char* gui; + + // Sound. + ALuint sound; // Characteristics. int crew; diff --git a/src/sound.c b/src/sound.c index 256f9a4..1b99d49 100644 --- a/src/sound.c +++ b/src/sound.c @@ -9,21 +9,43 @@ #include "music.h" #include "sound.h" -// This isn't always set? -#ifndef AL_FORMAT_VORBIS_EXT -#define AL_FORMAT_VORBIS_EXT 0x10003 -#endif +#define SOUND_PREFIX "snd/sounds/" +#define SOUND_SUFFIX ".wav" +// Give the buffers a name. typedef struct { - ALfloat x, y; -} alVector; + char* name; // Buffers name. + ALuint buffer; // Associated OpenAL buffer. +} alSound; +#define VOICE_PLAYING (1<<0) // Voice is playing. +#define VOICE_LOOPING (1<<1) // Voice is looping. +#define voice_set(v,f) ((v)->flags |= f) +#define voice_is(v,f) ((v)->flags & f) + +// Gobal device and context. static ALCcontext* al_context = NULL; static ALCdevice* al_device = NULL; +// Music player thread to assure streaming is perfect. static SDL_Thread* music_player = NULL; +// List of sounds available (All preloaded into a buffer). +static alSound* sound_list = NULL; +static int nsound_list = 0; + +// Current sources playing. +static alVoice** voice_stack = NULL; +static int nvoice_stack = 0; +static int mvoice_stack = 0; + +static int sound_makeList(void); +static int sound_load(ALuint* buffer, char* filename); +static void sound_free(alSound* snd); + int sound_init(void) { + const ALchar* device = alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER); + DEBUG("OpenAL using device '%s'", device); // Open the default device. al_device = alcOpenDevice(NULL); if(al_device == NULL) { @@ -38,11 +60,8 @@ int sound_init(void) { return -2; } - // We use the vorbis extension for AL to load it easily. - if(alIsExtensionPresent("AL_EXT_vorbis") == AL_FALSE) { - WARN("AL_EXT_vorbis not available in OpenAL context!"); - return -3; - } + // Clear the errors. + alGetError(); // Set active context. if(alcMakeContextCurrent(al_context)==AL_FALSE) { @@ -50,6 +69,10 @@ int sound_init(void) { return -4; } + // Load up all the sounds. + sound_makeList(); + + // Start the music server. music_init(); music_player = SDL_CreateThread(music_thread, NULL); @@ -59,6 +82,16 @@ int sound_init(void) { // Clean up after the sound system. void sound_exit(void) { + int i; + // Free the sounds. + for(i = 0; i < &nsound_list; i++) + sound_free(&sound_list[i]); + free(sound_list); + sound_list = NULL; + nsound_list = 0; + + // Must stop the music before killing it, + // then thread should commit suicide. music_stop(); music_kill(); SDL_WaitThread(music_player, NULL); @@ -71,19 +104,67 @@ void sound_exit(void) { if(al_device) alcCloseDevice(al_device); } -// Loads a vorbis file. -ALuint sound_sndCreate(char* filename) { - void* ovdata; +// Get the buffer to sound of [name]. +ALuint sound_get(char* name) { + int i; + for(i = 0; i < nsound_list; i++) + if(strcmp(name, sound_list[i].name)==0) + return sound_list[i].buffer; + WARN("Sound '%s' not found in sound list", name); + return 0; +} + +// Make list of available sounds. +static int sound_makeList(void) { + char** files; + uint32_t nfiles, i; + char tmp[64]; + int len; + + // Get the file list. + files = pack_listfiles(data, &nfiles); + + // Load the profiles. + for(i = 0; i < nfiles; i++) + if((strncmp(files[i], SOUND_PREFIX, strlen(SOUND_PREFIX))==0) && + (strncmp(files[i] + strlen(files[i]) - strlen(SOUND_SUFFIX), + SOUND_SUFFIX, strlen(SOUND_SUFFIX))==0)) { + + // Expand the selection size. + sound_list = realloc(sound_list, ++nsound_list * sizeof(alSound)); + + // Remove the prefix and suffix. + len = strlen(files[i]) - strlen(SOUND_SUFFIX SOUND_SUFFIX); + strncpy(tmp, files[i] + strlen(SOUND_PREFIX), len); + tmp[len] = '\0'; + + // give it the new name. + sound_list[nsound_list-1].name = strdup(tmp); + sound_load(&sound_list[nsound_list-1].buffer, files[i]); + } + + // Free the char* allocated by pack. + for(i = 0; i < nfiles; i++) + free(files[i]); + free(files); + + DEBUG("Loaded %d sound%c", nsound_list, (nsound_list==1)?' ':'s'); + + return 0; +} + +// Loads a sound into the sound_list. +static int sound_load(ALuint* buffer, char* filename) { + void* wavdata; unsigned int size; ALenum err; - ALuint buf; // Get the file data buffer from the packfile. - ovdata = pack_readfile(DATA, filename, &size); + wavdata = pack_readfile(DATA, filename, &size); // Bind to OpenAL buffer. - alGenBuffers(1, &buf); - alBufferData(buf, AL_FORMAT_VORBIS_EXT, ovdata, size, 44800); + alGenBuffers(1, buffer); + alBufferData(*buffer, AL_FORMAT_MONO16, wavdata, size, 22050); // Errors? if((err = alGetError()) != AL_NO_ERROR) { @@ -92,11 +173,112 @@ ALuint sound_sndCreate(char* filename) { } // Finish up. - free(ovdata); - return buf; + free(wavdata); + return 0; } -void sound_sndFree(const ALuint snd) { - alDeleteBuffers(1, &snd); +static void sound_free(alSound* snd) { + if(snd->name) free(snd->name); + alDeleteBuffers(1, &snd->buffer); +} + +// Update the sounds and prioritize them. +void sound_update(void) { + int i; + + // TODO: Prioritize the things. + + for(i = 0; i < nvoice_stack; i++) { + if(voice_is(voice_stack[i], VOICE_PLAYING)) { + // Update position. + alSource3f(voice_stack[i]->source, AL_POSITION, + voice_stack[i]->px, voice_stack[i]->py, 0.); + alSource3f(voice_stack[i]->source, AL_VELOCITY, + voice_stack[i]->vx, voice_stack[i]->vy, 0.); + + } + } +} + +// Create a dynamic moving voice. +alVoice* sound_addVoice(int priority, double px, double py, double vx, double vy, + const ALuint buffer, const int looping) { + + alVoice* voc; + ALenum err; + + nvoice_stack++; + if(nvoice_stack > mvoice_stack) + voice_stack = realloc(voice_stack, ++mvoice_stack*sizeof(alVoice*)); + + voc = malloc(sizeof(alVoice)); + voice_stack[nvoice_stack-1] = voc; + + // Try and grab a source. + voc->source = 0; + alGenSources(1, &voc->source); + err = alGetError(); + if(err != AL_NO_ERROR) voc->source = 0; + + // Set the data. + voc->priority = priority; + voc->start = SDL_GetTicks(); + voc->buffer = buffer; + if(looping) voice_set(voc, VOICE_LOOPING); + voc->px = px; + voc->py = py; + voc->vx = vx; + voc->vy = vy; + + // Set the source. + if(voc->source) { + alSourcei(voc->source, AL_SOURCE_RELATIVE, AL_TRUE); + alSourcef(voc->source, AL_GAIN, 1.); + alSourcei(voc->source, AL_BUFFER, buffer); + alSource3f(voc->source, AL_POSITION, voc->px, voc->py, 0.); + alSource3f(voc->source, AL_VELOCITY, voc->vx, voc->vy, 0.); + if(voice_is(voc, VOICE_LOOPING)) + alSourcei(voc->source, AL_LOOPING, AL_TRUE); + + // Try to play the source. + alSourcePlay(voc->source); + err = alGetError(); + if(err == AL_NO_ERROR) voice_set(voc, VOICE_PLAYING); + else DEBUG("Source player failure"); + } + return voc; +} + +void sound_delVoice(alVoice* voice) { + ALint stat; + int i; + + for(i = 0; i < nvoice_stack; i++) + if(voice == voice_stack[i]) + break; + + // No match found. + if(i >= nvoice_stack) { + WARN("Unable to find voice to free from stack"); + return; + } + + if(voice->source) { + alGetSourcei(voice->source, AL_SOURCE_STATE, &stat); + if(stat == AL_PLAYING) alSourceStop(voice->source); + alDeleteSources(1, &voice->source); + voice->source = 0; + } + + nvoice_stack--; + for(; i < nvoice_stack; i++) + voice_stack[i] = voice_stack[i+1]; +} + +void voice_update(alVoice* voice, double px, double py, double vx, double vy) { + voice->px = px; + voice->py = py; + voice->vx = vx; + voice->vy = vy; } diff --git a/src/sound.h b/src/sound.h index 06157b8..b8e62b1 100644 --- a/src/sound.h +++ b/src/sound.h @@ -2,15 +2,35 @@ #include <AL/al.h> #include "physics.h" +#define SOUND_REFERENCE_DIST 500. +#define SOUND_MAX_DIST 1000. + +// Virtual voice. +typedef struct { + ALuint source; // Source itself, 0 if not set. + ALuint buffer; // Buffer. + + int priority; // Base priority. + + double px, py; // Position. + double vx, vy; // Velocity. + + unsigned int start; // Time started in ms. + unsigned int flags; // Flags to set properties. +} alVoice; + // Sound subsystem. int sound_init(void); void sound_exit(void); +void sound_update(void); // Sound manupulation functions. -ALuint sound_sndCreate(char* filename); -void sound_sndFree(const ALuint snd); +ALuint sound_get(char* name); -// Source manipulation function. -#define sound_initSource(s) (alGenSources(1, &(s))) -#define sound_delSource(s) (alDeleteSources(1, &(s)) +// Voice manipulation function. +alVoice* sound_addVoice(int priority, double px, double py, double vx, double vy, + const ALuint buffer, const int looping); + +void sound_delVoice(alVoice* voice); +void voice_update(alVoice* voice, double px, double py, double vx, double vy); diff --git a/src/weapon.c b/src/weapon.c index b059eff..61956f5 100644 --- a/src/weapon.c +++ b/src/weapon.c @@ -14,6 +14,9 @@ #define weapon_isSmart(w) (w->think) +#define VOICE_PRIORITY_BOLD 10 // Default. +#define VOICE_PRIORITY_AMMP 8 // Higher. + // Some stuff from pilot. extern Pilot** pilot_stack; extern int pilots; @@ -29,7 +32,9 @@ typedef struct Weapon { const Outfit* outfit; // Related outfit that fired. unsigned int timer; // Mainly used to see when the weapon was fired. - // Update position and render. + //alVoice voice; // Virtual voise. + + // Update position and render. void(*update)(struct Weapon*, const double, WeaponLayer); // Position update and render. void(*think)(struct Weapon*); // Some missiles need to be inteligent. } Weapon; @@ -43,7 +48,6 @@ static Weapon** wfrontLayer = NULL; // Behind pilots. static int nwfrontLayer = 0; // Number of elements. static int mwfrontLayer = 0; // Allocated memory size. - static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2* pos, const Vec2* vel, const unsigned int parent, const unsigned int target); @@ -222,6 +226,11 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) { } if(weapon_isSmart(w)) (*w->think)(w); (*w->solid->update)(w->solid, dt); + + // Update the sound. + /*if(w->voise) + voice_update(w->voice, w->solid->pos.x, w->solid->pos.y, + w->solid->vel.x, w->solid->vel.y);*/ } // Good shot.