Created
January 16, 2023 02:46
-
-
Save samneggs/18c8690206cb1f33b5b9761e4b341dec to your computer and use it in GitHub Desktop.
Breakout game in MicroPython on Pi Pico with help from ChatGPT.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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