int detect_collision (struct pt *oldpos, struct pt *newpos, struct groundtri *gt) { double dist, t; struct vect v; struct pt p; dist = dist_pt_to_plane (newpos, >->pl); //THINK THROUGH IF NORMAL WILL ALWAYS BE POINTING IN CORRECT DIRECTION //AND IF A WALL MATTERS IF YOU GO THROUGH IT IN THE WRONG DIRECTION //DO OTHER GAMES CARE IF YOU GO THROUGH A WALL THE WRONG WAY? I DON'T //REMEMBER, HAVE TO CHECK if (dist >= 0) { return (0); } else { psub (&v, newpos, oldpos); t = -(gt->pl.a * oldpos->x + gt->pl.b * oldpos->y + gt->pl.c * oldpos->z + gt->pl.d) / (gt->pl.a * v.x + gt->pl.b * v.y + gt->pl.c * v.z); p.x = oldpos->x + v.x * t; p.y = oldpos->x + v.y * t; p.z = oldpos->x + v.z * t; return (pt_in_gt (&p, gt)); } return (0); }
int pt_in_gt (struct pt *p, struct groundtri *gt) { double theta; struct vect v1, v2; theta = 0; psub (&v1, >->p1, p); vnorm (&v1, &v1); psub (&v2, >->p2, p); vnorm (&v2, &v2); theta += acos (vdot (&v1, &v2)); psub (&v1, >->p2, p); vnorm (&v1, &v1); psub (&v2, >->p3, p); vnorm (&v2, &v2); theta += acos (vdot (&v1, &v2)); psub (&v1, >->p3, p); vnorm (&v1, &v1); psub (&v2, >->p1, p); vnorm (&v2, &v2); theta += acos (vdot (&v1, &v2)); if (theta >= DTOR ((360 - 1e-7))) { return (1); } return (0); }
int main(){ int gd = DETECT,gm; initgraph(&gd,&gm,NULL); point p1,p2; point l1,l2; p1.x=100; p1.y=100; p2.x=300; p2.y=300; l1.x=80; l1.y=130; l2.x=330; l2.y=150; rectangle(p1.x, p1.y,p2.x,p2.y); //line(l1.x,l1.y, l2.x,l2.y); point n[4]; point p[4]; point w[4]; point d[4]; n[0].x=-1;n[0].y=0; n[1].x=-1;n[1].y=0; n[2].x=0;n[2].y=1; n[3].x=0;n[3].y=-1; p[0].x=p1.x;p[0].y=p1.y; p[1].x=p2.x;p[1].y=p2.y; p[2].x=p1.x;p[2].y=p1.y; p[3].x=p2.x;p[3].y=p2.y; psub(l1,p[0],w[0]); psub(l1,p[1],w[1]); psub(l1,p[2],w[2]); psub(l1,p[3],w[3]); for(int i=0;i<4;i++) { d[i].x=l2.x-l1.x; d[i].y=l2.y-l1.y; } int nw[4]; int nd[4]; for(int i=0;i<4;i++){ nw[i]=mul(n[i],w[i]); nd[i]=mul(n[i],d[i]); } float tl=-10000; float tu=10000; for(int i=0;i<4;i++) { if(nd[i]>0) { float tm=nw[i]/nd[i]; if(tm>tl) tl=tm; } else { float tm=nw[i]/nd[i]; if(tm<tu) tu=tm; } } point rp1; point rp2; rp1.x=l1.x+d[0].x*tl; rp1.y=l1.y+d[0].y*tl; rp2.x=l1.x+d[0].x*tu; rp2.y=l1.y+d[0].y*tu; line(rp1.x,rp1.y, rp2.x,rp2.y); delay(10000); closegraph(); return 0; }
void old_grounded_moving (void) { double now, dt; struct pt newpos; struct groundtri *gt; struct vect v1, v2, ctrl_vel; now = get_secs (); dt = now - player.lasttime; ctrl_vel.x = 0; ctrl_vel.y = 0; ctrl_vel.z = 0; if (player.p.z <= ground_height (&player.p)) { switch (player.moving) { case BACK: ctrl_vel.x = -.3 * player.speed * cos (player.theta); ctrl_vel.y = -.3 * player.speed * sin (player.theta); break; case FORW: ctrl_vel.x = player.speed * cos (player.theta); ctrl_vel.y = player.speed * sin (player.theta); break; case SIDE_Q: ctrl_vel.x = player.speed * cos (player.theta + DTOR (90)); ctrl_vel.y = player.speed * sin (player.theta + DTOR (90)); break; case SIDE_E: ctrl_vel.x = player.speed * cos (player.theta - DTOR (90)); ctrl_vel.y = player.speed * sin (player.theta - DTOR (90)); break; case FORW_Q: ctrl_vel.x = player.speed * cos (player.theta + DTOR (45)); ctrl_vel.y = player.speed * sin (player.theta + DTOR (45)); break; case FORW_E: ctrl_vel.x = player.speed * cos (player.theta - DTOR (45)); ctrl_vel.y = player.speed * sin (player.theta - DTOR (45)); break; case BACK_Q: ctrl_vel.x = -.3 * player.speed * cos (player.theta - DTOR (45)); ctrl_vel.y = -.3 * player.speed * sin (player.theta - DTOR (45)); break; case BACK_E: ctrl_vel.x = -.3 * player.speed * cos (player.theta + DTOR (45)); ctrl_vel.y = -.3 * player.speed * sin (player.theta + DTOR (45)); break; } } newpos.x = player.p.x + ctrl_vel.x * dt; newpos.y = player.p.y + ctrl_vel.y * dt; newpos.z = player.p.z + ctrl_vel.z * dt; psub (&player.vel, &newpos, &player.p); vscal (&player.vel, &player.vel, 1 / dt); if ((gt = detect_plane (&newpos)) == NULL) { printf ("Can't find ground, moving player to start position " "to avoid seg fault\n"); player.p.x = 0; player.p.y = 0; player.p.z = ground_height (&player.p); player.movtype = GROUNDED; player.loc = detect_plane (&player.p); return; } if (gt->theta < DTOR (50)) { newpos.z = ground_height (&newpos); psub (&player.vel, &newpos, &player.p); vscal (&player.vel, &player.vel, 1 / dt); player.p = newpos; } else if (newpos.z > gt->pl.middle.z) { player.p = newpos; player.movtype = FALLING; printf ("switching to falling\n"); } else if (newpos.z <= gt->pl.middle.z) { if (gt == player.loc) { printf ("line %d: some sort of bug caused" " player to be in grounded mode while" " on steep plane\n", __LINE__); pt_on_z_plane (&newpos, &newpos, &player.loc->pl); player.p = newpos; printf ("shifting player to nearest point on" " plane with same z\n"); vset (&player.vel, 0, 0, 0); printf ("killing player velocity\n"); player.movtype = FALLING; printf ("switching to falling\n"); paused = YES; printf ("paused game\n"); return; } vnorm (&v2, &ctrl_vel); vcross (&v1, &player.loc->normv, >->normv); vnorm (&v1, &v1); if (vdot (&v1, &v2) < 0) vscal (&v1, &v1, -1); vscal (&ctrl_vel, &v1, vdot (&ctrl_vel, &v1)); newpos.x = player.p.x + ctrl_vel.x * dt; newpos.y = player.p.y + ctrl_vel.y * dt; newpos.z = player.p.z + ctrl_vel.z * dt; if ((gt = detect_plane (&newpos)) == NULL) { printf ("can't detect plane, exiting\n"); exit (1); } if (gt->theta < DTOR (50)) { newpos.z = ground_height (&newpos); psub (&player.vel, &newpos, &player.p); vscal (&player.vel, &player.vel, 1 / dt); printf ("bar\n"); player.p = newpos; } else { // struct groundtri *first_col, *last_col, *gt2; // int i; //PLAYER STARTS MOVING INTO GROUND BEFORE THIS EVER //HAPPENS printf ("pausing\n"); paused = YES; /* i = 0; */ /* first_col = NULL; */ /* last_col = NULL; */ /* for (gt2 = first_groundtri; gt2; gt2 = gt2->next) { */ /* if (detect_collision (&player.p, */ /* &newpos, gt2)) { */ /* if (first_col == NULL) { */ /* first_col = gt2; */ /* } else { */ /* last_col->next = gt2; */ /* } */ /* last_col = gt2; */ /* i++; */ /* } */ /* } */ /* if (first_col == NULL) { */ /* printf ("%s: %s: %d: something weird\n", */ /* __FILE__, __FUNCTION__, __LINE__); */ /* } */ /* printf ("number of collisions: %d\n", i); */ //TRY PROJECTING PLAYER TO LINE OF INTERSECTION //BETWEEN OLD & NEW PLANES. IF PLAYER IS STILL //INSIDE ANY PLANES, GRAB THREE PLANES AND GO //TO INTERSECTION POINT OF THOSE. MIGHT WANT //TO CHECK FOR OVER THREE PLANES JUST IN CASE /* printf ("player.z: %g\n", player.p.z); */ /* newpos = player.p; */ /* rnd_escape (&newpos, gt); */ /* printf ("ran rnd_escape\n"); */ /* gt = detect_plane (&newpos); */ /* double b2; */ /* b2 = newpos.y - (gt->pl.b / gt->pl.a) * newpos.x; */ /* newpos.x = -(b2 * gt->pl.a * gt->pl.b */ /* + gt->pl.c * newpos.z * gt->pl.a */ /* + gt->pl.d * gt->pl.a) */ /* / (square (gt->pl.a) + square (gt->pl.b)); */ /* newpos.y = (gt->pl.b / gt->pl.a) * newpos.x + b2; */ /* player.p = newpos; */ /* printf ("shifting player to nearest point on" */ /* " plane with same z\n"); */ /* gt = detect_plane (&player.p); */ /* printf ("re detected plane\n"); */ /* if (gt->theta >= DTOR (50)) { */ /* printf ("rnd_escape put player on slope," */ /* " changing player to falling\n"); */ /* player.movtype = FALLING; */ /* printf ("killing velocity\n"); */ /* vset (&player.vel, 0, 0, 0); */ /* } */ /* printf ("player.z: %g\n", player.p.z); */ } } else { printf ("this should never be printed\n"); } }
void grounded_moving (void) { double now, dt; struct pt newpos; struct groundtri *gt; struct vect ctrl_vel; now = get_secs (); dt = now - player.lasttime; ctrl_vel.x = 0; ctrl_vel.y = 0; ctrl_vel.z = 0; if (fabs (player.p.z - ground_height (&player.p)) <= 1e6) { switch (player.moving) { case BACK: ctrl_vel.x = -.3 * player.speed * cos (player.theta); ctrl_vel.y = -.3 * player.speed * sin (player.theta); break; case FORW: ctrl_vel.x = player.speed * cos (player.theta); ctrl_vel.y = player.speed * sin (player.theta); break; case SIDE_Q: ctrl_vel.x = player.speed * cos (player.theta + DTOR (90)); ctrl_vel.y = player.speed * sin (player.theta + DTOR (90)); break; case SIDE_E: ctrl_vel.x = player.speed * cos (player.theta - DTOR (90)); ctrl_vel.y = player.speed * sin (player.theta - DTOR (90)); break; case FORW_Q: ctrl_vel.x = player.speed * cos (player.theta + DTOR (45)); ctrl_vel.y = player.speed * sin (player.theta + DTOR (45)); break; case FORW_E: ctrl_vel.x = player.speed * cos (player.theta - DTOR (45)); ctrl_vel.y = player.speed * sin (player.theta - DTOR (45)); break; case BACK_Q: ctrl_vel.x = -.3 * player.speed * cos (player.theta - DTOR (45)); ctrl_vel.y = -.3 * player.speed * sin (player.theta - DTOR (45)); break; case BACK_E: ctrl_vel.x = -.3 * player.speed * cos (player.theta + DTOR (45)); ctrl_vel.y = -.3 * player.speed * sin (player.theta + DTOR (45)); break; } } newpos.x = player.p.x + ctrl_vel.x * dt; newpos.y = player.p.y + ctrl_vel.y * dt; newpos.z = player.p.z + ctrl_vel.z * dt; psub (&player.vel, &newpos, &player.p); vscal (&player.vel, &player.vel, 1 / dt); if ((gt = detect_plane (&newpos)) == NULL) { printf ("Can't find ground, moving player to start position " "to avoid seg fault\n"); player.p.x = 0; player.p.y = 0; player.p.z = ground_height (&player.p); player.movtype = GROUNDED; player.loc = detect_plane (&player.p); return; } if (gt->theta < DTOR (50)) { newpos.z = ground_height (&newpos); psub (&player.vel, &newpos, &player.p); vscal (&player.vel, &player.vel, 1 / dt); player.p = newpos; } else if (newpos.z > gt->pl.middle.z) { //imperfect detection of cliffs but tolerable for now player.p = newpos; player.movtype = FALLING; printf ("switching to falling\n"); } else { if (gt == player.loc) { printf ("line %d: HORRIBLE MESSINESS\n", __LINE__); paused = YES; printf ("paused game\n"); return; } struct vect v1, v2; vnorm (&v2, &ctrl_vel); vcross (&v1, &player.loc->normv, >->normv); vnorm (&v1, &v1); if (vdot (&v1, &v2) < 0) vscal (&v1, &v1, -1); vscal (&ctrl_vel, &v1, vdot (&ctrl_vel, &v1)); newpos.x = player.p.x + ctrl_vel.x * dt; newpos.y = player.p.y + ctrl_vel.y * dt; newpos.z = player.p.z + ctrl_vel.z * dt; newpos.z = ground_height (&newpos); psub (&player.vel, &newpos, &player.p); vscal (&player.vel, &player.vel, 1 / dt); player.p = newpos; } }