diff options
| author | Jules Laplace <jules@okfoc.us> | 2014-11-03 12:44:23 -0500 |
|---|---|---|
| committer | Jules Laplace <jules@okfoc.us> | 2014-11-03 12:44:23 -0500 |
| commit | 6b9cf0e41c4e0c09a715e59c162380b5fad42cba (patch) | |
| tree | 99bec285665859236b23a2ec5234c7adcce5ac7c | |
| parent | 4cd1bf2ab9944c1f0782e95b51b0da132909a189 (diff) | |
different collision algo for mobile movement
| -rw-r--r-- | public/assets/javascripts/rectangles/engine/rooms/mover.js | 179 | ||||
| -rw-r--r-- | public/assets/test/intersect3.html | 19 |
2 files changed, 147 insertions, 51 deletions
diff --git a/public/assets/javascripts/rectangles/engine/rooms/mover.js b/public/assets/javascripts/rectangles/engine/rooms/mover.js index 69e821f..5682be8 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/mover.js +++ b/public/assets/javascripts/rectangles/engine/rooms/mover.js @@ -5,6 +5,7 @@ Rooms.mover = new function(){ base.noclip = false var cursor = base.cursor = new Rect (0,0,0,0) + var cursor_copy = new Rect (0,0,0,0) var wall_vec = new Rect (0,0,0,0) var intersect = new vec2(0,0) @@ -28,6 +29,7 @@ Rooms.mover = new function(){ } base.update = function(pos){ + var intersect, collision, distance var radius = scene.camera.radius cam.y = pos.y @@ -41,23 +43,38 @@ Rooms.mover = new function(){ return } - var intersect = base.intersect(pos) + distance = sqrt(pow(cam.x-pos.x, 2), pow(cam.z-pos.z, 2)) + + // check if we've breached one of the walls.. clamp position if so. + // there are two algorithms for this now, ridiculously.. + // - the first one is smoother, best for keyboard use + // but if the distance travelled is greater than the min. distance from the wall, + // then there is a possibility of ejection from the room. so is bad for phone/mousewheel. - if (intersect && ! base.noclip) { - cam.x = intersect.a - cam.z = intersect.b - return + // - the second one determines fortuitously if we have breached any of the walls + // however it can get jumpy if you run into a wall.. thus it is best for devices like phone or mousewheel + // the benefit is you will never leave the room. + if (base.noclip) { + // in no-clip mode we walk through walls. } -/* - // check if we've breached one of the walls.. clamp position if so - var collision = base.room.collidesDisc(cam, pos, radius) + else if (distance < radius) { + collision = base.room.collidesDisc(cam, pos, radius) + + if (collision) { + cam.x = (collision & LEFT_RIGHT) ? base.room.rect.x.clampDisc(pos.x, radius) : pos.x + cam.z = (collision & FRONT_BACK) ? base.room.rect.y.clampDisc(pos.z, radius) : pos.z + return + } + } + else { + intersect = base.intersect(pos) + if (intersect) { + cam.x = intersect.a + cam.z = intersect.b + return + } + } - if (collision && ! base.noclip) { - cam.x = (collision & LEFT_RIGHT) ? base.room.rect.x.clampDisc(pos.x, radius) : pos.x - 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() @@ -83,39 +100,30 @@ Rooms.mover = new function(){ } } 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 closest_intersect, closest_wall, new_t, wall_t, t, min_t = 1 + + cursor_copy.x.a = cursor.x.a = cam.x + cursor_copy.x.b = cursor.x.b = cam.z + cursor_copy.y.a = cursor.y.a = pos.x + cursor_copy.y.b = 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) + cursor_copy.extend_ends(scene.camera.radius) + + origins.x = cursor_copy.x + origins.y = wall_vec.x Walls.list.forEach(function(wall, i){ - var actually_intersects, intersecting_face + var actually_intersects = false, intersecting_face + + wall.get_points(wall_vec) - 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 ) + t = perp(origins, wall_vec) / ( perp(cursor_copy, 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 + intersect.a = cursor_copy.x.a + ( cursor_copy.y.a - cursor_copy.x.a ) * t + intersect.b = cursor_copy.x.b + ( cursor_copy.y.b - cursor_copy.x.b ) * t if ( ! is_collinear( intersect, wall_vec ) ) return @@ -128,24 +136,76 @@ Rooms.mover = new function(){ actually_intersects = !! (intersecting_face && intersecting_face.y.a == 0) if (actually_intersects) { - closest_intersect = intersect.clone() + closest_intersect = intersect.clone() + closest_wall = wall_vec.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) + if (closest_intersect) { + + var aw, len, dd + aw = angle(closest_wall) + wall_vec.assign(closest_wall) + wall_vec.x.a -= scene.camera.radius * sin(aw) + wall_vec.x.b += scene.camera.radius * cos(aw) + wall_vec.y.a -= scene.camera.radius * sin(aw) + wall_vec.y.b += scene.camera.radius * cos(aw) + + origins.x = cursor.x + origins.y = wall_vec.x + + new_t = perp(origins, wall_vec) / ( perp(cursor, wall_vec) || 0.0000001 ) + wall_t = perp(origins, cursor) / ( perp(wall_vec, cursor) || 0.0000001 ) + + intersect.a = cursor.x.a + ( cursor.y.a - cursor.x.a ) * new_t + intersect.b = cursor.x.b + ( cursor.y.b - cursor.x.b ) * new_t + + // here compare len to the length of the wall in the direction we are travelling + dd = dot2(diff(closest_wall), diff(cursor)) + len = sqrt(dot(wall_vec, wall_vec)) + + if (dd > 0) { + len *= 1-abs(wall_t) + } + else { + len *= abs(wall_t) + aw += PI + } + + len = clamp(len, 0, (1-min_t) * sqrt(dot(cursor, cursor))) + + intersect.a += len * cos(aw) + intersect.b += len * sin(aw) + + wall_vec.normalize() + intersect.a = clamp(intersect.a, wall_vec.x.a, wall_vec.y.a) + intersect.b = clamp(intersect.b, wall_vec.x.b, wall_vec.y.b) + + return intersect + } + else { + return cursor.y } - return closest_intersect } + function diff (v) { + return new vec2(v.y.a - v.x.a, v.y.b - v.x.b) + } 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 angle2 (pa, pb) { + return atan2(pb.b - pa.b, pb.a - pa.a) + } + function normal (va) { + return atan2(va.x.a - va.y.a, va.y.b - va.x.b) + } + 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 dot2 (pa, pb) { + return pa.a * pb.a + pa.b * pb.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) } @@ -169,4 +229,27 @@ Rooms.mover = new function(){ return !! (on_x && on_y) } + cursor_copy.extend_ends = function(n){ + var a = angle(this) + this.x.a -= n*cos(a) + this.x.b -= n*sin(a) + this.y.a += n*cos(a) + this.y.b += n*sin(a) + return this + } + wall_vec.normalize = function(){ + var carry + if (this.x.a > this.y.a) { + console.log("SWAP X") + carry = this.x.a + this.x.a = this.y.a + this.y.a = carry + } + if (this.x.b > this.y.b) { + console.log("SWAP Y") + carry = this.x.b + this.x.b = this.y.b + this.y.b = carry + } + } } diff --git a/public/assets/test/intersect3.html b/public/assets/test/intersect3.html index ed81346..5440a76 100644 --- a/public/assets/test/intersect3.html +++ b/public/assets/test/intersect3.html @@ -217,8 +217,9 @@ function draw (time) { end_of_ray.a += len * cos(aw) end_of_ray.b += len * sin(aw) -// end_of_ray.a = clamp(end_of_ray.a, wall_vec.x.a, wall_vec.y.a) -// end_of_ray.b = clamp(end_of_ray.b, wall_vec.x.b, wall_vec.y.b) + wall_vec.normalize() + end_of_ray.a = clamp(end_of_ray.a, wall_vec.x.a, wall_vec.y.a) + end_of_ray.b = clamp(end_of_ray.b, wall_vec.x.b, wall_vec.y.b) drawPoint(end_of_ray) drawLine(closest_intersect2, end_of_ray, "#00f") @@ -295,7 +296,19 @@ cursor.extend_ends = function(n){ clone.y.b += n*sin(a) return clone } - +wall_vec.normalize = function(){ + var carry + if (this.x.a > this.y.a) { + carry = this.x.a + this.x.a = this.y.a + this.y.a = carry + } + if (this.x.b > this.y.b) { + carry = this.x.b + this.x.b = this.y.b + this.y.b = carry + } +} function animate(time){ requestAnimationFrame(animate) draw(time) |
