基于树莓派rp2040实现单板接小球游戏移植
基于rp2040实现复古游戏移植,实现移植,用过按键和四向摇杆进行控制。
标签
嵌入式系统
2022寒假在家练
hum2037
更新2022-03-17
中央民族大学
1238

项目总结报告

一、项目介绍

本文基于树莓派rp2040嵌入式系统实现单板接小球游戏移植,小球碰撞游戏可以通过四向摇杆和按键实现游戏界面的控制,小球在墙上反弹实现无规律运动,通过四向摇杆控制单板的左右移动,小球碰板继续运动,掉落则视为游戏失败,A\B按键可以调整游戏的难易和背景音乐的开关。

二、硬件介绍

作为一个嵌入式系统的学习平台,首先要基于核心芯片的核心板的特点以及嵌入式系统的关键知识点来定义这款学习平台:

  • 采用树莓派Pico核心芯片RP2040:
    • 双核Arm Cortex M0+内核,可以运行到133MHz
    • 264KB内存
    • 性能强大、高度灵活的可编程IO可用于高速数字接口
    • 片内温度传感器、并支持外部4路模拟信号输入,内部ADC采样率高达500Ksps、12位精度
    • 支持MicroPython、C、C++编程
  • 板上功能:
    • 240*240分辨率的彩色IPS LCD,SPI接口,控制器为ST7789
    • 四向摇杆 + 2个轻触按键 + 一个三轴姿态传感器MMA7660用做输入控制
    • 板上外扩2MB Flash,预刷MicroPython的UF2固件
    • 一个红外接收管 + 一个红外发射管
    • 一个三轴姿态传感器MMA7660
    • 一个蜂鸣器
    • 双排16Pin连接器,有SPI、I2C以及2路模拟信号输入
    • 可以使用MicroPython、C、C++编程
    • USB Type C连接器用于供电、程序下载

 

三、实现的功能及图片展示/主要代码

def menu(self):
        if k3.value()==0:
            time.sleep_ms(20)
            if k3.value()==0:
                display.fill(st7789.BLACK)
                self.begin()
                self.statue=0
                return
        if k1.value()==0:
            time.sleep_ms(20)
            if k1.value()==0:
                self.umode=1
                if(self.key_mode==0):
                    self.key_mode=1
                else:
                    self.key_mode=0
        if self.key_mode==0:
            if self.umode==1:
                self.umode=0
                display.text(font2, "MUSIC:",30,100)
                display.text(font2, "MODE:",30,30,st7789.RED)
                self.ukey=1
                if self.music_mode==0:
                    display.text(font2, "Open",130,100)
                else:
                    display.text(font2, "Close",130,100)
            if k2.value()==0:
                time.sleep_ms(20)
                if k2.value()==0:
                    self.ukey=1
                    self.game_mode=self.game_mode+1
                    if self.game_mode==3:
                        self.game_mode=0
            
            if self.game_mode==0:
                if self.ukey==1:
                    self.ukey=0
                    display.text(font2, "Hard",130,30,st7789.BLACK)
                    display.text(font2, "Easy",130,30,st7789.RED)
            if self.game_mode==1:
                if self.ukey==1:
                    self.ukey=0
                    display.text(font2, "Easy",130,30,st7789.BLACK)
                    display.text(font2, "Normal",130,30,st7789.RED)
            if self.game_mode==2:
                if self.ukey==1:
                    self.ukey=0
                    display.text(font2, "Normal",130,30,st7789.BLACK)
                    display.text(font2, "Hard",130,30,st7789.RED)
        else:
            if self.umode==1:
                self.umode=0
                self.umus=1
                display.text(font2, "MODE:",30,30)
                display.text(font2, "MUSIC:",30,100,st7789.RED)
                if self.game_mode==0:
                    display.text(font2, "Easy",130,30)
                    
                else:
                    if self.game_mode==1:
                        display.text(font2, "Normal",130,30)
                    else:
                        display.text(font2, "Hard",130,30)
            if k2.value()==0:
                time.sleep_ms(20)
                if k2.value()==0:
                    self.umus=1
                    if self.music_mode==0:
                        self.music_mode=1
                    else:
                        self.music_mode=0
            
            if self.music_mode==0:
                if self.umus==1:
                    self.umus=0
                    display.text(font2, "Close",130,100,st7789.BLACK)
                    display.text(font2, "Open",130,100,st7789.RED)
            else:
                if self.umus==1:
                    self.umus=0
                    display.text(font2, "Open",130,100,st7789.BLACK)
                    display.text(font2, "Close",130,100,st7789.RED)
        display.text(font2,"Start",160,190)

