random-walkers/random-walkers.js

153 lines
4.3 KiB
JavaScript

window.onload = function() {
var gui = new dat.GUI({
closed: false,
remembered: {
undefined: {
"0": {},
},
},
folders: {},
load: JSON,
width: 400,
autoPlace: false,
});
gui.add(controls, "step_time", 200, 2000).name("step time (ms)").step(1);
gui.add(controls, "fadeout", 0, 20).name("time to fade (0 to disable").step(1);
gui.addColor(controls, "color").name("guy color");
gui.add(controls, "restart_button").name("start again");
var customContainer = document.getElementById("controls-container");
customContainer.append(gui.domElement);
};
var controls = new(function() {
this.step_time = 500;
this.fadeout = 10;
this.color = "#FFB000";
this.restart_button = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
init_walk();
}
})()
// Define a new mod function that behaves different on negatives.
// now, (-1).mod(4) -> 3. not -1.
// taken from https://stackoverflow.com/a/4467559, which itself took from elsewhere
Number.prototype.mod = function (n) {
"use strict";
return ((this % n) + n) % n;
};
function init_walk() {
// Create array of walkers with set parameters, start walkers in center of canvas
walker_array = []
for (var i = 0; i < 1; i++) {
var walker = {
x_position: canvas.width / 2,
y_position: canvas.height / 2,
line_width: 1,
color: controls.color,
speed: 5,
angle: Math.random() * 360,
halt: false,
}
walker.x_velocity = walker.speed * Math.cos(walker.angle)
walker.y_velocity = walker.speed * Math.sin(walker.angle)
walker_array.push(walker)
}
setInterval(paint_canvas, 20);
}
function degrees_to_radians(degrees) {
var pi = Math.PI;
return degrees * (pi / 180);
}
function radians_to_degrees(radians) {
var pi = Math.PI;
return radians * (180 / pi);
}
function gen_angle_list(number_of_groups) {
/* Generate array of possible angles from limitation
For example, if the limitation of angles is 4, then 360 / 4 = 90, and resulting array will be angle_list = [0,90,180,270,360]
Including 0 & 360 is to give the walker equal chance to turn around and stay in the canvas
*/
var angle_list = []
var initial_angle = 360 / number_of_groups;
for (var i = 0; i < number_of_groups + 1; i++) {
angle_list.push(initial_angle * i);
}
return angle_list
}
function get_nearest_angle(goal, angle_list) {
// Source: https://stackoverflow.com/questions/8584902/get-closest-number-out-of-array
// Find nearest angle in possible direction array from new random angle
var closest = angle_list.reduce(function(prev, curr) {
return (Math.abs(curr - goal) < Math.abs(prev - goal) ? curr : prev);
});
return closest
}
var possible_directions = gen_angle_list(4);
function move_walker(walker, possible_directions) {
// Update new random direction & update velocity of walker
var new_angle = Math.random() * 360
walker.x_position = (walker.x_position + walker.x_velocity).mod(canvas.width);
walker.y_position = (walker.y_position + walker.y_velocity).mod(canvas.height);
walker.angle = degrees_to_radians(get_nearest_angle(new_angle, possible_directions))
walker.x_velocity = walker.speed * Math.cos(walker.angle)
walker.y_velocity = walker.speed * Math.sin(walker.angle)
}
function paint_canvas() {
// Regenerate possible angle list
possible_directions = gen_angle_list(4)
// Loop through all walkers, moving & painting accordingly
for (var i = 0; i < walker_array.length; i++) {
current_walker = walker_array[i];
// If walker hasn't hit the walls yet
if (!current_walker.halt) {
var prev_x = current_walker.x_position
var prev_y = current_walker.y_position
ctx.beginPath()
ctx.moveTo(prev_x, prev_y)
move_walker(current_walker, possible_directions);
ctx.strokeStyle = current_walker.color;
ctx.lineWidth = current_walker.line_width;
ctx.lineTo(current_walker.x_position, current_walker.y_position)
ctx.stroke()
ctx.closePath();
}
}
}
var canvas = document.getElementById("walker-canvas")
var ctx = canvas.getContext('2d')
ctx.canvas.width = document.getElementById("walker-canvas").clientWidth
ctx.canvas.height = document.getElementById("walker-canvas").clientHeight
var walker_array = []
init_walk();