Random Oscillator
Particle randomly moves from left to right
by wio_dude
HTML
<canvas id="canvas" width="600" height="600"></canvas>
<div id="config">
<input id="trail" type="checkbox" checked><label for="trail">Show Trail</label><br />
<input id="axes" type="checkbox" checked><label for="axes">Show Axes</label><br />
<input id="polar" type="checkbox" checked><label for="polar">Show Polar</label><br />
<input id="proj" type="checkbox"><label for="proj">Show Projection</label><br />
<input id="avg" type="checkbox"><label for="avg">Show Averages</label><br />
<input id="sound" type="checkbox"><label for="sound">Play Sound</label><br />
<select id="movetype">
<option value="basic" selected>Basic</option>
<option value="bezier">Bezier</option>
<option value="stop">Stop</option>
</select>
</div>
<br />
<textarea id="debug" cols="50" rows="10"></textarea>
CSS
canvas {
background-color: whitesmoke;
}
#config {
float: right;
}
JavaScript
const TAU = 2 * Math.PI;
const X_AXIS = 0;
const Y_AXIS = 1;
const AXES = [X_AXIS, Y_AXIS];
const MAX_SPEED = 1;
const MAX_DISPLACEMENT = 200;
const ACCELERATION = 0.15;
const DEBUG_UPDATE_FRAME = 40;
const MAX_GAIN = 0.05;
const MAX_SOUND_FREQUENCY = 40;
const MIN_SOUND_FREQUENCY = 10000;
const HISTORY_SECONDS = 5 * 60
const HISTORY_FRAMES = HISTORY_SECONDS * 60;
const ELEM_IDS = [
'canvas',
'debug',
'trail',
'axes',
'polar',
'avg',
'proj',
'sound',
'movetype',
];
const $e = {};
ELEM_IDS.forEach(id => {
$e[id] = document.getElementById(id)
});
const basic = {
init() {},
update(p, v) {
for (const axis of AXES) {
const r = 2 * Math.random();
const dir = r < 1 ? 1 : -1;
if (r < 1) {
v[axis] = Math.min(
0.5 * (MAX_DISPLACEMENT - p[axis]),
v[axis] + ACCELERATION);
} else {
v[axis] = Math.max(
0.5 * (-MAX_DISPLACEMENT - p[axis]),
v[axis] - ACCELERATION);
}
p[axis] += v[axis];
}
},
};
function random_point(xd, yd) {
return [
(2 * Math.random() - 1) * xd,
(2 * Math.random() - 1) * yd
]
}
function bezier_period(points) {
const [p0, p1, p2, p3] = points;
const upper = Math.hypot(p3[0] - p2[0], p3[1] - p2[1]) + Math.hypot(p2[0] - p1[0], p2[1] - p1[1]) + Math.hypot(p1[0] - p0[0], p1[1] - p0[1]);
const lower = Math.hypot(p3[0] - p0[0], p3[1] - p0[1]);
return (upper + lower) / 2;
}
function next_random_bezier(b, xd, yd) {
const [,, p2, p3] = b.points;
let control1 = [
Math.max(-xd, Math.min(xd, 2 * p3[0] + p2[0])),
Math.max(-yd, Math.min(yd, 2 * p3[1] + p2[1])),
];
const points = [
p3,
control1,
random_point(xd, yd),
random_point(xd, yd),
]
const period = bezier_period(points);
return {
points,
t: 0,
period,
}
}
function random_bezier(start, xd, yd) {
const points = [
start,
random_point(xd, yd),
random_point(xd, yd),
random_point(xd, yd),
];
...