Reputation: 425
I have this script in JS that implement a random walk with lerp, the problem is that with a pseudo-perfect randomness / distribution, my points always go to the top left. Can someone explain that ?
I know javascript randomness isn't perfect since it's based on the computer clock and calculations, however, with a certain amount of time, every points should stay around the center, because every probability cancels its opposite.
const canvas = document.querySelector('#myCanvas');
const ctx = canvas.getContext('2d');
const width = canvas.clientWidth;
const height = canvas.clientHeight;
canvas.width = width;
canvas.height = height;
// Amount of points
const AMOUNT = 15;
// Coordinate of the center of the screen
const centerX = width / 2;
const centerY = height / 2;
// Size of a point
const SIZE = 8;
// List containing all the point (placed by default at the center)
let points = Array.from({ length: AMOUNT }, () => [centerX, centerY]);
let pointsEnd = Array.from({ length: AMOUNT }, () => [centerX, centerY]);
// Keep count of the random distribution
let count = Array.from(new Array(4).keys());
function lerp(start, end, speed) {
return start + (end - start) * speed;
}
function render() {
// Clear the canvas
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
ctx.fillRect(0, 0, width, height);
// Loop through all the points
for (let i = 0; i < AMOUNT; i++) {
const point = points[i];
const pointEnd = pointsEnd[i];
// Draw the point
ctx.fillStyle = 'black';
ctx.fillRect(pointEnd[0] - SIZE / 2, pointEnd[1] - SIZE / 2, SIZE, SIZE);
// Generate the random number
const n = Math.floor(Math.random() * 4);
count[n]++;
// Get the sum of iterations
const sum = count.reduce((a, b) => a + b);
// Show the distribution of randomness
console.log(count.map((val, i) => i + ':' + Math.round((val / sum) * 100) + '%').join(' | '));
// Change coordinates depending on randomness
if (n == 2) point[0] += 1;
if (n == 3) pointEnd[0] -= 1;
if (n == 1) point[1] += 1;
if (n == 0) pointEnd[1] -= 1;
}
}
setInterval(() => {
requestAnimationFrame(render);
}, 1000 / 60);
<canvas id="myCanvas"></canvas>
Upvotes: 1
Views: 173
Reputation: 7913
The issue is how you are changing the coordinates based on randomness:
if (n == 2) point[0] += 1;
if (n == 3) pointEnd[0] -= 1;
if (n == 1) point[1] += 1;
if (n == 0) pointEnd[1] -= 1;
This doesn't account for all the ways the point can change, you need to adjust the point
and pointEnd
in each case:
if (n === 0) {
point[0] += 1;
pointEnd[0] += 1;
} else if (n === 1) {
point[0] -= 1;
pointEnd[0] -= 1;
} else if (n === 2) {
point[1] += 1;
pointEnd[1] += 1;
} else if (n === 3) {
point[1] -= 1;
pointEnd[1] -= 1;
}
const canvas = document.querySelector('#myCanvas');
const ctx = canvas.getContext('2d');
const width = canvas.clientWidth;
const height = canvas.clientHeight;
canvas.width = width;
canvas.height = height;
// Amount of points
const AMOUNT = 15;
// Coordinate of the center of the screen
const centerX = width / 2;
const centerY = height / 2;
// Size of a point
const SIZE = 8;
// List containing all the point (placed by default at the center)
let points = Array.from({ length: AMOUNT }, () => [centerX, centerY]);
let pointsEnd = Array.from({ length: AMOUNT }, () => [centerX, centerY]);
// Keep count of the random distribution
let count = Array.from(new Array(4).keys());
function lerp(start, end, speed) {
return start + (end - start) * speed;
}
function render() {
// Clear the canvas
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
ctx.fillRect(0, 0, width, height);
// Loop through all the points
for (let i = 0; i < AMOUNT; i++) {
const point = points[i];
const pointEnd = pointsEnd[i];
// Draw the point
ctx.fillStyle = 'black';
ctx.fillRect(pointEnd[0] - SIZE / 2, pointEnd[1] - SIZE / 2, SIZE, SIZE);
// Generate the random number
const n = Math.floor(Math.random() * 4);
console.log(n);
count[n]++;
// Get the sum of iterations
const sum = count.reduce((a, b) => a + b);
// Show the distribution of randomness
console.log(count.map((val, i) => i + ':' + Math.round((val / sum) * 100) + '%').join(' | '));
// Change coordinates depending on randomness
if (n === 0) {
point[0] += 1;
pointEnd[0] += 1;
} else if (n === 1) {
point[0] -= 1;
pointEnd[0] -= 1;
} else if (n === 2) {
point[1] += 1;
pointEnd[1] += 1;
} else if (n === 3) {
point[1] -= 1;
pointEnd[1] -= 1;
}
/*
if (n == 2) point[0] += 1;
if (n == 3) pointEnd[0] -= 1;
if (n == 1) point[1] += 1;
if (n == 0) pointEnd[1] -= 1;
*/
}
}
setInterval(() => {
requestAnimationFrame(render);
}, 1000 / 60);
<canvas id="myCanvas"></canvas>
Upvotes: 1