树莓派Pico上的游戏

树莓派Pico上的游戏

在这篇文章中,我想谈谈 Raspberry Pi Pico 上的游戏。

我记得我的第一部傻瓜手机,那时候叫 "电话"。它可以玩像蛇这样的简单游戏。那是一种边缘化的东西。

在此之前,你必须携带一个单独的掌上电脑,玩俄罗斯方块或更多的动态游戏系统,如Gameboy。

与90年代的手持设备相比,Raspberry Pi Pico是一个相当强大的微控制器。自然,它为我们提供了玩那个时代的游戏的能力。

Raspberry Pi Pico的功能有多强大

与80年代的控制台相比,Raspberry Pi Pico的功能非常强大。 

如果你编程的游戏与20世纪80年代的游戏的资源要求相似,Raspberry Pi Pico可能会轻而易举地通过它。

到了90年代,要说出这样一个明确的结论开始变得有点困难了。

一方面,如果你认为它是一个能够玩类似于Gameboy或手机上的游戏的设备,你可能会感到高兴。

然而,90年代后期的游戏变得更加费力。例如,你不会在Pico上玩Quake 3(1999年的游戏)。

事实上,虽然Raspberry Pi Pico可以播放《毁灭战士》(1993年),但对编码的人来说,这是一个为期6个月的努力,因为将游戏压缩到Raspberry Pi Pico的2MB存储空间是一个相当困难的任务。

因此,虽然Pico有两个133MHz的处理器,但它的内存和存储空间有限,这使得它很困难。

让我们看看它与Gameboy相比如何。

规格树莓派PicoGameboy (1989)彩色游戏机 (1998)
显示彩色LCD或电子墨水,这取决于你的想象力4种色调的灰度10、32、56种颜色
决议取决于你的显示器,但受限于Pico的资源。160x144px160×144 px
CPU133MHz双核4MHz4MHz/8MHz
内存264KB8KB32kb内存,16kb显存
储存2MB 游戏包盒:8MB ROM,128KB RAM游戏包盒:8MB ROM,128KB RAM

为什么在Pico上玩游戏而不是在Zero/Pi 4上?

好问题。

如你所知,Raspberry Pi Pico是一个微控制器,而Raspberry Pi Zero或Pi 4是微型计算机。

两者都可以玩游戏,但Raspberry Pi Pico的限制更多。

也就是说,如果你想在今天(2022年)用Raspberry Pi Zero或Pi 4s建立一个模拟器或游戏系统,你最好已经有一个,否则你最大的瓶颈就是库存。

要获得Pi Zero非常困难,要获得Pi 4也相当具有挑战性。

另一方面,Pico的内容很丰富。它也几乎可以立即启动,而微机皮克则要经历一个漫长的启动过程。

Pico的持续时间也更长。如果你想要一个能运行数小时且便于携带的移动装置,那么你用Pico会好很多。

最后,除了库存之外,Pico的库存也很充裕。

对Pi Zero和Pi 4来说是公平的,你绝对可以用这些微型计算机玩更好的游戏,获得更好的仿真效果。正如你在下一节所看到的,Pico在玩Zero或Pi 4会轻而易举地通过的游戏时确实很吃力。

Raspberry Pi Pico可以玩什么游戏?

我们先来看看修理工社区在Raspberry Pi Pico上都玩了些什么。

RP2040 "末日 "是对 "会不会末日 "的回答。

是的!Raspberry Pi Pico可以玩Doom。

一个来自德克萨斯州奥斯汀的名叫格雷厄姆-桑德森的家伙,成功地将《毁灭》移植到了树莓派Pico上。

他的神奇配方?

while (!convice_myself_its_probably_impossible()) {
    do_some_more();
}

在他的过程文件中解释说 他面临着树莓派Pico的硬件规格所带来的多种限制。毕竟,这不是一个用于游戏的设备。

尽管如此,格雷厄姆还决定使《毁灭战士》的移植工作更加困难。他希望得到《毁灭战士》的真实体验,这意味着要有320×200(彩色)的分辨率、立体声、OPL2音乐、保存和加载、网络多人游戏和其他原名中的功能。

在Raspberry Pi Pico上装这么多的游戏意味着内存方面的挑战。内存和存储都是关键问题。

首先,Raspberry Pi Pico只有2MB的存储空间,但Doom的共享软件版本是这个大小的两倍。虽然其他开发者可能会决定削减某些功能,如闪屏和降低纹理的取样,但格雷厄姆不想这样做。

内存也是另一个问题,Chocolate Doom源代码需要约1MB的内存,而Pico只有约264KB。内存紧张是因为渲染图形占用了RAM的一大块空间,但RAM对于游戏的顺利运行也非常重要。为了管理这两个方面,格雷厄姆不得不做他所谓的 "抽脂"。

你可以通过以下网址阅读更多信息 文件,观看 他的YouTube播放列表审查代码.

NES仿真器

Raspberry Pi Pico已被成功制成NES模拟器。

在仿真器区论坛的一个主题中,用户ropgar说,Raspberry Pi Pico具有模拟NES的能力,它可以做到每秒60帧,并且可以完美地模拟APU和PPP。

罗普加使用PS/2键盘作为控制器,但你也可以使用原始的NES控制器。

声音很好,视频和背景游戏音乐没有出现故障。

Pico有大约1.5MB的闪存空间,可用于不同的游戏,可以通过按Caps Lock键在游戏间切换来选择。 

ropgar设法在他的演示中加载的游戏有:吃豆子、Arkanoids、DK、小DK、BubbleBobble、Galaga和许多其他游戏。

有一个缺点是,没有公开的源代码或教程说明如何做到这一点。

用于Raspberry Pi Pico的Gameboy模拟器

你可以制作你自己的Gameboy外壳,然后用Raspberry Pi Pico来模拟Gameboy。

这里棘手的部分是,它实际上不是已经看到大量成功的东西。换句话说,你建立的东西可能有效,但不一定。

让我们来看看有哪些选择。

Rust Gameboy模拟器(OxidGB Pico Port)。

图片来源:u/j_selby (Reddit)

一看到屏幕上的口袋妖怪图像,我立刻兴奋起来。

然而,詹姆斯-塞尔比实际上写了关于他的Gameboy模拟器的挑战和缺点,该模拟器是用Rust编写的,名为OxidGB Pico Port。

"塞尔比说:"这是一次旅程--一次令人沮丧的旅程,但从教育的角度来说,我还是非常享受这次旅程。

问题和胜利

这里是主要的挑战。 Rust Gameboy模拟器 "不幸的是,在其目前的状态下并不完全可玩"。

塞尔比说,游戏只能得到大约10 FPS,因为模拟器的代码是一个瓶颈,以及到显示器的缓慢SPI接口。

有可能加快事情的进展,但这需要时间来计划和实施。

输入还没有配置好,因为游戏不能玩。 

测试OxidGB Pico端口

如果你想试一试,你可以按照塞尔比的指示在他的 OxidGB Pico端口的Github repo。

RP2040_GB仿真器

RP2040_GB仿真器硬件和设置,照片由Mahyar Koshkouei拍摄。

你可以尝试的另一个仿真器是 RP2040_GB,它是基于 花生-GB 仿真器。

RP2040_GB的性能还不错,Koshkouei说他的设置 "在没有音频模拟的情况下以超过70帧的速度运行。在跳帧和隔行扫描的情况下,可以以120帧的速度运行"。

正如你所看到的,RP2040_GB正在玩口袋妖怪。把ROM装到RP2040上的步骤是这样的。

  • 你必须拥有Pico SDK
  • 转换 .gb.gbc ROM到一个C头文件,使用 xxd 节目
  • 通过添加两行代码来修改转换后的文件(在Github readme中)。
  • 将ROM复制到 画面 文件夹,并进行编译。

这个模拟器有一些限制。

  • "这个模拟器是不准确的,而且在很大程度上是一项正在进行的工作......一些游戏可能运行不正确或根本无法运行。" 
  • Gameboy Color游戏会出现错误
  • 没有对微控制器进行优化。Koshkouei建议,"使用针对空间和速度进行优化的APU "可以帮助。

请参阅RP2040_GB的Github repo。

用树莓皮Pico编撰大型游戏

这个项目最好的地方是它很简单,而且说明足以让你迅速开始制作Raspberry Pi Pico游戏机。

Roger Bühler在他的Github上有零件、说明和演示。

大型游戏汇编包含以下游戏。

  1. 小小吉尔伯特
  2. 小小的把戏
  3. 小小侵略者 v3.1
  4. 小小弹球 v2
  5. 小小吃豆人 v1.2
  6. 小小炸弹人 v1.3
  7. 小巧的自行车 v1.2
  8. 小Bert 1.1
  9. 小小阿卡诺德 v2
  10. 小小特里斯 v2.1e
  11. 小小的牌子
  12. 小小DDug
  13. 小小导弹 v1.1
  14. Tiny Lander v1.0 ( 作者:Roger Buehler )
  15. 小小的莫泊桑
  16. 小管子

你需要的部件如下。

  1. 树莓派Pico
  2. SSD1309 128x64px SPI OLED显示屏(2.42英寸显示屏,2:1比例)。
  3. 压电式蜂鸣器
  4. 五个按钮
  5. 麵包板
  6. 跨接电缆
  7. 可选:10欧姆电阻,额定电压至少为10V和220uF的电解电容器

你还将需要 Adafruit的SSD1306库.

下面是连接显示器的方法。

  • GND -> 显示器GND 
  • 3V3(OUT) -> 显示屏VCC 
  • GP16 -> 显示DC(数据命令)。 
  • GP17 -> 显示CS(通道选择)。 
  • GP18 -> 显示SCL(时钟)。 
  • GP19 ->显示SDA(MOSI)。 
  • GP20 -> 显示RES(复位)。

并且要连接按钮。

  • GP15 -> 按钮向上 
  • GP14 -> 按钮下降 
  • GP13 -> 按钮 LEFT 
  • GP12 -> 按钮右键 
  • GP11 -- -- 按钮FIRE(所有按钮到GND)。

并连接压电式蜂鸣器。

  • GP10 -> 蜂鸣器(+) 
  • GND -> 蜂鸣器(-)

软件安装。

为了安装该软件,你需要使用Arduino IDE。

树莓派Pico上的类似玉兔的游戏(Pico-Tamachibi)。

为什么它被称为Pico-Tamachibi?

据该设备的创造者凯文-麦卡勒说,"tama "的意思是 "鸡蛋","chibi "指的是人物有一个大脑袋的图形。 

创建Tamachibi很容易,因为凯文在他90分钟的教程中介绍了每一步的方法。

建立你自己的游戏机

如果你想制作自己的Raspberry Pi Pico游戏机,一般有两种方法:购买现成的套件或自己制作。

现成的套件与DIY树莓派Pico游戏硬件的对比

虽然有可能从头开始,但你可能想跳过建立自己系统的麻烦,直接购买一个现成的软件包。

有一些基于RP2040的套件,可以让你直接跳到玩或开发自己的游戏。

让我们看看Pimoroni Picosystem,然后将其与使用单个零件建造类似东西的过程进行比较。

Pimoroni Picosystem

让我们来看看Pimoroni Picosystem。

正如你所看到的,它比Raspberry Pi Pico W大得多,但这也是因为它有一个四向D-pad,四个按钮,LCD屏幕,一个锂离子电池,压电扬声器和一个USB-C端口,以及其他附加功能。

它有相同的处理器和内存,因为Picosystem和Pico都使用RP2040芯片。以下是完整的规格。

  • 由RP2040(双臂Cortex M0+,264kB的SRAM)提供动力
  • 16MB的QSPI闪存支持XiP
  • 1.54英寸彩色SPI IPS LCD(240×240和120×120模式)。
  • D-pad和按钮
  • 525mAh锂电池(6小时以上)。
  • 压电式蜂鸣器/扬声器
  • 开/关电源按钮
  • RGB LED
  • 可编程,可通过USB-C充电(不包括电缆)。

