From 101011c6e8866f07d4f6d2994ec414bdb79d2ae8 Mon Sep 17 00:00:00 2001 From: Fbenas Date: Mon, 21 Sep 2020 01:37:51 +0100 Subject: Better edge detection and avoidance --- public/js/app.js | 96 +++++++++++++++++++++++++++++++++++------------ resources/js/app.js | 2 +- resources/js/component.js | 90 +++++++++++++++++++++++++++++++++----------- resources/js/scene.js | 4 +- 4 files changed, 146 insertions(+), 46 deletions(-) diff --git a/public/js/app.js b/public/js/app.js index b50828e..fdf81e7 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -1,49 +1,98 @@ class Component { constructor(radius, color, x, y, direction) { - this.perceptionDistance = 20; - this.turnStepAmount = 5; - this.collisionTurnStepAmount = 20; - this.stepAmount = 1; + this.rayLength = 100; + this.turnStepAmount = 0; + this.stepAmount = 5; this.radius = radius; this.x = x; this.y = y; this.direction = direction; this.color = color; + this.fieldOfView = 180; } move(context) { - this.direction += Math.random() * (2 * this.turnStepAmount) - this.turnStepAmount - var localDirection = this.direction; - // first we need to work out if we detect any walls - var perceptionVector = this.detectionPoint(this.x, this.y, this.perceptionDistance, localDirection); - - while (perceptionVector.x < 0 || perceptionVector.y < 0 || perceptionVector.x > context.canvas.width || perceptionVector.y > context.canvas.height) { - localDirection += Math.random() * (2 * this.collisionTurnStepAmount) - this.collisionTurnStepAmount - perceptionVector = this.detectionPoint(this.x, this.y, this.perceptionDistance, localDirection); - } + // this.direction += Math.random() * (2 * this.turnStepAmount) - this.turnStepAmount - // Here we should now have a new vector that's not clipping - this.direction = localDirection; - var vector = this.detectionPoint(this.x, this.y, this.stepAmount, this.direction); + this.direction = this.findNextRay(context); + 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 = 10; + 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) { + let rays = this.buildRays(); + + for (let i = 0; i < rays.length; i++) { + + let tweakAngle = 0; + if (i == 0 && Math.random() > 0.95) { + tweakAngle = this.turnStepAmount * Math.random() * 5; + } else { + tweakAngle = rays[i] * Math.random() * 3; + } + + let rayAngle = tweakAngle + this.direction + rays[i]; + + if (this.detectBox(context, context.canvas.width, context.canvas.height, rayAngle)) { + continue; + } + + return rayAngle; + } + + throw new Exception(); + } + + detectBox(context, width, height, direction) { + let perceptionVector = this.detectionPoint(this.x, this.y, this.rayLength, direction); + + if (perceptionVector.x < 0 || perceptionVector.y < 0 || perceptionVector.x > width || perceptionVector.y > height) { + this.drawRay(context, perceptionVector.x, perceptionVector.y, this.perceptionDistance, direction) + return true; + } + + return false; + } + update(context) { + this.updateBoid(context); + this.drawRay(context, this.x, this.y, this.rayLength, this.direction); + } + + updateBoid(context) { context.beginPath(); context.fillStyle = "blue"; context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); context.stroke(); - context.restore(); - context.beginPath(); - this.lineToAngle(context, this.x, this.y, this.perceptionDistance, this.direction); + } + + drawRay(context, x, y, perceptionDistance, direction) { context.lineWidth = 1; - // context.stroke(); + + context.beginPath(); + // this.lineToAngle(context, x, y, perceptionDistance, direction); + context.stroke(); context.restore(); } @@ -65,7 +114,6 @@ class Component { } detectionPoint(x1, y1, length, angle) { - angle *= Math.PI / 180; var x2 = x1 + length * Math.cos(angle), @@ -120,6 +168,7 @@ class Scene { Math.random() * this.gameArea.canvas.width, Math.random() * this.gameArea.canvas.height, Math.random() * 360 + // 18, 100, 180 ); this.components.push(new_component); } @@ -138,7 +187,8 @@ class Scene { // Kinda annoying, setInterval is a piece of shite and is always run from global scope // Therefore "this.update" will be undefined unless we bind it const updateMe = this.update.bind(this); - this.interval = setInterval(updateMe, 5); + this.interval = setInterval(updateMe, 20); + // updateMe(); this.started = true; } @@ -171,7 +221,7 @@ class Scene { } -let scene = new Scene(2, 500); +let scene = new Scene(10, 100); function stop() { scene.stop(); diff --git a/resources/js/app.js b/resources/js/app.js index 103a32f..797dc0f 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1,4 +1,4 @@ -let scene = new Scene(2, 500); +let scene = new Scene(10, 100); function stop() { scene.stop(); diff --git a/resources/js/component.js b/resources/js/component.js index 6d74e93..ec81489 100644 --- a/resources/js/component.js +++ b/resources/js/component.js @@ -1,49 +1,98 @@ class Component { constructor(radius, color, x, y, direction) { - this.perceptionDistance = 20; - this.turnStepAmount = 5; - this.collisionTurnStepAmount = 20; - this.stepAmount = 1; + this.rayLength = 100; + this.turnStepAmount = 0; + this.stepAmount = 5; this.radius = radius; this.x = x; this.y = y; this.direction = direction; this.color = color; + this.fieldOfView = 180; } move(context) { - this.direction += Math.random() * (2 * this.turnStepAmount) - this.turnStepAmount - var localDirection = this.direction; - // first we need to work out if we detect any walls - var perceptionVector = this.detectionPoint(this.x, this.y, this.perceptionDistance, localDirection); - - while (perceptionVector.x < 0 || perceptionVector.y < 0 || perceptionVector.x > context.canvas.width || perceptionVector.y > context.canvas.height) { - localDirection += Math.random() * (2 * this.collisionTurnStepAmount) - this.collisionTurnStepAmount - perceptionVector = this.detectionPoint(this.x, this.y, this.perceptionDistance, localDirection); - } + // this.direction += Math.random() * (2 * this.turnStepAmount) - this.turnStepAmount - // Here we should now have a new vector that's not clipping - this.direction = localDirection; - var vector = this.detectionPoint(this.x, this.y, this.stepAmount, this.direction); + this.direction = this.findNextRay(context); + 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 = 10; + 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) { + let rays = this.buildRays(); + + for (let i = 0; i < rays.length; i++) { + + let tweakAngle = 0; + if (i == 0 && Math.random() > 0.95) { + tweakAngle = this.turnStepAmount * Math.random() * 5; + } else { + tweakAngle = rays[i] * Math.random() * 3; + } + + let rayAngle = tweakAngle + this.direction + rays[i]; + + if (this.detectBox(context, context.canvas.width, context.canvas.height, rayAngle)) { + continue; + } + + return rayAngle; + } + + throw new Exception(); + } + + detectBox(context, width, height, direction) { + let perceptionVector = this.detectionPoint(this.x, this.y, this.rayLength, direction); + + if (perceptionVector.x < 0 || perceptionVector.y < 0 || perceptionVector.x > width || perceptionVector.y > height) { + this.drawRay(context, perceptionVector.x, perceptionVector.y, this.perceptionDistance, direction) + return true; + } + + return false; + } + update(context) { + this.updateBoid(context); + this.drawRay(context, this.x, this.y, this.rayLength, this.direction); + } + + updateBoid(context) { context.beginPath(); context.fillStyle = "blue"; context.arc(this.x, this.y, this.radius, 0, 2 * Math.PI); context.stroke(); - context.restore(); - context.beginPath(); - this.lineToAngle(context, this.x, this.y, this.perceptionDistance, this.direction); + } + + drawRay(context, x, y, perceptionDistance, direction) { context.lineWidth = 1; - // context.stroke(); + + context.beginPath(); + // this.lineToAngle(context, x, y, perceptionDistance, direction); + context.stroke(); context.restore(); } @@ -65,7 +114,6 @@ class Component { } detectionPoint(x1, y1, length, angle) { - angle *= Math.PI / 180; var x2 = x1 + length * Math.cos(angle), diff --git a/resources/js/scene.js b/resources/js/scene.js index 194a77b..684cd11 100644 --- a/resources/js/scene.js +++ b/resources/js/scene.js @@ -18,6 +18,7 @@ class Scene { Math.random() * this.gameArea.canvas.width, Math.random() * this.gameArea.canvas.height, Math.random() * 360 + // 18, 100, 180 ); this.components.push(new_component); } @@ -36,7 +37,8 @@ class Scene { // Kinda annoying, setInterval is a piece of shite and is always run from global scope // Therefore "this.update" will be undefined unless we bind it const updateMe = this.update.bind(this); - this.interval = setInterval(updateMe, 5); + this.interval = setInterval(updateMe, 20); + // updateMe(); this.started = true; } -- cgit v1.2.3