Published
Edited
Nov 29, 2019
Insert cell
Insert cell
Insert cell
viewof newGame = button("new game");
Insert cell
Insert cell
colors = ["#c84848", "#c66c3a", "#b47a2f", "#a2a229", "#49a049", "#4348c8"]; // array of colors
Insert cell
bricks = {
newGame;
const rows = 6;
const columns = Math.floor(w / 50);
const padding = 3, top = 70;
const width = (w - (columns + 1) * padding - 2 * scale) / columns
let bricks = new Array(rows).fill(1).map(() => new Array(columns).fill(1));
eachBrick(bricks, (brick, row, col) => {
bricks[row][col] = {
w: width,
h: scale,
x: scale + padding * (col + 1) + col * width,
y: top + (scale + padding) * row,
color: colors[row]
}
});

return bricks;
}
Insert cell
function eachBrick(bricks, cb) {
for (let row = 0; row < bricks.length; row++) {
for (let col = 0; col < bricks[row].length; col++) {
let brick = bricks[row][col];
if (!brick) continue; // continue: if current brick not exist, move onto next brick
if (cb(brick, row, col)) return; // if callback on the brick return true, then exit and leave the rest of bricks alone; if return undefined, keep working on the next brick
}
}
}
Insert cell
mutable gameover = {
newGame;
return false;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
mutable paddleX = w/2 - paddleLength/2;
Insert cell
mousemove = c.canvas.onmousemove = e => {
if ( paddleLength/2 + scale <= e.offsetX && e.offsetX <= w - paddleLength/2 - scale ) {
mutable paddleX = e.offsetX - paddleLength/2
} else if ( paddleLength/2 + scale > e.offsetX ) {
mutable paddleX = scale
} else {
mutable paddleX = w - paddleLength - scale
}

}
Insert cell

mutable ball = {
newGame;
return {r: scale, x: w/2, y: h - 2*scale, xSpeed: speed, ySpeed: -speed};

}
Insert cell
gameloop = {
let n = 0;
let {r, x, xSpeed, y, ySpeed} = mutable ball;
function pauseBall(duration){
mutable ball = {r, x, y, xSpeed, ySpeed}
return Promises.delay(duration, mutable ball)
}
while (!mutable gameover) {
x = x + xSpeed;
y = y + ySpeed;

if (x < r + scale) {
xSpeed = Math.abs(xSpeed);
// yield pauseBall(1000);

}
if (x + r > w - scale) {
xSpeed = -Math.abs(xSpeed);
// yield pauseBall(1000);
}
if (y < r + scale) {
ySpeed = Math.abs(ySpeed);
// yield pauseBall(1000);
}
if (y + r > h) {
ySpeed = -Math.abs(ySpeed);
// yield pauseBall(0);
}
mutable ball = {r, x, y, xSpeed, ySpeed};
let px = mutable paddleX;
if (y + r > h - scale
&& x + r > px
&& x - r < px + paddleLength) {
yield pauseBall(0);

ySpeed = -ySpeed;
xSpeed = ((x - px) / paddleLength - 0.5) * Math.PI * speed;
}
if ( y + r > h ) {
mutable gameover = true;
yield pauseBall(3000);
}
yield true;
}
}
Insert cell
draw = {
gameloop;
c.fillStyle="black";
c.fillRect(0,0,w,h);
// draw the thick walls
c.fillStyle = "#444";
c.fillRect(0, 0, w, scale);
c.fillRect(0, 0, scale, h);
c.fillRect(w-scale, 0, scale, h);
// draw the bricks
eachBrick(bricks, (brick, row, col) => {
c.fillStyle = brick.color;
c.fillRect(brick.x, brick.y, brick.w, brick.h);
});
const {r, x, y} = mutable ball;
c.beginPath();
c.fillStyle = "red";
c.arc(x, y, r, 0, 2 * Math.PI);
c.fill();
// c.fillStyle = "green"
// c.font = "15px Arial"
// if ( y + r > h ) c.fillText(`y + r > h : ${y + r > h} gameover: ${gameover}`, (x < w/2)? x + 20 : x - 170, y - 20);

c.fillStyle = "blue";
c.fillRect(mutable paddleX,
h - scale,
paddleLength,
scale);
c.fillStyle = "cyan";
c.fillRect(mutable paddleX, h - scale, 2, 2)


}
Insert cell
videoyt("Aznz6oLbuFQ")
Insert cell
import {videoyt, slider, button} from "@embracelife/tutorial-utilities"
Insert cell
FileAttachment("chart.svg").image()
Insert cell
FileAttachment("chart.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