mirror of
https://github.com/w23/xash3d-fwgs
synced 2025-01-18 23:00:01 +01:00
engine: client: more accurate ScreenShake implementation, thanks @vasiavasiavasia95 for sharing it
This commit is contained in:
parent
8d6ac3fad4
commit
1affc36f06
@ -2119,58 +2119,52 @@ pfnCalcShake
|
||||
*/
|
||||
void GAME_EXPORT pfnCalcShake( void )
|
||||
{
|
||||
int i;
|
||||
float fraction, freq;
|
||||
float localAmp;
|
||||
screen_shake_t *const shake = &clgame.shake;
|
||||
float frametime, fraction, freq;
|
||||
int i;
|
||||
|
||||
if( clgame.shake.time == 0 )
|
||||
return;
|
||||
|
||||
if(( cl.time > clgame.shake.time ) || clgame.shake.amplitude <= 0 || clgame.shake.frequency <= 0 )
|
||||
if( cl.time > shake->time || shake->amplitude <= 0 || shake->frequency <= 0 || shake->duration <= 0 )
|
||||
{
|
||||
memset( &clgame.shake, 0, sizeof( clgame.shake ));
|
||||
// reset shake
|
||||
if( shake->time != 0 )
|
||||
{
|
||||
shake->time = 0;
|
||||
shake->applied_angle = 0;
|
||||
VectorClear( shake->applied_offset );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( cl.time > clgame.shake.next_shake )
|
||||
{
|
||||
// higher frequency means we recalc the extents more often and perturb the display again
|
||||
clgame.shake.next_shake = cl.time + ( 1.0f / clgame.shake.frequency );
|
||||
frametime = cl_clientframetime();
|
||||
|
||||
// compute random shake extents (the shake will settle down from this)
|
||||
if( cl.time > shake->next_shake )
|
||||
{
|
||||
// get next shake time based on frequency over duration
|
||||
shake->next_shake = (float)cl.time + shake->frequency / shake->duration;
|
||||
|
||||
// randomize each shake
|
||||
for( i = 0; i < 3; i++ )
|
||||
clgame.shake.offset[i] = COM_RandomFloat( -clgame.shake.amplitude, clgame.shake.amplitude );
|
||||
clgame.shake.angle = COM_RandomFloat( -clgame.shake.amplitude * 0.25f, clgame.shake.amplitude * 0.25f );
|
||||
shake->offset[i] = COM_RandomFloat( -shake->amplitude, shake->amplitude );
|
||||
shake->angle = COM_RandomFloat( -shake->amplitude * 0.25f, shake->amplitude * 0.25f );
|
||||
}
|
||||
|
||||
// ramp down amplitude over duration (fraction goes from 1 to 0 linearly with slope 1/duration)
|
||||
fraction = ( clgame.shake.time - cl.time ) / clgame.shake.duration;
|
||||
// get initial fraction and frequency values over the duration
|
||||
fraction = ((float)cl.time - shake->time ) / shake->duration;
|
||||
freq = fraction != 0.0f ? ( shake->frequency / fraction ) * shake->frequency : 0.0f;
|
||||
|
||||
// ramp up frequency over duration
|
||||
if( fraction )
|
||||
{
|
||||
freq = ( clgame.shake.frequency / fraction );
|
||||
}
|
||||
else
|
||||
{
|
||||
freq = 0;
|
||||
}
|
||||
// quickly approach zero but apply time over sine wave
|
||||
fraction *= fraction * sin( cl.time * freq );
|
||||
|
||||
// square fraction to approach zero more quickly
|
||||
fraction *= fraction;
|
||||
// apply shake offset
|
||||
for( i = 0; i < 3; i++ )
|
||||
shake->applied_offset[i] = shake->offset[i] * fraction;
|
||||
|
||||
// Sine wave that slowly settles to zero
|
||||
fraction = fraction * sin( cl.time * freq );
|
||||
// apply roll angle
|
||||
shake->applied_angle = shake->angle * fraction;
|
||||
|
||||
// add to view origin
|
||||
VectorScale( clgame.shake.offset, fraction, clgame.shake.applied_offset );
|
||||
|
||||
// add to roll
|
||||
clgame.shake.applied_angle = clgame.shake.angle * fraction;
|
||||
|
||||
// drop amplitude a bit, less for higher frequency shakes
|
||||
localAmp = clgame.shake.amplitude * ( host.frametime / ( clgame.shake.duration * clgame.shake.frequency ));
|
||||
clgame.shake.amplitude -= localAmp;
|
||||
// decrease amplitude, but slower on longer shakes or higher frequency
|
||||
shake->amplitude -= shake->amplitude * ( frametime / ( shake->frequency * shake->duration ));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2181,8 +2175,11 @@ pfnApplyShake
|
||||
*/
|
||||
void GAME_EXPORT pfnApplyShake( float *origin, float *angles, float factor )
|
||||
{
|
||||
if( origin ) VectorMA( origin, factor, clgame.shake.applied_offset, origin );
|
||||
if( angles ) angles[ROLL] += clgame.shake.applied_angle * factor;
|
||||
if( origin )
|
||||
VectorMA( origin, factor, clgame.shake.applied_offset, origin );
|
||||
|
||||
if( angles )
|
||||
angles[ROLL] += clgame.shake.applied_angle * factor;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1854,10 +1854,17 @@ Set screen shake
|
||||
*/
|
||||
void CL_ParseScreenShake( sizebuf_t *msg )
|
||||
{
|
||||
clgame.shake.amplitude = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<12));
|
||||
clgame.shake.duration = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<12));
|
||||
clgame.shake.frequency = (float)(word)MSG_ReadShort( msg ) * (1.0f / (float)(1<<8));
|
||||
clgame.shake.time = cl.time + Q_max( clgame.shake.duration, 0.01f );
|
||||
float amplitude = (float)(word)MSG_ReadShort( msg ) * ( 1.0f / (float)( 1 << 12 ));
|
||||
float duration = (float)(word)MSG_ReadShort( msg ) * ( 1.0f / (float)( 1 << 12 ));
|
||||
float frequency = (float)(word)MSG_ReadShort( msg ) * ( 1.0f / (float)( 1 << 8 ));
|
||||
|
||||
// don't overwrite larger existing shake
|
||||
if( amplitude > clgame.shake.amplitude )
|
||||
clgame.shake.amplitude = amplitude;
|
||||
|
||||
clgame.shake.duration = duration;
|
||||
clgame.shake.time = cl.time + clgame.shake.duration;
|
||||
clgame.shake.frequency = frequency;
|
||||
clgame.shake.next_shake = 0.0f; // apply immediately
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user