menu函数实现游戏难易的选择

def board_move(self):
        adc = control.read_u16()
        duty = int(adc * (3000-0)/0xffff)+100
        if duty>2000:
            display.fill_rect(self.board_width+self.board_position,230,2,self.board_height,st7789.WHITE)
            display.fill_rect(self.board_position,230,2,self.board_height,st7789.BLACK)
            self.board_position=self.board_position+2
            if self.board_position>=239-self.board_width:
                self.board_position=239-self.board_width
        if duty<1000:
            display.fill_rect(self.board_width+self.board_position,230,2,self.board_height,st7789.BLACK)
            display.fill_rect(self.board_position,230,2,self.board_height,st7789.WHITE)
            self.board_position=self.board_position-2
            if self.board_position<=0:
                self.board_position=0

board函数控制游戏界面板子的左右移动

def ball_move(self):
        if self.direction==0:
            display.fill_rect(self.ball_x+1,20+self.ball_y,20,1,st7789.WHITE)
            display.fill_rect(20+self.ball_x,self.ball_y+1,1,19,st7789.WHITE)
            display.fill_rect(self.ball_x,self.ball_y,20,1,st7789.BLACK)
            display.fill_rect(self.ball_x,self.ball_y+1,1,19,st7789.BLACK)
            self.ball_x=self.ball_x+1
            self.ball_y=self.ball_y+1
            if self.ball_y>=219:
                self.statue=1
                display.fill(st7789.BLACK)
                return
            if self.ball_x>=219:
                self.ball_x=219
                self.direction=2
                return
        
        if self.direction==1:
            display.fill_rect(self.ball_x-1,self.ball_y-1,20,1,st7789.WHITE)
            display.fill_rect(self.ball_x-1,self.ball_y,1,19,st7789.WHITE)
            display.fill_rect(self.ball_x+19,self.ball_y,1,20,st7789.BLACK)
            display.fill_rect(self.ball_x,self.ball_y+19,19,1,st7789.BLACK)
            self.ball_x=self.ball_x-1
            self.ball_y=self.ball_y-1
            if self.ball_y<=0:
                self.ball_y=0
                self.direction=2
                return
            if self.ball_x<=0:
                self.ball_x=0
                self.direction=3
                return
            
        if self.direction==2:
            display.fill_rect(self.ball_x-1,self.ball_y+1,1,20,st7789.WHITE)
            display.fill_rect(self.ball_x,self.ball_y+20,19,1,st7789.WHITE)
            display.fill_rect(self.ball_x,self.ball_y,19,1,st7789.BLACK)
            display.fill_rect(self.ball_x+19,self.ball_y,1,20,st7789.BLACK)
            self.ball_x=self.ball_x-1
            self.ball_y=self.ball_y+1
            if self.ball_y>=219:
                self.statue=1
                display.fill(st7789.BLACK)
                return
            if self.ball_x<=0:
                self.ball_x=0
                self.direction=0
                return
        if self.direction==3:
            display.fill_rect(self.ball_x+1,self.ball_y-1,20,1,st7789.WHITE)
            display.fill_rect(self.ball_x+20,self.ball_y,1,19,st7789.WHITE)
            display.fill_rect(self.ball_x,self.ball_y,1,20,st7789.BLACK)
            display.fill_rect(self.ball_x+1,self.ball_y+19,19,1,st7789.BLACK)
            self.ball_x=self.ball_x+1
            self.ball_y=self.ball_y-1
            if self.ball_y<=0:
                self.ball_y=0
                self.direction=0
                return
            if self.ball_x>=219:
                self.ball_x=219
                self.direction=1
                return

ball函数,小球碰撞在墙上呈现的不规律的轨迹

def collision(self):        
        if self.ball_y>=199+self.board_height:
            i=self.board_position-20
            j=self.board_position+self.board_width
            if i<=0:
                i=0
            if self.ball_x>=i:
                if self.ball_x<=j:
                    n=random.randint(0,9)
                    #print(n)
                    if self.direction==0:
                        if n<=4:
                            self.direction=1
                        else:    
                            self.direction=3
                    if self.direction==2:
                        if n<=4:
                            self.direction=3
                        else:
                            self.direction=1
                    self.score=self.score+1
                    print(self.score)
                    if self.score%10==0:
                        self.game_mode=self.game_mode+1
                        if self.game_mode==1:
                            display.fill_rect(self.board_position+41,230,20,10,st7789.BLACK)
                        else:
                            if self.game_mode==2:
                                display.fill_rect(self.board_position+21,230,20,10,st7789.BLACK)
                        if self.game_mode>=2:
                            self.game_mode=2

