[Add] Audio engine is now working, it It's fully tuned enough yet however.
[Change] Refactored ship.c to comply with xml.* standards.
This commit is contained in:
parent
afd612ef17
commit
529ca21644
@ -153,6 +153,8 @@ void music_exit(void) {
|
|||||||
for(i = 0; i < nmusic_selection; i++)
|
for(i = 0; i < nmusic_selection; i++)
|
||||||
free(music_selection[i]);
|
free(music_selection[i]);
|
||||||
free(music_selection);
|
free(music_selection);
|
||||||
|
|
||||||
|
SDL_DestroyMutex(music_vorbis_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal music loading ruitines.
|
// Internal music loading ruitines.
|
||||||
@ -220,6 +222,10 @@ static void music_free(void) {
|
|||||||
SDL_mutexV(music_vorbis_lock);
|
SDL_mutexV(music_vorbis_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void music_volume(const double vol) {
|
||||||
|
alSourcef(music_source, AL_GAIN, (ALfloat)vol);
|
||||||
|
}
|
||||||
|
|
||||||
// Music control functions.
|
// Music control functions.
|
||||||
void music_load(const char* name) {
|
void music_load(const char* name) {
|
||||||
int i;
|
int i;
|
||||||
|
@ -9,6 +9,7 @@ int music_init(void);
|
|||||||
void music_exit(void);
|
void music_exit(void);
|
||||||
|
|
||||||
// Music control.
|
// Music control.
|
||||||
|
void music_volume(const double vol);
|
||||||
void music_load(const char* name);
|
void music_load(const char* name);
|
||||||
void music_play(void);
|
void music_play(void);
|
||||||
void music_stop(void);
|
void music_stop(void);
|
||||||
|
@ -159,6 +159,8 @@ static void outfit_parseSAmmo(Outfit* tmp, const xmlNodePtr parent) {
|
|||||||
OUTFIT_GFX"%s.png", xml_get(node));
|
OUTFIT_GFX"%s.png", xml_get(node));
|
||||||
tmp->gfx_space = gl_newSprite(str, 6, 6);
|
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")) {
|
else if(xml_isNode(node, "damage")) {
|
||||||
cur = node->children;
|
cur = node->children;
|
||||||
do {
|
do {
|
||||||
@ -170,6 +172,7 @@ static void outfit_parseSAmmo(Outfit* tmp, const xmlNodePtr parent) {
|
|||||||
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
|
#define MELEMENT(o,s) if((o) == 0) WARN("Outfit '%s' missing '"s"' element", tmp->name)
|
||||||
if(tmp->gfx_space == NULL)
|
if(tmp->gfx_space == NULL)
|
||||||
WARN("Outfit '%s' missing 'gfx' element", tmp->name);
|
WARN("Outfit '%s' missing 'gfx' element", tmp->name);
|
||||||
|
MELEMENT(tmp->sound, "sound");
|
||||||
MELEMENT(tmp->thrust, "thrust");
|
MELEMENT(tmp->thrust, "thrust");
|
||||||
MELEMENT(tmp->turn, "turn");
|
MELEMENT(tmp->turn, "turn");
|
||||||
MELEMENT(tmp->speed, "speed");
|
MELEMENT(tmp->speed, "speed");
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "opengl.h"
|
#include "opengl.h"
|
||||||
|
#include "sound.h"
|
||||||
|
|
||||||
#define outfit_isProp(o,p) ((o)->properties & p)
|
#define outfit_isProp(o,p) ((o)->properties & p)
|
||||||
// Property flags.
|
// Property flags.
|
||||||
@ -46,6 +47,7 @@ typedef struct {
|
|||||||
double damage_armour, damage_shield; // Damage.
|
double damage_armour, damage_shield; // Damage.
|
||||||
|
|
||||||
glTexture* gfx_space;
|
glTexture* gfx_space;
|
||||||
|
ALuint sound; // Sound to play.
|
||||||
};
|
};
|
||||||
struct { // Launcher.
|
struct { // Launcher.
|
||||||
//unsigned int delay; // Delay between shots.
|
//unsigned int delay; // Delay between shots.
|
||||||
|
@ -254,6 +254,10 @@ static void pilot_update(Pilot* pilot, const double dt) {
|
|||||||
// Should not go faster.
|
// Should not go faster.
|
||||||
vect_pset(&pilot->solid->vel, VMOD(pilot->solid->vel) - 0.3*pilot->ship->thrust*dt,
|
vect_pset(&pilot->solid->vel, VMOD(pilot->solid->vel) - 0.3*pilot->ship->thrust*dt,
|
||||||
VANGLE(pilot->solid->vel));
|
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.
|
// 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) {
|
if(flags & PILOT_PLAYER) {
|
||||||
|
alSourcef(pilot->source, AL_GAIN, 0.);
|
||||||
pilot->think = player_think; // Players don't need to thing! :P
|
pilot->think = player_think; // Players don't need to thing! :P
|
||||||
pilot->render = NULL; // Render will be called from player_think
|
pilot->render = NULL; // Render will be called from player_think
|
||||||
pilot_setFlag(pilot, PILOT_PLAYER); // It's a player!
|
pilot_setFlag(pilot, PILOT_PLAYER); // It's a player!
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "ai.h"
|
#include "ai.h"
|
||||||
#include "outfit.h"
|
#include "outfit.h"
|
||||||
#include "faction.h"
|
#include "faction.h"
|
||||||
|
#include "sound.h"
|
||||||
#include "ship.h"
|
#include "ship.h"
|
||||||
|
|
||||||
#define PLAYER_ID 1
|
#define PLAYER_ID 1
|
||||||
@ -66,6 +67,10 @@ typedef struct Pilot {
|
|||||||
PilotOutfit* secondary; // Secondary weapon.
|
PilotOutfit* secondary; // Secondary weapon.
|
||||||
PilotOutfit* ammo; // Secondary ammo (if needed).
|
PilotOutfit* ammo; // Secondary ammo (if needed).
|
||||||
|
|
||||||
|
// Sound source.
|
||||||
|
ALuint source;
|
||||||
|
|
||||||
|
// Misc.
|
||||||
unsigned int flags; // Used for AI etc.
|
unsigned int flags; // Used for AI etc.
|
||||||
unsigned int ptimer; // Generic timer for internal pilot use.
|
unsigned int ptimer; // Generic timer for internal pilot use.
|
||||||
|
|
||||||
|
11
src/player.c
11
src/player.c
@ -174,7 +174,8 @@ void player_new(void) {
|
|||||||
d = RNG(0, 359)/180.*M_PI;
|
d = RNG(0, 359)/180.*M_PI;
|
||||||
|
|
||||||
pilot_create(ship, "Player", faction_get("Player"), NULL, d, &v, NULL, PILOT_PLAYER);
|
pilot_create(ship, "Player", faction_get("Player"), NULL, d, &v, NULL, PILOT_PLAYER);
|
||||||
gl_bindCamera(&player->solid->pos);
|
alSourcef(player->source, AL_GAIN, 0.5);
|
||||||
|
gl_bindCamera(&player->solid->pos); // Set opengl camers.
|
||||||
space_init(system);
|
space_init(system);
|
||||||
|
|
||||||
// Welcome message.
|
// Welcome message.
|
||||||
@ -796,6 +797,14 @@ void player_think(Pilot* player) {
|
|||||||
pilot_shoot(player, player_target, 1);
|
pilot_shoot(player, player_target, 1);
|
||||||
|
|
||||||
vect_pset(&player->solid->force, player->ship->thrust * player_acc, player->solid->dir);
|
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.
|
// Modify the radar resolution.
|
||||||
|
101
src/ship.c
101
src/ship.c
@ -38,81 +38,83 @@ static Ship* ship_parse(xmlNodePtr parent) {
|
|||||||
ShipOutfit* otmp, *ocur;
|
ShipOutfit* otmp, *ocur;
|
||||||
|
|
||||||
char str[PATH_MAX] = "\0";
|
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");
|
if(tmp->name == NULL) WARN("Ship in "SHIP_DATA" has invalid or no name");
|
||||||
|
|
||||||
node = parent->xmlChildrenNode;
|
node = parent->xmlChildrenNode;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// Load all the data.
|
// Load all the data.
|
||||||
if(strcmp((char*)node->name, "GFX")==0) {
|
if(xml_isNode(node,"GFX")) {
|
||||||
snprintf(str, strlen((char*)node->children->content)+sizeof(SHIP_GFX)+sizeof(SHIP_EXT),
|
snprintf(str, strlen(xml_get(node)) + sizeof(SHIP_GFX) + sizeof(SHIP_EXT),
|
||||||
SHIP_GFX"%s"SHIP_EXT, (char*)node->children->content);
|
SHIP_GFX"%s"SHIP_EXT, xml_get(node));
|
||||||
tmp->gfx_space = gl_newSprite(str, 6, 6);
|
tmp->gfx_space = gl_newSprite(str, 6, 6);
|
||||||
// Target.
|
// Target.
|
||||||
snprintf(str, strlen((char*)node->children->content)+sizeof(SHIP_GFX)+sizeof(SHIP_TARGET)+sizeof(SHIP_EXT),
|
snprintf(str, strlen(xml_get(node)) + sizeof(SHIP_GFX)+sizeof(SHIP_TARGET)+sizeof(SHIP_EXT),
|
||||||
SHIP_GFX"%s"SHIP_TARGET SHIP_EXT, (char*)node->children->content);
|
SHIP_GFX"%s"SHIP_TARGET SHIP_EXT, xml_get(node));
|
||||||
tmp->gfx_target = gl_newImage(str);
|
tmp->gfx_target = gl_newImage(str);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(strcmp((char*)node->name, "GUI")==0)
|
else if(xml_isNode(node, "GUI"))
|
||||||
tmp->gui = strdup((char*)node->children->content);
|
tmp->gui = strdup(xml_get(node));
|
||||||
else if(strcmp((char*)node->name, "class")==0)
|
else if(xml_isNode(node, "sound"))
|
||||||
tmp->class = atoi((char*)node->children->content);
|
tmp->sound = sound_get(xml_get(node));
|
||||||
else if(strcmp((char*)node->name, "movement")==0) {
|
else if(xml_isNode(node, "class"))
|
||||||
|
tmp->class = atoi(xml_get(node));
|
||||||
|
else if(xml_isNode(node, "movement")) {
|
||||||
cur = node->children;
|
cur = node->children;
|
||||||
do {
|
do {
|
||||||
if(strcmp((char*)cur->name, "thrust")==0)
|
if(xml_isNode(cur, "thrust"))
|
||||||
tmp->thrust = atoi((char*)cur->children->content);
|
tmp->thrust = xml_getInt(cur);
|
||||||
else if(strcmp((char*)cur->name, "turn")==0)
|
else if(xml_isNode(cur, "turn"))
|
||||||
tmp->turn = atoi((char*)cur->children->content);
|
tmp->turn = xml_getInt(cur);
|
||||||
else if(strcmp((char*)cur->name, "speed")==0)
|
else if(xml_isNode(cur, "speed"))
|
||||||
tmp->speed = atoi((char*)cur->children->content);
|
tmp->speed = xml_getInt(cur);
|
||||||
} while((cur = cur->next));
|
} while((cur = cur->next));
|
||||||
}
|
}
|
||||||
else if(strcmp((char*)node->name, "health")==0) {
|
else if(xml_isNode(node, "health")) {
|
||||||
cur = node->children;
|
cur = node->children;
|
||||||
do {
|
do {
|
||||||
if(strcmp((char*)cur->name, "armour")==0)
|
if(xml_isNode(cur, "armour"))
|
||||||
tmp->armour = (double)atoi((char*)cur->children->content);
|
tmp->armour = (double)xml_getInt(cur);
|
||||||
else if(strcmp((char*)cur->name, "shield")==0)
|
else if(xml_isNode(cur, "shield"))
|
||||||
tmp->shield = (double)atoi((char*)cur->children->content);
|
tmp->shield = (double)xml_getInt(cur);
|
||||||
else if(strcmp((char*)cur->name, "energy")==0)
|
else if(xml_isNode(cur, "energy"))
|
||||||
tmp->energy = (double)atoi((char*)cur->children->content);
|
tmp->energy = (double)xml_getInt(cur);
|
||||||
else if(strcmp((char*)cur->name, "armour_regen")==0)
|
else if(xml_isNode(cur, "armour_regen"))
|
||||||
tmp->armour_regen = (double)(atoi((char*)cur->children->content))/60.0;
|
tmp->armour_regen = (double)(xml_getInt(cur))/60.0;
|
||||||
else if(strcmp((char*)cur->name, "shield_regen")==0)
|
else if(xml_isNode(cur, "shield_regen"))
|
||||||
tmp->shield_regen = (double)(atoi((char*)cur->children->content))/60.0;
|
tmp->shield_regen = (double)(xml_getInt(cur))/60.0;
|
||||||
else if(strcmp((char*)cur->name, "energy_regen")==0)
|
else if(xml_isNode(cur, "energy_regen"))
|
||||||
tmp->energy_regen = (double)(atoi((char*)cur->children->content))/60.0;
|
tmp->energy_regen = (double)(xml_getInt(cur))/60.0;
|
||||||
} while((cur = cur->next));
|
} while((cur = cur->next));
|
||||||
}
|
}
|
||||||
else if(strcmp((char*)node->name, "characteristics")==0) {
|
else if(xml_isNode(node, "characteristics")) {
|
||||||
cur = node->children;
|
cur = node->children;
|
||||||
do {
|
do {
|
||||||
if(strcmp((char*)cur->name, "crew")==0)
|
if(xml_isNode(cur, "crew"))
|
||||||
tmp->crew = atoi((char*)cur->children->content);
|
tmp->crew = xml_getInt(cur);
|
||||||
else if(strcmp((char*)cur->name, "mass")==0)
|
else if(xml_isNode(cur, "mass"))
|
||||||
tmp->mass = (double)atoi((char*)cur->children->content);
|
tmp->mass = (double)xml_getInt(cur);
|
||||||
else if(strcmp((char*)cur->name, "cap_weapon")==0)
|
else if(xml_isNode(cur, "cap_weapon"))
|
||||||
tmp->cap_weapon = atoi((char*)cur->children->content);
|
tmp->cap_weapon = xml_getInt(cur);
|
||||||
else if(strcmp((char*)cur->name, "cap_cargo")==0)
|
else if(xml_isNode(cur, "cap_cargo"))
|
||||||
tmp->cap_cargo = atoi((char*)cur->children->content);
|
tmp->cap_cargo = xml_getInt(cur);
|
||||||
} while((cur = cur->next));
|
} while((cur = cur->next));
|
||||||
}
|
}
|
||||||
else if(strcmp((char*)node->name, "outfits")==0) {
|
else if(xml_isNode(node, "outfits")) {
|
||||||
cur = node->children;
|
cur = node->children;
|
||||||
do {
|
do {
|
||||||
if(strcmp((char*)cur->name, "outfit")==0) {
|
if(xml_isNode(cur, "outfit")) {
|
||||||
otmp = MALLOC_L(ShipOutfit);
|
otmp = MALLOC_L(ShipOutfit);
|
||||||
otmp->data = outfit_get((char*)cur->children->content);
|
otmp->data = outfit_get(xml_get(cur));
|
||||||
xstr = xmlGetProp(cur, (xmlChar*)"quantity");
|
stmp = xml_nodeProp(cur, "quantity");
|
||||||
if(!xstr)
|
if(!stmp)
|
||||||
WARN("Ship '%s' is missing tag 'quantity for outfit '%s'", tmp->name, otmp->data->name);
|
WARN("Ship '%s' is missing tag 'quantity for outfit '%s'", tmp->name, otmp->data->name);
|
||||||
otmp->quantity = atoi((char*)xstr);
|
otmp->quantity = atoi(stmp);
|
||||||
free(xstr);
|
free(stmp);
|
||||||
otmp->next = NULL;
|
otmp->next = NULL;
|
||||||
|
|
||||||
if((ocur = tmp->outfit) == NULL) tmp->outfit = otmp;
|
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)
|
#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->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->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->thrust, "thrust");
|
||||||
MELEMENT(tmp->turn, "turn");
|
MELEMENT(tmp->turn, "turn");
|
||||||
MELEMENT(tmp->speed, "speed");
|
MELEMENT(tmp->speed, "speed");
|
||||||
MELEMENT(tmp->crew, "crew");
|
|
||||||
MELEMENT(tmp->mass, "mass");
|
|
||||||
MELEMENT(tmp->armour, "armour");
|
MELEMENT(tmp->armour, "armour");
|
||||||
MELEMENT(tmp->armour_regen, "armour_regen");
|
MELEMENT(tmp->armour_regen, "armour_regen");
|
||||||
MELEMENT(tmp->shield, "shield");
|
MELEMENT(tmp->shield, "shield");
|
||||||
MELEMENT(tmp->shield_regen, "shield_regen");
|
MELEMENT(tmp->shield_regen, "shield_regen");
|
||||||
MELEMENT(tmp->energy, "energy");
|
MELEMENT(tmp->energy, "energy");
|
||||||
MELEMENT(tmp->energy_regen, "energt_regen");
|
MELEMENT(tmp->energy_regen, "energt_regen");
|
||||||
|
MELEMENT(tmp->crew, "crew");
|
||||||
|
MELEMENT(tmp->mass, "mass");
|
||||||
MELEMENT(tmp->cap_cargo, "cap_cargo");
|
MELEMENT(tmp->cap_cargo, "cap_cargo");
|
||||||
MELEMENT(tmp->cap_weapon, "cap_weapon");
|
MELEMENT(tmp->cap_weapon, "cap_weapon");
|
||||||
#undef MELEMENT
|
#undef MELEMENT
|
||||||
|
@ -37,6 +37,9 @@ typedef struct {
|
|||||||
// GUI interface.
|
// GUI interface.
|
||||||
char* gui;
|
char* gui;
|
||||||
|
|
||||||
|
// Sound.
|
||||||
|
ALuint sound;
|
||||||
|
|
||||||
// Characteristics.
|
// Characteristics.
|
||||||
int crew;
|
int crew;
|
||||||
int mass;
|
int mass;
|
||||||
|
126
src/sound.c
126
src/sound.c
@ -9,20 +9,29 @@
|
|||||||
#include "music.h"
|
#include "music.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
|
|
||||||
// This isn't always set?
|
#define SOUND_PREFIX "snd/sounds/"
|
||||||
#ifndef AL_FORMAT_VORBIS_EXT
|
#define SOUND_SUFFIX ".wav"
|
||||||
#define AL_FORMAT_VORBIS_EXT 0x10003
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ALfloat x, y;
|
char* name;
|
||||||
} alVector;
|
ALuint buffer;
|
||||||
|
} alSound;
|
||||||
|
|
||||||
|
// Gobal device and context.
|
||||||
static ALCcontext* al_context = NULL;
|
static ALCcontext* al_context = NULL;
|
||||||
static ALCdevice* al_device = NULL;
|
static ALCdevice* al_device = NULL;
|
||||||
|
|
||||||
|
// Music player thread to assure streaming is perfect.
|
||||||
static SDL_Thread* music_player = NULL;
|
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;
|
||||||
|
|
||||||
|
static int sound_makeList(void);
|
||||||
|
static int sound_load(ALuint* buffer, char* filename);
|
||||||
|
static void sound_free(alSound* snd);
|
||||||
|
|
||||||
int sound_init(void) {
|
int sound_init(void) {
|
||||||
// Open the default device.
|
// Open the default device.
|
||||||
al_device = alcOpenDevice(NULL);
|
al_device = alcOpenDevice(NULL);
|
||||||
@ -38,18 +47,16 @@ int sound_init(void) {
|
|||||||
return -2;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set active context.
|
// Set active context.
|
||||||
if(alcMakeContextCurrent(al_context)==AL_FALSE) {
|
if(alcMakeContextCurrent(al_context)==AL_FALSE) {
|
||||||
WARN("Failure to set default context");
|
WARN("Failure to set default context");
|
||||||
return -4;
|
return -4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load up all the sounds.
|
||||||
|
sound_makeList();
|
||||||
|
|
||||||
|
// Start the music server.
|
||||||
music_init();
|
music_init();
|
||||||
music_player = SDL_CreateThread(music_thread, NULL);
|
music_player = SDL_CreateThread(music_thread, NULL);
|
||||||
|
|
||||||
@ -59,6 +66,16 @@ int sound_init(void) {
|
|||||||
|
|
||||||
// Clean up after the sound system.
|
// Clean up after the sound system.
|
||||||
void sound_exit(void) {
|
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_stop();
|
||||||
music_kill();
|
music_kill();
|
||||||
SDL_WaitThread(music_player, NULL);
|
SDL_WaitThread(music_player, NULL);
|
||||||
@ -71,19 +88,67 @@ void sound_exit(void) {
|
|||||||
if(al_device) alcCloseDevice(al_device);
|
if(al_device) alcCloseDevice(al_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads a vorbis file.
|
// Get the buffer to sound of [name].
|
||||||
ALuint sound_sndCreate(char* filename) {
|
ALuint sound_get(char* name) {
|
||||||
void* ovdata;
|
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;
|
unsigned int size;
|
||||||
ALenum err;
|
ALenum err;
|
||||||
ALuint buf;
|
|
||||||
|
|
||||||
// Get the file data buffer from the packfile.
|
// Get the file data buffer from the packfile.
|
||||||
ovdata = pack_readfile(DATA, filename, &size);
|
wavdata = pack_readfile(DATA, filename, &size);
|
||||||
|
|
||||||
// Bind to OpenAL buffer.
|
// Bind to OpenAL buffer.
|
||||||
alGenBuffers(1, &buf);
|
alGenBuffers(1, buffer);
|
||||||
alBufferData(buf, AL_FORMAT_VORBIS_EXT, ovdata, size, 44800);
|
alBufferData(*buffer, AL_FORMAT_MONO16, wavdata, size, 22050);
|
||||||
|
|
||||||
// Errors?
|
// Errors?
|
||||||
if((err = alGetError()) != AL_NO_ERROR) {
|
if((err = alGetError()) != AL_NO_ERROR) {
|
||||||
@ -92,11 +157,26 @@ ALuint sound_sndCreate(char* filename) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Finish up.
|
// Finish up.
|
||||||
free(ovdata);
|
free(wavdata);
|
||||||
return buf;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sound_sndFree(const ALuint snd) {
|
static void sound_free(alSound* snd) {
|
||||||
alDeleteBuffers(1, &snd);
|
if(snd->name) free(snd->name);
|
||||||
|
alDeleteBuffers(1, &snd->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ALuint sound_dynSource(double px, double py, double vx, double vy, int looping) {
|
||||||
|
ALuint tmp;
|
||||||
|
|
||||||
|
alGenSources(1, &tmp);
|
||||||
|
|
||||||
|
alSourcei(tmp, AL_SOURCE_RELATIVE, AL_TRUE);
|
||||||
|
alSource3f(tmp, AL_POSITION, px, py, 0.);
|
||||||
|
alSource3f(tmp, AL_VELOCITY, vx, vy, 0.);
|
||||||
|
|
||||||
|
if(looping) alSourcei(tmp, AL_LOOPING, AL_TRUE);
|
||||||
|
|
||||||
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,15 +2,16 @@
|
|||||||
#include <AL/al.h>
|
#include <AL/al.h>
|
||||||
#include "physics.h"
|
#include "physics.h"
|
||||||
|
|
||||||
|
#define SOUND_REFERENCE_DIST 500.
|
||||||
|
#define SOUND_MAX_DIST 1000.
|
||||||
|
|
||||||
// Sound subsystem.
|
// Sound subsystem.
|
||||||
int sound_init(void);
|
int sound_init(void);
|
||||||
void sound_exit(void);
|
void sound_exit(void);
|
||||||
|
|
||||||
// Sound manupulation functions.
|
// Sound manupulation functions.
|
||||||
ALuint sound_sndCreate(char* filename);
|
ALuint sound_get(char* name);
|
||||||
void sound_sndFree(const ALuint snd);
|
|
||||||
|
|
||||||
// Source manipulation function.
|
// Source manipulation function.
|
||||||
#define sound_initSource(s) (alGenSources(1, &(s)))
|
ALuint sound_dynSource(double px, double py, double vx, double vy, int looping);
|
||||||
#define sound_delSource(s) (alDeleteSources(1, &(s))
|
|
||||||
|
|
||||||
|
22
src/weapon.c
22
src/weapon.c
@ -29,6 +29,8 @@ typedef struct Weapon {
|
|||||||
const Outfit* outfit; // Related outfit that fired.
|
const Outfit* outfit; // Related outfit that fired.
|
||||||
unsigned int timer; // Mainly used to see when the weapon was fired.
|
unsigned int timer; // Mainly used to see when the weapon was fired.
|
||||||
|
|
||||||
|
ALuint source; // Source for sound.
|
||||||
|
|
||||||
// Update position and render.
|
// Update position and render.
|
||||||
void(*update)(struct Weapon*, const double, WeaponLayer); // Position update and render.
|
void(*update)(struct Weapon*, const double, WeaponLayer); // Position update and render.
|
||||||
void(*think)(struct Weapon*); // Some missiles need to be inteligent.
|
void(*think)(struct Weapon*); // Some missiles need to be inteligent.
|
||||||
@ -44,6 +46,7 @@ static int nwfrontLayer = 0; // Number of elements.
|
|||||||
static int mwfrontLayer = 0; // Allocated memory size.
|
static int mwfrontLayer = 0; // Allocated memory size.
|
||||||
|
|
||||||
|
|
||||||
|
static void weapon_sound(Weapon* w);
|
||||||
static Weapon* weapon_create(const Outfit* outfit, const double dir,
|
static Weapon* weapon_create(const Outfit* outfit, const double dir,
|
||||||
const Vec2* pos, const Vec2* vel, const unsigned int parent,
|
const Vec2* pos, const Vec2* vel, const unsigned int parent,
|
||||||
const unsigned int target);
|
const unsigned int target);
|
||||||
@ -125,6 +128,14 @@ void weapons_update(const double dt) {
|
|||||||
weapons_updateLayer(dt, WEAPON_LAYER_FG);
|
weapons_updateLayer(dt, WEAPON_LAYER_FG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Play the weapon sound.
|
||||||
|
static void weapon_sound(Weapon* w) {
|
||||||
|
w->source = sound_dynSource(w->solid->pos.x, w->solid->pos.y,
|
||||||
|
w->solid->vel.x, w->solid->vel.y, 0);
|
||||||
|
alSourcei(w->source, AL_BUFFER, w->outfit->sound);
|
||||||
|
alSourcePlay(w->source);
|
||||||
|
}
|
||||||
|
|
||||||
// Update all weapons in the layer.
|
// Update all weapons in the layer.
|
||||||
static void weapons_updateLayer(const double dt, const WeaponLayer layer) {
|
static void weapons_updateLayer(const double dt, const WeaponLayer layer) {
|
||||||
Weapon** wlayer;
|
Weapon** wlayer;
|
||||||
@ -222,6 +233,10 @@ static void weapon_update(Weapon* w, const double dt, WeaponLayer layer) {
|
|||||||
}
|
}
|
||||||
if(weapon_isSmart(w)) (*w->think)(w);
|
if(weapon_isSmart(w)) (*w->think)(w);
|
||||||
(*w->solid->update)(w->solid, dt);
|
(*w->solid->update)(w->solid, dt);
|
||||||
|
|
||||||
|
// Update the sound.
|
||||||
|
alSource3f(w->source, AL_POSITION, w->solid->pos.x, w->solid->pos.y, 0.);
|
||||||
|
alSource3f(w->source, AL_VELOCITY, w->solid->vel.x, w->solid->vel.y, 0.);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Good shot.
|
// Good shot.
|
||||||
@ -260,14 +275,17 @@ static Weapon* weapon_create(const Outfit* outfit, const double dir, const Vec2*
|
|||||||
vectcpy(&v, vel);
|
vectcpy(&v, vel);
|
||||||
vect_cadd(&v, outfit->speed*cos(rdir), outfit->speed*sin(rdir));
|
vect_cadd(&v, outfit->speed*cos(rdir), outfit->speed*sin(rdir));
|
||||||
w->solid = solid_create(mass, rdir, pos, &v);
|
w->solid = solid_create(mass, rdir, pos, &v);
|
||||||
|
weapon_sound(w);
|
||||||
break;
|
break;
|
||||||
case OUTFIT_TYPE_MISSILE_SEEK_AMMO:
|
case OUTFIT_TYPE_MISSILE_SEEK_AMMO:
|
||||||
mass = w->outfit->mass;
|
mass = w->outfit->mass;
|
||||||
w->solid = solid_create(mass, dir, pos, vel);
|
w->solid = solid_create(mass, dir, pos, vel);
|
||||||
w->think = think_seeker; // Eeek!!!
|
w->think = think_seeker; // Eeek!!!
|
||||||
|
weapon_sound(w);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Just dump it where the player is.
|
// Just dump it where the player is.
|
||||||
|
w->source = 0;
|
||||||
w->solid = solid_create(mass, dir, pos, vel);
|
w->solid = solid_create(mass, dir, pos, vel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -336,6 +354,10 @@ static void weapon_destroy(Weapon* w, WeaponLayer layer) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for(i = 0; wlayer[i] != w; i++); // Get us to the current posision.
|
for(i = 0; wlayer[i] != w; i++); // Get us to the current posision.
|
||||||
|
if(w->source) {
|
||||||
|
alSourceStop(wlayer[i]->source);
|
||||||
|
alDeleteSources(1, &wlayer[i]->source);
|
||||||
|
}
|
||||||
weapon_free(wlayer[i]);
|
weapon_free(wlayer[i]);
|
||||||
wlayer[i] = NULL;
|
wlayer[i] = NULL;
|
||||||
(*nlayer)--;
|
(*nlayer)--;
|
||||||
|
Loading…
Reference in New Issue
Block a user