图形模式

PicoSystem支持两种图形模式。

  • 240×240:LCD的原始分辨率
  • 120×120:像素加倍模式(节省RAM)。

Picosystem上的游戏是什么样子的?

在Picosystem上玩游戏很容易。只需按下电源按钮,你就可以看到预装的游戏 "超级广场兄弟"。

该游戏是一个简单的平台游戏,很像马里奥。

皮摩罗尼还包括其他游戏。

  • 超级广场兄弟 由Scorpion Games制作 - 一个有弹性的四边形平台游戏 (预装游戏)
  • 点状物 - 点弹出的益智游戏。创建两个或更多的链子,竞相获得最大的分数。
  • 岩石和钻石 - 躲避石块和抓取钻石的经典游戏。
  • 几何学 - 用激光击碎太空巨石,以制造更小的太空巨石!
  • 彩虹上升 - 黑暗之魂》的程序生成的垂直跳跃谜题。好运。
  • 超级布利特卡丁车 Daft_Freak - 一个基于 "Mode7 "的赛车游戏。

为了安装这些游戏,请做以下工作。

  • 下载文件。
  • 将您的Picosystem插入电脑
  • 按住X键,并按下电源键。
  • Picosystem应该被安装成一个名为RPI-RP2的驱动器。
  • 将下载的.uf2文件复制到驱动器上。它将自动加载。

由于某些原因,我的USB-C到USB-C电缆没有工作,但USB-A到USB-C电缆在Picosystem上工作。如果您没有看到红色LED灯亮起,那么请尝试其他电缆。

为你自己的游戏编程

Picosystem最好的部分是它为你提供了一个创建你自己的游戏的系统。

与其从头开始编码,PicoSystem附带了一个特殊的API,可以帮助你创建你的游戏。

它还消除了很多购买单个部件的繁琐工作,如液晶屏、按钮、跳线、面包板,然后弄清楚让所有这些工作所需的库和包。

PicoSystem的API具有在屏幕上绘制东西、输出音频、硬件功能和其他实用功能。这使你更容易建立你的游戏。

就像Raspberry Pi Pico一样,PicoSystem可以用C++或MicroPython进行编码。 

用Picosystem进行游戏编程容易吗?

我建议你有一些时间和耐心,以便用Picosystem建立自己的游戏。

文档提供了基础知识,以便让你开始工作,但如果你以前有一些游戏编程的知识,这将是最好的。

对于初学者来说,最大的挑战是没有多少资源可以教你如何编码样本项目。然而,这里有一个参考清单,可以帮助你。

Picosystem MicroPython指南(在readme中)。

Picosystem MicroPython实例

Picosystem C++ Github

Picosystem C++例子

Picosystem API小抄,外加图像、字体转换器 (在侧边栏)

DIY系统。创建硬件

YouMakeTech的指南 该书带领读者了解如何制作一个完整的游戏机,包括外壳、音响系统和永久焊接。

对于我们的比较,让我们看看建造一个DIY装置与Picosystem的成本是多少,后者是一个完整的套件。

YMT的游戏系统Pimoroni Picosystem
案例可选的,3D打印($4.47为STL蓝图,加上灯丝和3D打印机的租赁/操作费用)。包括
树莓派Pico$5用于Pico H,因为你将需要针座。包括
OLED显示屏$15(0.96英寸显示屏)包括
钮扣可忽略不计包括
麵包板$15(面包板套件)包括
跳线包括在面包板套件中包括
螺钉高达$1包括
压电式可忽略不计 包括
总成本$40.47,不包括3D打印费用$70

因此,让我们看看不同层级的DIY设置的最终成本。

设置费用
没有电池$40.47不包括3D打印费用
锂离子电池$8
Pimoroni Pico Lipo$16.39 - $4(由于我们使用的是Pimoroni Pico的替代品,我们可以扣除Raspberry Pi Pico的成本)
电池供电的套件总计$60.86,不包括3D打印费用

只是要注意的是--YouMakeTech说,你可以用低于$20的价格建造这个。然而,在我的研究中,与Picosystem相匹配的DIY装置的成本其实相差不大,特别是当你考虑到软件和便利性时。

YouMakeTech的原型,有两个按钮,一个屏幕,可以玩乒乓。

这就是说,DIY路线是一个很好的学习机会。挑战我的一件事是屏幕。YouMakeTech的例子使用的是I2C连接,而我的屏幕使用的是4针的SPI接口。这要么需要改变编码,要么需要对硬件进行修改,以便继续进行。如果你喜欢挑战,DIY路线就适合你。

那么,DIY与Picosystem相比,有什么优势呢?

优点/缺点DIY皮考斯系统
硬件组装你DIY一切你什么都不自己动手
软件这里没有什么帮助。你自己DIY一切,并学习如何操作每个组件。你必须学习Picosystem的API
学习机会更大的学习机会,因为你是把不同的部分拼凑起来的较小。它是现成的,软件将是这里最大的学习机会
延伸性既然你建造了它,你可以改变LCD屏幕,添加更多的按钮,添加LED,等等。除非你想把一个完整的系统拆开,否则不多。

在Picosystem与DIY系统上创建类似Pong的游戏

我的一个好奇的实验涉及到了解使用Picosystem开发一个游戏和从头开始做一个游戏要花多少精力。

为了比较这两个系统,我将在YouMakeTech的DIY系统和Picosystem上建立一个类似于Pong的单人游戏。

该游戏的前提很简单。这是一个类似于庞克的单人游戏,每当你的球从球拍上弹起时,你会得到10分。如果球掉到屏幕底部,你就会得到一个 "游戏结束 "的信息。

在这两个系统上创建游戏遵循一个简单的工作流程,所有这些都指向Thonny。

你需要将MicroPython闪存到Pico上,然后你将使用Thonny来编码你的程序。 

你在Picosystem上闪现的MicroPython与官方MicroPython UF2文件不同,所以要确保你闪现的是正确的,因为Picosystem会在官方MicroPython版本上运行。它只是不能按原计划运行。

现在,让我们来看看两者之间的一些基本差异。我这里不包括游戏逻辑,只比较软硬件互动和编程模式的差异。

你可以在这里看到YouMakeTech的代码。

第一个区别:硬件代码

在DIY路线上,事情非常 "原始"。这里有一些初始化显示器、GPIO和按钮的代码,你不需要用Picosystem来做。

from machine import Pin, PWM, I2C,
from ssd1306 import SSD1306_I2C

# Buttons
up = Pin(2, Pin.IN, Pin.PULL_UP)
down = Pin(3, Pin.IN, Pin.PULL_UP)
left = Pin(4, Pin.IN, Pin.PULL_UP)
right = Pin(5, Pin.IN, Pin.PULL_UP)
button1 = Pin(6, Pin.IN, Pin.PULL_UP)
button2 = Pin(7, Pin.IN, Pin.PULL_UP)

# Buzzer connected to GP18
buzzer = PWM(Pin(18))

# OLED Screen connected to GP14 (SDA) and GP15 (SCL)
i2c = machine.I2C(1, sda = Pin(14), scl = Pin(15), freq = 400000)
oled = SSD1306_I2C(SCREEN_WIDTH, SCREEN_HEIGHT, i2c)

第二个区别。Picosystem的API

如果你在Picosystem上写代码,你就必须在其系统内写。

在YouMakeTech的例子中,所有游戏逻辑都被封装在一个 而真 循环。这包括按钮互动、碰撞检测和对屏幕的绘制。

在Picosystem中,你需要在三个功能范围内进行写作--- init(), update() 绘制().

在我的代码中,所有游戏的逻辑都写在 update() 包括碰撞处理和D-pad互动。

在一个简单的乒乓游戏中,我使用了API中的几个函数,使事情变得更简单。