碰撞函数

import uos
import machine
import st7789 as st7789
from fonts import vga2_8x8 as font1
from fonts import vga1_16x32 as font2
import random
import framebuf

image_file0 = "/logo.bin" #图片文件地址

st7789_res = 0
st7789_dc  = 1
disp_width = 240
disp_height = 240
CENTER_Y = int(disp_width/2)
CENTER_X = int(disp_height/2)
print(uos.uname())
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)
#
print(spi0)
display = st7789.ST7789(spi0, disp_width, disp_width,
                          reset=machine.Pin(st7789_res, machine.Pin.OUT),
                          dc=machine.Pin(st7789_dc, machine.Pin.OUT),
                          xstart=0, ystart=0, rotation=0)
display.fill(st7789.BLACK)
display.text(font2, "Hello!", 10, 10)
display.text(font2, "RPi Pico", 10, 40)
display.text(font2, "MicroPython", 35, 100)
display.text(font2, "EETREE", 35, 150)
display.text(font2, "www.eetree.cn", 30, 200)
f_image = open(image_file0, 'rb')


for i in range(5000):
    display.pixel(random.randint(0, disp_width),
          random.randint(0, disp_height),
          st7789.color565(random.getrandbits(8),random.getrandbits(8),random.getrandbits(8)))
    
for column in range(1,240):
                buf=f_image.read(480)
                display.blit_buffer(buf, 1, column, 240, 1)
        

LCD点灯函数

import uos
import mypong
from buzzer_music import music
from machine import Pin
from time import sleep_ms
from machine import Pin,PWM
pwm = PWM(Pin(23))
pong=mypong.Pong()
song = '0 A#4 1 1;2 F5 1 1;4 D#5 1 1;8 D5 1 1;11 D5 1 1;6 A#4 1 1;14 D#5 1 1;18 A#4 1 1;20 D#5 1 1;22 A#4 1 1;24 D5 1 1;27 D5 1 1;30 D#5 1 1;32 A#4 1 1;34 F5 1 1;36 D#5 1 1;38 A#4 1 1;40 D5 1 1;43 D5 1 1;46 D#5 1 1;50 A#4 1 1;52 D#5 1 1;54 G5 1 1;56 F5 1 1;59 D#5 1 1;62 F5 1 1;64 A#4 1 1;66 F5 1 1;68 D#5 1 1;70 A#4 1 1;72 D5 1 1;75 D5 1 1;78 D#5 1 1;82 A#4 1 1;84 D#5 1 1;86 A#4 1 1;88 D5 1 1;91 D5 1 1;94 D#5 1 1;96 A#4 1 1;100 D#5 1 1;102 A#4 1 1;104 D5 1 1;107 D5 1 1;110 D#5 1 1;114 A#4 1 1;116 D#5 1 1;118 G5 1 1;120 F5 1 1;123 D#5 1 1;126 F5 1 1;98 F5 1 1'
mySong = music(song, pins=[Pin(23)])
i=0


pong.start_page()
pong.menu_begin()
while True:
    pong.mode()
    if pong.music_mode==0 and pong.statue==0:
        i=i+1
        if i%pong.times==0:
            mySong.tick()
    else:
        pwm.duty_u16(0)
    if pong.statue==0:
        pong.run()
    else:
        if pong.statue==1:
            pong.stop()
        else:
           pong.menu()
    print(pong.game_mode)
    sleep_ms(pong.time)

游戏主函数

四、遇到的问题

由于代码编写出现错误,导致结果展示出现问题,后来通过代码改写得到解决。

五、未来的计划和建议

未来将更加深对嵌入式系统的学习,掌握多种语言编写能力,弄清楚代码功能,并及时纠正和编写,针对不断出现的错误反映的是自身能力的不足,日后将不断的提升自己,做到流畅甚至得心应手。

六、实现的结果及截图

FiDGatrLCM0YfXJD6QWivUDlOy0R

FkCxGH9PDk1G8ojfD1ZMrJQJnM_T

通过四向摇杆控制小板的左右移动,A\B按键可以调整游戏的难易和背景音乐的开关。

软硬件
元器件
RP2040
树莓派基金会推出的双核Arm Cortex M0+微控制器,133MHz时钟速率,264KB SRAM,支持C/C++、MicroPython编程
附件下载
代码.rar
代码
团队介绍
中央民族大学 马云
评论
0 / 100
查看更多
目录
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号