From ce60972fcb333adfaa20aa2e21a78e60f665db77 Mon Sep 17 00:00:00 2001 From: FintasticMan <52415484+FintasticMan@users.noreply.github.com> Date: Tue, 19 Jan 2021 08:48:34 +0100 Subject: [PATCH] Add an interactive UI This brings an interactive UI with the options to pause the sim, hide individual elements or the whole thing, and change the speed at which it runs. This also adds a system where if the only car that's left is the best one from last time, it will just kill that car. This saves a bunch of time while training because whenever there are no improvements in a generation, you don't have to wait for the car to die to go to the next gen. --- car.js | 11 ++++- index.html | 20 +++++++- sketch.js | 137 ++++++++++++++++++++++++++++++++++++++++------------- style.css | 4 ++ 4 files changed, 136 insertions(+), 36 deletions(-) create mode 100644 style.css diff --git a/car.js b/car.js index 150882d..c12e8ee 100644 --- a/car.js +++ b/car.js @@ -58,6 +58,15 @@ class Car { rect(0, 0, this.l, this.w); pop(); + + if (showFitness) { + push(); + textFont("monospace"); + textSize(16); + fill(0, 255, 0); + text(this.score, this.pos.x + 5, this.pos.y - 5); + pop(); + } } isColliding(track) { @@ -184,7 +193,7 @@ class Car { for (let i = 0; i < casts.length; i++) { push(); stroke(255); - strokeWeight(2); + strokeWeight(1); line(this.pos.x, this.pos.y, casts[i].x, casts[i].y); pop(); } diff --git a/index.html b/index.html index 07db8bc..a26d103 100644 --- a/index.html +++ b/index.html @@ -12,6 +12,24 @@ + - + +
+ +

+ FPS: 0 +
CPS: 0 (calculations per second) +
cars: 0 +
generation: 0 +

+ +

+ +
+
+
+
speed: 1 116 +

+ diff --git a/sketch.js b/sketch.js index be4f38d..bee088a 100644 --- a/sketch.js +++ b/sketch.js @@ -19,11 +19,30 @@ let generation = 0; const cars = []; let raceTrack; -let speed = 16; +let speed; let visual = true; +// HTML elements +let fpsSpan; +let cpsSpan; +let carsSpan; +let genSpan; + +// User-controlled values +let pauseButton; +let pause = false; +let visualButton; +let castsButton; +let fitnessButton; +let showFitness = true; +let speedSlider; +let speedSpan; + +let canvas; + function setup() { - createCanvas(1280, 720); + canvas = createCanvas(1280, 720); + canvas.parent("#canvas"); background(191); strokeWeight(4); @@ -31,23 +50,19 @@ function setup() { raceTrack = new RaceTrack(innerPos, outerPos, checkpoints); + makeElements(); + newGeneration(); // noLoop(); } function draw() { - if (keyIsDown(DOWN_ARROW)) { - visual = false; - // speed = 1; - } else if (keyIsDown(UP_ARROW)) { - visual = true; - // speed = 10; - } - clear(); background(191); + checkUserInputs(); + for (let j = 0; j < speed; j++) { calcPos(); } @@ -61,13 +76,78 @@ function draw() { newGeneration(); } - push(); - textSize(16); - textFont("monospace"); - text("FPS: " + round(frameRate()), 16, 32); - text("cars: " + (amount - deadCars), 16, 64); - text("generation: " + generation, 16, 96); - pop(); + fpsSpan.html(round(frameRate())); + cpsSpan.html(round(frameRate() * speed)); + carsSpan.html(amount - deadCars); + genSpan.html(generation); +} + + +function checkUserInputs() { + speed = speedSlider.value(); + speedSpan.html(speed); +} + +function makeElements() { + fpsSpan = select("#fps"); + cpsSpan = select("#cps"); + carsSpan = select("#cars"); + genSpan = select("#gen"); + + pauseButton = select("#pause"); + pauseButton.mousePressed(togglePause); + visualButton = select("#visual"); + visualButton.mousePressed(toggleVisual); + castsButton = select("#casts"); + castsButton.mousePressed(toggleCasts); + fitnessButton = select("#fitness"); + fitnessButton.mousePressed(toggleFitness); + + speedSlider = select("#speedSlider"); + speedSpan = select("#speed"); +} + + +function togglePause() { + pause = !pause; + + if (pause) { + noLoop(); + pauseButton.html("play"); + } else { + loop(); + pauseButton.html("pause"); + } +} + +function toggleVisual() { + visual = !visual; + + if (visual) { + visualButton.html("hide everything"); + } else { + visualButton.html("show everything"); + } +} + +function toggleCasts() { + drawRaycasts = !drawRaycasts; + + if (drawRaycasts) { + castsButton.html("hide raycasts"); + } else { + castsButton.html("show raycasts"); + } +} + +function toggleFitness() { + showFitness = !showFitness; + + if (showFitness) { + fitnessButton.html("hide fitness"); + } else { + fitnessButton.html("show fitness"); + } } @@ -148,23 +228,6 @@ function mutateItem(x) { } } -// function mutateLittle(x) { -// if (random() < 0.04) { -// let offset = randomGaussian(0, 0.1); -// let newx = x + offset; -// if (newx < -1) { -// newx = -1; -// } else if (newx > 1) { -// newx = 1; -// } -// console.log(newx); -// return newx; -// // return random(-1, 1); -// } else { -// return x; -// } -// } - function calcPos() { // Cycle through all of the cars for (let i = 0; i < cars.length; i++) { @@ -183,6 +246,12 @@ function calcPos() { } } + + if (deadCars === cars.length - 1 && cars[amount - 1].alive) { + cars[amount - 1].score++; + cars[amount - 1].alive = false; + deadCars++; + } } function drawCars() { diff --git a/style.css b/style.css new file mode 100644 index 0000000..ad2397d --- /dev/null +++ b/style.css @@ -0,0 +1,4 @@ +* { + font-family: monospace; + font-size: 16px; +}