相交(x1, y1, w1, h1, x2, y2, w2, h2)  可能是这里最大的帮助。你将传递两个方块的坐标和大小,如果有交集,它将返回true。在本例中,这两个矩形是球和杆(又称桨)。intersects()函数的缺点是它不能检测到碰撞发生在哪一边,所以我不得不写额外的代码来处理酒吧一边的碰撞问题。

Picosystem的API将在你开发更复杂的游戏时真正大放异彩,因为它已经有了帧缓冲器、音频输出、混合等的方法。 

Pimoroni Picosystem Pong-like游戏的代码

#bar_pos_x = pixels from left, e.g. 0 from left
bar_pos_x = 50
#bar_pos_y = pixels from top, e.g. 100px from top
bar_pos_y = 100
BAR_WIDTH = 30

LENGTH_CONSTANT = 5

ball_speed = 1
ball_pos_x = 10
ball_pos_y = 10
ball_dx = 2
ball_dy = 2

score = 0
game_over = False

def update(tick):
    
    global bar_pos_x
    global bar_pos_y
    global ball_pos_x
    global ball_pos_y
    global ball_dx
    global ball_dy
    global ball_speed
    global score
    global game_over
    
    def reverse_ball_dx():
        global ball_dx
        ball_dx = ball_dx * -1
        
    def reverse_ball_dy():
        global ball_dy
        ball_dy = ball_dy * -1
    
    ball_pos_x += ball_dx
    ball_pos_y += ball_dy
    
    if button(LEFT) and bar_pos_x > 0:
        bar_pos_x -= 1
    
    if button(RIGHT) and bar_pos_x < 120 - BAR_WIDTH :
        bar_pos_x += 1
        
    if ball_pos_x <= 0 :
        ball_pos_x = 0
        reverse_ball_dx()
        
    if ball_pos_x >= 120 - LENGTH_CONSTANT :
        ball_pos_x = 120 - LENGTH_CONSTANT
        reverse_ball_dx()
        
    if ball_pos_y >= 120 - LENGTH_CONSTANT :
        game_over = True
        
    if ball_pos_y <= 0:
        ball_pos_y = 0
        reverse_ball_dy()
        
    if intersects(bar_pos_x,bar_pos_y,BAR_WIDTH,LENGTH_CONSTANT, ball_pos_x, ball_pos_y, LENGTH_CONSTANT,LENGTH_CONSTANT):
        
        reverse_ball_dy()
        score += 10
        
        #main intersection of ball and bar. if they intersect, check if they are intersecting on the sides.
        #if not on sides (i.e. on top) reverse Y direction. Or else, reverse X direction.
        if intersects(bar_pos_x,bar_pos_y,1,LENGTH_CONSTANT, ball_pos_x, ball_pos_y, LENGTH_CONSTANT,LENGTH_CONSTANT):
            
            #intersecting on left
            
            reverse_ball_dx()
            ball_pos_x -= 2
            
        if intersects(bar_pos_x + BAR_WIDTH,bar_pos_y,1,LENGTH_CONSTANT, ball_pos_x, ball_pos_y, LENGTH_CONSTANT,LENGTH_CONSTANT):
            
            #intersecting on right
            
            reverse_ball_dx()
            ball_pos_x += 2

        
def draw(tick):
    
    if game_over:
        pen(0,0,0)
        clear()
        pen(15,15,15)
        text("Game Over", 35, 60)
        
        
    else:
        pen(0, 0, 0)
        clear()
        pen(15,15,15)
    
        #draw bar (paddle)
        frect(bar_pos_x,bar_pos_y,BAR_WIDTH,LENGTH_CONSTANT)
    
        #draw the ball
        frect(ball_pos_x, ball_pos_y, LENGTH_CONSTANT,LENGTH_CONSTANT)
        text(str(score), 80, 20)
    
start()

有什么游戏可以推荐吗?

如果你有适用于Raspberry Pi Pico的游戏,请在下面留言并附上网址。

如果您想了解我们的 "百丽宫项目 "系列,请访问 这里.

1评论

  1. Mt 在4 月 15, 2024在12:06 上午

    pimoroni 系统是否有代码允许您使用外部附件/设备(如小型 Fpga)来提高性能?

发表评论