From a4908f150053316383fbfaee0477e7b4123ce3ca Mon Sep 17 00:00:00 2001 From: Fbenas Date: Tue, 13 Oct 2020 19:46:05 +0100 Subject: Refactor --- public/js/app.js | 75 ++++++++++------- resources/js/app.js | 2 +- resources/js/boid.js | 202 ++++++++++++++++++++++++++++++++++++++++++++++ resources/js/component.js | 202 ---------------------------------------------- resources/js/flock.js | 15 ++++ resources/js/scene.js | 33 ++++---- webpack.mix.js | 3 +- 7 files changed, 287 insertions(+), 245 deletions(-) create mode 100644 resources/js/boid.js delete mode 100644 resources/js/component.js create mode 100644 resources/js/flock.js diff --git a/public/js/app.js b/public/js/app.js index c9e5c27..e60548e 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,15 +1,15 @@ -class Component { +class Boid { constructor(context, radius, color, x, y, direction, id) { this.rayLength = 40; - this.turnStepAmount = 5; + this.turnStepAmount = 20; this.stepAmount = 4; this.radius = radius; this.x = x; this.y = y; this.direction = direction; this.color = color; - this.fieldOfView = 180; + this.fieldOfView = 270; this.id = id; this.boidBuffer = 20; @@ -21,7 +21,7 @@ class Component { this.direction = this.findNextRay(context, boids); - var vector = this.detectionPoint(this.x, this.y, this.stepAmount, this.direction); + var vector = this.findPoint(this.x, this.y, this.stepAmount, this.direction); this.x = vector.x; this.y = vector.y; @@ -49,7 +49,7 @@ class Component { for (let i = 0; i < rays.length; i++) { let tweakAngle = 0; // if (Math.random() > 0.95) { - // tweakAngle = this.turnStepAmount * Math.random() * 5; + // tweakAngle = this.turnStepAmount * Math.random() - (this.turnStepAmount / 2); // } let rayAngle = tweakAngle + this.direction + rays[i]; @@ -75,7 +75,7 @@ class Component { continue; } - let thisFututrePosition = this.detectionPoint(this.x, this.y, this.boidBuffer, direction); + let thisFututrePosition = this.findPoint(this.x, this.y, this.boidBuffer, direction); let thisPath = { x1: this.x, y1: this.y, @@ -83,7 +83,7 @@ class Component { y2: thisFututrePosition.y }; - let boidFuturePosition = this.detectionPoint(boids[i].x, boids[i].y, boids[i].boidBuffer, boids[i].direction); + let boidFuturePosition = this.findPoint(boids[i].x, boids[i].y, boids[i].boidBuffer, boids[i].direction); let boidPath = { x1: boids[i].x, y1: boids[i].y, @@ -135,7 +135,7 @@ class Component { } detectBox(context, width, height, direction) { - let perceptionVector = this.detectionPoint(this.x, this.y, this.rayLength, direction); + let perceptionVector = this.findPoint(this.x, this.y, this.rayLength, direction); if (perceptionVector.x - this.radius < 0 || perceptionVector.y - this.radius < 0 || @@ -162,17 +162,17 @@ class Component { } drawRay(context, x, y, perceptionDistance, direction) { + let point = this.findPoint(x, y, perceptionDistance, direction); context.lineWidth = 1; - context.beginPath(); - this.lineToAngle(context, x, y, perceptionDistance, direction); + context.moveTo(x, y); + context.lineTo(point.x, point.y); context.stroke(); context.restore(); } lineToAngle(context, x1, y1, length, angle) { - angle *= Math.PI / 180; var x2 = x1 + length * Math.cos(angle), @@ -187,7 +187,7 @@ class Component { }; } - detectionPoint(x1, y1, length, angle) { + findPoint(x1, y1, length, angle) { angle *= Math.PI / 180; var x2 = x1 + length * Math.cos(angle), @@ -201,6 +201,22 @@ class Component { } +class Flock { + constructor() { + this.boids = []; + } + + run() { + for (let i = 0; i < this.boids.length; i++) { + this.boids[i].run(boids); + } + } + + addBoid(boid) { + this.boids.push(boid); + } +} + class GameArea { constructor(canvas_width, canvas_height) { @@ -224,6 +240,10 @@ class GameArea { class Scene { + // boid radius + // no of boids + // scene width + // scene height constructor(component_size, no_of_components) { this.component_size = component_size; this.no_of_components = no_of_components; @@ -237,25 +257,26 @@ class Scene { initComponents() { let components = []; for (let i = 0; i < this.no_of_components; i++) { - let x, y, z; - if (i == 0) { - x = 100; - y = 100; - z = 0; - } else { - x = 105; - y = 100; - z = 180; - } + // let x, y, z; + // if (i == 0) { + // x = 100; + // y = 100; + // z = 0; + // } else { + // x = 105; + // y = 100; + // z = 180; + // } - components.push(new Component( + components.push(new Boid( this.gameArea.context, this.component_size, "black", + 300, 300, Math.random() * 360, // x, y, z, - Math.random() * (this.gameArea.canvas.width - 100) + 50, - Math.random() * (this.gameArea.canvas.height - 100) + 50, - Math.random() * 360, + // Math.random() * (this.gameArea.canvas.width - 100) + 50, + // Math.random() * (this.gameArea.canvas.height - 100) + 50, + // Math.random() * 360, i )); } @@ -310,7 +331,7 @@ class Scene { } -let scene = new Scene(5, 20); +let scene = new Scene(5, 100); function stop() { scene.stop(); diff --git a/resources/js/app.js b/resources/js/app.js index 47cabd6..b107a71 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, 100); function stop() { scene.stop(); diff --git a/resources/js/boid.js b/resources/js/boid.js new file mode 100644 index 0000000..6075cc2 --- /dev/null +++ b/resources/js/boid.js @@ -0,0 +1,202 @@ +class Boid { + + constructor(context, radius, color, x, y, direction, id) { + this.rayLength = 40; + this.turnStepAmount = 20; + this.stepAmount = 4; + this.radius = radius; + this.x = x; + this.y = y; + this.direction = direction; + this.color = color; + this.fieldOfView = 270; + this.id = id; + this.boidBuffer = 20; + + this.update(context); + } + + move(context, boids) { + // this.direction += Math.random() * (2 * this.turnStepAmount) - this.turnStepAmount + + this.direction = this.findNextRay(context, boids); + + var vector = this.findPoint(this.x, this.y, this.stepAmount, this.direction); + this.x = vector.x; + this.y = vector.y; + + this.update(context); + } + + buildRays() { + let rays = new Array(); + + let rayInteval = 2; + let noOfSteps = this.fieldOfView / rayInteval; + for (let i = 0; i < noOfSteps / 2; i++) { + if (i != 0) { + rays.push(rayInteval * -i); + } + rays.push(rayInteval * i); + } + + return rays; + } + + findNextRay(context, boids) { + let rays = this.buildRays(); + + 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]; + + if (i == 0 && this.detectBoid(context, rayAngle, boids)) { + continue; + } + + if (this.detectBox(context, context.canvas.width, context.canvas.height, rayAngle)) { + continue; + } + + return rayAngle; + } + console.log(this.x, this.y); + console.log('cannot find suitable ray'); + } + + detectBoid(context, direction, boids) { + for (let i = 0; i < boids.length; i++) { + // rule out ourselves + if (this.id == boids[i].id) { + continue; + } + + let thisFututrePosition = this.findPoint(this.x, this.y, this.boidBuffer, direction); + let thisPath = { + x1: this.x, + y1: this.y, + x2: thisFututrePosition.x, + y2: thisFututrePosition.y + }; + + let boidFuturePosition = this.findPoint(boids[i].x, boids[i].y, boids[i].boidBuffer, boids[i].direction); + let boidPath = { + x1: boids[i].x, + y1: boids[i].y, + x2: boidFuturePosition.x, + y2: boidFuturePosition.y + }; + + let thisIntersectsBoid = this.pathsIntersect( + thisPath.x1, thisPath.y1, thisPath.x2, thisPath.y2, boidPath.x1, boidPath.y1, boidPath.x2, boidPath.y2 + ); + + if (thisIntersectsBoid) { + return true; + } + } + + return false; + } + + pathsIntersect(x1, y1, x2, y2, x3, y3, x4, y4) { + // Check if none of the lines are of length 0 + if ((x1 === x2 && y1 === y2) || (x3 === x4 && y3 === y4)) { + return false + } + + let denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)) + + // // Lines are parallel + // if (denominator === 0) { + // return false + // } + + let ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator + let ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator + + // is the intersection along the segments + if (ua < 0 || ua > 1 || ub < 0 || ub > 1) { + return false + } + + // Return a object with the x and y coordinates of the intersection + let x = x1 + ua * (x2 - x1) + let y = y1 + ua * (y2 - y1) + + return { + x, + y + } + } + + detectBox(context, width, height, direction) { + let perceptionVector = this.findPoint(this.x, this.y, this.rayLength, direction); + + if (perceptionVector.x - this.radius < 0 || + perceptionVector.y - this.radius < 0 || + perceptionVector.x + this.radius > width - 0 || + perceptionVector.y + this.radius > height - 0 + ) { + return true; + } + + return false; + } + + update(context) { + this.drawBoid(context); + this.drawRay(context, this.x, this.y, this.rayLength, this.direction); + } + + drawBoid(context) { + context.beginPath(); + context.fillStyle = "blue"; + context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); + context.stroke(); + context.restore(); + } + + drawRay(context, x, y, perceptionDistance, direction) { + let point = this.findPoint(x, y, perceptionDistance, direction); + context.lineWidth = 1; + context.beginPath(); + context.moveTo(x, y); + context.lineTo(point.x, point.y); + context.stroke(); + + context.restore(); + } + + lineToAngle(context, x1, y1, length, angle) { + angle *= Math.PI / 180; + + var x2 = x1 + length * Math.cos(angle), + y2 = y1 + length * Math.sin(angle); + + context.moveTo(x1, y1); + context.lineTo(x2, y2); + + return { + x: x2, + y: y2 + }; + } + + findPoint(x1, y1, length, angle) { + angle *= Math.PI / 180; + + var x2 = x1 + length * Math.cos(angle), + y2 = y1 + length * Math.sin(angle); + + return { + x: x2, + y: y2 + }; + } + +} diff --git a/resources/js/component.js b/resources/js/component.js deleted file mode 100644 index 373b66a..0000000 --- a/resources/js/component.js +++ /dev/null @@ -1,202 +0,0 @@ -class Component { - - constructor(context, radius, color, x, y, direction, id) { - this.rayLength = 40; - this.turnStepAmount = 5; - this.stepAmount = 4; - this.radius = radius; - this.x = x; - this.y = y; - this.direction = direction; - this.color = color; - this.fieldOfView = 180; - this.id = id; - this.boidBuffer = 20; - - this.update(context); - } - - move(context, boids) { - // this.direction += Math.random() * (2 * this.turnStepAmount) - this.turnStepAmount - - this.direction = this.findNextRay(context, boids); - - var vector = this.detectionPoint(this.x, this.y, this.stepAmount, this.direction); - this.x = vector.x; - this.y = vector.y; - - this.update(context); - } - - buildRays() { - let rays = new Array(); - - let rayInteval = 2; - let noOfSteps = this.fieldOfView / rayInteval; - for (let i = 0; i < noOfSteps / 2; i++) { - if (i != 0) { - rays.push(rayInteval * -i); - } - rays.push(rayInteval * i); - } - - return rays; - } - - findNextRay(context, boids) { - let rays = this.buildRays(); - - for (let i = 0; i < rays.length; i++) { - let tweakAngle = 0; - // if (Math.random() > 0.95) { - // tweakAngle = this.turnStepAmount * Math.random() * 5; - // } - - let rayAngle = tweakAngle + this.direction + rays[i]; - - if (i == 0 && this.detectBoid(context, rayAngle, boids)) { - continue; - } - - if (this.detectBox(context, context.canvas.width, context.canvas.height, rayAngle)) { - continue; - } - - return rayAngle; - } - console.log(this.x, this.y); - console.log('cannot find suitable ray'); - } - - detectBoid(context, direction, boids) { - for (let i = 0; i < boids.length; i++) { - // rule out ourselves - if (this.id == boids[i].id) { - continue; - } - - let thisFututrePosition = this.detectionPoint(this.x, this.y, this.boidBuffer, direction); - let thisPath = { - x1: this.x, - y1: this.y, - x2: thisFututrePosition.x, - y2: thisFututrePosition.y - }; - - let boidFuturePosition = this.detectionPoint(boids[i].x, boids[i].y, boids[i].boidBuffer, boids[i].direction); - let boidPath = { - x1: boids[i].x, - y1: boids[i].y, - x2: boidFuturePosition.x, - y2: boidFuturePosition.y - }; - - let thisIntersectsBoid = this.pathsIntersect( - thisPath.x1, thisPath.y1, thisPath.x2, thisPath.y2, boidPath.x1, boidPath.y1, boidPath.x2, boidPath.y2 - ); - - if (thisIntersectsBoid) { - return true; - } - } - - return false; - } - - pathsIntersect(x1, y1, x2, y2, x3, y3, x4, y4) { - // Check if none of the lines are of length 0 - if ((x1 === x2 && y1 === y2) || (x3 === x4 && y3 === y4)) { - return false - } - - let denominator = ((y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1)) - - // // Lines are parallel - // if (denominator === 0) { - // return false - // } - - let ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denominator - let ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denominator - - // is the intersection along the segments - if (ua < 0 || ua > 1 || ub < 0 || ub > 1) { - return false - } - - // Return a object with the x and y coordinates of the intersection - let x = x1 + ua * (x2 - x1) - let y = y1 + ua * (y2 - y1) - - return { - x, - y - } - } - - detectBox(context, width, height, direction) { - let perceptionVector = this.detectionPoint(this.x, this.y, this.rayLength, direction); - - if (perceptionVector.x - this.radius < 0 || - perceptionVector.y - this.radius < 0 || - perceptionVector.x + this.radius > width - 0 || - perceptionVector.y + this.radius > height - 0 - ) { - return true; - } - - return false; - } - - update(context) { - this.drawBoid(context); - this.drawRay(context, this.x, this.y, this.rayLength, this.direction); - } - - drawBoid(context) { - context.beginPath(); - context.fillStyle = "blue"; - context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); - context.stroke(); - context.restore(); - } - - drawRay(context, x, y, perceptionDistance, direction) { - context.lineWidth = 1; - - context.beginPath(); - this.lineToAngle(context, x, y, perceptionDistance, direction); - context.stroke(); - - context.restore(); - } - - lineToAngle(context, x1, y1, length, angle) { - - angle *= Math.PI / 180; - - var x2 = x1 + length * Math.cos(angle), - y2 = y1 + length * Math.sin(angle); - - context.moveTo(x1, y1); - context.lineTo(x2, y2); - - return { - x: x2, - y: y2 - }; - } - - detectionPoint(x1, y1, length, angle) { - angle *= Math.PI / 180; - - var x2 = x1 + length * Math.cos(angle), - y2 = y1 + length * Math.sin(angle); - - return { - x: x2, - y: y2 - }; - } - -} diff --git a/resources/js/flock.js b/resources/js/flock.js new file mode 100644 index 0000000..952aecd --- /dev/null +++ b/resources/js/flock.js @@ -0,0 +1,15 @@ +class Flock { + constructor() { + this.boids = []; + } + + run() { + for (let i = 0; i < this.boids.length; i++) { + this.boids[i].run(boids); + } + } + + addBoid(boid) { + this.boids.push(boid); + } +} diff --git a/resources/js/scene.js b/resources/js/scene.js index 7e7e895..d035827 100644 --- a/resources/js/scene.js +++ b/resources/js/scene.js @@ -1,5 +1,9 @@ class Scene { + // boid radius + // no of boids + // scene width + // scene height constructor(component_size, no_of_components) { this.component_size = component_size; this.no_of_components = no_of_components; @@ -13,25 +17,26 @@ class Scene { initComponents() { let components = []; for (let i = 0; i < this.no_of_components; i++) { - let x, y, z; - if (i == 0) { - x = 100; - y = 100; - z = 0; - } else { - x = 105; - y = 100; - z = 180; - } + // let x, y, z; + // if (i == 0) { + // x = 100; + // y = 100; + // z = 0; + // } else { + // x = 105; + // y = 100; + // z = 180; + // } - components.push(new Component( + components.push(new Boid( this.gameArea.context, this.component_size, "black", + 300, 300, Math.random() * 360, // x, y, z, - Math.random() * (this.gameArea.canvas.width - 100) + 50, - Math.random() * (this.gameArea.canvas.height - 100) + 50, - Math.random() * 360, + // Math.random() * (this.gameArea.canvas.width - 100) + 50, + // Math.random() * (this.gameArea.canvas.height - 100) + 50, + // Math.random() * 360, i )); } diff --git a/webpack.mix.js b/webpack.mix.js index 5b5d5cf..f75384b 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -13,7 +13,8 @@ const mix = require('laravel-mix'); mix.scripts( [ - 'resources/js/component.js', + 'resources/js/boid.js', + 'resources/js/flock.js', 'resources/js/gameArea.js', 'resources/js/scene.js', 'resources/js/app.js', -- cgit v1.2.3