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: