news 2026/10/7 5:11:05

Python+Pygame实战:开发2D飞机驾驶模拟器

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python+Pygame实战:开发2D飞机驾驶模拟器

最近短视频平台总刷到女孩驾驶飞机的视频,驾驶舱里密密麻麻的仪表伴随着操纵动作不断跳动,看着相当过瘾。说实话,视频里的飞机型号我不太研究得明白,但作为常年写 Python 的开发者,我第一反应是:这些驾驶仪表背后的逻辑,其实完全可以用代码模拟出来。

本文就从飞行模拟器入手,基于 Python + Pygame 实现一个简化版的 2D 飞机驾驶模拟器。你不需要有航空背景,只需要能运行 Python 代码。读完这篇文章,你将理解飞行仪表的基本含义、飞机物理模型的简化思路,并收获一个完整可运行的驾驶模拟小项目。

1. 背景与核心概念

1.1 飞行模拟器是什么

飞行模拟器(Flight Simulator)是用计算机软件模拟真实飞机飞行过程的系统。大型飞行模拟器用于飞行员训练,例如常见的塞斯纳、波音 737 模拟机;民用领域则更常见于微软模拟飞行(MSFS)、X-Plane 等专业软件。

整套系统通常由以下部分组成:

  • 飞行物理模型:模拟升力、重力、推力、阻力。
  • 飞机仪表系统:空速表、高度表、姿态仪、升降速率表等。
  • 环境渲染:天空、地面、云层、机场跑道。
  • 驾驶舱交互:操纵杆、油门、脚舵、控制按键。

一个完整的飞行模拟器工程量巨大,但我们可以拆出核心逻辑,用 Pygame 写出一个 2D 简化版本。它不追求真实气动方程,只保留“驾驶飞机”最核心的操纵体验:控制俯仰角、控制油门、观察仪表。

1.2 本文实现的模拟器功能清单

本文的 Pygame 项目包含以下功能:

  • 用方向键控制飞机俯仰角(上键抬头,下键低头)。
  • 用左右方向键控制油门大小。
  • 模拟空速随油门变化、高度随俯仰角变化的简单物理模型。
  • 渲染天空、云朵、地面和飞机图形。
  • 绘制空速表、高度表、升降速率表三个核心仪表。

项目的核心代码只有几百行,全部使用 Python 标准库之外的 Pygame 实现,适合入门图形界面开发和游戏物理模拟。

1.3 为什么选择 Pygame

Pygame 是 Python 中最常用的 2D 游戏开发库,基于 SDL(Simple DirectMedia Layer)封装。它具备以下优势:

  • 不需要安装复杂的游戏引擎,pip install pygame即可使用。
  • 提供窗口管理、事件处理、图形绘制、音频播放等完整功能。
  • 文档和社区资料丰富,遇到问题容易排查。
  • 适合教学和轻量级项目,代码可读性高。

对我们这个“驾驶模拟器”需求来说,Pygame 的绘图和事件反馈机制刚刚好。

2. 环境准备与版本说明

2.1 开发环境

本文示例以常见环境为准,版本需要根据你的实际开发环境适当调整:

  • 操作系统:Windows / macOS / Linux 均可。
  • Python:3.8 及以上版本。
  • Pygame:2.x 版本。
  • 开发工具:VS Code、PyCharm、或任意支持 Python 的文本编辑器。

如果电脑上还没有安装 Pygame,可以通过 pip 直接安装:

pip install pygame

安装完成后,可以通过一条命令快速验证:

python -m pygame.examples.audiowin

这个命令会打开一个 Pygame 示例窗口,如果窗口正常显示,说明环境没问题。

2.2 项目目录结构

为了让文章内容更清晰,我会按以下目录组织项目:

plane_simulator/ ├── main.py # 程序入口 └── requirements.txt # 依赖声明

虽然真实项目中往往会把飞机类、物理逻辑、仪表绘制拆成独立模块,但对于入门演示,单文件能降低阅读和调试成本。文章最后会补充模块化拆分建议。

2.3 核心依赖声明

requirements.txt内容如下:

pygame>=2.1.0

如果后续准备做更复杂的扩展,再考虑引入 NumPy 做矩阵运算、Pymunk 做碰撞物理等。本文不引入额外依赖。

3. 飞行模拟核心原理拆解

3.1 真实飞行中的四大作用力

在真实飞行中,飞机主要受到四个作用力:

作用力方向来源
重力垂直向下地球引力
升力垂直于机翼向上机翼上下表面压力差
推力沿机身轴线向前发动机
阻力沿机身轴线向后空气摩擦力与压差阻力

水平飞行时,推力近似等于阻力,升力近似等于重力。飞机转弯、爬升、下降时,这些力会发生更复杂的变化。

完整的飞行力学模型要考虑空气密度、机翼面积、升力系数、阻力系数等参数,计算量较大。对于入门级模拟器,我们没有必要完全复刻气动方程,而是采用简化运动学模型。

3.2 2D 飞行模型的简化思路

本文把飞机压缩到二维平面内,只考虑水平方向和垂直方向的变化。

核心状态量有三个:

  • 空速speed:飞机在当前环境中的前进速度。
  • 俯仰角pitch:机头相对水平线的角度,正值为抬头。
  • 油门throttle:油门大小,范围在 0 到 1 之间。

通过俯仰角和空速,可以计算飞机的水平速度和垂直速度:

水平速度 = speed * cos(pitch) 垂直速度 = speed * sin(pitch)

在 Pygame 的屏幕坐标系中,y 轴方向向下(顶部为 0),所以模型里的“向上抬头”对应 y 坐标减小。

用一个简化公式描述油门对空速的影响:

加速度 = 油门 * 推力系数 - 阻力系数 * 当前速度

这样做的好处是:油门越大,速度增长越快;但速度越大,阻力也越大,最终会收敛到一个平衡速度,避免出现无限加速的不真实情况。

3.3 仪表盘的核心参数

为了让驾驶者知道飞机当前状态,仪表盘需要展示几个关键数据:

  • 空速(Speed):飞机相对空气的速度,单位可以自定,例如像素/秒。
  • 高度(Altitude):飞机离地面的高度,同样以像素为单位。
  • 升降速率(Climb Rate):飞机每秒钟上升或下降多少像素,正值表示上升,负值表示下降。

这三个参数互为因果,能直观反映当前驾驶决策是否合理。例如抬头时升降速率变为正值,但空速会下降;低头时升降速率变为负值,空速会上升,这与真实飞机的基本直觉一致。

3.4 Pygame 的游戏循环机制

Pygame 程序本质上是一个不断循环执行的过程:

  1. 处理用户事件(键盘、鼠标、窗口关闭等)。
  2. 根据时间步长更新游戏状态。
  3. 绘制当前画面。
  4. 控制帧率并进入下一帧。

核心代码如下:

clock = pygame.time.Clock() while running: dt = clock.tick(60) / 1000.0 # 处理事件 # 更新状态 # 绘制画面 pygame.display.flip()

clock.tick(60)会把帧率限制在 60 FPS,并返回上一帧经历的毫秒数。这个值除以 1000 转为秒,就是时间步长dt。每次更新状态时都乘以dt,可以保证不同帧率下运动速度保持一致。

4. 完整实战:Pygame 飞机驾驶模拟器

现在进入核心部分。我会从零搭建这个飞行模拟器,代码可以复制后直接运行。

4.1 创建项目文件

在项目目录下创建main.py,并粘贴以下代码。

4.2 初始化与全局常量

# 文件路径:plane_simulator/main.py import math import sys import pygame # 初始化 Pygame,包括字体模块 pygame.init() pygame.font.init() # 屏幕尺寸 SCREEN_WIDTH = 1000 SCREEN_HEIGHT = 800 # 地面高度(像素) GROUND_Y = 580 # 仪表面板顶部位置 PANEL_Y = 650 # 帧率 FPS = 60 # 颜色定义 SKY_BLUE = (135, 206, 235) GROUND_GREEN = (34, 139, 34) PANEL_GRAY = (210, 215, 220) WHITE = (255, 255, 255) BLACK = (20, 20, 20) RED = (200, 30, 30) ORANGE = (230, 126, 34) CLOUD_WHITE = (255, 255, 255)

这里需要解释几个点:

  • pygame.font.init()用于初始化字体模块,后续绘制仪表文字时需要用到。
  • 屏幕设置为 1000x800,底部预留了 150 像素高度的仪表面板区域。
  • GROUND_Y表示地面在屏幕坐标中的纵坐标,飞机的 y 坐标由其高度换算而来。

