Skip to content

Instantly share code, notes, and snippets.

@samneggs
Created January 16, 2023 02:46
Show Gist options
  • Select an option

  • Save samneggs/18c8690206cb1f33b5b9761e4b341dec to your computer and use it in GitHub Desktop.

Select an option

Save samneggs/18c8690206cb1f33b5b9761e4b341dec to your computer and use it in GitHub Desktop.
Breakout game in MicroPython on Pi Pico with help from ChatGPT.
# Breakout game
from machine import Pin,SPI,PWM,ADC
import framebuf, gc
import time, array, _thread
from time import sleep, ticks_us, ticks_diff
from lcd_1_8 import LCD_1inch8
from random import randint
from sys import exit
MAXSCREEN_X = const(160)
MAXSCREEN_Y = const(128)
class Player():
def __init__(self):
self.x = 80
self.y = 127
self.length = 30
self.lives = 3
self.score = 0
player=Player()
class Ball():
def __init__(self):
self.x = player.x + player.length //2
self.y = 120
self.dx = -1
self.dy = -1
self.radius = 5
class Block:
def __init__(self, x, y, width, height, hits_needed, color, row):
self.x = x
self.y = y
self.width = width
self.height = height
self.hits_needed = hits_needed
self.current_hits = 0
self.color = color # default color of the block
self.row = row
def draw(self):
# Draw the block on the screen using the x, y, width, and height properties
LCD.fill_rect(self.x, self.y, self.width, self.height, self.color)
def hit(self):
global num_blocks
# Update the current_hits property and check if the block is broken
self.current_hits += 1
num_blocks -= 1
if self.current_hits >= self.hits_needed:
# remove the block from the game
pass
else:
# change color of the block
self.color = 0x7777 # change the color of the block when it's hit
def init_blocks():
global blocks,colors,num_blocks, score
num_blocks_column = 9
num_blocks_row = 5
block_width = 15
block_height = 5
block_hits_needed = 1
num_blocks = num_blocks_column * num_blocks_row
score = [9,7,5,3,1]
red = 0x00F8
orange = 0x20FD
yellow = 0xE0FF
green = 0xE007
blue = 0x1F00
colors = [red, orange, yellow, green, blue]
blocks = [[Block((block_width + 2) * column + 2, (block_height + 2) * row + 2, block_width, block_height, block_hits_needed, colors[row], row) for column in range(num_blocks_column)] for row in range(num_blocks_row)]
for row in blocks:
for block in row:
block.draw()
LCD.show()
def init_joystick():
global POT_X,POT_Y,POT_X_ZERO,POT_Y_ZERO
POT_X = machine.ADC(27)
POT_Y = machine.ADC(26)
POT_X_ZERO = 0
POT_Y_ZERO = 0
for i in range(1000):
POT_X_ZERO += POT_X.read_u16()
POT_Y_ZERO += POT_Y.read_u16()
POT_X_ZERO = POT_X_ZERO//1000
POT_Y_ZERO = POT_Y_ZERO//1000
pot_scale = 12
def read_joystick():
pot_scale = 13
x_inc = int(POT_X.read_u16() - POT_X_ZERO)>>pot_scale
y_inc = int(POT_Y.read_u16() - POT_Y_ZERO)>>pot_scale
if int(abs(x_inc))<2:
x_inc=0
if int(abs(y_inc))<2:
y_inc=0
player.x -= x_inc
if player.x < 0:
player.x = 0
if player.x > MAXSCREEN_X - player.length:
player.x = MAXSCREEN_X - player.length
def init_ball():
global ball
ball = Ball()
show_score()
while fire.value():
LCD.fill_rect(0,70,160,128-70,0)
read_joystick()
ball.x = player.x + player.length //2
draw()
LCD.show()
def show_score():
LCD.fill(0)
draw()
LCD.text('Score '+ str(player.score),30,40,0xffff)
LCD.text('Lives left '+ str(player.lives),30,55,0xffff)
LCD.show()
def move_ball():
global SOUND
ball.x += ball.dx
ball.y += ball.dy
if ball.x > MAXSCREEN_X-ball.radius:
ball.x = MAXSCREEN_X-ball.radius
ball.dx = -ball.dx
if ball.x < ball.radius:
ball.x = ball.radius
ball.dx = -ball.dx
if ball.y > MAXSCREEN_Y-ball.radius: # miss ball
player.lives -= 1
if player.lives == 0:
end_of_game()
return
SOUND = 3
init_ball()
if ball.y < ball.radius:
ball.y = ball.radius
ball.dy = -ball.dy
def draw():
for row in blocks:
for block in row:
block.draw()
LCD.ellipse(ball.x,ball.y,ball.radius,ball.radius,0xffFF,True)
LCD.line(player.x,player.y,player.x+player.length,player.y,0xffff)
def check_collision_ball():
global SOUND
if (ball.x+ball.radius >= player.x) and (ball.x-ball.radius <= player.x + player.length) and (ball.y >= player.y - ball.radius):
ball.dy = -ball.dy
ball.y -= 1
SOUND = 2
def check_collision_block():
global SOUND
for row in blocks:
for block in row:
if (ball.x + ball.radius >= block.x) and (ball.x - ball.radius <= block.x + block.width) and (ball.y + ball.radius >= block.y) and (ball.y - ball.radius <= block.y + block.height):
ball.dy = -ball.dy
block.hit()
if block.hits_needed == block.current_hits:
row.remove(block)
player.score += score[block.row]
SOUND = 1
if num_blocks == 0:
end_of_level()
def end_of_level():
global SOUND
init_blocks()
init_ball()
SOUND = 4
def end_of_game():
global SOUND, player
SOUND = 5
LCD.fill(0)
draw()
LCD.text('Score '+ str(player.score),30,40,0xffff)
LCD.text('Game Over',30,55,0xffff)
LCD.show()
while fire.value():
pass
init_blocks()
player=Player()
init_ball()
def sound_block_hit():
volume = 2000
tone = 1000
power.on()
Buzz.duty_u16(volume)
Buzz.freq(tone)
for delay in range(10000):
pass
power.off()
def sound_paddle_hit():
volume = 2000
tone = 500
power.on()
Buzz.duty_u16(volume)
Buzz.freq(tone)
for delay in range(10000):
pass
power.off()
def sound_paddle_miss():
volume = 2000
tone = 100
power.on()
Buzz.duty_u16(volume)
Buzz.freq(tone)
for delay in range(30000):
pass
power.off()
def play_pacman_theme():
power.on()
notes= [493, 987, 739, 587,987, 739, 587, 523,1047, 830, 659, 523, 659, 523,
493, 987, 739, 587, 987,739, 587, 622, 698, 740, 784, 830, 830, 880, 932, 987]
duration = [16, 16, 16, 16,32, 16, 8, 16,16, 16, 16, 32, 16, 8,16, 16, 16, 16, 32,16, 8, 32, 32, 32,32, 32, 32, 32, 32, 16, 8]
for i in range(len(notes)):
Buzz.duty_u16(1000)
Buzz.freq(notes[i])
time.sleep(2.5/duration[i])
power.off()
def play_underworld():
power.on()
notes = [261, 523, 220, 440, 233, 466, 0,0,261, 523, 220, 440, 233, 466, 0,
0, 349, 698, 293, 587, 311, 622, 0, 0, 349, 698, 293, 587, 311, 622, 0,
0, 622, 277, 587, 554, 622, 622, 196, 185, 277, 261, 369,349, 329, 233, 440,
415, 622, 247, 233, 220, 196, 0, 0, 0 ]
duration = [12, 12, 12, 12, 12, 12, 6, 3, 12, 12, 12, 12, 12, 12, 6,
3, 12, 12, 12, 12, 12, 12, 6, 3, 12, 12, 12, 12, 12, 12, 6, 6, 18, 18, 18,
6, 6, 6, 6, 6, 6, 18, 18, 18,18, 18, 18, 10, 10, 10, 10, 10, 10, 3, 3, 3]
for i in range(len(notes)):
Buzz.duty_u16(1000)
n = notes[i]
if n>0:
Buzz.freq(notes[i])
time.sleep(2/duration[i])
power.off()
def sound_thread():
global SOUND
sleep(1)
while(1):
if SOUND==1:
sound_block_hit()
if SOUND==1:
SOUND = 0
if SOUND==2:
sound_paddle_hit()
if SOUND==2:
SOUND = 0
if SOUND==3:
sound_paddle_miss()
if SOUND==3:
SOUND = 0
if SOUND==4:
play_pacman_theme()
if SOUND==4:
SOUND = 0
if SOUND==5:
play_underworld()
if SOUND==5:
SOUND = 0
if __name__=='__main__':
fire = Pin(22, Pin.IN, Pin.PULL_UP)
power = Pin(16, machine.Pin.OUT)
Buzz = machine.PWM(Pin(17, machine.Pin.OUT))
pwm = PWM(Pin(13))
pwm.freq(1000)
pwm.duty_u16(0x7fff)#max 65535
LCD = LCD_1inch8()
SOUND = 4
_thread.start_new_thread(sound_thread, ())
init_joystick()
init_blocks()
init_ball()
while(1):
LCD.fill(0)
read_joystick()
move_ball()
check_collision_ball()
check_collision_block()
draw()
LCD.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment