From 81caa72aed6ad8f653aabb191b099ec3d544bf2b Mon Sep 17 00:00:00 2001 From: Fbenas Date: Wed, 14 Oct 2020 00:48:34 +0100 Subject: Add future collision detection... ish --- public/js/app.js | 104 +++++++++++++++++++++++++++++++++++++------------- resources/js/app.js | 2 +- resources/js/boid.js | 81 ++++++++++++++++++++++++++++++--------- resources/js/scene.js | 21 +++++++--- 4 files changed, 156 insertions(+), 52 deletions(-) diff --git a/public/js/app.js b/public/js/app.js index 361321c..2ae96dc 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -14,27 +14,34 @@ class Boid { this.scene_height = scene_height; // Boid "dynamic" properties - this.rayLength = 40; + this.rayLength = 60; + this.wallBuffer = 40; this.turnStepAmount = 20; - this.stepAmount = 4; - this.fieldOfView = 270; + this.stepAmount = 2; + this.fieldOfView = 180; this.boidBuffer = 20; } move(boids) { // this.direction += Math.random() * (2 * this.turnStepAmount) - this.turnStepAmount + let direction = this.findNextRay(boids); - this.direction = this.findNextRay(boids); + if (!direction) { + return false; + } + this.direction = direction; var vector = this.findPoint(this.x, this.y, this.stepAmount, this.direction); this.x = vector.x; this.y = vector.y; + + return true; } buildRays() { let rays = new Array(); - let rayInteval = 2; + let rayInteval = 5; let noOfSteps = this.fieldOfView / rayInteval; let is_clockwise = Math.random() >= 0.5; @@ -61,27 +68,33 @@ class Boid { findNextRay(boids) { let rays = this.buildRays(); + let collision = false; for (let i = 0; i < rays.length; i++) { - let tweakAngle = 0; - // if (Math.random() > 0.95) { - // tweakAngle = this.turnStepAmount * Math.random() - (this.turnStepAmount / 2); - // } - - let rayAngle = tweakAngle + this.direction + rays[i]; + let rayAngle = this.direction + rays[i]; // Check against all other boids if (this.detectBoids(rayAngle, boids)) { + if (i == 0) { + collision = true; + } continue; } // Check against scene boundaries if (this.detectBox(this.scene_width, this.scene_height, rayAngle)) { + if (i == 0) { + collision = true; + } continue; } return rayAngle; } + if (!collision) { + return this.direction; + } + console.log('cannot find suitable ray'); return false; } @@ -112,9 +125,16 @@ class Boid { if (intersect) { console.log('boids intersect detected'); + return true; } - return intersect; + return this.willBoidsIntersect(boid, direction); + } + + willBoidsIntersect(boid, direction) { + let future_position = this.findPoint(this.x, this.y, this.rayLength, direction); + + return this.lineIntersectsCircle(this.x, future_position.x, this.y, future_position.y, boid.radius * 2, boid.x, boid.y); } boidsIntersect(boid) { @@ -145,13 +165,36 @@ class Boid { if (!x4 || !y4) { return false; } - console.log('intersecting circles'); + return { x: x4, y: y4 }; } + lineIntersectsCircle(x1, x2, y1, y2, r, rx, ry) { + // first r is at 0,0 so we must first move the line the same distance + // Normalize points + x1 -= rx; + y1 -= ry; + x2 -= rx; + y2 -= ry; + + let dx = x2 - x1; + let dy = y2 - y1; + + let dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); + let dd = (x1 * y2) - (x2 * y1); + + let di = (Math.pow(r, 2) * Math.pow(dr, 2)) - Math.pow(dd, 2); + + if (di < 0) { + return false; + } else { + return true; + } + } + distanceBetweenPoints(x1, x2, y1, y2) { let dx = Math.abs(x1 - x2); let dy = Math.abs(y1 - y2); @@ -219,7 +262,7 @@ class Boid { } detectBox(width, height, direction) { - let point = this.findPoint(this.x, this.y, this.rayLength, direction); + let point = this.findPoint(this.x, this.y, this.wallBuffer, direction); if (point.x - this.radius < 0 || point.y - this.radius < 0 || @@ -235,18 +278,18 @@ class Boid { findPoint(x1, y1, length, angle) { angle *= Math.PI / 180; - var x2 = x1 + length * Math.cos(angle), - y2 = y1 + length * Math.sin(angle); + let x2 = x1 + length * Math.cos(angle); // must be rad + let y2 = y1 + length * Math.sin(angle); // must be radrayLength return { - x: x2, - y: y2 + x: parseFloat((Number(x2).toFixed(2))), + y: parseFloat(Number(y2).toFixed(2)) }; } draw(context) { this.drawBoid(context); - // this.drawRay(context, this.x, this.y, this.rayLength, this.direction); + this.drawRay(context, this.x, this.y, this.rayLength, this.direction); } drawBoid(context) { @@ -326,14 +369,15 @@ class Scene { initBoids() { let boids = []; + for (let i = 0; i < this.no_of_boids; i++) { boids.push(new Boid( this.boid_radius, "black", - // 300, 300, Math.random() * 360, - Math.random() * (this.gameArea.canvas.width - 100) + 50, - Math.random() * (this.gameArea.canvas.height - 100) + 50, - Math.random() * 360, + // 300, 300, 90, + parseFloat(Number(Math.random() * (this.gameArea.canvas.width - 100) + 50).toFixed(1)), + parseFloat(Number(Math.random() * (this.gameArea.canvas.height - 100) + 50).toFixed(1)), + parseFloat(Number(Math.random() * 360).toFixed(2)), i, this.width, this.height @@ -362,11 +406,19 @@ class Scene { } update() { + if (!this.started) { + return; + } this.gameArea.clear(); - for (let i = 0; i < this.no_of_boids; i++) { - this.boids[i].move(this.boids); + for (let i = 0; i < this.boids.length; i++) { + let result = this.boids[i].move(this.boids); this.boids[i].draw(this.gameArea.context); + if (!result) { + continue; + } + } + return true; } stop() { @@ -391,7 +443,7 @@ class Scene { } -let scene = new Scene(5, 20); +let scene = new Scene(5, 10); function stop() { scene.stop(); diff --git a/resources/js/app.js b/resources/js/app.js index 47cabd6..d900e4a 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1,4 +1,4 @@ -let scene = new Scene(5, 20); +let scene = new Scene(5, 10); function stop() { scene.stop(); diff --git a/resources/js/boid.js b/resources/js/boid.js index a15022a..a3aefea 100644 --- a/resources/js/boid.js +++ b/resources/js/boid.js @@ -14,27 +14,34 @@ class Boid { this.scene_height = scene_height; // Boid "dynamic" properties - this.rayLength = 40; + this.rayLength = 60; + this.wallBuffer = 40; this.turnStepAmount = 20; - this.stepAmount = 4; - this.fieldOfView = 270; + this.stepAmount = 2; + this.fieldOfView = 180; this.boidBuffer = 20; } move(boids) { // this.direction += Math.random() * (2 * this.turnStepAmount) - this.turnStepAmount + let direction = this.findNextRay(boids); - this.direction = this.findNextRay(boids); + if (!direction) { + return false; + } + this.direction = direction; var vector = this.findPoint(this.x, this.y, this.stepAmount, this.direction); this.x = vector.x; this.y = vector.y; + + return true; } buildRays() { let rays = new Array(); - let rayInteval = 2; + let rayInteval = 5; let noOfSteps = this.fieldOfView / rayInteval; let is_clockwise = Math.random() >= 0.5; @@ -61,27 +68,33 @@ class Boid { findNextRay(boids) { let rays = this.buildRays(); + let collision = false; for (let i = 0; i < rays.length; i++) { - let tweakAngle = 0; - // if (Math.random() > 0.95) { - // tweakAngle = this.turnStepAmount * Math.random() - (this.turnStepAmount / 2); - // } - - let rayAngle = tweakAngle + this.direction + rays[i]; + let rayAngle = this.direction + rays[i]; // Check against all other boids if (this.detectBoids(rayAngle, boids)) { + if (i == 0) { + collision = true; + } continue; } // Check against scene boundaries if (this.detectBox(this.scene_width, this.scene_height, rayAngle)) { + if (i == 0) { + collision = true; + } continue; } return rayAngle; } + if (!collision) { + return this.direction; + } + console.log('cannot find suitable ray'); return false; } @@ -112,9 +125,16 @@ class Boid { if (intersect) { console.log('boids intersect detected'); + return true; } - return intersect; + return this.willBoidsIntersect(boid, direction); + } + + willBoidsIntersect(boid, direction) { + let future_position = this.findPoint(this.x, this.y, this.rayLength, direction); + + return this.lineIntersectsCircle(this.x, future_position.x, this.y, future_position.y, boid.radius * 2, boid.x, boid.y); } boidsIntersect(boid) { @@ -145,13 +165,36 @@ class Boid { if (!x4 || !y4) { return false; } - console.log('intersecting circles'); + return { x: x4, y: y4 }; } + lineIntersectsCircle(x1, x2, y1, y2, r, rx, ry) { + // first r is at 0,0 so we must first move the line the same distance + // Normalize points + x1 -= rx; + y1 -= ry; + x2 -= rx; + y2 -= ry; + + let dx = x2 - x1; + let dy = y2 - y1; + + let dr = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2)); + let dd = (x1 * y2) - (x2 * y1); + + let di = (Math.pow(r, 2) * Math.pow(dr, 2)) - Math.pow(dd, 2); + + if (di < 0) { + return false; + } else { + return true; + } + } + distanceBetweenPoints(x1, x2, y1, y2) { let dx = Math.abs(x1 - x2); let dy = Math.abs(y1 - y2); @@ -219,7 +262,7 @@ class Boid { } detectBox(width, height, direction) { - let point = this.findPoint(this.x, this.y, this.rayLength, direction); + let point = this.findPoint(this.x, this.y, this.wallBuffer, direction); if (point.x - this.radius < 0 || point.y - this.radius < 0 || @@ -235,18 +278,18 @@ class Boid { findPoint(x1, y1, length, angle) { angle *= Math.PI / 180; - var x2 = x1 + length * Math.cos(angle), - y2 = y1 + length * Math.sin(angle); + let x2 = x1 + length * Math.cos(angle); // must be rad + let y2 = y1 + length * Math.sin(angle); // must be radrayLength return { - x: x2, - y: y2 + x: parseFloat((Number(x2).toFixed(2))), + y: parseFloat(Number(y2).toFixed(2)) }; } draw(context) { this.drawBoid(context); - // this.drawRay(context, this.x, this.y, this.rayLength, this.direction); + this.drawRay(context, this.x, this.y, this.rayLength, this.direction); } drawBoid(context) { diff --git a/resources/js/scene.js b/resources/js/scene.js index 770eb92..f8858b6 100644 --- a/resources/js/scene.js +++ b/resources/js/scene.js @@ -19,14 +19,15 @@ class Scene { initBoids() { let boids = []; + for (let i = 0; i < this.no_of_boids; i++) { boids.push(new Boid( this.boid_radius, "black", - // 300, 300, Math.random() * 360, - Math.random() * (this.gameArea.canvas.width - 100) + 50, - Math.random() * (this.gameArea.canvas.height - 100) + 50, - Math.random() * 360, + // 300, 300, 90, + parseFloat(Number(Math.random() * (this.gameArea.canvas.width - 100) + 50).toFixed(1)), + parseFloat(Number(Math.random() * (this.gameArea.canvas.height - 100) + 50).toFixed(1)), + parseFloat(Number(Math.random() * 360).toFixed(2)), i, this.width, this.height @@ -55,11 +56,19 @@ class Scene { } update() { + if (!this.started) { + return; + } this.gameArea.clear(); - for (let i = 0; i < this.no_of_boids; i++) { - this.boids[i].move(this.boids); + for (let i = 0; i < this.boids.length; i++) { + let result = this.boids[i].move(this.boids); this.boids[i].draw(this.gameArea.context); + if (!result) { + continue; + } + } + return true; } stop() { -- cgit v1.2.3