4.3 飞机类

接下来定义飞机类。飞机负责维护自身状态,并接收键盘输入进行状态更新。

class Plane: def __init__(self, start_x, start_y, start_altitude): # 屏幕坐标 self.x = start_x self.y = start_y # 高度(像素,相对地面) self.altitude = start_altitude # 空速(像素/秒) self.speed = 120.0 # 俯仰角(弧度,正值表示抬头) self.pitch = 0.0 # 油门(0~1) self.throttle = 0.6 # 升降速率(像素/秒,正值表示上升) self.climb_rate = 0.0 # 参数边界 self.min_speed = 0.0 self.max_speed = 420.0 self.max_throttle = 1.0 self.max_pitch = math.radians(40) def update(self, dt): # 1. 根据油门和阻力计算加速度 accel = self.throttle * 160 - 0.04 * self.speed self.speed += accel * dt self.speed = max(self.min_speed, min(self.max_speed, self.speed)) # 2. 限制俯仰角在正负 40 度之间 self.pitch = max(-self.max_pitch, min(self.max_pitch, self.pitch)) # 3. 计算升降速率 self.climb_rate = self.speed * math.sin(self.pitch) # 4. 更新水平位置 self.x += self.speed * math.cos(self.pitch) * dt # 5. 更新高度,限制最小值避免穿过地面 self.altitude += self.climb_rate * dt self.altitude = max(10.0, self.altitude) # 6. 将高度换算为屏幕纵坐标 self.y = GROUND_Y - self.altitude def handle_keys(self, dt): keys = pygame.key.get_pressed() # 上键抬头,下键低头 if keys[pygame.K_UP]: self.pitch += 1.2 * dt if keys[pygame.K_DOWN]: self.pitch -= 1.2 * dt # 左键减小油门,右键增大油门 if keys[pygame.K_LEFT]: self.throttle -= 0.3 * dt if keys[pygame.K_RIGHT]: self.throttle += 0.3 * dt # 限制油门范围 self.throttle = max(0.0, min(self.max_throttle, self.throttle))

这个类最关键的方法是update。它按照“速度模型 -> 俯仰角限制 -> 升降速率 -> 位置更新”的顺序执行。

4.4 绘制仪表盘

仪表盘是飞行的眼睛。为了让代码更容易复用,我把一个圆形仪表封装成函数。

def polar_to_cartesian(cx, cy, radius, angle_deg): """角度转屏幕坐标,angle_deg=0 时指向圆顶,顺时针旋转""" rad = math.radians(angle_deg) x = cx + radius * math.sin(rad) y = cy - radius * math.cos(rad) return x, y
def draw_gauge(screen, cx, cy, radius, title, value, min_val, max_val): """在指定位置绘制一个圆形仪表盘""" center = (cx, cy) # 仪表盘背景 pygame.draw.circle(screen, (240, 245, 248), center, radius) pygame.draw.circle(screen, BLACK, center, radius, 2) # 字体 small_font = pygame.font.Font(None, 18) mid_font = pygame.font.Font(None, 22) # 绘制刻度 num_ticks = 20 for i in range(num_ticks + 1): angle = 135 + (i / num_ticks) * 270 major = i % 4 == 0 start_r = radius - 10 if major else radius - 5 end_r = radius - 2 start = polar_to_cartesian(cx, cy, start_r, angle) end = polar_to_cartesian(cx, cy, end_r, angle) pygame.draw.line(screen, BLACK, start, end, 2 if major else 1) # 主刻度上显示数值 if major: tick_value = min_val + (max_val - min_val) * i / num_ticks label = small_font.render(str(int(tick_value)), True, BLACK) pos = polar_to_cartesian(cx, cy, radius - 18, angle) label_rect = label.get_rect(center=pos) screen.blit(label, label_rect) # 指针位置 norm = (value - min_val) / (max_val - min_val) norm = max(0.0, min(1.0, norm)) pointer_angle = 135 + norm * 270 pointer_end = polar_to_cartesian(cx, cy, int(radius * 0.65), pointer_angle) pygame.draw.line(screen, RED, center, pointer_end, 3) # 仪表中心圆点 pygame.draw.circle(screen, BLACK, center, 4) # 仪表标题和当前数值 title_surface = mid_font.render(title, True, BLACK) title_rect = title_surface.get_rect(center=(cx, cy - 22)) screen.blit(title_surface, title_rect) value_surface = mid_font.render(f"{value:.1f}", True, BLACK) value_rect = value_surface.get_rect(center=(cx, cy + 18)) screen.blit(value_surface, value_rect)

