Skip to content

Instantly share code, notes, and snippets.

@jeiting
Created February 15, 2026 11:42
Show Gist options
  • Select an option

  • Save jeiting/22ef83a265bf5e22de0a8454fe5983b0 to your computer and use it in GitHub Desktop.

Select an option

Save jeiting/22ef83a265bf5e22de0a8454fe5983b0 to your computer and use it in GitHub Desktop.
Airplane GameBoy Breakout
#include <stdint.h>
#include <stdio.h>
#include <gb/gb.h>
// Screen is 20 tiles across, 18 tiles tall
// Blocks should fill from 1,2 to 18, 9
uint8_t paddleSprite[] = {
0b00000000, 0b00000000,
0b00000000, 0b00000000,
0b00000000, 0b00000000,
0b11111111, 0b11111111,
0b11111111, 0b11111111,
0b00000000, 0b00000000,
0b00000000, 0b00000000,
0b00000000, 0b00000000
};
uint8_t blockSprite[] = {
0b00000000, 0b00000000,
0b00000000, 0b00000000,
0b00000000, 0b00000000,
0b01111110, 0b01111110,
0b01111110, 0b01111110,
0b00000000, 0b00000000,
0b00000000, 0b00000000,
0b00000000, 0b00000000
};
uint8_t ballSprite[] = {
0b00000000, 0b00000000,
0b00111100, 0b00111100,
0b01111110, 0b01111110,
0b01111110, 0b01111110,
0b01111110, 0b01111110,
0b01111110, 0b01111110,
0b00111100, 0b00111100,
0b00000000, 0b00000000
};
uint8_t blankTile[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t blockLayout[] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,
0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
uint8_t blankBlockLayout[] = {0x00};
int paddleX = 50;
int paddleY = 140;
int ballX, ballY;
int ballVx, ballVy;
void resetBall() {
ballX = paddleX-8;
ballY = paddleY-5;
ballVx = 0;
ballVy = 0;
}
void startBall() {
ballVx = rand() % 2 - 1; // 0, 1, 2 -> -1, 0, 1
ballVy = -2;
}
int checkPaddleCollision() {
if (ballVy < 0) return 0;
if (((ballY > 135) && ballY < (140 + 5))
&& (ballX > paddleX - 4) && (ballX < (paddleX + 8 + 4))) {
return 1;
} else {
return 0;
}
}
void main() {
SHOW_SPRITES;
SHOW_BKG;
// Load the paddle
set_sprite_data(0, 1, paddleSprite);
set_sprite_tile(0, 0);
// Load the ball
set_sprite_data(1, 1, ballSprite);
set_sprite_tile(1, 1);
// Load the background
set_bkg_data(0, 1, blankTile);
fill_bkg_rect(0, 0, DEVICE_SCREEN_WIDTH, DEVICE_SCREEN_HEIGHT, 0);
set_bkg_data(1, 1, blockSprite);
set_bkg_tiles(0, 0, DEVICE_SCREEN_WIDTH, DEVICE_SCREEN_HEIGHT, blockLayout);
set_bkg_tiles(2, 2, 1, 1, 0);
resetBall();
while (1) {
uint8_t joypadState = joypad();
if (joypadState & J_LEFT) paddleX -= 2;
if (joypadState & J_RIGHT) paddleX += 2;
move_sprite(0, paddleX, 140);
if (joypadState & J_A && ballVx == 0)
startBall();
if (ballVy != 0) {
// Check collisions
// Left and Right wall
if (ballX > 160) {
ballVx = -ballVx;
ballX = 160;
} else if (ballX < 8) {
ballVx = -ballVx;
ballX = 8;
}
// Top and bottom
if (ballY > 144+8) {
// You lose
resetBall();
} else if (ballY < 8) {
ballVy = -ballVy;
ballY = 8;
}
// Paddle
if (checkPaddleCollision()) {
ballVy = -ballVy;
}
// Check block collision
int blockX, blockY;
blockX = ballX / 8;
blockY = ballY / 8;
if (blockX > 0 && blockY > 0) {
uint16_t blockIndex = (blockY * 20 + blockX);
uint8_t block = blockLayout[blockIndex];
blockLayout[blockIndex] = 0x00;
set_bkg_tiles(blockX, blockY, 1, 1, blankBlockLayout);
// if (block == 0x01) {
// ballVy = -ballVy;
// ballVx = -ballVx;
// }
}
ballX += ballVx;
ballY += ballVy;
} else {
ballX = paddleX;
}
move_sprite(1, ballX, ballY);
while (!(joypad() & J_B)) {}
vsync();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment