基于树莓派RP2040实现拼图游戏的移植报告
项目介绍:该项目采用树莓派Pico核心芯片RP2040,有上位机中用Thony进行代码编译,经USB串口输入芯片内,实现游戏--拼图的移植。代码采用MicroPython语言进行编写,借用了在电脑上实现拼图游戏的部分代码结构,以及编写思维,将其转成适合与板卡手柄相连接操作的代码。最终实现在板卡机上简易的9*9拼图游戏。
设计思路:
硬件介绍:
(1)采用树莓派Pico核心芯片RP2040,双核Arm Cortex M0+内核,可以运行到133MHz;264KB内存;性能强大、高度灵活的可编程IO可用于高速数字接口;片内温度传感器、并支持外部4路模拟信号输入,内部ADC采样率高达500Ksps、12位精度;支持MicroPython、C、C++编程
(2)
板上功能:240*240分辨率的彩色IPS LCD,SPI接口,控制器为ST7789;四向摇杆 + 2个轻触按键 + 一个三轴姿态传感器MMA7660用做输入控制;板上外扩2MB Flash,预刷MicroPython的UF2固件;一个红外接收管 + 一个红外发射管;一个三轴姿态传感器MMA7660;一个蜂鸣器;双排16Pin连接器,有SPI、I2C以及2路模拟信号输入;可以使用MicroPython、C、C++编程;USB Type C连接器用于供电、程序下载
实现功能:用摇杆遥控黑块进行左右移动,最后完成拼图。
图片展示:
主要代码:
#头文件
import uos
import machine
from machine import Pin, SPI, ADC
import st7789 as st7789
#from fonts import vga2_8x8 as font1
#from fonts import vga1_16x32 as font2
import random
import framebuf
import time
# 设置画布尺寸
w = 240
h = 240
buf=[[None]*3]*240
st7789_res = 0
st7789_dc = 1
spi_sck=machine.Pin(2)
spi_tx=machine.Pin(3)
spi0=machine.SPI(0,baudrate=4000000, phase=1, polarity=1, sck=spi_sck, mosi=spi_tx)
#
display = st7789.ST7789(spi0, w, w,
reset=machine.Pin(st7789_res, machine.Pin.OUT),
dc=machine.Pin(st7789_dc, machine.Pin.OUT),
xstart=0, ystart=0, rotation=0)
image_file0 = "logo.bin" #图片文件地址
#
xAxis = ADC(Pin(29))
yAxis = ADC(Pin(28))
# 定义图像块的边长
image_size = w / 3
# 定义图像块坐标列表
all_coordinates = [[image_size * 0.5, image_size * 0.5], [image_size * 1.5, image_size * 0.5],
[image_size * 2.5, image_size * 0.5], [image_size * 0.5, image_size * 1.5],
[image_size * 1.5, image_size * 1.5], [image_size * 2.5, image_size * 1.5],
[image_size * 0.5, image_size * 2.5], [image_size * 1.5, image_size * 2.5],
[image_size * 2.5, image_size * 2.5]
]
# 棋盘的行列
row = 3
col = 3
# 保存所有图像块的列表
board = [[None, None, None], [None, None, None], [None, None, None]]
# 定义一个图像块的类
class Square:
# 定义一个构造函数,用于初始化
def __init__(self, coordinate):
self.center = coordinate
self.isblack = False
mp = [[None, None, None], [None, None, None], [None, None, None]]
def drawall():
for i in range(3):
for j in range(3):
if board[i][j].isblack:
mp[i][j]=2,2
continue
for k in range(3):
for h in range(3):
if board[i][j].center== [h*80+40, k*80+40]:
mp[i][j]=k,h
#
#print(board[i][j].center,i,j)
f_image = open(image_file0, 'rb')
display.fill(st7789.BLACK)
#print(mp[0][1],i,j)
for i in range(240):
for j in range(3):
if board[i//80][j].isblack:
buf[i][j]=f_image.read(240//3*2)
#display.blit_buffer(buf[i][j], b*80+1, i-i//80*80+a*80+1, 80, 1)
#print(buf[i][j])
continue
[a,b]=mp[i//80][j]
#print(a,b,i//80,j,i)
buf[i][j]=f_image.read(240//3*2)
#if i//80==2 and j==2:
#break
display.blit_buffer(buf[i][j], b*80+1, i-i//80*80+a*80+1, 80, 1)
# 定义一个方法进行拼接
def init_board():
# 打乱图像
# 填充并且拼接图版
for i in range(row):
for j in range(col):
idx = i * row + j
squar_center = all_coordinates[idx]
if idx==8:
board[i][j] = Square(squar_center)
board[i][j].isblack = True
else:
board[i][j] = Square(squar_center)
board[i][j].isblack = False
for t in range(99):
i=random.randrange(3)
j=random.randrange(3)
k=random.randrange(3)
h=random.randrange(3)
#i,j,k,h=2,2,2,1
board[i][j].center,board[k][h].center= board[k][h].center, board[i][j].center
#判断对错
def is_right():
for i in range(row):
for j in range(col):
print(board[i][j].center,[i*80+40,j*80+40])
if board[i][j].center != [j*80+40,i*80+40]:
return False
return True
#摇杆控制左右
def dir_select():
xValue = xAxis.read_u16()
yValue = yAxis.read_u16()
for i in range(3):
for j in range(3):
if board[i][j].isblack:
x,y=board[i][j].center
for k in range(3):
for h in range(3):
if k ==i and h==j:
continue
if [x-80,y]==board[k][h].center and xValue<15000:
board[i][j].center,board[k][h].center= board[k][h].center, board[i][j].center
print(1,x,y,k,h,board[k][h].center, board[i][j].isblack)
elif [x+80,y]==board[k][h].center and xValue>45000:
print(2,x,y,k,h,board[k][h].center, board[i][j].isblack)
board[i][j].center,board[k][h].center= board[k][h].center, board[i][j].center
elif [x,y-80]==board[k][h].center and yValue<15000:
print(3,x,y,k,h,board[k][h].center, board[i][j].isblack)
board[i][j].center,board[k][h].center= board[k][h].center, board[i][j].center
elif [x,y+80]==board[k][h].center and yValue>45000:
print(4,x,y,k,h,board[k][h].center, board[i][j].isblack)
board[i][j].center,board[k][h].center= board[k][h].center, board[i][j].center
#director = snake.DOWN
def main():
init_board()
drawall()
while True:
if is_right():
for i in range(3):
for j in range(3):
if board[i][j].isblack:
mp[i][j]=2,2
continue
for k in range(3):
for h in range(3):
if board[i][j].center== [h*80+40, k*80+40]:
mp[i][j]=k,h
f_image = open(image_file0, 'rb')
for i in range(240):
for j in range(3):
[a,b]=mp[i//80][j]
buf[i][j]=f_image.read(240//3*2)
display.blit_buffer(buf[i][j], b*80+1, i-i//80*80+a*80+1, 80, 1)
break
dir_select()
drawall()
time.sleep(2)
main()
遇到的主要难题:主要是图片的读入和画出以及黑色块左右移动问题。图片读入和画出最后通过计算坐标的方式解决,黑块的移动通过刷黑全屏然后通过交换两个位置的坐标再刷黑得到解决。
未来的建设:还有两个按键没被用上,就是A,B键,以及游戏没有好看的载入页面和音乐,希望后期能不断完善吧