仪表盘的坐标转换是这段代码里的重点。polar_to_cartesian约定角度 0 度在圆顶部,顺时针增加。135 度表示左下角,405 度等价于右下角,正好跨过 270 度的扇形区域。

4.5 绘制飞机与背景

飞机的图形本质上是一个多边形,通过局部坐标定义形状,再根据俯仰角旋转。

def draw_plane(screen, plane): # 飞机局部坐标,机头朝右 local_points = [ (45, 0), # 机头 (18, -10), # 机身右上方 (-10, -16), # 机翼右端 (-20, -16), # 机翼左端 (-30, -8), # 尾部右上方 (-35, -4), # 尾翼末端 (-35, 4), # 尾翼下方 (-30, 8), # 尾部右下 (-20, 16), # 机翼左下 (-10, 16), # 机翼下 (18, 10), # 机身右下 ] cos_p = math.cos(plane.pitch) sin_p = math.sin(plane.pitch) points = [] for px, py in local_points: # 注意:屏幕坐标系 y 轴向下,因此旋转矩阵与数学坐标相反 rx = px * cos_p + py * sin_p ry = -px * sin_p + py * cos_p points.append((plane.x + rx, plane.y + ry)) pygame.draw.polygon(screen, RED, points) pygame.draw.polygon(screen, BLACK, points, 2)

背景绘制函数包含天空、云朵和地面。

def draw_background(screen): # 天空背景 screen.fill(SKY_BLUE) # 云朵 pygame.draw.ellipse(screen, CLOUD_WHITE, (100, 80, 130, 45)) pygame.draw.ellipse(screen, CLOUD_WHITE, (140, 60, 90, 35)) pygame.draw.ellipse(screen, CLOUD_WHITE, (720, 130, 140, 40)) pygame.draw.ellipse(screen, CLOUD_WHITE, (750, 110, 80, 30)) # 地面 pygame.draw.rect(screen, GROUND_GREEN, (0, GROUND_Y, SCREEN_WIDTH, SCREEN_HEIGHT - GROUND_Y))

4.6 主循环与仪表面板布局

最后是主函数。它创建窗口、实例化飞机、进入游戏循环,并在底部面板上绘制仪表。

def main(): screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption("2D 飞机驾驶模拟器 - Pygame") clock = pygame.time.Clock() plane = Plane(180, GROUND_Y - 250, 250) running = True while running: # 限制帧率,并取得时间步长 dt = clock.tick(FPS) / 1000.0 # 处理事件 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 更新飞机状态 plane.handle_keys(dt) plane.update(dt) # 绘制场景 draw_background(screen) draw_plane(screen, plane) # 绘制仪表面板背景 pygame.draw.rect(screen, PANEL_GRAY, (0, PANEL_Y, SCREEN_WIDTH, SCREEN_HEIGHT - PANEL_Y)) # 三个核心仪表 draw_gauge(screen, 180, 730, 42, "SPEED", plane.speed, 0, 420) draw_gauge(screen, 330, 730, 42, "ALT", plane.altitude, 0, 600) draw_gauge(screen, 480, 730, 42, "CLIMB", plane.climb_rate, -200, 200) # 刷新画面 pygame.display.flip() pygame.quit() sys.exit() if __name__ == "__main__": main()

4.7 运行与验证

在项目目录执行:

python main.py

预期效果如下:

  • 打开一个 1000x800 的窗口。
  • 蓝色天空、绿色地面、白色云朵。
  • 一架红色飞机位于屏幕左侧约 250 米高度位置。
  • 底部面板上有三个仪表,分别显示速度、高度和升降速率。

按键盘方向键:

  • ↑:飞机抬头,高度上升,速度逐渐下降。
  • ↓:飞机低头,高度下降,速度逐渐加快。
  • →:油门增大,速度上升,飞机更有动力。
  • ←:油门减小,速度下降,飞机开始下坠。

通过调整俯仰角和油门,可以让飞机进入相对稳定的平飞状态:此时空速较快、高度几乎不变、升降速率接近 0。

5. 常见问题与排查思路

5.1 窗口打开后立即闪退

问题现象常见原因解决思路
窗口一闪而过Pygame 未正确初始化确认代码中调用pygame.init()
窗口一闪而过主循环结束条件被误触发检查事件处理中的QUIT逻辑
启动报错pygame.error字体模块未初始化调用pygame.font.init()

排查步骤:

  1. 在代码开头打印一条测试语句,确认程序执行到了哪里。
  2. 把main()调用放在if __name__ == "__main__":下。
  3. 使用命令行运行,直接查看报错信息。

5.2 飞机瞬间飞出屏幕

问题现象常见原因解决思路
飞机一秒内消失更新位置时没有乘以时间步长dt所有运动更新都需要乘以dt
飞机高度变成负数俯仰角或速度过大限制俯仰角范围,并对高度设置最小值

dt的正确使用是游戏开发的常识性问题。如果忘记乘以dt,运动速度会与帧率强相关,高帧率时飞快,低帧率时缓慢。

5.3 仪表指针数值显示为 0

问题现象常见原因解决思路
指针一直指向最小值Plane对象没有传入仪表绘制函数确认plane实例存在并传入
指针指向异常数值未归一化到 0~1检查(value - min_val) / (max_val - min_val)
数值显示为 0仪表单位和飞机速度单位不一致统一单位,建议全部使用像素

5.4 键盘按键无响应

问题现象常见原因解决思路
按方向键没有反应窗口没有获得焦点点击窗口后再按键
按键反应迟钝把按键判断写在事件循环中需要使用pygame.key.get_pressed()检测持续按键
按键冲突多个按键同时按下get_pressed()本身支持同时检测,需要在更新中处理逻辑

6. 最佳实践与工程建议

6.1 物理模型与界面分离

前面的单文件实现简单清晰,但后续如果要扩展,建议把代码拆成独立模块:

plane_simulator/ ├── main.py # 主循环 ├── plane.py # 飞机状态与物理 ├── instruments.py # 仪表绘制 ├── world.py # 背景与环境 └── config.py # 常量配置

物理模型不应该把 Pygame 的绘制代码混在一起,否则后面替换渲染层会非常痛苦。比如你想将项目改为命令行模拟,或接入 WebSocket 显示仪表数据,拆分会轻松很多。

6.2 使用固定时间步长

目前的主循环使用clock.tick(FPS) / 1000.0作为时间步长,这在大多数机器上表现正常。但如果某帧绘制耗时过长,dt会偏大,可能导致物理计算出现跳变。

更稳健的做法是固定时间步长累积更新:

fixed_dt = 1 / 60 accumulator = 0.0 while running: frame_time = clock.tick(FPS) / 1000.0 accumulator += frame_time while accumulator >= fixed_dt: plane.update(fixed_dt) accumulator -= fixed_dt

这种方式可以减少物理模型对帧率波动的敏感度,适合继续扩展复杂物理运算。

6.3 仪表刻度参数化

draw_gauge虽然已经封装为通用函数,但刻度数量、颜色、量程都是硬编码,后续调整不够灵活。可以进一步改造成一个Gauge类:

class Gauge: def __init__(self, title, min_val, max_val, unit="px/s"): self.title = title self.min_val = min_val self.max_val = max_val self.unit = unit def draw(self, screen, cx, cy, radius, value): ...

做成对象后,可以在配置阶段统一创建仪表,主循环只负责传值,页面布局也更清晰。

6.4 参数和安全边界

模拟器是教学项目,不会带来真实飞行安全风险,但代码中的边界条件仍然值得关注:

  • 高度最小值:防止飞机穿过地面。
  • 俯仰角范围:防止飞机垂直翻转。
  • 速度范围:防止数值溢出。

如果未来接入真实飞行数据,或者把模拟器用于飞行训练辅助,必须重视这些边界条件的工程化设计,同时加入异常报警机制。

6.5 日志与调试信息

在开发调试阶段,推荐在终端输出关键状态:

