Merge branch 'loop-camera' into 'master'

Loop camera + camera turning interpolation fix

See merge request KartKrew/Kart!1557
This commit is contained in:
James R. 2023-11-12 02:28:52 +00:00
commit f1c24d0eeb
8 changed files with 135 additions and 6 deletions

View file

@ -502,6 +502,15 @@ typedef enum
BOT_ITEM_PR__MAX
} botItemPriority_e;
typedef struct {
tic_t enter_tic, exit_tic;
tic_t zoom_in_speed, zoom_out_speed;
fixed_t dist;
angle_t pan;
fixed_t pan_speed; // in degrees
tic_t pan_accel, pan_back;
} sonicloopcamvars_t;
// player_t struct for loop state
typedef struct {
fixed_t radius;
@ -511,6 +520,7 @@ typedef struct {
vector2_t origin_shift;
vector2_t shift;
boolean flip;
sonicloopcamvars_t camera;
} sonicloopvars_t;
// player_t struct for power-ups

View file

@ -295,6 +295,7 @@ Obj_LoopEndpointCollide
{
player_t *player = toucher->player;
sonicloopvars_t *s = &player->loop;
sonicloopcamvars_t *cam = &s->camera;
mobj_t *anchor = end_anchor(end);
mobj_t *center = anchor ? anchor_center(anchor) : NULL;
@ -352,6 +353,30 @@ Obj_LoopEndpointCollide
s->flip = center_has_flip(center);
cam->enter_tic = leveltime;
cam->exit_tic = INFTICS;
if (center->thing_args[4]) // is camera distance set?
{
cam->zoom_out_speed = center->thing_args[2];
cam->zoom_in_speed = center->thing_args[3];
cam->dist = center->thing_args[4] * FRACUNIT;
cam->pan = FixedAngle(center->thing_args[5] * FRACUNIT);
cam->pan_speed = center->thing_args[6] * FRACUNIT;
cam->pan_accel = center->thing_args[7];
cam->pan_back = center->thing_args[8];
}
else
{
cam->zoom_out_speed = 20;
cam->zoom_in_speed = 60;
cam->dist = radius;
cam->pan = ANGLE_22h;
cam->pan_speed = 6*FRACUNIT;
cam->pan_accel = 10;
cam->pan_back = 40;
}
player->speed =
3 * (player->speed + toucher->momz) / 2;

View file

@ -37,6 +37,7 @@ void P_HaltPlayerOrbit(player_t *player)
player->mo->flags &= ~(MF_NOCLIPHEIGHT);
player->loop.radius = 0;
player->loop.camera.exit_tic = leveltime;
}
void P_ExitPlayerOrbit(player_t *player)

View file

@ -684,6 +684,17 @@ static void P_NetArchivePlayers(savebuffer_t *save)
WRITEFIXED(save->p, players[i].loop.shift.y);
WRITEUINT8(save->p, players[i].loop.flip);
// sonicloopcamvars_t
WRITEUINT32(save->p, players[i].loop.camera.enter_tic);
WRITEUINT32(save->p, players[i].loop.camera.exit_tic);
WRITEUINT32(save->p, players[i].loop.camera.zoom_in_speed);
WRITEUINT32(save->p, players[i].loop.camera.zoom_out_speed);
WRITEFIXED(save->p, players[i].loop.camera.dist);
WRITEANGLE(save->p, players[i].loop.camera.pan);
WRITEFIXED(save->p, players[i].loop.camera.pan_speed);
WRITEUINT32(save->p, players[i].loop.camera.pan_accel);
WRITEUINT32(save->p, players[i].loop.camera.pan_back);
// ACS has read access to this, so it has to be net-communicated.
// It is the ONLY roundcondition that is sent over the wire and I'd like it to stay that way.
WRITEUINT32(save->p, players[i].roundconditions.unlocktriggers);
@ -1212,6 +1223,17 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
players[i].loop.shift.y = READFIXED(save->p);
players[i].loop.flip = READUINT8(save->p);
// sonicloopcamvars_t
players[i].loop.camera.enter_tic = READUINT32(save->p);
players[i].loop.camera.exit_tic = READUINT32(save->p);
players[i].loop.camera.zoom_in_speed = READUINT32(save->p);
players[i].loop.camera.zoom_out_speed = READUINT32(save->p);
players[i].loop.camera.dist = READFIXED(save->p);
players[i].loop.camera.pan = READANGLE(save->p);
players[i].loop.camera.pan_speed = READFIXED(save->p);
players[i].loop.camera.pan_accel = READUINT32(save->p);
players[i].loop.camera.pan_back = READUINT32(save->p);
// ACS has read access to this, so it has to be net-communicated.
// It is the ONLY roundcondition that is sent over the wire and I'd like it to stay that way.
players[i].roundconditions.unlocktriggers = READUINT32(save->p);

View file

@ -3083,6 +3083,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
fixed_t scaleDiff;
fixed_t cameraScale = mapobjectscale;
sonicloopcamvars_t *loop = &player->loop.camera;
tic_t loop_out = leveltime - loop->enter_tic;
tic_t loop_in = max(leveltime, loop->exit_tic) - loop->exit_tic;
thiscam->old_x = thiscam->x;
thiscam->old_y = thiscam->y;
thiscam->old_z = thiscam->z;
@ -3207,6 +3211,58 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
camdist = FixedMul(cv_cam_dist[num].value, cameraScale);
camheight = FixedMul(cv_cam_height[num].value, cameraScale);
if (loop_in < loop->zoom_in_speed)
{
fixed_t f = loop_out < loop->zoom_out_speed
? (loop_out * FRACUNIT) / loop->zoom_out_speed
: FRACUNIT - ((loop_in * FRACUNIT) / loop->zoom_in_speed);
camspeed -= FixedMul(f, camspeed - (FRACUNIT/10));
camdist += FixedMul(f, loop->dist);
}
if (loop_in < max(loop->pan_back, 1))
{
fixed_t f = (loop_in * FRACUNIT) / max(loop->pan_back, 1);
fixed_t dx = mo->x - thiscam->x;
fixed_t dy = mo->y - thiscam->y;
angle_t th = R_PointToAngle2(0, 0, dx, dy);
fixed_t d = AngleFixed(focusangle - th);
if (d > 180*FRACUNIT)
{
d -= (360*FRACUNIT);
}
focusangle = th + FixedAngle(FixedMul(f, d));
if (loop_in == 0)
{
focusaiming = R_PointToAngle2(0, thiscam->z, FixedHypot(dx, dy), mo->z);
}
}
if (loop_in == 0)
{
tic_t accel = max(loop->pan_accel, 1);
fixed_t f = (min(loop_out, accel) * FRACUNIT) / accel;
INT32 turn = AngleDeltaSigned(focusangle, player->loop.yaw - loop->pan);
INT32 turnspeed = FixedAngle(FixedMul(f, loop->pan_speed));
if (turn > turnspeed)
{
if (turn < ANGLE_90)
{
turnspeed = -(turnspeed);
}
focusangle += turnspeed;
}
}
if (timeover)
{
const INT32 timeovercam = max(0, min(180, (player->karthud[khud_timeovercam] - 2*TICRATE)*15));
@ -3889,6 +3945,11 @@ DoABarrelRoll (player_t *player)
fixed_t smoothing;
if (player->loop.radius)
{
return;
}
if (player->respawn.state != RESPAWNST_NONE)
{
player->tilt = 0;

View file

@ -140,10 +140,6 @@ void R_InterpolateView(fixed_t frac)
prevview = newview;
}
viewx = R_LerpFixed(prevview->x, newview->x, frac);
viewy = R_LerpFixed(prevview->y, newview->y, frac);
viewz = R_LerpFixed(prevview->z, newview->z, frac);
viewangle = R_LerpAngle(prevview->angle, newview->angle, frac);
aimingangle = R_LerpAngle(prevview->aim, newview->aim, frac);
viewroll = R_LerpAngle(prevview->roll, newview->roll, frac);
@ -151,6 +147,12 @@ void R_InterpolateView(fixed_t frac)
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
fixed_t zoom = R_LerpFixed(prevview->zoom, newview->zoom, frac);
viewx = R_LerpFixed(prevview->x, newview->x, frac) - FixedMul(viewcos, zoom);
viewy = R_LerpFixed(prevview->y, newview->y, frac) - FixedMul(viewsin, zoom);
viewz = R_LerpFixed(prevview->z, newview->z, frac);
viewplayer = newview->player;
viewsector = R_PointInSubsector(viewx, viewy)->sector;

View file

@ -48,6 +48,7 @@ struct viewvars_t {
fixed_t x;
fixed_t y;
fixed_t z;
fixed_t zoom;
boolean sky;
sector_t *sector;
player_t *player;

View file

@ -1244,6 +1244,7 @@ void R_SetupFrame(int s)
newview->x = r_viewmobj->x;
newview->y = r_viewmobj->y;
newview->z = r_viewmobj->z;
newview->zoom = 0;
R_SetupCommonFrame(player, r_viewmobj->subsector);
}
@ -1252,9 +1253,13 @@ void R_SetupFrame(int s)
{
r_viewmobj = NULL;
newview->x = thiscam->x;
newview->y = thiscam->y;
fixed_t x = player->mo ? player->mo->x : thiscam->x;
fixed_t y = player->mo ? player->mo->y : thiscam->y;
newview->x = x;
newview->y = y;
newview->z = thiscam->z + (thiscam->height>>1);
newview->zoom = FixedHypot(thiscam->x - x, thiscam->y - y);
R_SetupCommonFrame(player, thiscam->subsector);
}
@ -1267,6 +1272,7 @@ void R_SetupFrame(int s)
newview->x = r_viewmobj->x;
newview->y = r_viewmobj->y;
newview->z = player->viewz;
newview->zoom = 0;
R_SetupCommonFrame(player, r_viewmobj->subsector);
}
@ -1297,6 +1303,7 @@ void R_SkyboxFrame(int s)
newview->x = r_viewmobj->x;
newview->y = r_viewmobj->y;
newview->z = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle!
newview->zoom = 0;
if (mapheaderinfo[gamemap-1])
{