Published
Edited
Dec 3, 2019
Insert cell
Insert cell
Insert cell
viewof scale = slider({min: 1, max: 10, value: 5, step: 1, title: "ball size"});
Insert cell
viewof speed = slider({min: 5, max: 50, value: 1, step: 1, title: "ball speed"});
Insert cell
Insert cell
Insert cell
mutable xPaddle = 0
Insert cell
viewof paddleLength = slider({min: 20, max: 700, value: 100, step: 10, title: "paddle length"})
Insert cell
canvas.canvas.onmousemove = e => {
// mutable xPaddle = (e.offsetX <= w - paddleLength) ? e.offsetX : w - paddleLength;
if (e.offsetX <= paddleLength/2) {
mutable xPaddle = 0;
} else if (e.offsetX > paddleLength/2 && w - e.offsetX > paddleLength/2) {
mutable xPaddle = e.offsetX - paddleLength/2;
} else {
mutable xPaddle = w - paddleLength;
}
}
Insert cell
viewof canvas = {
const c = DOM.context2d(w, h);
c.canvas.value = c;
return c.canvas;
}
Insert cell
mutable ball = ({x: w/2, y: h-scale, r: scale, xSpeed: speed, ySpeed: speed})
Insert cell
b
Insert cell
reverse = {
b;
return !this;
}
Insert cell
gameloop = {

let { x, y, r, xSpeed, ySpeed} = mutable ball;

while (true) {
// moving
if (reverse) {
x = x + xSpeed;
y = y + ySpeed;

} else {
x = x - xSpeed;
y = y - ySpeed;

}
function pauseBall(duration) {
mutable ball = {x, y, r, xSpeed, ySpeed};
return Promises.delay(1000, mutable ball);
}
// reverse direction conditions
if ( x - r < 0) {
xSpeed = -xSpeed; // xSpeed = Math.abs(xSpeed)
// mutable ball = {x, y, r, xSpeed, ySpeed};
// yield Promises.delay(1000, true);
yield pauseBall(1000);
}
if ( x + r > w) {
xSpeed = -xSpeed; // xSpeed = -Math.abs(xSpeed)
// mutable ball = {x, y, r, xSpeed, ySpeed};
// yield Promises.delay(1000, false);
yield pauseBall(1000);
}
if ( y + r > h) {
ySpeed = -ySpeed;
// mutable ball = {x, y, r, xSpeed, ySpeed};
// yield Promises.delay(1000, mutable ball);
yield pauseBall(1000);
}
if ( y - r < 0) {
ySpeed = -ySpeed;
// mutable ball = {x, y, r, xSpeed, ySpeed};
// yield Promises.delay(1000, mutable ball);
yield pauseBall(1000);
}
mutable ball = {x, y, r, xSpeed, ySpeed}
// return mutable ball
yield false
}


}
Insert cell
gameloop
Insert cell
drawing = {
gameloop
const {x, y, r} = mutable ball;
// let {x, y, r} = ball;
canvas.fillStyle = "purple";
canvas.fillRect(0, 0, w, h);
canvas.beginPath();
canvas.fillStyle = "red";
canvas.arc(x, y, r, 0, 2 * Math.PI);
canvas.fill();
// inspection info
canvas.fillStyle = "green";
if (x - r < 0) {
// canvas.strokeText(50);
canvas.font = '30px serif';
canvas.fillText(`x - r = ${x - r} < 0, ${x - r < 0}`, w/2, h/2);
}
if (x + r > w) {
canvas.font = '30px serif';
canvas.fillText(`x + r = ${x + r} > ${w}, ${x + r > w}`, w/2, h/2);
}
if (y + r > h) {
canvas.font = '30px serif';
canvas.fillText(`y + r = ${y + r} > ${h}, ${y + r > h}`, w/2, h/2);
}
if (y - r < 0) {
canvas.font = '30px serif';
canvas.fillText(`y - r = ${y - r} > 0, ${y - r < 0}`, w/2, h/2);
}
// draw paddle
canvas.fillStyle = "cyan";
canvas.fillRect(xPaddle, h - scale, paddleLength, scale);
}
Insert cell
import { slider, videoyt, button} from "@embracelife/tutorial-utilities"
Insert cell
FileAttachment("visualizer.png").image()
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more