diff options
| author | Julie Lala <jules@okfoc.us> | 2014-10-31 22:38:27 -0400 |
|---|---|---|
| committer | Julie Lala <jules@okfoc.us> | 2014-10-31 22:38:27 -0400 |
| commit | a61ad3cea5b7a76777d594d1a6d960943a0e776f (patch) | |
| tree | 404981bc53e3101ed6081fad3326de5036fb2a56 | |
| parent | dc4db9d58f9868694d71b697e5351596cadc4054 (diff) | |
correctly intercepting walls in mover
| -rw-r--r-- | public/assets/javascripts/rectangles/engine/rooms/mover.js | 188 | ||||
| -rw-r--r-- | public/assets/test/intersect3.html | 10 |
2 files changed, 105 insertions, 93 deletions
diff --git a/public/assets/javascripts/rectangles/engine/rooms/mover.js b/public/assets/javascripts/rectangles/engine/rooms/mover.js index 8ce00fe..69e821f 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/mover.js +++ b/public/assets/javascripts/rectangles/engine/rooms/mover.js @@ -4,6 +4,14 @@ Rooms.mover = new function(){ base.room = null base.noclip = false + var cursor = base.cursor = new Rect (0,0,0,0) + var wall_vec = new Rect (0,0,0,0) + var intersect = new vec2(0,0) + + var origins = new Rect() + origins.x = cursor.x + origins.y = wall_vec.x + base.init = function(){ base.bind() base.update(scene.camera) @@ -33,6 +41,14 @@ Rooms.mover = new function(){ return } + var intersect = base.intersect(pos) + + if (intersect && ! base.noclip) { + cam.x = intersect.a + cam.z = intersect.b + return + } +/* // check if we've breached one of the walls.. clamp position if so var collision = base.room.collidesDisc(cam, pos, radius) @@ -41,96 +57,13 @@ Rooms.mover = new function(){ cam.z = (collision & FRONT_BACK) ? base.room.rect.y.clampDisc(pos.z, radius) : pos.z return } - +*/ // in this case, we appear to have left the room.. // $(".face.active").removeClass("active") Walls.clearBodyColor() base.room = null } -/* - var dz = new vec2( cam.z, pos.z ) - dz.normalize() - - var dx = new vec2( cam.x, pos.x ) - dx.normalize() - - // first check if the cam-pos movement intersects the wall. - // next check if it intersects any of the surface frames - // if we can pass through the wall at this point, we do not need to clamp. - // otherwise, get the distance along the cam-pos vector where we would hit the wall and clamp to it. - Walls.list.forEach(function(wall){ - var t = -1 - switch (wall.side) { - case FRONT: - if (cam.z >= wall.edge + radius && wall.edge + radius >= pos.z && wall.vec.intersects(dx) ) { - t = check_intersection( front_back_intersection, cam, pos, dx, wall, radius ) - } - break - case BACK: - // console.log(cam.z|0, wall.edge-radius, pos.z|0, wall.vec.intersects(dx)) - if (cam.z <= wall.edge - radius && wall.edge - radius <= pos.z && wall.vec.intersects(dx) ) { - t = check_intersection( front_back_intersection, cam, pos, dx, wall, -radius ) - console.log(t) - } - break - case LEFT: - if (cam.x >= wall.edge + radius && wall.edge + radius >= pos.x && wall.vec.intersects(dz) ) { - t = check_intersection( left_right_intersection, cam, pos, dz, wall, radius ) - } - break - case RIGHT: - if (cam.x <= wall.edge - radius && wall.edge - radius <= pos.x && wall.vec.intersects(dz) ) { - t = check_intersection( left_right_intersection, cam, pos, dz, wall, -radius ) - } - break - } - if (0 <= t && t <= 1) { - pos.x = cam.x + (pos.x - cam.x) * t - pos.z = cam.z + (pos.z - cam.z) * t - - dz = new vec2( cam.z, pos.z ) - dz.normalize() - - dx = new vec2( cam.x, pos.x ) - dx.normalize() - } - }) - - function check_intersection(intersection_function, cam, pos, cam_pos_vector, wall, radius) { - var t = -1 - wall.surface.faces.some(function(face, i){ - if (face.y.a == 0 && face.x.intersects(cam_pos_vector)) { - t = intersection_function( cam, pos, wall, face, radius ) - console.log(">>", t) - if (0 <= t && t <= 1) { - return true - } - else { - t = -1 - } - } - return false - }) - return t - } - function left_right_intersection (cam, pos, wall, face, radius) { - var perp_n = (face.x.a - face.x.b) * (wall.edge - cam.z + radius) - var perp_d = (face.x.a - face.x.b) * (pos.z - cam.z) - if (perp_d == 0) return Infinity - return perp_n / perp_d - } - function front_back_intersection (cam, pos, wall, face, radius) { - // va.vx*vb.vy - va.vy*vb.vx - var perp_n = (face.x.b - face.x.a) * (wall.edge - cam.x + radius) - var perp_d = (face.x.b - face.x.a) * (pos.x - cam.x) - - console.log((pos.x - cam.x), wall.edge - cam.x, radius) - - if (perp_d == 0) return Infinity - return perp_n / perp_d - } -*/ // collision test failed, so update position cam.x = pos.x cam.z = pos.z @@ -148,7 +81,92 @@ Rooms.mover = new function(){ } app.tube("change-room", { room: base.room }) } - } + base.intersect = function(pos){ + var closest_intersect, t, min_t = 1 + + cursor.x.a = cam.x + cursor.x.b = cam.z + cursor.y.a = pos.x + cursor.y.b = pos.z + + var a = angle(cursor) + cursor.y.a += scene.camera.radius * cos(a) + cursor.y.b += scene.camera.radius * sin(a) + + Walls.list.forEach(function(wall, i){ + var actually_intersects, intersecting_face + if (wall.side & LEFT_RIGHT) { + wall_vec.x.a = wall.edge + wall_vec.x.b = wall.vec.a + wall_vec.y.a = wall.edge + wall_vec.y.b = wall.vec.b + } + else { + wall_vec.x.a = wall.vec.a + wall_vec.x.b = wall.edge + wall_vec.y.a = wall.vec.b + wall_vec.y.b = wall.edge + } + + t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) + + if ( min_t < t || t < 0 || 1 < t ) return + + intersect.a = cursor.x.a + ( cursor.y.a - cursor.x.a ) * t + intersect.b = cursor.x.b + ( cursor.y.b - cursor.x.b ) * t + + if ( ! is_collinear( intersect, wall_vec ) ) return + + if (wall.side & LEFT_RIGHT) { + intersecting_face = wall.surface.face_for_x(intersect.b) + } + else { + intersecting_face = wall.surface.face_for_x(intersect.a) + } + + actually_intersects = !! (intersecting_face && intersecting_face.y.a == 0) + if (actually_intersects) { + closest_intersect = intersect.clone() + min_t = t + } + }) + + if (min_t < 1) { + var a = angle(cursor) + closest_intersect.a -= scene.camera.radius * cos(a) + closest_intersect.b -= scene.camera.radius * sin(a) + } + return closest_intersect + } + function angle (va) { + return atan2(va.y.b - va.x.b, va.y.a - va.x.a) + } + function dot (va, vb) { + return (va.y.a - va.x.a) * (vb.y.a - vb.x.a) + (va.y.b - va.x.b) * (vb.y.b - vb.x.b) + } + function perp (va, vb) { + return (va.y.a - va.x.a) * (vb.y.b - vb.x.b) - (va.y.b - va.x.b) * (vb.y.a - vb.x.a) + } + function is_collinear (p, vec) { + var on_x, on_y + var pa = round(p.a), pb = round(p.b) + + if (vec.x.a < vec.y.a) { + on_x = vec.x.a <= pa && pa <= vec.y.a + } + else { + on_x = vec.x.a >= pa && pa >= vec.y.a + } + + if (vec.x.b < vec.y.b) { + on_y = vec.x.b <= pb && pb <= vec.y.b + } + else { + on_y = vec.x.b >= pb && pb >= vec.y.b + } + + return !! (on_x && on_y) + } } diff --git a/public/assets/test/intersect3.html b/public/assets/test/intersect3.html index e897e8a..1e2a1a4 100644 --- a/public/assets/test/intersect3.html +++ b/public/assets/test/intersect3.html @@ -167,12 +167,12 @@ function draw () { } drawPoint(intersect) - if (actually_intersects && intersecting_face && t < min_t) { + if (actually_intersects && t < min_t) { min_t = t hud.innerHTML += t + "<br>" var clone = intersect.clone() clone.t = t - closest_face = intersecting_face + closest_intersect = intersecting_face closest_intersect = clone } }) @@ -185,12 +185,6 @@ function draw () { ctx.fillStyle = "#00f" drawPoint(closest_intersect) drawLine(cursor.x, closest_intersect, "#00f") - // closest_face.vec - - // get the closest intersect, i.e. the one with smallest t value - // get the angle of the cursor - // move the desired position to pos - 20px - } } function drawLine (pa, pb, color, headless) { |
