VIDEO
At Zaitronics, we've recently built an upgraded version of a Raspberry Pi Pico 2, called Nexus RP2350 LiPo, with the intension of being a drop in replacement for any existing Pico projects. To demonstrate the board's capabilities, I've designed a simple Space Dodger game which requires very few parts most makers should have. For this version, we used a 1.3 inch OLED from Waveshare, but any similar small display should work with slight adjustments in the code.
Parts List:
Wiring (if you are not using the Nexus + OLED stack)
OLED Pin
RP2350 / Pico Pin
VCC
3.3 V
GND
GND
SCK
GP10
MOSI
GP11
DC
GP8
RST
GP12
CS
GP9
Button
RP2350 / Pico Pin
Button A (UP
GP15 + GND (internal pull-up used)
Button B DOWN
GP17 + GND (internal pull-up used)
How to Play
Button A (GP15) → move ship UP
Button B (GP17) → move ship DOWN
Avoid the white squares coming from the right
Your score is survival time + 10 points per dodged ball
The game gets faster the longer you survive
Tweaking Difficulty
Variable
Effect
Suggested range
ball_speed = 1.8
Starting speed
1.2 – 2.5
speed_increment
How quickly it accelerates
0.0005 – 0.002
Spawn chance line
How often new balls appear
0.02 – 0.06
Ball size in loop
6×6 is good visibility
4–8
Complete Ready-to-Flash Code (MicroPython)
Copy the entire code below into Thonny (or any MicroPython IDE) and save as main.py on your board.
from machine import Pin, SPI
import framebuf, time, random
# Display pins
DC = 8
RST = 12
MOSI = 11
SCK = 10
CS = 9
# Button pins
keyA = Pin (15 , Pin.IN, Pin.PULL_UP)
keyB = Pin (17 , Pin.IN, Pin.PULL_UP)
# OLED driver class (same as yours)
class OLED_1inch3 (framebuf.FrameBuffer):
def __init__(self):
self.width = 128
self.height = 64
self.rotate = 0
self.cs = Pin (CS, Pin.OUT)
self.rst = Pin (RST, Pin.OUT)
self.cs (1 )
self.spi = SPI (1 , 20000000 , polarity=0 , phase=0 , sck=Pin (SCK), mosi=Pin (MOSI), miso=None)
self.dc = Pin (DC, Pin.OUT)
self.dc (1 )
self.buffer = bytearray (self.height * self.width // 8)
super ().__init__(self.buffer, self.width, self.height, framebuf.MONO_HMSB)
self.init_display ()
self.white = 0xffff
self.balck = 0x0000
def write_cmd (self, cmd):
self.cs (1 )
self.dc (0 )
self.cs (0 )
self.spi.write (bytearray ([cmd]))
self.cs (1 )
def write_data (self, buf):
self.cs (1 )
self.dc (1 )
self.cs (0 )
self.spi.write (bytearray ([buf]))
self.cs (1 )
def init_display (self):
self.rst (1 )
time.sleep (0.001 )
self.rst (0 )
time.sleep (0.01 )
self.rst (1 )
for cmd in (
0xAE , 0x00 , 0x10 , 0xB0 , 0xDC , 0x00 , 0x81 , 0x6F , 0x21 ,
0xA1 if self.rotate == 180 else 0xA0 ,
0xC0 , 0xA4 , 0xA6 , 0xA8 , 0x3F , 0xD3 , 0x60 , 0xD5 , 0x41 ,
0xD9 , 0x22 , 0xDB , 0x35 , 0xAD , 0x8A , 0xAF
):
self.write_cmd (cmd)
def show (self):
self.write_cmd (0xB0 )
for page in range (0 , 64 ):
self.column = page if self.rotate == 180 else 63 - page
self.write_cmd (0x00 + (self.column & 0x0F ))
self.write_cmd (0x10 + (self.column >> 4 ))
for num in range (0 , 16 ):
self.write_data (self.buffer[page * 16 + num])
# Initialize display
OLED = OLED_1inch3 ()
# Ball list: each ball is [x, y]
balls = []
# Spaceship position
ship_x = 0
ship_y = 28
ship_w = 6
ship_h = 6
# Draw spaceship
def draw_ship (x, y, scale=2 ):
"" "
Draw the spaceship pattern at (x, y)
scale: how many screen pixels per pattern pixel
" ""
pattern = [
"00000000000" ,
"000xxx00000" ,
"0000xxxx000" ,
"xxxxxxxxx00" ,
"00xxx00xxx0" ,
"0xxxx000xxx" ,
"00xxx00xxx0" ,
"xxxxxxxxx00" ,
"0000xxxx000" ,
"000xxx00000" ,
"00000000000" ,
]
for row_idx, row in enumerate (pattern):
for col_idx, pixel in enumerate (row):
if pixel == "x" :
OLED.fill_rect (x + col_idx*scale, y + row_idx*scale, scale, scale, OLED.white)
import time
# Game variables
score = 0
ball_speed = 2 # initial speed of balls
speed_increment = 0.05 # increase speed over time
start_time = time.ticks_ms () # start timer
# Main loop
while True:
OLED.fill (0 ) # clear screen
# Update score based on elapsed time
elapsed_ms = time.ticks_diff (time.ticks_ms (), start_time)
score = elapsed_ms // 100 # roughly increments every 0.1 second
# Display score
OLED.text ("Score: {}" .format(score), 0 , 0 )
# Move spaceship up/down
if keyA.value () == 0 : # up
ship_y = max (0 , ship_y - 2 )
if keyB.value () == 0 : # down
ship_y = min (OLED.height - ship_h*2 , ship_y + 2 ) # scale=2
# Randomly spawn a new ball on the right
if random.random () < 0.05 : # reduce spawn rate for balance
y = random.randint (0 , OLED.height - 4 )
balls.append ([127 , y])
# Draw and update balls
new_balls = []
for ball in balls:
x, y = ball
OLED.fill_rect (x, y, 4 , 4 , OLED.white) # 4 x4 ball
x -= int (ball_speed) # move left
if x > 0 :
new_balls.append ([x, y])
balls = new_balls
# Gradually increase speed
ball_speed += speed_increment / 50 # slow acceleration
# Draw spaceship
draw_ship (ship_x, ship_y)
OLED.show ()
time.sleep (0.05 )
Additional Resources
Full Driver & Examples : Check the Waveshare wiki for the original MicroPython library: https://www.waveshare.com/wiki/Pico-OLED-1.3 (includes C/C++ too).
Customization Ideas : Modify the ship pattern, add a buzzer on GP16 for collision sounds, or implement high-score saving to onboard flash.