*** collision.c.orig Mon Apr 27 08:38:12 1998 --- collision.c Mon May 4 00:51:30 1998 *************** *** 59,65 **** #define in_range(o1, o2, r) \ (DELTA((o1)->pos.x, (o2)->pos.x) < (r) \ && DELTA((o1)->pos.y, (o2)->pos.y) < (r)) ! #else /* proposed edgewrap version: */ #define in_range(o1, o2, r) \ (BIT(World.rules->mode, WRAP_PLAY) \ --- 59,67 ---- #define in_range(o1, o2, r) \ (DELTA((o1)->pos.x, (o2)->pos.x) < (r) \ && DELTA((o1)->pos.y, (o2)->pos.y) < (r)) ! #endif ! ! #if 0 /* proposed edgewrap version: */ #define in_range(o1, o2, r) \ (BIT(World.rules->mode, WRAP_PLAY) \ *************** *** 81,86 **** --- 83,151 ---- && DELTA((o1)->pos.y, (o2)->pos.y) < (r))) #endif + /* The very first "analytical" collision patch, XPilot 3.6.2 + Faster than other patches and accurate below half warp-speed + Trivial common subexpressions are eliminated by any reasonable compiler, + and kept here for readability. + Written by Pontus (Rakk, Kepler) pontus@ctrl-c.liu.se Jan 1998 + Kudos to Svenske and Mad Gurka for beta testing, and Murx for + being a collision patch pioneer. + */ + + int in_range(int p1x,int p1y,int p2x,int p2y,int q1x,int q1y,int q2x,int q2y,int r) { + + long fac1,fac2; + double tmin,fminx,fminy; + long top,bot; + bool mpx,mpy,mqx,mqy; + + /* Get the wrapped coordinates straight */ + if (BIT(World.rules->mode, WRAP_PLAY)) { + if ((mpx = (ABS(p2x-p1x)>World.width/2))) { + if (p1x>p2x) p1x-=World.width; else p2x-=World.width; + } + if ((mpy = (ABS(p2y-p1y)>World.height/2))) { + if (p1y>p2y) p1y-=World.height; else p2y-=World.height; + } + if ((mqx = (ABS(q2x-q1x)>World.width/2))) { + if (q1x>q2x) q1x-=World.width; else q2x-=World.width; + } + if ((mqy = (ABS(q2y-q1y)>World.height/2))) { + if (q1y>q2y) q1y-=World.height; else q2y-=World.height; + } + + if (mpx && !mqx && (q2x>World.width/2 || q1x>World.width/2)) { + q1x-=World.width; q2x-=World.width; + } + + if (mqy && !mpy && (q2y>World.height/2 || q1y>World.height/2)) { + q1y-=World.height; q2y-=World.height; + } + + if (mqx && !mpx && (p2x>World.width/2 || p1x>World.width/2)) { + p1x-=World.width; p2x-=World.width; + } + + if (mqy && !mpy && (p2y>World.height/2 || p1y>World.height/2)) { + p1y-=World.height; p2y-=World.height; + } + + } + + /* Do the detection */ + if ((p2x-q2x)*(p2x-q2x)+(p2y-q2y)*(p2y-q2y) < r*r) return 1; + fac1=-p1x+p2x+q1x-q2x; + fac2=-p1y+p2y+q1y-q2y; + top=-(fac1*(-p2x+q2x)+fac2*(-p2y+q2y)); + bot=(fac1*fac1+fac2*fac2); + if (top<0 || bot<1 || top>bot) return 0; + tmin=((double) top)/((double) bot); + fminx=-p2x+q2x+fac1*tmin; + fminy=-p2y+q2y+fac2*tmin; + if (fminx*fminx+fminy*fminyused, OBJ_PHASING_DEVICE)) continue; ! if (!in_range((object *)pl, (object *)Players[j], ! 2*SHIP_SZ-6)) { continue; } --- 397,406 ---- } if (BIT(Players[j]->used, OBJ_PHASING_DEVICE)) continue; ! if (!in_range(pl->prevpos.x,pl->prevpos.y,pl->pos.x,pl->pos.y, ! Players[j]->prevpos.x,Players[j]->prevpos.y, ! Players[j]->pos.x,Players[j]->pos.y, ! 2*SHIP_SZ-6)){ continue; } *************** *** 685,691 **** } range = SHIP_SZ + obj->pl_range; ! if (!in_range((object *)pl, obj, range)) continue; if (obj->id != -1) { --- 752,760 ---- } range = SHIP_SZ + obj->pl_range; ! if (!in_range(pl->prevpos.x,pl->prevpos.y,pl->pos.x,pl->pos.y, ! obj->prevpos.x,obj->prevpos.y,obj->pos.x,obj->pos.y, ! range)) continue; if (obj->id != -1) { *************** *** 723,729 **** * Objects actually only hit the player if they are really close. */ radius = SHIP_SZ + obj->pl_radius; ! hit = (radius >= range || in_range((object *)pl, obj, radius)); rel_velocity = LENGTH(pl->vel.x - obj->vel.x, pl->vel.y - obj->vel.y); /* --- 792,801 ---- * Objects actually only hit the player if they are really close. */ radius = SHIP_SZ + obj->pl_radius; ! hit = (radius >= range || ! in_range(pl->prevpos.x,pl->prevpos.y,pl->pos.x,pl->pos.y, ! obj->prevpos.x,obj->prevpos.y,obj->pos.x,obj->pos.y, ! range)); rel_velocity = LENGTH(pl->vel.x - obj->vel.x, pl->vel.y - obj->vel.y); /* *** walls.c.orig Tue Apr 21 11:29:49 1998 --- walls.c Mon May 4 00:51:00 1998 *************** *** 1831,1836 **** --- 1831,1838 ---- int dist; move_info_t mi; move_state_t ms; + bool pos_update = false; + Object_position_remember(obj); *************** *** 1873,1878 **** --- 1875,1881 ---- for (;;) { Move_segment(&ms); if (!(ms.done.x | ms.done.y)) { + pos_update |= ( ms.crash || ms.bounce); if (ms.crash) { break; } *************** *** 1935,1940 **** --- 1938,1944 ---- if (ms.crash) { Object_crash(&ms); } + if (pos_update) Object_position_remember(obj); } static void Player_crash(move_state_t *ms, int pt, bool turning) *************** *** 2125,2130 **** --- 2129,2135 ---- vector r[RES]; ivec sign; /* sign (-1 or 1) of direction */ ipos block; /* block index */ + bool pos_update = false; if (BIT(pl->status, PLAYING|PAUSE|GAME_OVER|KILLED) != PLAYING) { *************** *** 2252,2257 **** --- 2257,2263 ---- crash = -1; for (i = 0; i < pl->ship->num_points; i++) { Move_segment(&ms[i]); + pos_update |= (ms[i].crash || ms[i].bounce); if (ms[i].crash) { crash = i; break; *************** *** 2448,2453 **** --- 2454,2460 ---- if (ms[worst].crash) { Player_crash(&ms[worst], worst, false); } + if (pos_update) Player_position_remember(pl); } void Turn_player(int ind)