This is an implementation of the vintage Atari game called Breakout.
Connect:
- Buzzer Brick to Port 2C
- Rotary Switch Brick to Port 2A and 4A
- OLED Display Brick to Port 4E
Run the following script:
var bricks = [], ball_x, ball_y, ball_xv, ball_yv, bat_pos;
var screen = new OledDisplay();
var buzzer = new Buzzer(PORT_2C);
var rsw = new RotarySwitch(PORT_2A, PORT_4A);
while(true) {
init_game();
wait_start();
draw_arena();
while(true) {
screen.startBuffer();
move_bat();
var game_ended = move_ball();
screen.flushBuffer();
if (game_ended) break;
else if (game_won()) {
wait_win();
break;
}
}
}
function init_game() {
for(var b=0; b<6*25; b++) bricks[b] = true;
ball_x = Math.floor(screen.width()/2 + random(-screen.width()/4, screen.width()/4));
ball_y = Math.floor(screen.height()*3/4);
ball_xv = 1;
ball_yv = -1;
bat_pos = screen.width()/2;
}
function wait_start() {
var last_time = Date.now();
while(true) {
screen.clear();
var t = Date.now();
while(Date.now() - t < 500) if (rsw.clicked()) return;
screen.setFont(FONT_NORMAL);
screen.drawString(15, 25, "Press button");
screen.drawString(35, 45, "to start");
t = Date.now(0);
while(Date.now() - t < 500) if (rsw.clicked()) return;
}
}
function wait_win() {
var music = true;
while(true) {
screen.clear();
var t = Date.now();
while(Date.now() - t < 500) if (rsw.clicked()) return;
screen.setFont(FONT_LARGE);
screen.drawString(5, 2, "YOU WIN!");
if (!music) {
music = true;
for (var i=0; i<3; i++) buzzer.playNote(NOTE_E, 5, 150); delay(10);
buzzer.playNote(NOTE_C, 5, 500);
}
t = Date.now();
while(Date.now() - t < 500) if (rsw.clicked()) return;
}
}
function draw_arena() {
screen.startBuffer();
screen.clear();
// Draw walls
screen.drawLine(0, 0, 127, 0);
screen.drawLine(0, 0, 0, 63);
screen.drawLine(127, 0, 127, 63);
// Draw bricks
for (var i=0; i<6*25; i++) draw_brick(i, COLOR_WHITE);
// Ball
screen.drawPixel(ball_x, ball_y);
// Bat
draw_bat(COLOR_WHITE);
screen.flushBuffer();
}
function draw_bat(color) {
screen.setColor(color);
screen.drawLine(bat_pos, 60, bat_pos + 10, 60);
}
function move_bat() {
draw_bat(COLOR_BLACK);
bat_pos += rsw.getDelta()*4;
bat_pos = Math.min(Math.max(bat_pos, 0), 116);
draw_bat(COLOR_WHITE);
}
function move_ball() {
var b = -1, hit = false;
// Depending on which direction the ball hits the brick, adjust xv and yv accordingly
if (((ball_x - 2) % 5 == 0) && ((ball_y - 14) % 3 == 0)) {
b = which_brick(ball_x + ball_xv, ball_y + ball_yv);
if (b > -1 && bricks[b]) {
ball_xv = -ball_xv;
ball_yv = -ball_yv;
}
}
else if ((ball_x - 2) % 5 == 0) {
b = which_brick(ball_x + ball_xv, ball_y);
if(b > -1 && bricks[b]) ball_xv = -ball_xv;
}
else if ((ball_y - 14) % 3 == 0) {
b = which_brick(ball_x, ball_y + ball_yv);
if (b > -1 && bricks[b]) ball_yv = -ball_yv;
}
// Remove brick that was hit
if (b != -1 && bricks[b]) {
hit = true;
bricks[b] = false;
draw_brick(b, COLOR_BLACK);
}
// Move ball to new position
screen.setColor(COLOR_BLACK);
screen.drawPixel(ball_x, ball_y);
ball_x += ball_xv;
ball_y += ball_yv;
screen.setColor(COLOR_WHITE);
screen.drawPixel(ball_x, ball_y);
// Check if we hit the walls and adjust xv and yv accordingly
if (ball_x <= 1 || ball_x >= 128-2) {
hit = true;
ball_xv = -ball_xv;
}
if (ball_y <=1 || (ball_y == 59 && (ball_x >= bat_pos && ball_x <= bat_pos+10))) {
hit = true;
ball_yv = -ball_yv;
}
// If the ball hit something, play hit tone
if (hit) buzzer.playTone(200, 50);
// If ball is out of play, play death tone and return true to signal end of game
if (ball_y >= 80) {
for (var t=500; t>=10; t-=10) buzzer.playTone(t, 20);
return true;
}
// Return false to signal game is still in play
return false;
}
// Given (x,y) coordinates, figure out which brick was hit
function which_brick(x, y) {
var brick_x = Math.floor((x - 2) / 5);
var brick_y = Math.floor((y - 14) / 3);
if (brick_y > 5 || brick_y < 0) return -1;
if (brick_x > 24) brick_x = 24;
return (brick_y * 25) + brick_x;
}
// Draw given brick in given color
function draw_brick(b, color) {
var r = Math.floor(b / 25);
var c = b % 25;
screen.setColor(color);
screen.drawLine(c*5 + 2, r*3 + 14, c*5 + 5, r*3 + 14);
screen.drawLine(c*5 + 2, r*3 + 15, c*5 + 5, r*3 + 15);
}
// Game is won if all bricks are out of play
function game_won() {
for (var b=0; b<6*25; b++) if (bricks[b]) return false;
return true;
}
Here's how it looks in play: