📄 ui_players.c
字号:
} else {
lf->backlerp = 1.0 - (float)( dp_realtime - lf->oldFrameTime ) / ( lf->frameTime - lf->oldFrameTime );
}
}
/*
===============
UI_PlayerAnimation
===============
*/
static void UI_PlayerAnimation( playerInfo_t *pi, int *legsOld, int *legs, float *legsBackLerp,
int *torsoOld, int *torso, float *torsoBackLerp ) {
// legs animation
pi->legsAnimationTimer -= uis.frametime;
if ( pi->legsAnimationTimer < 0 ) {
pi->legsAnimationTimer = 0;
}
UI_LegsSequencing( pi );
if ( pi->legs.yawing && ( pi->legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_IDLE ) {
UI_RunLerpFrame( pi, &pi->legs, LEGS_TURN );
} else {
UI_RunLerpFrame( pi, &pi->legs, pi->legsAnim );
}
*legsOld = pi->legs.oldFrame;
*legs = pi->legs.frame;
*legsBackLerp = pi->legs.backlerp;
// torso animation
pi->torsoAnimationTimer -= uis.frametime;
if ( pi->torsoAnimationTimer < 0 ) {
pi->torsoAnimationTimer = 0;
}
UI_TorsoSequencing( pi );
UI_RunLerpFrame( pi, &pi->torso, pi->torsoAnim );
*torsoOld = pi->torso.oldFrame;
*torso = pi->torso.frame;
*torsoBackLerp = pi->torso.backlerp;
}
/*
==================
UI_SwingAngles
==================
*/
static void UI_SwingAngles( float destination, float swingTolerance, float clampTolerance,
float speed, float *angle, qboolean *swinging ) {
float swing;
float move;
float scale;
if ( !*swinging ) {
// see if a swing should be started
swing = AngleSubtract( *angle, destination );
if ( swing > swingTolerance || swing < -swingTolerance ) {
*swinging = qtrue;
}
}
if ( !*swinging ) {
return;
}
// modify the speed depending on the delta
// so it doesn't seem so linear
swing = AngleSubtract( destination, *angle );
scale = fabs( swing );
if ( scale < swingTolerance * 0.5 ) {
scale = 0.5;
} else if ( scale < swingTolerance ) {
scale = 1.0;
} else {
scale = 2.0;
}
// swing towards the destination angle
if ( swing >= 0 ) {
move = uis.frametime * scale * speed;
if ( move >= swing ) {
move = swing;
*swinging = qfalse;
}
*angle = AngleMod( *angle + move );
} else if ( swing < 0 ) {
move = uis.frametime * scale * -speed;
if ( move <= swing ) {
move = swing;
*swinging = qfalse;
}
*angle = AngleMod( *angle + move );
}
// clamp to no more than tolerance
swing = AngleSubtract( destination, *angle );
if ( swing > clampTolerance ) {
*angle = AngleMod( destination - (clampTolerance - 1) );
} else if ( swing < -clampTolerance ) {
*angle = AngleMod( destination + (clampTolerance - 1) );
}
}
/*
======================
UI_MovedirAdjustment
======================
*/
static float UI_MovedirAdjustment( playerInfo_t *pi ) {
vec3_t relativeAngles;
vec3_t moveVector;
VectorSubtract( pi->viewAngles, pi->moveAngles, relativeAngles );
AngleVectors( relativeAngles, moveVector, NULL, NULL );
if ( Q_fabs( moveVector[0] ) < 0.01 ) {
moveVector[0] = 0.0;
}
if ( Q_fabs( moveVector[1] ) < 0.01 ) {
moveVector[1] = 0.0;
}
if ( moveVector[1] == 0 && moveVector[0] > 0 ) {
return 0;
}
if ( moveVector[1] < 0 && moveVector[0] > 0 ) {
return 22;
}
if ( moveVector[1] < 0 && moveVector[0] == 0 ) {
return 45;
}
if ( moveVector[1] < 0 && moveVector[0] < 0 ) {
return -22;
}
if ( moveVector[1] == 0 && moveVector[0] < 0 ) {
return 0;
}
if ( moveVector[1] > 0 && moveVector[0] < 0 ) {
return 22;
}
if ( moveVector[1] > 0 && moveVector[0] == 0 ) {
return -45;
}
return -22;
}
/*
===============
UI_PlayerAngles
===============
*/
static void UI_PlayerAngles( playerInfo_t *pi, vec3_t legs[3], vec3_t torso[3], vec3_t head[3] ) {
vec3_t legsAngles, torsoAngles, headAngles;
float dest;
float adjust;
VectorCopy( pi->viewAngles, headAngles );
headAngles[YAW] = AngleMod( headAngles[YAW] );
VectorClear( legsAngles );
VectorClear( torsoAngles );
// --------- yaw -------------
// allow yaw to drift a bit
if ( ( pi->legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE
|| ( pi->torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_STAND ) {
// if not standing still, always point all in the same direction
pi->torso.yawing = qtrue; // always center
pi->torso.pitching = qtrue; // always center
pi->legs.yawing = qtrue; // always center
}
// adjust legs for movement dir
adjust = UI_MovedirAdjustment( pi );
legsAngles[YAW] = headAngles[YAW] + adjust;
torsoAngles[YAW] = headAngles[YAW] + 0.25 * adjust;
// torso
UI_SwingAngles( torsoAngles[YAW], 25, 90, SWINGSPEED, &pi->torso.yawAngle, &pi->torso.yawing );
UI_SwingAngles( legsAngles[YAW], 40, 90, SWINGSPEED, &pi->legs.yawAngle, &pi->legs.yawing );
torsoAngles[YAW] = pi->torso.yawAngle;
legsAngles[YAW] = pi->legs.yawAngle;
// --------- pitch -------------
// only show a fraction of the pitch angle in the torso
if ( headAngles[PITCH] > 180 ) {
dest = (-360 + headAngles[PITCH]) * 0.75;
} else {
dest = headAngles[PITCH] * 0.75;
}
UI_SwingAngles( dest, 15, 30, 0.1f, &pi->torso.pitchAngle, &pi->torso.pitching );
torsoAngles[PITCH] = pi->torso.pitchAngle;
// pull the angles back out of the hierarchial chain
AnglesSubtract( headAngles, torsoAngles, headAngles );
AnglesSubtract( torsoAngles, legsAngles, torsoAngles );
AnglesToAxis( legsAngles, legs );
AnglesToAxis( torsoAngles, torso );
AnglesToAxis( headAngles, head );
}
/*
===============
UI_PlayerFloatSprite
===============
*/
static void UI_PlayerFloatSprite( playerInfo_t *pi, vec3_t origin, qhandle_t shader ) {
refEntity_t ent;
memset( &ent, 0, sizeof( ent ) );
VectorCopy( origin, ent.origin );
ent.origin[2] += 48;
ent.reType = RT_SPRITE;
ent.customShader = shader;
ent.radius = 10;
ent.renderfx = 0;
trap_R_AddRefEntityToScene( &ent );
}
/*
======================
UI_MachinegunSpinAngle
======================
*/
float UI_MachinegunSpinAngle( playerInfo_t *pi ) {
int delta;
float angle;
float speed;
int torsoAnim;
delta = dp_realtime - pi->barrelTime;
if ( pi->barrelSpinning ) {
angle = pi->barrelAngle + delta * SPIN_SPEED;
} else {
if ( delta > COAST_TIME ) {
delta = COAST_TIME;
}
speed = 0.5 * ( SPIN_SPEED + (float)( COAST_TIME - delta ) / COAST_TIME );
angle = pi->barrelAngle + delta * speed;
}
torsoAnim = pi->torsoAnim & ~ANIM_TOGGLEBIT;
if( torsoAnim == TORSO_ATTACK2 ) {
torsoAnim = TORSO_ATTACK;
}
if ( pi->barrelSpinning == !(torsoAnim == TORSO_ATTACK) ) {
pi->barrelTime = dp_realtime;
pi->barrelAngle = AngleMod( angle );
pi->barrelSpinning = !!(torsoAnim == TORSO_ATTACK);
}
return angle;
}
/*
===============
UI_DrawPlayer
===============
*/
void UI_DrawPlayer( float x, float y, float w, float h, playerInfo_t *pi, int time ) {
refdef_t refdef;
refEntity_t legs;
refEntity_t torso;
refEntity_t head;
refEntity_t gun;
refEntity_t barrel;
refEntity_t flash;
vec3_t origin;
int renderfx;
vec3_t mins = {-16, -16, -24};
vec3_t maxs = {16, 16, 32};
float len;
float xx;
if ( !pi->legsModel || !pi->torsoModel || !pi->headModel || !pi->animations[0].numFrames ) {
return;
}
dp_realtime = time;
if ( pi->pendingWeapon != -1 && dp_realtime > pi->weaponTimer ) {
pi->weapon = pi->pendingWeapon;
pi->lastWeapon = pi->pendingWeapon;
pi->pendingWeapon = -1;
pi->weaponTimer = 0;
if( pi->currentWeapon != pi->weapon ) {
trap_S_StartLocalSound( weaponChangeSound, CHAN_LOCAL );
}
}
UI_AdjustFrom640( &x, &y, &w, &h );
y -= jumpHeight;
memset( &refdef, 0, sizeof( refdef ) );
memset( &legs, 0, sizeof(legs) );
memset( &torso, 0, sizeof(torso) );
memset( &head, 0, sizeof(head) );
refdef.rdflags = RDF_NOWORLDMODEL;
AxisClear( refdef.viewaxis );
refdef.x = x;
refdef.y = y;
refdef.width = w;
refdef.height = h;
refdef.fov_x = (int)((float)refdef.width / 640.0f * 90.0f);
xx = refdef.width / tan( refdef.fov_x / 360 * M_PI );
refdef.fov_y = atan2( refdef.height, xx );
refdef.fov_y *= ( 360 / M_PI );
// calculate distance so the player nearly fills the box
len = 0.7 * ( maxs[2] - mins[2] );
origin[0] = len / tan( DEG2RAD(refdef.fov_x) * 0.5 );
origin[1] = 0.5 * ( mins[1] + maxs[1] );
origin[2] = -0.5 * ( mins[2] + maxs[2] );
refdef.time = dp_realtime;
trap_R_ClearScene();
// get the rotation information
UI_PlayerAngles( pi, legs.axis, torso.axis, head.axis );
// get the animation state (after rotation, to allow feet shuffle)
UI_PlayerAnimation( pi, &legs.oldframe, &legs.frame, &legs.backlerp,
&torso.oldframe, &torso.frame, &torso.backlerp );
renderfx = RF_LIGHTING_ORIGIN | RF_NOSHADOW;
//
// add the legs
//
legs.hModel = pi->legsModel;
legs.customSkin = pi->legsSkin;
VectorCopy( origin, legs.origin );
VectorCopy( origin, legs.lightingOrigin );
legs.renderfx = renderfx;
VectorCopy (legs.origin, legs.oldorigin);
trap_R_AddRefEntityToScene( &legs );
if (!legs.hModel) {
return;
}
//
// add the torso
//
torso.hModel = pi->torsoModel;
if (!torso.hModel) {
return;
}
torso.customSkin = pi->torsoSkin;
VectorCopy( origin, torso.lightingOrigin );
UI_PositionRotatedEntityOnTag( &torso, &legs, pi->legsModel, "tag_torso");
torso.renderfx = renderfx;
trap_R_AddRefEntityToScene( &torso );
//
// add the head
//
head.hModel = pi->headModel;
if (!head.hModel) {
return;
}
head.customSkin = pi->headSkin;
VectorCopy( origin, head.lightingOrigin );
UI_PositionRotatedEntityOnTag( &head, &torso, pi->torsoModel, "tag_head");
head.renderfx = renderfx;
trap_R_AddRefEntityToScene( &head );
//
// add the gun
//
if ( pi->currentWeapon != WP_NONE ) {
memset( &gun, 0, sizeof(gun) );
gun.hModel = pi->weaponModel;
VectorCopy( origin, gun.lightingOrigin );
UI_PositionEntityOnTag( &gun, &torso, pi->torsoModel, "tag_weapon");
gun.renderfx = renderfx;
trap_R_AddRefEntityToScene( &gun );
}
//
// add the spinning barrel
//
if ( pi->realWeapon == WP_MACHINEGUN || pi->realWeapon == WP_GAUNTLET || pi->realWeapon == WP_BFG ) {
vec3_t angles;
memset( &barrel, 0, sizeof(barrel) );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -