news 2026/5/30 13:16:56

Arduino双人按键游戏:从硬件搭建到软件编程的嵌入式入门实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Arduino双人按键游戏:从硬件搭建到软件编程的嵌入式入门实战

1. 项目概述:一个双人竞技按键游戏的诞生

几年前我第一次接触Arduino时,和很多新手一样,面对琳琅满目的传感器和闪烁的LED,既兴奋又有点无从下手。官方示例里的“Blink”固然经典,但总感觉少了点“玩”的乐趣。我当时就想,能不能用手里最简单的元件——几个按钮、两颗LED——做个能和朋友一起玩的小东西?这个念头最终催生了这个“双人按键游戏”项目。它本质上是一个反应速度测试器:两个玩家各控制一个按钮,比赛谁能在最短时间内按够设定的次数(比如20次),先完成者的LED会以胜利的闪烁宣告获胜。

这个项目的价值远不止于游戏本身。对于刚踏入嵌入式世界的新手来说,它像是一把钥匙,帮你理解微控制器如何成为连接代码与物理世界的桥梁。你会亲手触摸到“数字输入”和“数字输出”这两个最核心的概念,看着自己写的几行逻辑如何驱动真实的灯光,并响应真实的按压动作。整个过程涵盖了从电路构思、面包板搭建、代码编写与调试,到最终焊接封装成型的完整闭环。即使你没有任何电子或编程基础,跟着走一遍,也能对“硬件+软件”协同工作的基本模式建立起清晰的认知。下面,我就把这个从零到一的过程拆开揉碎了讲给你听。

2. 核心思路与设计迭代:从想法到可玩的游戏

任何项目都不是一蹴而就的,这个双人游戏也不例外。我的设计过程经历了几个关键的迭代,这些思考对于初学者规划自己的项目很有参考价值。

2.1 初始构想与遇到的现实问题

我最开始的想法比最终版本复杂得多:我想做一个“灯光解谜”游戏。设想是有一个由多个LED组成的阵列,玩家通过按下不同的按钮来改变LED的亮灭状态,有些按钮会同时影响多个LED,最终目标是将所有LED点亮。这听起来像个有趣的逻辑挑战。

但很快我就撞了墙。问题不在于Arduino做不到,而在于我当时的编程和逻辑组织能力不足以清晰定义每个按钮与多个LED之间复杂的联动关系。代码会迅速变得臃肿且难以调试,状态管理混乱。这个教训很深刻:对于入门项目,尤其是第一个项目,核心目标应该是“成功运行”,而不是“功能复杂”。复杂的想法可以留到你对平台更熟悉之后。

2.2 简化与核心玩法的确立

于是,我果断退了一步,将目标简化为最直接的互动:按按钮,灯亮。最初的版本就是一个按钮控制一个LED,按一下,灯亮。但马上又出现了新问题——这算什么游戏呢?毫无挑战性和目标感。

为了引入目标,我首先想到的是加入计时器,比赛谁在固定时间内按的次数多。然而,当时我对Arduino的中断和定时器函数掌握不牢,引入计时逻辑后,整个按键检测的代码就出现了各种奇怪的Bug(比如计数不准、程序卡死)。这又是一个关键节点:当你引入一个新功能导致系统崩溃时,不妨想想是否有更优雅的替代方案

我的解决方案是去掉独立的计时器,转而利用“对手”作为天然的计时器。将游戏改为“先按满20次者胜”,这样,游戏时间完全由两个玩家的相对速度决定,无需复杂的独立计时模块。这个改动一下子让代码清爽了许多,也真正有了“竞技”的意味。这种“竞速”机制是许多经典街机游戏的灵魂,简单又有效。

2.3 细节打磨与防作弊机制

核心玩法确定后,剩下的就是打磨细节。一个必须解决的问题是:如果玩家一直按住按钮不放,程序可能会认为他在连续快速按压,从而作弊得分。这就是硬件项目中常见的“按键消抖”和“状态检测”问题。

在软件层面,我采用的策略不是简单地检测按钮是否被按下(digitalRead(pin) == LOW),而是检测按钮的“状态变化”。具体来说,程序会记住按钮上一次的状态,只有当检测到按钮从“释放”变为“按下”的瞬间(一个“上升沿”或“下降沿”,取决于你的电路是上拉还是下拉),才计一次有效按压。这样,长按只会计一次分。这部分逻辑被我封装成了独立的函数,使得主循环非常简洁。将特定功能模块化函数化,是让代码保持清晰、易于维护的好习惯

3. 硬件电路搭建详解

理论说得再多,不如动手接根线。硬件部分是所有想法落地的基础,我们一步步来。

3.1 所需元件清单与选型考量

这是我用到的核心元件,你也可以根据手头资源灵活替换:

  • Arduino Uno x1: 项目的大脑。选择Uno是因为它普及度最高,资料丰富,USB供电和编程都非常方便。对于这个项目,任何具有足够数字IO引脚(至少需要4个:2输入,2输出)的Arduino兼容板(如Nano、Leonardo)都可以。
  • ** tactile按钮 x2**: 也就是常说的轻触开关。建议选择四脚按钮,它在面包板上的稳定性比两脚按钮好得多。颜色最好和对应的LED区分开。
  • LED(发光二极管)x2: 不同颜色,用于区分玩家。注意,LED必须串联电阻,否则直接接到5V电源上会瞬间烧毁。我用了220Ω的电阻,这是一个在保证亮度和安全之间的常用值。
  • 220Ω 电阻 x2: 用于限制LED的电流。计算公式很简单:电阻值 R = (电源电压 - LED压降) / 期望电流。对于Arduino的5V输出和普通LED(压降约2V),如果希望电流在10-20mA,电阻值在150Ω-300Ω之间都合适。
  • 10kΩ 电阻 x2: 用于按钮的下拉电阻。这是关键!当按钮未按下时,这个电阻将输入引脚稳定地连接到GND(低电平),防止引脚悬空产生不确定的随机信号(噪声)。
  • 面包板 x1: 用于无焊接的电路原型搭建。
  • 公对公杜邦线若干: 连接各元件。

注意:电阻色环辨认是新手的一道坎。如果不确定,可以用万用表的电阻档测量一下。220Ω常见色环是“红红棕金”,10kΩ是“棕黑橙金”。

3.2 电路连接原理与步骤

电路图是工程师的语言,但我们可以用更直白的方式描述连接关系。我们的目标是构建两个完全独立的“玩家单元”,每个单元包含一个按钮(输入)和一个LED(输出),最后共地。

连接步骤(建议对照原理图操作):

  1. 供电准备:将面包板两侧的电源长条连接起来。用一根线将Arduino的5V引脚连接到面包板的正极(+)长条,另一根线将GND引脚连接到面包板的负极(-)长条。这样整个面包板就有了统一的电源和地。
  2. 搭建玩家1单元
    • LED部分:取一个LED,长脚(阳极+)通过一个220Ω电阻,连接到Arduino的某个数字引脚(例如引脚8,定义为输出)。短脚(阴极-)直接连接到面包板的GND长条。
    • 按钮部分:取一个按钮,跨接在面包板中间沟槽上。按钮一侧的一个引脚用杜邦线连接到面包板的5V长条。同一侧的另一个引脚,必须通过一个10kΩ电阻连接到面包板的GND长条。同时,从这个引脚(也就是连接10kΩ电阻和按钮的交接点)引出一根线,连接到Arduino的某个数字引脚(例如引脚2,定义为输入)。按钮另一侧的两个引脚暂时空置或连接到GND(具体看按钮内部结构,通常四脚按钮对角线两两相通)。
  3. 搭建玩家2单元:完全重复步骤2,使用另一组元件。例如,LED接到引脚9,按钮接到引脚3
  4. 最终检查:确保所有GND(Arduino的GND、电阻的GND端、LED的阴极)都最终连通到了同一个GND网络。这是电路正常工作的基础,很多诡异的问题都源于地线没接好。

电路原理浅析

  • LED电路:当Arduino的引脚8输出HIGH(5V)时,电流从引脚流出,经过电阻和LED,流向GND,形成回路,LED点亮。输出LOW时,两端电压相等,无电流,LED熄灭。
  • 按钮电路(下拉电阻接法):当按钮未按下时,输入引脚通过10kΩ电阻“下拉”到GND,所以digitalRead读到的是LOW。当按钮按下时,5V电源直接通过按钮连接到输入引脚,此时digitalRead读到的是HIGH。10kΩ电阻在这里至关重要,它避免了引脚悬空时感应到的杂波被误认为是按键信号。

4. 软件编程与逻辑实现

硬件是躯体,软件是灵魂。下面我们深入代码,看看如何让这个躯体活起来。

4.1 代码结构全局观

完整的代码可以在文末找到,这里我们先梳理骨架。一个典型的Arduino程序包含两个主要函数:

  • void setup(): 只在设备上电或复位后运行一次。用于初始化设置,如配置引脚模式、初始化串口等。
  • void loop(): 在setup()之后,会无限循环执行。我们的主要游戏逻辑就在这里。

此外,为了代码清晰,我们将按键检测和计分逻辑封装成了自定义函数。

4.2 核心变量与引脚定义

程序开头,我们先定义一些常量,这能让代码更易读、易修改。

// 玩家1的硬件连接引脚 const int button1Pin = 2; // 按钮连接到数字引脚2 const int led1Pin = 8; // LED连接到数字引脚8 // 玩家2的硬件连接引脚 const int button2Pin = 3; const int led2Pin = 9; // 游戏参数 const int winScore = 20; // 获胜所需分数 // 游戏状态变量 int score1 = 0; int score2 = 0; // 按键状态跟踪变量(用于消抖和检测变化) byte lastButton1State = LOW; byte lastButton2State = LOW;

这里用byte类型存储上一次按钮状态,因为它只存0或1(LOW/HIGH),节省内存。定义winScore为常量,方便以后调整游戏难度。

4.3 初始化设置 (setup函数)

setup()中,我们告诉Arduino每个引脚的角色。

