Merge pull request 'Merge SRB2 Classic's Antimony PathTraverse' (#79) from antimony-pathtraverse into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/79
This commit is contained in:
commit
a4b695da04
4 changed files with 61 additions and 339 deletions
|
|
@ -167,7 +167,6 @@ extern fixed_t t_cam_dist[MAXSPLITSCREENPLAYERS], t_cam_height[MAXSPLITSCREENPLA
|
|||
void P_AddPlayerScore(player_t *player, UINT32 amount);
|
||||
void P_ResetCamera(player_t *player, camera_t *thiscam);
|
||||
boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam);
|
||||
void P_SlideCameraMove(camera_t *thiscam);
|
||||
void P_DemoCameraMovement(camera_t *cam, UINT8 num);
|
||||
void P_ToggleDemoCamera(UINT8 viewnum);
|
||||
boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled);
|
||||
|
|
|
|||
195
src/p_map.c
195
src/p_map.c
|
|
@ -3115,55 +3115,10 @@ static boolean P_ThingHeightClip(mobj_t *thing)
|
|||
// SLIDE MOVE
|
||||
// Allows the player to slide along any angled walls.
|
||||
//
|
||||
static fixed_t bestslidefrac, secondslidefrac;
|
||||
static line_t *bestslideline;
|
||||
static line_t *secondslideline;
|
||||
static mobj_t *slidemo;
|
||||
static fixed_t tmxmove, tmymove;
|
||||
|
||||
//
|
||||
// P_HitCameraSlideLine
|
||||
//
|
||||
static void P_HitCameraSlideLine(line_t *ld, camera_t *thiscam)
|
||||
{
|
||||
INT32 side;
|
||||
angle_t lineangle, moveangle, deltaangle;
|
||||
fixed_t movelen, newlen;
|
||||
|
||||
if (ld->slopetype == ST_HORIZONTAL)
|
||||
{
|
||||
tmymove = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ld->slopetype == ST_VERTICAL)
|
||||
{
|
||||
tmxmove = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
side = P_PointOnLineSide(thiscam->x, thiscam->y, ld);
|
||||
lineangle = ld->angle;
|
||||
|
||||
if (side == 1)
|
||||
lineangle += ANGLE_180;
|
||||
|
||||
moveangle = R_PointToAngle2(0, 0, tmxmove, tmymove);
|
||||
deltaangle = moveangle-lineangle;
|
||||
|
||||
if (deltaangle > ANGLE_180)
|
||||
deltaangle += ANGLE_180;
|
||||
|
||||
lineangle >>= ANGLETOFINESHIFT;
|
||||
deltaangle >>= ANGLETOFINESHIFT;
|
||||
|
||||
movelen = P_AproxDistance(tmxmove, tmymove);
|
||||
newlen = FixedMul(movelen, FINECOSINE(deltaangle));
|
||||
|
||||
tmxmove = FixedMul(newlen, FINECOSINE(lineangle));
|
||||
tmymove = FixedMul(newlen, FINESINE(lineangle));
|
||||
}
|
||||
|
||||
//
|
||||
// P_HitSlideLine
|
||||
// Adjusts the xmove / ymove
|
||||
|
|
@ -3271,57 +3226,6 @@ static void P_HitBounceLine(line_t *ld)
|
|||
deltaangle = R_PointToAngle2(0, 0, tmxmove, tmymove);
|
||||
}
|
||||
|
||||
//
|
||||
// PTR_SlideCameraTraverse
|
||||
//
|
||||
static boolean PTR_SlideCameraTraverse(intercept_t *in)
|
||||
{
|
||||
line_t *li;
|
||||
opening_t open = {0};
|
||||
|
||||
I_Assert(in->isaline);
|
||||
|
||||
li = in->d.line;
|
||||
|
||||
// one-sided linedef
|
||||
if (!li->backsector)
|
||||
{
|
||||
if (P_PointOnLineSide(mapcampointer->x, mapcampointer->y, li))
|
||||
return true; // don't hit the back side
|
||||
goto isblocking;
|
||||
}
|
||||
|
||||
// set openrange, opentop, openbottom
|
||||
P_CameraLineOpening(li, &open);
|
||||
|
||||
if (open.range < mapcampointer->height)
|
||||
goto isblocking; // doesn't fit
|
||||
|
||||
if (open.ceiling - mapcampointer->z < mapcampointer->height)
|
||||
goto isblocking; // mobj is too high
|
||||
|
||||
if (open.floor - mapcampointer->z > 0) // We don't want to make the camera step up.
|
||||
goto isblocking; // too big a step up
|
||||
|
||||
// this line doesn't block movement
|
||||
return true;
|
||||
|
||||
// the line does block movement,
|
||||
// see if it is closer than best so far
|
||||
isblocking:
|
||||
{
|
||||
if (in->frac < bestslidefrac)
|
||||
{
|
||||
secondslidefrac = bestslidefrac;
|
||||
secondslideline = bestslideline;
|
||||
bestslidefrac = in->frac;
|
||||
bestslideline = li;
|
||||
}
|
||||
}
|
||||
|
||||
return false; // stop
|
||||
}
|
||||
|
||||
/*
|
||||
static boolean PTR_LineIsBlocking(line_t *li)
|
||||
{
|
||||
|
|
@ -3382,105 +3286,6 @@ static boolean PTR_SlideTraverse(intercept_t *in)
|
|||
}
|
||||
*/
|
||||
|
||||
//
|
||||
// P_SlideCameraMove
|
||||
//
|
||||
// Tries to slide the camera along a wall.
|
||||
//
|
||||
void P_SlideCameraMove(camera_t *thiscam)
|
||||
{
|
||||
fixed_t leadx, leady, trailx, traily, newx, newy;
|
||||
INT32 hitcount = 0;
|
||||
INT32 retval = 0;
|
||||
|
||||
bestslideline = NULL;
|
||||
|
||||
retry:
|
||||
if (++hitcount == 3)
|
||||
goto stairstep; // don't loop forever
|
||||
|
||||
// trace along the three leading corners
|
||||
if (thiscam->momx > 0)
|
||||
{
|
||||
leadx = thiscam->x + thiscam->radius;
|
||||
trailx = thiscam->x - thiscam->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leadx = thiscam->x - thiscam->radius;
|
||||
trailx = thiscam->x + thiscam->radius;
|
||||
}
|
||||
|
||||
if (thiscam->momy > 0)
|
||||
{
|
||||
leady = thiscam->y + thiscam->radius;
|
||||
traily = thiscam->y - thiscam->radius;
|
||||
}
|
||||
else
|
||||
{
|
||||
leady = thiscam->y - thiscam->radius;
|
||||
traily = thiscam->y + thiscam->radius;
|
||||
}
|
||||
|
||||
bestslidefrac = FRACUNIT+1;
|
||||
|
||||
mapcampointer = thiscam;
|
||||
|
||||
P_PathTraverse(leadx, leady, leadx + thiscam->momx, leady + thiscam->momy,
|
||||
PT_ADDLINES, PTR_SlideCameraTraverse);
|
||||
P_PathTraverse(trailx, leady, trailx + thiscam->momx, leady + thiscam->momy,
|
||||
PT_ADDLINES, PTR_SlideCameraTraverse);
|
||||
P_PathTraverse(leadx, traily, leadx + thiscam->momx, traily + thiscam->momy,
|
||||
PT_ADDLINES, PTR_SlideCameraTraverse);
|
||||
|
||||
// move up to the wall
|
||||
if (bestslidefrac == FRACUNIT+1)
|
||||
{
|
||||
retval = P_TryCameraMove(thiscam->x, thiscam->y + thiscam->momy, thiscam);
|
||||
// the move must have hit the middle, so stairstep
|
||||
stairstep:
|
||||
if (!retval) // Allow things to drop off.
|
||||
P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y, thiscam);
|
||||
return;
|
||||
}
|
||||
|
||||
// fudge a bit to make sure it doesn't hit
|
||||
bestslidefrac -= 0x800;
|
||||
if (bestslidefrac > 0)
|
||||
{
|
||||
newx = FixedMul(thiscam->momx, bestslidefrac);
|
||||
newy = FixedMul(thiscam->momy, bestslidefrac);
|
||||
|
||||
retval = P_TryCameraMove(thiscam->x + newx, thiscam->y + newy, thiscam);
|
||||
|
||||
if (!retval)
|
||||
goto stairstep;
|
||||
}
|
||||
|
||||
// Now continue along the wall.
|
||||
// First calculate remainder.
|
||||
bestslidefrac = FRACUNIT - (bestslidefrac+0x800);
|
||||
|
||||
if (bestslidefrac > FRACUNIT)
|
||||
bestslidefrac = FRACUNIT;
|
||||
|
||||
if (bestslidefrac <= 0)
|
||||
return;
|
||||
|
||||
tmxmove = FixedMul(thiscam->momx, bestslidefrac);
|
||||
tmymove = FixedMul(thiscam->momy, bestslidefrac);
|
||||
|
||||
P_HitCameraSlideLine(bestslideline, thiscam); // clip the moves
|
||||
|
||||
thiscam->momx = tmxmove;
|
||||
thiscam->momy = tmymove;
|
||||
|
||||
retval = P_TryCameraMove(thiscam->x + tmxmove, thiscam->y + tmymove, thiscam);
|
||||
|
||||
if (!retval)
|
||||
goto retry;
|
||||
}
|
||||
|
||||
static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
|
|
|
|||
202
src/p_maputl.c
202
src/p_maputl.c
|
|
@ -1736,10 +1736,6 @@ static boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac)
|
|||
boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
|
||||
INT32 flags, traverser_t trav)
|
||||
{
|
||||
fixed_t xt1, yt1, xt2, yt2;
|
||||
fixed_t xstep, ystep, partialx, partialy, xintercept, yintercept;
|
||||
INT32 mapx, mapy, mapxstep, mapystep, count;
|
||||
|
||||
validcount++;
|
||||
intercept_p = intercepts;
|
||||
|
||||
|
|
@ -1756,170 +1752,94 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
|
|||
|
||||
px1 -= bmaporgx;
|
||||
py1 -= bmaporgy;
|
||||
xt1 = (unsigned)px1>>MAPBLOCKSHIFT;
|
||||
yt1 = (unsigned)py1>>MAPBLOCKSHIFT;
|
||||
|
||||
px2 -= bmaporgx;
|
||||
py2 -= bmaporgy;
|
||||
xt2 = (unsigned)px2>>MAPBLOCKSHIFT;
|
||||
yt2 = (unsigned)py2>>MAPBLOCKSHIFT;
|
||||
|
||||
if (xt2 > xt1)
|
||||
// blockmap traversal algorithm ported from antimony
|
||||
int gridpos_x = (unsigned)px1 >> MAPBLOCKSHIFT;
|
||||
int gridpos_y = (unsigned)py1 >> MAPBLOCKSHIFT;
|
||||
if (flags & PT_ADDLINES)
|
||||
if (!P_BlockLinesIterator(gridpos_x, gridpos_y, PIT_AddLineIntercepts))
|
||||
return false; // early out
|
||||
if (flags & PT_ADDTHINGS)
|
||||
if (!P_BlockThingsIterator(gridpos_x, gridpos_y, PIT_AddThingIntercepts))
|
||||
return false; // early out
|
||||
|
||||
int endpos_x = (unsigned)px2 >> MAPBLOCKSHIFT;
|
||||
int endpos_y = (unsigned)py2 >> MAPBLOCKSHIFT;
|
||||
if (gridpos_x == endpos_x && gridpos_y == endpos_y)
|
||||
return P_TraverseIntercepts(trav, FRACUNIT);
|
||||
|
||||
fixed_t pos_x = px1;
|
||||
fixed_t pos_y = py1;
|
||||
fixed_t dist_x = px2 - px1;
|
||||
fixed_t dist_y = py2 - py1;
|
||||
int dir_x = dist_x < 0 ? -1 : 1;
|
||||
int dir_y = dist_y < 0 ? -1 : 1;
|
||||
fixed_t delta_x;
|
||||
fixed_t delta_y;
|
||||
// special cases for 0 to avoid crashes
|
||||
if (dist_y == 0)
|
||||
{
|
||||
mapxstep = 1;
|
||||
partialx = FRACUNIT - ((px1>>MAPBTOFRAC) & FRACMASK);
|
||||
ystep = FixedDiv(py2 - py1, abs(px2 - px1));
|
||||
delta_x = INT32_MAX;
|
||||
delta_y = 0;
|
||||
}
|
||||
else if (xt2 < xt1)
|
||||
else if (dist_x == 0)
|
||||
{
|
||||
mapxstep = -1;
|
||||
partialx = (px1>>MAPBTOFRAC) & FRACMASK;
|
||||
ystep = FixedDiv(py2 - py1, abs(px2 - px1));
|
||||
delta_x = 0;
|
||||
delta_y = INT32_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
mapxstep = 0;
|
||||
partialx = FRACUNIT;
|
||||
ystep = 256*FRACUNIT;
|
||||
delta_x = FixedDiv2(dist_x, abs(dist_y));
|
||||
delta_y = FixedDiv2(dist_y, abs(dist_x));
|
||||
}
|
||||
|
||||
yintercept = (py1>>MAPBTOFRAC) + FixedMul(partialx, ystep);
|
||||
while (gridpos_x >= 0 && gridpos_y >= 0 && gridpos_x < bmapwidth && gridpos_y < bmapheight)
|
||||
{
|
||||
fixed_t hitx_x;
|
||||
if (dir_x > 0)
|
||||
hitx_x = (gridpos_x+1) << MAPBLOCKSHIFT;
|
||||
else
|
||||
hitx_x = gridpos_x << MAPBLOCKSHIFT;
|
||||
|
||||
if (yt2 > yt1)
|
||||
{
|
||||
mapystep = 1;
|
||||
partialy = FRACUNIT - ((py1>>MAPBTOFRAC) & FRACMASK);
|
||||
xstep = FixedDiv(px2 - px1, abs(py2 - py1));
|
||||
}
|
||||
else if (yt2 < yt1)
|
||||
{
|
||||
mapystep = -1;
|
||||
partialy = (py1>>MAPBTOFRAC) & FRACMASK;
|
||||
xstep = FixedDiv(px2 - px1, abs(py2 - py1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapystep = 0;
|
||||
partialy = FRACUNIT;
|
||||
xstep = 256*FRACUNIT;
|
||||
}
|
||||
xintercept = (px1>>MAPBTOFRAC) + FixedMul(partialy, xstep);
|
||||
fixed_t hity_y;
|
||||
if (dir_y > 0)
|
||||
hity_y = (gridpos_y+1) << MAPBLOCKSHIFT;
|
||||
else
|
||||
hity_y = gridpos_y << MAPBLOCKSHIFT;
|
||||
|
||||
// [RH] Fix for traces that pass only through blockmap corners. In that case,
|
||||
// xintercept and yintercept can both be set ahead of mapx and mapy, so the
|
||||
// for loop would never advance anywhere.
|
||||
|
||||
if (abs(xstep) == FRACUNIT && abs(ystep) == FRACUNIT)
|
||||
{
|
||||
if (ystep < 0)
|
||||
hitx_x -= pos_x;
|
||||
hity_y -= pos_y;
|
||||
fixed_t hitx_y = FixedMul(delta_y, abs(hitx_x));
|
||||
fixed_t hity_x = FixedMul(delta_x, abs(hity_y));
|
||||
if (FixedMul(hitx_x, hitx_x) + FixedMul(hitx_y, hitx_y) > FixedMul(hity_x, hity_x) + FixedMul(hity_y, hity_y))
|
||||
{
|
||||
partialx = FRACUNIT - partialx;
|
||||
gridpos_y += dir_y;
|
||||
pos_x += hity_x;
|
||||
pos_y += hity_y;
|
||||
}
|
||||
if (xstep < 0)
|
||||
else
|
||||
{
|
||||
partialy = FRACUNIT - partialy;
|
||||
gridpos_x += dir_x;
|
||||
pos_x += hitx_x;
|
||||
pos_y += hitx_y;
|
||||
}
|
||||
if (partialx == partialy)
|
||||
{
|
||||
xintercept = xt1 << FRACBITS;
|
||||
yintercept = yt1 << FRACBITS;
|
||||
}
|
||||
}
|
||||
|
||||
// Step through map blocks.
|
||||
// Count is present to prevent a round off error
|
||||
// from skipping the break.
|
||||
mapx = xt1;
|
||||
mapy = yt1;
|
||||
|
||||
for (count = 0; count < 100; count++)
|
||||
{
|
||||
if (flags & PT_ADDLINES)
|
||||
{
|
||||
P_BlockLinesIterator(mapx, mapy, PIT_AddLineIntercepts);
|
||||
}
|
||||
|
||||
if (!P_BlockLinesIterator(gridpos_x, gridpos_y, PIT_AddLineIntercepts))
|
||||
return false; // early out
|
||||
if (flags & PT_ADDTHINGS)
|
||||
{
|
||||
P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts);
|
||||
}
|
||||
|
||||
// both coordinates reached the end, so end the traversing.
|
||||
if ((mapxstep | mapystep) == 0)
|
||||
{
|
||||
if (!P_BlockThingsIterator(gridpos_x, gridpos_y, PIT_AddThingIntercepts))
|
||||
return false; // early out
|
||||
if (gridpos_x == endpos_x && gridpos_y == endpos_y)
|
||||
break;
|
||||
}
|
||||
|
||||
// [RH] Handle corner cases properly instead of pretending they don't exist.
|
||||
switch ( (((yintercept >> FRACBITS) == mapy) << 1) | ((xintercept >> FRACBITS) == mapx) )
|
||||
{
|
||||
case 0: // neither xintercept nor yintercept match!
|
||||
{
|
||||
count = 100; // Stop traversing, because somebody screwed up.
|
||||
break;
|
||||
}
|
||||
case 1: // xintercept matches
|
||||
{
|
||||
xintercept += xstep;
|
||||
mapy += mapystep;
|
||||
if (mapy == yt2)
|
||||
{
|
||||
mapystep = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: // yintercept matches
|
||||
{
|
||||
yintercept += ystep;
|
||||
mapx += mapxstep;
|
||||
if (mapx == xt2)
|
||||
{
|
||||
mapxstep = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: // xintercept and yintercept both match
|
||||
{
|
||||
// The trace is exiting a block through its corner. Not only does the block
|
||||
// being entered need to be checked (which will happen when this loop
|
||||
// continues), but the other two blocks adjacent to the corner also need to
|
||||
// be checked.
|
||||
if (flags & PT_ADDLINES)
|
||||
{
|
||||
P_BlockLinesIterator(mapx + mapxstep, mapy, PIT_AddLineIntercepts);
|
||||
P_BlockLinesIterator(mapx, mapy + mapystep, PIT_AddLineIntercepts);
|
||||
}
|
||||
|
||||
if (flags & PT_ADDTHINGS)
|
||||
{
|
||||
P_BlockThingsIterator(mapx + mapxstep, mapy, PIT_AddThingIntercepts);
|
||||
P_BlockThingsIterator(mapx, mapy + mapystep, PIT_AddThingIntercepts);
|
||||
}
|
||||
|
||||
xintercept += xstep;
|
||||
yintercept += ystep;
|
||||
|
||||
mapx += mapxstep;
|
||||
mapy += mapystep;
|
||||
|
||||
if (mapx == xt2)
|
||||
{
|
||||
mapxstep = 0;
|
||||
}
|
||||
if (mapy == yt2)
|
||||
{
|
||||
mapystep = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go through the sorted list
|
||||
return P_TraverseIntercepts(trav, FRACUNIT);
|
||||
}
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// BLOCKMAP ITERATORS
|
||||
// =========================================================================
|
||||
|
|
|
|||
|
|
@ -3642,8 +3642,6 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
|
|||
{
|
||||
fixed_t camspeed = P_AproxDistance(thiscam->momx, thiscam->momy);
|
||||
|
||||
P_SlideCameraMove(thiscam);
|
||||
|
||||
if (!resetcalled && P_AproxDistance(thiscam->momx, thiscam->momy) == camspeed)
|
||||
{
|
||||
P_ResetCamera(player, thiscam);
|
||||
|
|
|
|||
Loading…
Reference in a new issue