资讯动态

Pygame游戏开发入门:从零搭建可跑跳Demo与避坑指南

发布时间:2026/10/25 10:30:10 来源:尧图企业网站定制
1. 从一行代码到一块画布Pygame 到底在做什么第一次接触 Pygame 的人脑子里往往有个很朴素的疑问我写 Python 写得好好的怎么突然就要跟“游戏”扯上关系了其实 Pygame 没那么玄乎它本质上就是一套帮你在屏幕上“画画”和“收键盘鼠标消息”的工具箱。你给它一个窗口尺寸它给你一块可以涂涂改改的画布你告诉它“把这张图贴到坐标 (100, 200)”它就在那一格像素上把图铺上去。就这么简单。我刚开始用 Pygame 的时候最大的感受是它不像那些大型游戏引擎那样把什么都替你包好反而更像一个“半成品”。窗口要自己建主循环要自己写每一帧要自己控制刷新。听起来麻烦但这恰恰是它适合新手的地方——你能亲眼看到游戏是怎么一帧一帧“跑”起来的而不是被引擎的黑盒吞掉所有细节。这篇文章适合谁看如果你已经会写 Python 的基本语法知道什么是变量、循环、函数但从来没碰过图形界面或者游戏开发那 Pygame 是一个非常好的起点。它不会一上来就甩给你一堆物理引擎、着色器、实体组件系统而是让你用最直白的方式理解“游戏循环”这件事。反过来如果你已经用过 Unity 或者 Godot再回头看 Pygame也能帮你把那些被引擎隐藏的底层逻辑补上。我打算按一个真实项目的推进节奏来写先搞清楚 Pygame 的安装和最小可运行结构再拆解它最核心的几个模块——显示、事件、时间、绘图、声音然后动手做一个能跑能跳的小 Demo最后把新手最容易踩的坑一个个列出来。整个过程不需要你有多强的数学功底但需要你愿意动手敲代码、跑起来看效果。注意Pygame 的版本更新比较频繁不同版本之间个别 API 会有细微差异。我下面用的写法以 Pygame 2.x 为准如果你用的是更早的版本遇到报错先查一下官方文档的版本迁移说明。2. 装好环境再谈其他Pygame 安装与最小可运行骨架2.1 安装 Pygame 的正确姿势与常见报错处理安装 Pygame 本身只有一行命令pip install pygame但就是这一行在不同系统上能折腾出不少花样。Windows 上一般很顺pip 会直接拉取预编译好的 wheel 包。macOS 上如果用的是 Apple Silicon 芯片早期版本可能需要从源码编译现在 2.x 版本基本都有对应的 arm64 wheel问题不大。Linux 上则要注意先装好 SDL 相关的系统依赖否则 pip 装完了 import 的时候会报找不到共享库。我实测下来最稳的做法是先确认 Python 版本在 3.8 以上然后用虚拟环境隔离项目。虚拟环境的好处是万一 Pygame 跟其他库有版本冲突你直接删掉整个环境重来就行不会污染系统 Python。python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install pygame装完之后别急着写游戏先跑一句验证import pygame print(pygame.version.ver)如果这行能打印出版本号说明安装没问题。如果报ModuleNotFoundError大概率是 pip 装到了另一个 Python 解释器下面检查一下which python和which pip是不是指向同一个环境。提示有些教程会让你装pygame1.9.6这种老版本除非你有明确的兼容性需求否则直接用最新稳定版就好。老版本在 Python 3.10 以上经常出问题。2.2 一个窗口、一个循环Pygame 程序的最小骨架Pygame 程序有一个几乎固定的骨架我把它叫做“四件套”初始化、建窗口、主循环、退出。任何复杂的游戏都是在这个骨架上长出来的。import pygame import sys pygame.init() screen pygame.display.set_mode((800, 600)) pygame.display.set_caption(我的第一个 Pygame 窗口) clock pygame.time.Clock() running True while running: for event in pygame.event.get(): if event.type pygame.QUIT: running False screen.fill((30, 30, 30)) pygame.display.flip() clock.tick(60) pygame.quit() sys.exit()这短短二十几行包含了 Pygame 最核心的几个概念。pygame.init()会把显示、声音、字体等子系统全部初始化一遍。set_mode返回的screen就是那块画布后面所有绘制操作都往它上面招呼。pygame.event.get()每一帧把事件队列里的消息全部取出来你不取队列就会越积越多窗口就会卡死。clock.tick(60)是帧率控制器它让循环每秒最多跑 60 次同时返回上一帧到这一帧经过了多少毫秒。很多人第一次写的时候会忘记screen.fill()结果窗口里全是上一帧的残影。Pygame 的绘制是“叠加”的你不清屏新画的东西就盖在旧内容上面。所以每一帧的顺序永远是处理事件、清屏、绘制、刷新显示。2.3 主循环为什么长这样帧率、事件与刷新的三角关系主循环是 Pygame 的心脏理解它比记住任何 API 都重要。你可以把主循环想象成一个不停转的轮子每一圈做四件事收消息、算状态、画画面、等一会儿。“等一会儿”这一步就是clock.tick(60)干的事。如果不加它循环会以 CPU 能跑多快就跑多快的速度疯狂转你的风扇会起飞而且游戏逻辑会因为帧率不稳定而变得诡异。加上它之后循环被限制在每秒 60 圈每圈大约 16.6 毫秒。这个 16.6 毫秒是有讲究的大多数显示器的刷新率是 60Hz也就是每秒刷新 60 次游戏帧率和显示器刷新率对齐画面看起来最顺滑。pygame.event.get()返回的是一个事件列表里面可能有键盘按下、鼠标移动、窗口关闭等各种消息。你遍历这个列表根据event.type决定怎么处理。这里有个新手常犯的错误把event.get()写在循环外面或者只调用一次。事件队列是“取走就没了”的机制你必须每一帧都把它清空否则系统会认为你的程序没有响应。pygame.display.flip()和pygame.display.update()的区别也值得说一句。flip()会把整个屏幕重绘一遍update()可以只更新你指定的矩形区域。对于小游戏来说两者性能差异可以忽略用flip()更省心。但如果你以后做大地图或者粒子效果update()按区域刷新能省不少性能。3. 把画面动起来显示、绘图与坐标系统3.1 坐标系与矩形Pygame 里一切位置的基础Pygame 的坐标系跟数学课上学的那个不太一样。原点(0, 0)在窗口的左上角x 轴向右递增y 轴向下递增。这意味着 y 值越大位置越靠下。刚开始可能会不习惯但记住“左上角是起点往下往右都是加”就行了。Pygame 里最常用的位置表示是Rect对象。它用四个数描述一个矩形x、y是左上角坐标width、height是宽高。Rect 有很多方便的属性比如center、centerx、centery、left、right、top、bottom你可以直接读写这些属性来移动矩形不用自己算坐标。rect pygame.Rect(100, 100, 50, 50) rect.center (400, 300) # 直接把矩形中心挪到窗口正中Rect 还支持碰撞检测两个 Rect 之间用colliderect()就能判断是否重叠。这个功能在游戏里太有用了子弹打敌人、角色踩平台底层都是矩形碰撞。虽然它只能做轴对齐的矩形检测对于大多数 2D 游戏来说已经够用。3.2 绘制基本图形矩形、圆、线条与多边形Pygame 的draw模块提供了一组画基本图形的函数它们都是往screen上直接画不需要额外的对象。pygame.draw.rect(screen, (255, 0, 0), (100, 100, 80, 60)) pygame.draw.circle(screen, (0, 255, 0), (400, 300), 50) pygame.draw.line(screen, (0, 0, 255), (0, 0), (800, 600), 3) pygame.draw.polygon(screen, (255, 255, 0), [(200, 200), (300, 150), (350, 250)])每个函数的参数顺序略有不同但基本是画布、颜色、位置或点列表、线宽。颜色用 RGB 三元组表示每个分量 0 到 255。线宽是可选的不写就是填充。这里有个细节draw.rect的第三个参数可以是一个Rect对象也可以是一个四元组。如果你传四元组它内部会临时创建一个 Rect。频繁绘制的时候提前创建好 Rect 对象复用比每次传四元组稍微省一点开销不过对于小游戏来说这点差异可以忽略。注意draw函数画出来的图形是“实心”的除非你指定线宽。比如draw.rect不传线宽就是填充矩形传了线宽就变成空心边框。这个行为跟有些图形库相反别搞混了。3.3 加载与显示图片从文件到屏幕的完整链路画基本图形只能做原型真正做游戏还是要用图片。Pygame 加载图片用pygame.image.load()player_img pygame.image.load(player.png).convert_alpha() player_rect player_img.get_rect() player_rect.center (400, 300) screen.blit(player_img, player_rect)这里有两个关键点。第一convert_alpha()是必须的它把图片转换成 Pygame 内部最适合快速绘制的像素格式同时保留透明通道。不加这个每帧绘制时 Pygame 都要做一次格式转换帧率会明显下降。第二blit()是“贴图”操作把一张图贴到另一张图上。它的第二个参数可以是坐标元组也可以是 Rect 对象。图片的透明通道靠 PNG 格式的 alpha 通道实现。如果你用 JPG它没有透明信息图片周围会带一个白色或黑色的方框。所以做游戏素材优先用 PNG。图片的缩放用pygame.transform.scale()旋转用pygame.transform.rotate()。这两个操作都比较耗时不要在每一帧里对同一张图反复缩放旋转。正确的做法是在游戏初始化阶段就把图片处理成需要的大小和角度存成变量主循环里直接 blit。4. 让玩家能操作事件处理与输入响应4.1 键盘事件按下、松开与持续按住的区别Pygame 的键盘事件有两种处理方式。一种是事件驱动KEYDOWN和KEYUP事件只在按键状态改变的那一瞬间触发一次。另一种是状态查询pygame.key.get_pressed()返回一个布尔序列告诉你当前哪些键正被按住。for event in pygame.event.get(): if event.type pygame.KEYDOWN: if event.key pygame.K_SPACE: player_jump() keys pygame.key.get_pressed() if keys[pygame.K_LEFT]: player_x - speed if keys[pygame.K_RIGHT]: player_x speed这两种方式适用的场景不同。跳跃、射击、确认这类“一次性动作”用事件驱动更合适因为你不希望按住空格就连续跳。左右移动、加速这类“持续状态”用get_pressed()更自然因为玩家按住方向键就应该一直移动。我见过不少新手把移动也写成 KEYDOWN 事件结果按一下动一下手感极其僵硬。记住这个区分状态用查询动作用事件。4.2 鼠标事件点击、移动与滚轮鼠标事件同样有事件驱动和状态查询两套。MOUSEBUTTONDOWN和MOUSEBUTTONUP对应按下和松开event.button告诉你按的是左键1、中键2还是右键3。MOUSEMOTION在鼠标移动时触发event.pos是当前坐标event.rel是相对上一帧的位移。for event in pygame.event.get(): if event.type pygame.MOUSEBUTTONDOWN: if event.button 1: print(左键点击了, event.pos) if event.type pygame.MOUSEMOTION: mouse_x, mouse_y event.pospygame.mouse.get_pos()可以随时获取鼠标当前位置不用等事件。做拖拽、瞄准这类功能时直接查询位置比监听 MOUSEMOTION 更简单。滚轮事件在 Pygame 2.x 里是MOUSEWHEELevent.y表示滚动方向正数向上负数向下。老版本里滚轮被当作按钮 4 和 5 处理如果你看到老代码里判断event.button 4那就是滚轮向上。4.3 事件队列的坑为什么你的窗口会“无响应”事件队列是 Pygame 跟操作系统之间的消息通道。操作系统把键盘、鼠标、窗口消息塞进这个队列你的程序每一帧把它取空。如果你不取队列满了之后操作系统就会认为你的程序卡死了窗口标题栏会显示“无响应”。我踩过的一个坑是在事件循环里做了耗时操作。比如按下一个键之后在事件处理分支里跑了一个几百毫秒的计算这期间事件队列没人管窗口就卡住了。正确的做法是事件处理只做标记和状态切换真正的重活放到主循环的更新阶段去做或者用单独的线程处理。另一个坑是pygame.event.get()和pygame.event.poll()混用。poll()每次只取一个事件如果你在一个循环里既用get()又用poll()事件会被两处瓜分导致某些事件丢失。选定一种方式从头用到尾。5. 动手做一个能跑能跳的小 Demo5.1 需求拆解这个 Demo 要有什么光讲概念容易飘我们直接做一个最小可玩的 Demo。需求很简单一个窗口里面有一个方块代表玩家可以用左右方向键移动按空格跳跃地面有重力方块会落回地面。再加一个可以左右移动的障碍物碰到就重置位置。这个 Demo 覆盖了 Pygame 的几个核心环节主循环、事件处理、状态更新、绘制、碰撞检测。代码量不大但麻雀虽小五脏俱全。5.2 完整代码与逐段解析import pygame import sys pygame.init() WIDTH, HEIGHT 800, 600 screen pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption(跑跳 Demo) clock pygame.time.Clock() # 玩家属性 player pygame.Rect(100, 400, 40, 60) player_vx 0 player_vy 0 on_ground False GRAVITY 0.8 JUMP_POWER -15 MOVE_SPEED 5 # 地面 ground pygame.Rect(0, 500, WIDTH, 100) # 障碍物 obstacle pygame.Rect(600, 460, 40, 40) obstacle_speed 3 font pygame.font.SysFont(simhei, 24) running True while running: for event in pygame.event.get(): if event.type pygame.QUIT: running False if event.type pygame.KEYDOWN: if event.key pygame.K_SPACE and on_ground: player_vy JUMP_POWER on_ground False keys pygame.key.get_pressed() player_vx 0 if keys[pygame.K_LEFT]: player_vx -MOVE_SPEED if keys[pygame.K_RIGHT]: player_vx MOVE_SPEED # 物理更新 player.x player_vx player_vy GRAVITY player.y player_vy # 地面碰撞 if player.bottom ground.top: player.bottom ground.top player_vy 0 on_ground True # 边界限制 if player.left 0: player.left 0 if player.right WIDTH: player.right WIDTH # 障碍物移动 obstacle.x obstacle_speed if obstacle.right WIDTH or obstacle.left 0: obstacle_speed -obstacle_speed # 碰撞检测 if player.colliderect(obstacle): player.x 100 player.y 400 player_vy 0 # 绘制 screen.fill((40, 44, 52)) pygame.draw.rect(screen, (100, 200, 100), ground) pygame.draw.rect(screen, (200, 80, 80), player) pygame.draw.rect(screen, (80, 120, 220), obstacle) text font.render(方向键移动空格跳跃, True, (255, 255, 255)) screen.blit(text, (20, 20)) pygame.display.flip() clock.tick(60) pygame.quit() sys.exit()这段代码里物理更新部分是最值得琢磨的。player_vy GRAVITY每一帧给垂直速度加上重力player.y player_vy再把速度应用到位置上。这就是最简单的欧拉积分虽然不够精确但对于这种小 Demo 完全够用。跳跃的实现有个细节on_ground标记。只有在地面上的时候按空格才能跳否则在空中可以无限跳那就变成“空中飞人”了。on_ground在落地时设为 True起跳时设为 False。碰撞检测用的是colliderect()它返回两个 Rect 是否重叠。重叠之后我把玩家位置重置到起点这是一种最简单的“碰撞响应”。真实游戏里可能会扣血、播放动画、击退但原理是一样的。5.3 参数调优重力、跳跃力与手感的关系上面代码里的GRAVITY 0.8和JUMP_POWER -15不是随便写的。它们决定了跳跃的高度和滞空时间。你可以自己改这两个数感受一下重力越大下落越快跳跃越“重”。跳跃力越大负得越多跳得越高。跳跃力除以重力大致决定了跳到最高点需要多少帧。比如 15 / 0.8 约等于 18.75 帧按 60 帧每秒算大约 0.31 秒到达最高点。手感这个东西很主观但有一个经验大多数平台跳跃游戏从起跳到落回地面的总时间在 0.5 到 0.8 秒之间比较舒服。你可以用这个作为调参的起点然后微调。提示如果你想让跳跃有“可变高度”——按住空格跳得高轻点跳得低——可以在松开空格的时候如果player_vy还是负数就把它乘以一个小于 1 的系数比如 0.5。这样上升速度会骤减跳跃高度就下来了。6. 新手最容易踩的八个坑与排查思路6.1 窗口一闪而过或者直接卡死窗口一闪而过通常是主循环没有正确保持。检查running变量是不是在某个地方被意外设成了 False或者while循环的条件写错了。另一个常见原因是pygame.event.get()没有在循环里调用导致 QUIT 事件没被处理但这种情况一般是卡死而不是闪退。卡死的话先看事件循环是不是被某个耗时操作堵住了。可以在循环里加一句print(pygame.time.get_ticks())看看每帧的时间间隔是不是稳定在 16 毫秒左右。如果某几帧突然变成几百毫秒那就是那里有阻塞。6.2 图片加载失败或显示成黑块图片加载失败首先检查路径。Pygame 的相对路径是相对于“当前工作目录”不是相对于脚本文件所在目录。如果你在 IDE 里运行工作目录可能是项目根目录也可能是脚本目录很容易搞混。稳妥的做法是用os.path.join(os.path.dirname(__file__), assets, player.png)拼绝对路径。显示成黑块通常是忘了convert()或convert_alpha()。没有转换的 Surface 在 blit 的时候会做实时格式转换有时候会出问题。另外如果图片本身有透明背景但你没用convert_alpha()透明部分会变成黑色。6.3 帧率不稳定或者 CPU 占用过高帧率不稳定的头号原因是clock.tick()的位置不对。它应该放在主循环的最后所有绘制完成之后。如果你把它放在循环开头那它控制的是“上一帧结束到这一帧开始”的时间逻辑上也能跑但容易让人困惑。CPU 占用过高一般是两个原因要么没加clock.tick()循环全速跑要么在循环里做了大量重复计算比如每帧都重新加载图片、重新渲染文字。图片和字体渲染的结果应该缓存起来不要每帧重做。6.4 事件处理中的典型错误最常见的错误是在for event in pygame.event.get()循环里又调用了pygame.event.get()。这会导致事件被两层循环瓜分行为变得不可预测。记住事件队列只在一个地方取取出来的事件在同一个循环里处理完。另一个错误是混淆event.key和event.unicode。event.key是键码比如pygame.K_a适合做控制。event.unicode是字符比如a或A适合做文本输入。做游戏控制用event.key做聊天框输入用event.unicode。6.5 碰撞检测不准或穿透colliderect()做的是矩形重叠检测它不管两个物体在这一帧里移动了多远。如果物体移动速度很快比如一帧移动 50 像素而障碍物只有 20 像素宽那物体可能这一帧在障碍物左边下一帧已经在右边了中间的重叠状态被跳过就发生了“穿透”。解决穿透有两种思路。一种是限制最大速度让每帧位移小于最小障碍物尺寸。另一种是做“连续碰撞检测”在移动路径上采样多个点逐个检测。对于小游戏限制速度通常就够了。如果速度必须很快可以在移动前先算好目标位置然后分几步移动每步检测一次。6.6 文字显示成方块或乱码中文显示成方块是因为默认字体不支持中文。pygame.font.SysFont()可以指定字体名比如simhei、microsoftyahei。但更稳妥的方式是用pygame.font.Font()直接加载一个字体文件font pygame.font.Font(assets/simhei.ttf, 24)这样不管系统有没有装这个字体都能正常显示。字体文件要跟游戏一起打包别指望用户系统里一定有。6.7 退出时资源没有释放pygame.quit()会关闭所有 Pygame 子系统释放显示、声音等资源。如果你在退出前还持有 Surface 或 Sound 对象的引用它们会在quit()之后失效。所以正确的顺序是先退出主循环再pygame.quit()最后sys.exit()。如果你用了pygame.mixer播放音乐最好在quit()之前先pygame.mixer.music.stop()避免退出时音频线程还在跑导致卡顿。6.8 打包成可执行文件后的路径问题用 PyInstaller 打包之后__file__的路径会变资源文件的相对路径全部失效。解决办法是用sys._MEIPASS判断是否在打包环境中运行import sys, os def resource_path(relative): if hasattr(sys, _MEIPASS): return os.path.join(sys._MEIPASS, relative) return os.path.join(os.path.abspath(.), relative)这个函数在开发环境和打包环境都能正确找到资源。打包的时候记得把 assets 目录一起加进去PyInstaller 用--add-data参数指定。7. 从 Demo 到小项目下一步可以怎么扩展7.1 加入精灵类与精灵组当游戏里的对象超过三四个用 Rect 一个个手动管理就有点乱了。Pygame 提供了Sprite类和Group类来帮你组织。Sprite 是一个带图像和矩形的对象Group 可以批量更新和绘制 Sprite。class Player(pygame.sprite.Sprite): def __init__(self): super().__init__() self.image pygame.Surface((40, 60)) self.image.fill((200, 80, 80)) self.rect self.image.get_rect() self.rect.topleft (100, 400) self.vy 0 def update(self): self.vy GRAVITY self.rect.y self.vy if self.rect.bottom 500: self.rect.bottom 500 self.vy 0用 Sprite 的好处是碰撞检测可以用pygame.sprite.spritecollide()一次性检测一个精灵和一组精灵的碰撞不用自己写循环。对于子弹、敌人、道具这类数量多的对象Sprite 和 Group 能省很多代码。7.2 用 Surface 做离屏渲染与图层管理Pygame 的 Surface 不一定是屏幕你可以创建任意大小的 Surface 作为“离屏画布”。比如做视差滚动背景可以把远山、近树分别画在不同的 Surface 上然后以不同速度移动它们。bg_far pygame.Surface((WIDTH, HEIGHT)) bg_far.fill((50, 50, 80)) # 在 bg_far 上画远处的山 screen.blit(bg_far, (0, 0))离屏渲染的另一个用途是做 UI 层。把血条、分数、按钮画在一个独立的 Surface 上最后统一 blit 到屏幕这样 UI 不会被游戏世界的绘制操作干扰。7.3 声音与音乐让 Demo 有反馈Pygame 的mixer模块负责声音。初始化的时候用pygame.mixer.init()然后加载音效jump_sound pygame.mixer.Sound(assets/jump.wav) jump_sound.play()背景音乐用pygame.mixer.music.load()和pygame.mixer.music.play(-1)-1表示循环播放。音效和音乐是两套不同的通道音效可以多个同时播放音乐同一时间只能有一首。注意mixer.init()有时候会因为音频设备问题报错尤其是在没有声卡的服务器上。可以用pygame.mixer.init()包在 try-except 里失败了就跳过声音功能不影响游戏主逻辑。7.4 用 Clock 与 Delta Time 做帧率无关的移动前面 Demo 里的移动速度是“每帧多少像素”这跟帧率绑定了。如果帧率从 60 掉到 30移动速度就减半。更专业的做法是用 delta timedt clock.tick(60) / 1000.0 # 转换成秒 player.x speed * dt这样速度的单位变成“每秒多少像素”不管帧率怎么变移动速度都是恒定的。对于简单游戏每帧固定速度也能用但如果你以后想支持不同刷新率的显示器delta time 是必须的。8. 一些让我少走弯路的实操心得Pygame 这个库说简单也简单说坑也多。我把自己踩过的几个印象深刻的点分享一下希望能帮你省点时间。第一个心得不要过早优化。我刚开始的时候总想着“这个循环能不能少跑一次”“这个 Surface 能不能复用”结果代码写得极其复杂bug 一堆。后来想通了先把功能跑通用clock.tick()把帧率稳住大部分小游戏在现在的电脑上都能跑满 60 帧。真遇到性能问题再用pygame.time.get_ticks()定位瓶颈别凭感觉猜。第二个心得颜色和坐标用常量。把(255, 0, 0)这种颜色值直接写在绘制调用里过两天自己都忘了哪个是玩家哪个是敌人。定义一组常量比如RED (255, 0, 0)、PLAYER_START (100, 400)代码可读性会好很多。第三个心得善用 print 调试。Pygame 的 bug 很多时候是逻辑问题不是崩溃。比如玩家卡在墙里、跳跃高度不对、碰撞没触发。在这些地方加一句print(player.rect, player.vy)跑几帧看看数值变化比盯着代码空想快得多。第四个心得素材先凑合。做原型的时候别花时间找美术资源用纯色矩形代替。等玩法确定了再替换成真正的图片。我见过太多人卡在“找不到合适的素材”这一步结果游戏逻辑一行没写。第五个心得多看官方文档的示例。Pygame 的文档不算特别详细但每个模块都有示例代码。遇到不熟悉的 API先看示例怎么用比在网上搜零散的教程靠谱。文档里的示例都是能直接跑的改一改就能用到自己项目里。最后说一个关于学习节奏的建议。Pygame 涉及的知识点其实不少图形、事件、声音、碰撞、动画、状态管理。别想着一次全学会。先做一个能显示窗口和移动方块的程序跑起来。然后加图片加声音加碰撞。每加一个功能跑一次确认没问题再加下一个。这种“小步快跑”的方式比一次性写几百行然后面对一堆报错要舒服得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