void setup() { // 初始化LED引脚为输出模式 pinMode(led1Pin, OUTPUT); pinMode(led2Pin, OUTPUT); // 初始化按钮引脚为输入模式 pinMode(button1Pin, INPUT); // 注意:这里使用INPUT,因为我们已经通过外部下拉电阻确定了默认低电平 // 初始状态:关闭所有LED digitalWrite(led1Pin, LOW); digitalWrite(led2Pin, LOW); // 初始化串口,用于调试(可选,但强烈推荐) Serial.begin(9600); Serial.println("Game Start!"); }

实操心得:即使项目不用串口通信,也养成在setup()里开启串口(Serial.begin(9600))的习惯。在调试时,用Serial.print()输出变量值或状态信息,是定位问题最快的方法,比盯着LED猜强多了。

4.4 主循环与游戏逻辑核心 (loop函数)

loop()函数是游戏的心脏,它以极高的频率不断循环执行。

void loop() { // 1. 检查玩家1的按钮动作并更新分数 score1 += checkButton(button1Pin, &lastButton1State); // 传递按钮引脚和状态变量的地址 // 2. 检查玩家2的按钮动作并更新分数 score2 += checkButton(button2Pin, &lastButton2State); // 3. 更新LED显示当前比分(例如,每得5分快闪一下) updateLEDs(); // 4. 检查获胜条件 if (score1 >= winScore) { player1Win(); resetGame(); } if (score2 >= winScore) { player2Win(); resetGame(); } // 加入微小延迟,稳定循环速度(非必须,但有时有益) // delay(1); }

主循环的逻辑非常清晰:检测输入 -> 更新状态 -> 更新输出 -> 检查全局条件。这是一种经典的状态机模型。

4.5 关键函数深度解析

4.5.1 按键检测函数 (checkButton)

这是实现防长按作弊的核心。

int checkButton(int buttonPin, byte *lastState) { int scoreIncrement = 0; byte currentButtonState = digitalRead(buttonPin); // 读取当前物理状态 // 核心逻辑:只有状态发生变化时(从HIGH到LOW或LOW到HIGH),才进行判断 if (currentButtonState != *lastState) { // 消抖:等待几毫秒,避开机械触点振动的干扰期 delay(5); // 再次读取,确认状态 currentButtonState = digitalRead(buttonPin); // 确认状态确实发生了变化,并且当前状态是我们关心的“按下”状态(假设按下为HIGH) if (currentButtonState == HIGH && *lastState == LOW) { scoreIncrement = 1; // 一次有效的按压,计1分 Serial.print("Button on pin "); Serial.print(buttonPin); Serial.println(" pressed."); } // 更新上一次状态记录 *lastState = currentButtonState; } // 如果没有有效按压,返回0 return scoreIncrement; }

为什么这样写?

  1. 状态比较if (currentButtonState != *lastState)这行确保了只在按钮状态改变(按下或释放的瞬间)时进入处理逻辑,长按期间状态不变,不会重复计分。
  2. 软件消抖delay(5)是为了消除机械按钮触点闭合/断开时产生的物理抖动(通常持续几毫秒到十几毫秒)。没有消抖,一次按压可能会被误读为多次。这是一种简单的软件消抖,对于实时性要求不高的游戏足够用。更高级的方法是用millis()函数实现非阻塞消抖。
  3. 检测边沿if (currentButtonState == HIGH && *lastState == LOW)这个条件检测的是一个“上升沿”(从低到高)。在我们的下拉电阻电路中,按钮按下就是产生一个上升沿。你也可以改为检测下降沿,逻辑同理。
4.5.2 获胜判定与反馈函数

当有玩家达到目标分数时,触发胜利反馈。

void player1Win() { Serial.println("Player 1 Wins!"); for (int i = 0; i < 5; i++) { // 闪烁5次 digitalWrite(led1Pin, HIGH); delay(200); digitalWrite(led1Pin, LOW); delay(200); } } void resetGame() { score1 = 0; score2 = 0; digitalWrite(led1Pin, LOW); digitalWrite(led2Pin, LOW); Serial.println("Game Reset. Ready for next round!"); }

胜利反馈用了一个简单的for循环实现LED闪烁。resetGame()函数在胜利动画后调用,将分数归零,LED熄灭,准备下一轮。

5. 系统调试与问题排查实录

代码写完、电路接好,点击上传,但灯不亮、按钮没反应?别慌,这是学习的必经之路。下面是我在调试中遇到的一些典型问题及解决方法。

5.1 常见问题速查表

问题现象可能原因排查步骤与解决方案
LED完全不亮1. 正负极接反。
2. 限流电阻太大或开路。
3. 引脚模式设置错误(应为OUTPUT)。
4. 代码中LED引脚始终输出LOW
1. 确认LED长脚(阳极)接信号,短脚(阴极)接GND。
2. 用万用表通断档检查电阻和线路是否连通。
3. 检查setup()中是否有pinMode(ledPin, OUTPUT)
4. 写个简单测试程序,让该引脚digitalWrite(ledPin, HIGH)
LED常亮,不受控制1. LED引脚与5V短路。
2. 程序逻辑错误,一直输出HIGH
1. 断电,检查面包板接线是否有金属丝短路。
2. 用串口打印输出值,或单步调试逻辑。
按钮按下无反应1. 按钮引脚模式错误(应为INPUT)。
2. 下拉电阻未接或虚接。
3. 按钮损坏或接触不良。
4. 程序读取的是错误的引脚。
1. 检查pinMode(buttonPin, INPUT)
2. 确保10kΩ电阻一端接按钮-引脚交汇点,一端接GND。
3. 用万用表通断档测试按钮按下时是否导通。
4. 用Serial.print(digitalRead(buttonPin))在循环中打印引脚状态,观察按下时是否从0变1。
按钮一直显示被按下(状态常为HIGH)1. 上拉/下拉电阻接错。下拉电阻应接在引脚与GND之间,如果接在引脚与5V之间,就成了上拉,逻辑相反。
2. 引脚内部上拉被启用,但外部电路冲突。
1. 检查电路,确认是下拉接法(按钮接5V,引脚通过电阻接GND)。
2. 如果使用了INPUT_PULLUP模式,则外部不应再接任何上拉/下拉电阻,按钮另一端应直接接GND。
计分不准,按一次加好几分按键抖动未处理增加软件消抖延时(如delay(5)),或实现更优的非阻塞消抖逻辑(记录millis()时间戳)。
一个玩家得分导致另一个玩家LED也闪代码中获胜判断或LED控制逻辑写串了。仔细检查player1Win()player2Win()函数中控制的LED引脚是否正确。确保resetGame()只重置自己的游戏状态。

5.2 串口调试:你的最佳伙伴

在问题排查中,我强烈推荐使用Arduino IDE的串口监视器。在代码关键位置插入Serial.print()语句,就像给程序安装了“监控摄像头”。

例如,在checkButton函数里打印状态变化,在loop里打印当前分数:

void loop() { // ... 其他代码 ... Serial.print("Score1: "); Serial.print(score1); Serial.print(" | Score2: "); Serial.println(score2); delay(100); // 减慢打印速度,便于观察 }

通过观察这些输出,你可以清晰地看到程序是否按预期运行,变量值是否正确变化,从而快速定位问题是出在硬件连接、信号读取还是逻辑判断上。

5.3 硬件排查“三板斧”

当软件排查无误后,问题很可能在硬件:

  1. 目视检查:首先断电,仔细检查所有杜邦线插接是否牢固,有无松脱;检查LED、电阻、按钮的引脚是否在面包板插孔中接触良好;检查有无导线金属部分意外触碰导致短路。
  2. 万用表检查
    • 通断档:检查从Arduino引脚到元件,再到GND/5V的路径是否连通。
    • 电压档:上电后,测量按钮未按下时,输入引脚对GND电压(应接近0V);按下时(应接近5V)。
  3. 最小系统法:如果问题复杂,可以拔掉大部分连线,只接一个LED和一个按钮,用一个最简单的程序测试(如按按钮灯亮)。确认这个最小单元工作后,再逐步添加其他部分。

6. 从原型到成品:焊接与封装

当面包板上的原型运行稳定后,你就可以考虑把它变成一个更结实、更美观的“产品”了。这一步能极大提升项目的成就感和实用性。

6.1 焊接:将临时连接永久化

焊接是为了用更可靠的方式替代面包板上的杜邦线连接。你需要一块万用板(洞洞板)、电烙铁、焊锡丝和助焊剂。

我的焊接经验与教训

  1. 规划布局:在焊接前,用铅笔在万用板背面大致规划元件位置。一个重要的原则是:将需要与外壳交互的元件(按钮、LED)放在板子一侧,将其他元件(电阻、连接线)放在另一侧。这能极大方便后续安装到外壳里。我最初没注意这点,导致板子安装时内部线路非常别扭。
  2. 先固定,后焊接:先将按钮、LED、排针等元件插入板子,在背面用胶带或用手按住,然后翻转板子进行焊接。确保元件紧贴板子。
  3. 焊接技巧:烙铁头同时接触元件引脚和焊盘,约1-2秒后,从另一侧送入焊锡丝。焊锡熔化并自然流满焊盘后,先撤走焊锡丝,再移开烙铁。一个良好的焊点应该呈光滑的圆锥形。
  4. 连线:可以使用元件本身多余的引脚进行弯折连接,也可以用单独的导线(如剪下的电阻腿或专用导线)在板子背面进行连接。连接后,务必用万用表通断档检查每条线路是否连通,且与相邻线路是否短路。
  5. 教训:杜邦线的线芯很细,直接焊接容易因过热而脱落。焊接前最好先给线头上一点锡(搪锡)。我在焊接时弄断了好几根线,就是因为操作不当。

6.2 外壳制作与安装

一个合适的外壳能让项目瞬间提升档次。我利用了一个现成的木盒。

步骤与建议

  1. 测量与定位:将焊接好的电路板放在盒盖内侧,用笔精确标记出按钮轴和LED灯珠需要穿出的位置。
  2. 开孔:使用合适尺寸的钻头在标记处钻孔。对于按钮,孔径要略小于按钮的螺纹直径或卡扣尺寸,以便能卡紧。对于LED,孔要能让灯珠刚好露出。
  3. 固定电路板:这是挑战。我的盒子和电路板之间有较大空隙,直接用胶水粘接面积小,不牢固。我的解决方案是:先在电路板四角点少量热熔胶或AB胶初步定位,然后用强度高、有柔性的材料(如我用的纤维胶带,你可用尼龙扎带或L型支架)进行辅助加固。核心是要抵消按钮被反复按压时对板子产生的剪切力和扭力
  4. 最终组装:将按钮和LED从外壳外部插入孔中,在内部用螺母或垫片固定好按钮。将Arduino板也用类似方式固定在盒内空余位置。最后将所有导线整理捆扎,避免杂乱。

避坑指南:外壳安装后,务必再次上电测试!我曾遇到过安装时导线被压破皮导致短路,或者按钮引脚被外壳挤压变形接触不良的情况。确保一切正常后再合上盖子。

7. 项目总结与扩展思路

回顾整个项目,从最初一个模糊的想法,到中间的逻辑碰壁、电路调试,再到最后的焊接封装,每一步都是对“发现问题-解决问题”能力的锻炼。对于初学者,最大的收获可能不是做出了一个多么精巧的游戏,而是完整地走通了一个嵌入式小产品的开发流程:定义需求 -> 设计简化方案 -> 搭建硬件原型 -> 编写调试软件 -> 优化细节 -> 产品化封装。

这个项目还有很大的扩展空间,你可以尝试:

  • 增加声音反馈:加入一个无源蜂鸣器,在按键或获胜时发出不同音效。
  • 改变游戏模式:比如“限时模式”,在指定时间内(用millis()函数实现倒计时)看谁按的次数多;或者“反应速度测试”,随机点亮一个LED,看对应玩家谁先按下按钮。
  • 加入显示设备:用一块OLED屏幕显示分数、倒计时、胜利信息,甚至更复杂的游戏界面。
  • 无线化:用两块Arduino加NRF24L01无线模块,制作成两个独立的无线手柄,进行远程对战。

硬件项目的乐趣就在于,一旦你掌握了基础,就可以像搭积木一样,组合不同的传感器和执行器,创造出无限的可能。这个双人按键游戏就是一个完美的起点,希望它能点燃你动手创造的热情。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/30 13:13:58

Apache Spark:从数据处理瓶颈到统一计算引擎的演进与实践

1. 项目概述&#xff1a;从数据处理的“石器时代”到“工业革命” 十年前&#xff0c;当我第一次面对一个需要处理几十GB日志文件的任务时&#xff0c;我的工具箱里只有一台配置尚可的服务器、一个关系型数据库和一些自己写的Python脚本。那个过程&#xff0c;现在回想起来&…

作者头像 李华
网站建设 2026/5/30 13:13:58

事务码 UDO 的真实使用场景,从补丁移植、版本差异到 ABAP 开发交付的安全网

在 SAP ABAP 日常开发里,UDO 这个事务码并不是业务顾问经常打开的那类前台事务,也不是用来维护销售订单、采购订单、物料主数据的功能入口。它更像一把放在资深开发者工具箱深处的手术刀,平时安静地待着,一旦遇到跨版本补丁、法律变更、标准代码差异分析、上游版本向下游版…

作者头像 李华
网站建设 2026/5/30 13:08:04

从Arduino到机械艺术:构建稳定可靠的滚珠时钟全栈指南

1. 项目概述&#xff1a;一个会“思考”的机械时间艺术如果你和我一样&#xff0c;对精密的机械传动和电子控制的结合着迷&#xff0c;那么“滚珠时钟”这个项目绝对能让你在工作室里待上好几个愉快的周末。这不仅仅是一个显示时间的装置&#xff0c;更是一个看得见的物理计算过…

作者头像 李华
网站建设 2026/5/30 13:08:01

RabbitMQ性能优化:打造高性能消息队列系统的实践指南

RabbitMQ性能优化&#xff1a;打造高性能消息队列系统的实践指南 在高并发场景下&#xff0c;RabbitMQ的性能直接影响着整个系统的吞吐量和响应速度。RabbitMQ是一个精心设计的高性能消息中间件&#xff0c;但默认配置可能无法充分发挥其性能潜力。通过合理的性能优化&#xff…

作者头像 李华
网站建设 2026/5/30 13:07:45

Perseus开源补丁:3步解锁《碧蓝航线》全皮肤的终极指南

Perseus开源补丁&#xff1a;3步解锁《碧蓝航线》全皮肤的终极指南 【免费下载链接】Perseus Azur Lane scripts patcher. 项目地址: https://gitcode.com/gh_mirrors/pers/Perseus 还在为《碧蓝航线》中那些精美皮肤只能远观而烦恼吗&#xff1f;Perseus开源补丁为你带…

作者头像 李华
网站建设 2026/5/30 13:04:04

RPFM:全面战争MOD开发效率革命,6大功能让复杂编辑变简单

RPFM&#xff1a;全面战争MOD开发效率革命&#xff0c;6大功能让复杂编辑变简单 【免费下载链接】rpfm Rusted PackFile Manager (RPFM) is a... reimplementation in Rust and Qt6 of PackFile Manager (PFM), one of the best modding tools for Total War Games. 项目地址…

作者头像 李华