footsteps

git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@1357 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
driAn
2007-10-14 12:58:26 +00:00
parent 7befa37ee5
commit 6f4868ab9f
15 changed files with 266 additions and 148 deletions
+116 -45
View File
@@ -42,12 +42,29 @@ struct soundslot
int uses, maxuses;
};
struct soundloc
{
vec loc;
bool inuse;
soundslot *slot;
entity *ent;
struct soundloc
{
soundslot *slot;
bool inuse;
int radius, size;
physent *pse; // players/phys
entity *ent; // map ents
vec o; // static
vec loc() { return pse ? pse->o : (ent ? vec(ent->x, ent->y, ent->z) : o); }
void sleep()
{
if(ent) { ent->soundinuse = false; slot->uses--; }
inuse = false;
}
void awake()
{
if(ent) { ent->soundinuse = true; slot->uses++; }
inuse = true;
}
};
vector<soundloc> soundlocs;
@@ -228,41 +245,76 @@ void clearmapsounds()
#else
if(FSOUND_IsPlaying(i)) FSOUND_StopSound();
#endif
soundlocs[i].inuse = false;
soundlocs[i].ent->visible = false;
soundlocs[i].slot->uses--;
soundlocs[i].sleep();
}
mapsounds.setsizenodelete(0);
}
void checkmapsounds()
{
//const vector<entity *> &ents = et->getents();
loopv(ents)
{
entity &e = ents[i];
vec o(e.x, e.y, e.z);
if(e.type!=SOUND || e.visible || camera1->o.dist(o)>=e.attr2) continue;
if(e.type!=SOUND || e.soundinuse || camera1->o.dist(o)>=e.attr2) continue;
playsound(e.attr1, NULL, &e);
}
}
VAR(footsteps, 0, 1, 1);
VAR(footstepradius, 0, 16, 25);
VAR(footstepalign, 5, 15, 4000);
int findsoundloc(int sound, physent *p)
{
loopv(soundlocs) if(soundlocs[i].pse == p && soundlocs[i].slot == &gamesounds[sound]) return i;
return -1;
}
void checkplayerloopsounds()
{
loopv(players)
{
playerent *p = players[i];
if(!p) continue;
if(footsteps && camera1->o.dist(p->o) < footstepradius)
{
int idx = findsoundloc(S_FOOTSTEPS, p);
if(idx == -1 || !soundlocs[idx].inuse)
{
// sync to model animation
int basetime = -((int)(size_t)p&0xFFF);
int time = lastmillis-basetime;
int speed = 1860/p->maxspeed;
// TODO: share with model code
if(time%speed < footstepalign) playsound(S_FOOTSTEPS, p);
}
}
// add other sounds here
}
}
VAR(stereo, 0, 1, 1);
void updatechanvol(int chan, int svol, const vec *loc = NULL, entity *ent = NULL)
void updatechanvol(int chan, int svol, soundloc *sl)
{
int vol = soundvol, pan = 255/2;
if(loc || ent)
if(sl)
{
vec v;
float dist = camera1->o.dist(ent ? vec(ent->x, ent->y, ent->z) : *loc, v);
if(ent)
float dist = camera1->o.dist(sl->loc(), v);
int rad = sl->radius;
if(rad >= 0)
{
int rad = ent->attr2;
if(ent->attr3)
int size = sl->size;
if(size > 0)
{
rad -= ent->attr3;
dist -= ent->attr3;
rad -= size;
dist -= size;
}
vol -= (int)(min(max(dist/rad, 0), 1)*soundvol);
}
@@ -271,6 +323,18 @@ void updatechanvol(int chan, int svol, const vec *loc = NULL, entity *ent = NULL
vol -= (int)(dist*3/4*soundvol/255); // simple mono distance attenuation
if(vol<0) vol = 0;
}
if(sl->pse) // control looping physent sound volume
{
if(sl->slot == &gamesounds[S_FOOTSTEPS]) // control footsteps
{
if(sl->pse->type == ENT_PLAYER || sl->pse->type == ENT_BOT)
{
playerent *p = (playerent *)sl->pse;
bool nofootsteps = p->state != CS_ALIVE || lastmillis-p->lastpain < 300 || (!p->onfloor && p->timeinair>50) || (!p->move && !p->strafe);
if(nofootsteps) vol = 0; // TODO: fade out?
}
}
}
if(stereo && (v.x != 0 || v.y != 0) && dist>0)
{
float yaw = -atan2f(v.x, v.y) - camera1->yaw*RAD; // relative angle of sound along X-Y axis
@@ -286,15 +350,33 @@ void updatechanvol(int chan, int svol, const vec *loc = NULL, entity *ent = NULL
FSOUND_SetVolume(chan, vol);
FSOUND_SetPan(chan, pan);
#endif
}
}
void newsoundloc(int chan, const vec *loc, soundslot *slot, entity *ent = NULL)
int soundrad(int sound)
{
const int rads[] =
{
S_FOOTSTEPS, 16,
-1
};
for(const int *r = rads; *r >= 0; r += 2) if(*r==sound) return r[1];
return -1;
}
soundloc *newsoundloc(int sound, int chan, soundslot *slot, physent *p = NULL, entity *ent = NULL, const vec *loc = NULL)
{
if(!p && !ent && !loc) return NULL;
while(chan >= soundlocs.length()) soundlocs.add().inuse = false;
soundlocs[chan].loc = ent ? vec(ent->x, ent->y, ent->z) : *loc;
soundlocs[chan].inuse = true;
soundlocs[chan].slot = slot;
soundlocs[chan].ent = ent;
soundloc *sl = &soundlocs[chan];
sl->inuse = true;
sl->slot = slot;
sl->pse = p;
sl->ent = ent && !p ? ent : NULL;
sl->o = loc && !ent ? *loc : vec(0,0,0);
sl->radius = ent ? ent->attr2 : soundrad(sound);
sl->size = ent ? ent->attr3 : -1;
sl->awake();
return &soundlocs[chan];
}
void updatevol()
@@ -302,21 +384,15 @@ void updatevol()
if(nosound) return;
loopv(soundlocs) if(soundlocs[i].inuse)
{
soundloc &sl = soundlocs[i];
#ifdef USE_MIXER
if(Mix_Playing(i))
#else
if(FSOUND_IsPlaying(i))
#endif
updatechanvol(i, soundlocs[i].slot->vol, &soundlocs[i].loc, soundlocs[i].ent);
else
{
soundlocs[i].inuse = false;
if(soundlocs[i].ent)
{
soundlocs[i].ent->visible = false;
soundlocs[i].slot->uses--;
}
}
updatechanvol(i, soundlocs[i].slot->vol, &sl);
else sl.sleep();
}
#ifndef USE_MIXER
if(mod && FMUSIC_IsFinished(mod)) musicdone();
@@ -328,12 +404,12 @@ void updatevol()
VARP(maxsoundsatonce, 0, 5, 100);
void playsound(int n, const vec *loc, entity *ent)
void playsound(int n, physent *p, entity *ent, const vec *loc)
{
if(nosound) return;
if(!soundvol) return;
if(!ent)
if(!ent) // fixme
{
static int soundsatonce = 0, lastsoundmillis = 0;
if(totalmillis==lastsoundmillis) soundsatonce++; else soundsatonce = 1;
@@ -372,13 +448,8 @@ void playsound(int n, const vec *loc, entity *ent)
#endif
if(chan<0) return;
if(ent)
{
ent->visible = true;
slot.uses++;
}
if(loc || ent) newsoundloc(chan, loc, &slot, ent);
updatechanvol(chan, slot.vol, loc, ent);
soundloc *sl = p || ent || loc ? newsoundloc(n, chan, &slot, p, ent, loc) : NULL;
updatechanvol(chan, slot.vol, sl);
#ifndef USE_MIXER
FSOUND_SetPaused(chan, false);
#endif
@@ -389,7 +460,7 @@ void playsoundname(char *s, const vec *loc, int vol)
if(!vol) vol = 100;
int id = findsound(s, vol, gamesounds);
if(id < 0) id = addsound(s, vol, 0, gamesounds);
playsound(id, loc);
playsound(id, NULL, NULL, loc);
}
void sound(int *n) { playsound(*n); }