print(f"speed={plane.speed:.1f}, altitude={plane.altitude:.1f}, climb={plane.climb_rate:.1f}")

如果仪表数值与预期不符,通过日志能快速定位是物理模型的问题还是绘制函数的问题。

7. 总结与学习路线

7.1 核心收获

通过这个项目,我们完成了三件事:

  1. 理解了飞行仪表的基本含义:空速、高度、升降速率。
  2. 掌握了 Pygame 游戏循环、键盘交互、图形绘制的完整流程。
  3. 实现了一个从物理模型到仪表显示的闭环驾驶模拟器。

代码本身并不复杂,但它把抽象物理概念变成了可以交互的图形程序,这是教学和快速原型开发最有价值的地方。

7.2 进阶方向

如果你打算继续深入,推荐以下方向:

  • 物理模型升级:加入升力系数、阻力系数、空气密度,让飞机更容易失速和悬停,更贴近真实飞机特性。
  • 3D 渲染:使用 Ursina、Panda3D 或 Godot 引擎,实现第一人称驾驶舱视角。
  • 地图与导航:加入滚动大地图,结合经纬度坐标和罗盘仪表。
  • 数据记录回放:把飞机状态写入 CSV,后续使用分析工具查看飞行轨迹。
  • 接入真实硬件:使用 Arduino 制作操纵杆和油门踏板,通过串口读取输入。

这篇文章的核心是帮助你把“驾驶飞机”的概念用工程手段落地。下一步,建议你动手修改代码中的参数,比如把推力系数从 160 改为 80,观察飞机是否还能保持平飞状态。参数变化带来的直观反馈,比任何理论讲解都更深刻。

如果本文对你有帮助,可以收藏备用,也欢迎对照代码多调几版参数,体验不同的飞行手感。

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

Google代理实操指南:三个策略让跨境电商订单量上涨

做跨境这几年,我最大的感受是:很多卖家把增长希望全押在平台内流量上,却忽略了Google这座原本就属于自己的矿。这里说的“Google代理”,我理解为两层意思,一是Google官方认证的广告投放代理服务商,二是通过…

作者头像 李华
网站建设 2026/10/7 5:09:27

两年日报实践:如何用结构化模板和索引机制提升工作复盘效率

写"Daily Report"这件事,我坚持了整整两年。每天花五分钟记录当天发生了什么,看似简单,真正做下来却踩了不少坑——一开始记成了流水账,后来变成了情绪发泄,再后来干脆断更一个月。直到我把这套日报体系彻底…

作者头像 李华
网站建设 2026/10/7 5:09:16

思科路由器配置实战:从CLI模式到OSPF、NAT与ACL的完整指南

简介:思科路由器配置命令详解及实例.docx是一份面向网络工程师、运维人员及CCNA学习者的技术手册,系统梳理了思科路由器从基础到进阶的配置要点。文档共45页,涵盖路由器配置基础(CLI模式、常用命令、IP寻址、静态路由)…

作者头像 李华
网站建设 2026/10/7 5:07:46

CLIP模型原理与实战:从对比学习到图文检索微调全解析

CLIP这个词,这两年但凡碰过多模态、搞过图文搜索、玩过Stable Diffusion的,基本都绕不开。但很多人对它的理解,就停在“一个能把图片和文本映射到同一个向量空间的模型”。真要读懂论文,或者想在自己项目里用好它,甚至…

作者头像 李华
网站建设 2026/10/7 5:07:46

AI工程化落地实战:大模型、Skills与MCP协议四层架构

1. 这不是资源清单,而是一份AI工程化落地的实战地图“压箱底全翻出来了”——这句话我看到时笑了。不是因为夸张,而是太真实。过去三年,我经手过27个AI辅助开发项目,从给制造业客户做缺陷识别模型,到帮设计团队搭低代码…

作者头像 李华
网站建设 2026/10/7 5:07:28

机箱前置USB3.1速度慢?PCIe扩展卡改造全攻略

最近帮朋友修一台 AMD 平台的台式机,折腾来折腾去,问题的根源特别典型:机箱前置的 USB 3.1 Type-C 口,平时插手机、插移动硬盘都没反应或者速度慢得离谱,拆开侧板一看,前置 USB 3.1 的排线确实接着&#xf…

作者头像 李华