← 所有文章

在 iPhone 上造一个像素艺术世界:16 位时代的大师们早就懂的事

Final Fantasy VI 的一名队员是 16×24 像素,战斗中可用的颜色只有 12 种,46 个姿势最多由 181 块图块拼成,而同一个 sprite 要走遍野外、世界地图和每一场战斗。1 Pokémon Emerald 用双层结构的 16×16“元图块”画出每一座城镇,地图上的一格是 16 位:10 位给图块,2 位给碰撞,4 位给高度。2 Celeste 以 320×180 渲染整个世界,再乘以 6。3 这三个数字里装着全部手艺:定下格子,定下调色板,定下画布,然后才在里面作画。我们自己的 app Kiradex 里有一座用 RealityKit 渲染的像素广场,可拿它对照这份记录,大多数项目都不及格:28 块图块是临时拍脑袋的平涂色,没有色阶,没有描边规则,没有遮挡,走路只有两帧。于是我认真做了功课:六份有出处的 SNES 时代调研报告、从反编译结果里读出的 Pokémon 图块系统、当代的大师们、手艺本身、Apple 的渲染路径,以及作为社交世界的收集类游戏。下面就是我当初希望有人写给我的那份指南,含全部数字、在 3 倍 iPhone 屏幕和 iPhone Duo 两块显示屏上保持像素锐利的实测配方,以及按规则重建我们这个世界后的第一批成果。

TL;DR

  • 大师们都是从约束往外推的。 SNES 给的是:16 色图块所用的 8 组背景调色板和 8 组 sprite 调色板(各 15 色)、8×8 的图块、每条扫描线 32 个 sprite。Square 的答案是一个 16×24 的格子、一座姿势库,外加图块共用。41 Game Boy 给的是四级灰度,Pokémon Red 的图块集装 96 块图块;Game Freak 的答案是 32×32 的区块,再加上一个不用多画一笔就能让草丛遮住你双脚的优先级位。56
  • 让一个像素世界读起来像同一个地方,靠的是三个决定: 统一的光照方向和阴影色相(Seiken Densetsu 3 团队用深蓝和紫色而不是黑色来上阴影)、对每个 sprite 都适用的同一条描边规则(FF VI 的剪影边缘有 93% 近乎纯黑,Secret of Mana 则一点黑都没有),以及用色相偏移的色阶而非一明一暗的色块。3389
  • 当代的光照分级表,底层还负担得起,顶层则足以拖垮一个团队。 Moonlighter 靠叠加 sprite 伪造光;Celeste 把所有灯光当作遮罩画进一张 2048 像素的图集;Eastward 为每个资源手绘凹凸贴图;HD-2D 用其制作人的话说“比你想的更贵”,而玩家会把它的景深关掉。10111213
  • 在 Apple 平台上,如果这个 2D 世界里只有一件真正的 3D 物体,就留在 RealityKit,并把它的 AR 默认项关掉。 像素艺术的每一项需求都有已写入文档的 API(nearest 采样器、不用 mipmap、不透明度阈值、逐帧 UV 变换),但 RealityView 默认会施加运动模糊和 HDR 色调映射,这份配方会连同景深、颗粒和抗锯齿一并关掉。141516 在我们这么做之前,走路的角色每迈一步都糊成一片。
  • iPhone 上的整数倍缩放,是用像素而不是点来做的算术。 在 3 倍下,一个纹素占六像素就是 2 点,所以 16 纹素的图块是 32 点;iPhone 18 Pro Max 在每纹素八像素时显示 10.3×22.4 块图块,展开的 iPhone Duo 在六像素时是 29.7×20.9 块,而现行 iPhone 没有一款的高度能被 320 整除,所以“正好 20 块高”永远意味着黑边。17
  • 自有素材、按规则绘制,才是干净的路。 美国版权局 2025 年 1 月的报告称,就著作权而言“提示词本身并不提供足够的控制”;画风不受保护,但具体的图块和角色受保护。于是我们造了一座“锻炉”,用一套 58 色调色板和手工设定的规则画出每一块图块,第一块试验田和重建后的广场放在文末。1819

1. 16 位大师们面对的是什么

Super Nintendo 没有帧缓冲。它的图像处理器必须每 186 纳秒吐出一个像素,而显存的响应要 100 纳秒,于是它从一张 8×8 图块构成的地图里预取八个像素,并在水平消隐期间把 sprite 拼进行缓冲。4 美术们所做的一切都源自于此。为了 16 色图块,256 项的色彩存储被切成 8 组背景调色板和 8 组 sprite 调色板,每组 15 色外加一个透明索引;背景用前半段,sprite 用后半段。21 sprite 有 8、16、32、64 像素见方四种,同时只能启用两种尺寸,对象存储里最多 128 个,而任何一条扫描线上最多 32 个 sprite 或 34 个八像素碎片,超出的部分直接消失。21 多数 RPG 所用模式(Mode 1)下的背景是两层 16 色加一层 4 色,而 Mode 7 是一张由 256 块图块组成的 1,024×1,024 像素图块地图22,可以逐扫描线施加仿射变换,把它压成一道地平线。23 显存一共只有 64 KB,图块地图、背景图块和 sprite 图块都挤在里面。20

另一堵墙是卡带容量。Final Fantasy IV 以 8 兆位出货,Final Fantasy V 是 16 兆位,Final Fantasy VI 是 24 兆位,Chrono Trigger 在后期从 24 扩到 32 兆位。Chrono Trigger 的总监时田贵司这样形容第一个数字的量级:“这张卡能塞下四个 FFIV。”至于多出来的八兆位,设计师 Yasuhiko Kamata 说“八兆里大概有六兆用在了图形上”。2425 坂口博信形容 FF V 的最后几个月,是全组人“能从彼此那里抢多少空间就抢多少”。26

观看:Graphics & Palettes, SNES Features Pt. 01, Retro Game Mechanics Explained

约束逼出来的做法

约束 数值 美术的应对
图块尺寸 8×8,16 色 以 8 像素为单元思考,拼出共用一组调色板和一种翻转的 16×16“元图块”20
每块图块的调色板 八组中的一组,15 色 把元图块关进同一组调色板;给草、石、木一组可跨城镇复用的中性调色板20
sprite 尺寸 8/16/32/64 见方,16×32 与 32×64 一个 16×24 的主角,是一个 16×16 对象加两个 8×8,或者一个留空行的 16×32;Chrono Trigger 里更高的 Crono 是逐帧摆位的 16×16 方块堆叠2127
sprite 图块索引 9 位,512 块 一名角色的整套姿势塞得进图块预算:FF VI 一名队员 181 块1
扫描线上限 32 个 sprite,272 个 sprite 像素 怪物放到背景层去;四个 16 宽的主角加上特效就已经逼近上限214
翻转 逐 sprite 的水平与垂直 对称姿势只画一次;Crono 的左脚就是右脚翻过来27
色彩运算 加、减、减半 水、幽灵和半透明文本框用 50% 混合;夜晚用减法28

我一再回头去看的那个数字,是姿势预算。sprite 编辑器为 FF VI 的每个角色列出 17 段动画和 13 个静态姿势,合计 46 个独立姿势,加上翻转约 92 个,每个姿势六块图块,姿势之间大量共用;走路和另外三个三姿势动画按 1-2-1-3 播放,所以屏幕上看到的是四帧循环。1 北濑佳范说 FF VI 的“图案数是 FF V 的两倍多”,正因如此,一个 sprite 才能同时服务野外和战斗。7 表现力来自帧数,而不是像素。

涩谷员子的方法

涩谷员子画了 Final Fantasy I 到 VI 的 sprite,并主导了 Pixel Remaster 的重绘。她对工作的自述,是这份记录中最清晰的方法论陈述。关于一个 sprite 从哪里起笔:“原则上我会说,我是从面而不是从线开始的。”然后“我先把大块面积粗粗填满,再一点点细化下去,像雕刻一样”。8 关于可辨识度:“玩家必须分得清角色,所以我看着设定稿,只保留最有特征的那几处。”29 关于 FF IV 的 16×16 sprite 为何没有描边:“每一个像素都是生死攸关的事,我根本没有余裕去想把它们用在轮廓上。”8 坂口博信补上了这在动画上的后果:“他们没法把手臂举得很高,所以表达高兴的唯一办法就是原地转圈!”8

观看:Kazuko Shibuya on 35 years of pixel art, Square Enix

插画师和像素美术是两个人,中间隔着一段文字。坂口博信说:“我们向天野先生约插画时,是用文字描述来下单的。”8 到了 Chrono Trigger,鸟山明“只画了角色插画和概念设定”,背面一次也没画过;sprite 组的 Uchiyama 说:“我们只能靠猜。”30 野村哲也把 FF VI 的最终 boss 画在速写本上,“一屏一屏地”画,扫描进来,再照着扫描件做出 sprite。31 到 1994 年,流程其实已经是混合式的:魔法特效先在另一套 3D 工具里建模,再叠上去。32

三种“观感”,量化来看

评论者把 FF VI、Chrono Trigger 和 Secret of Mana 统称为“SNES 的样子”,仿佛那是一回事。其实是三回事,而差别大半在描边方针上。我们从一个按动作逐段拆分的爱好者素材库里,各取一款游戏的一名主角,先确认每张都是精确的 2 倍放大,再把站立帧的每一个边缘像素归类为近乎纯黑(各通道均不超过 255 中的 40)、中间暗色或亮色。9

游戏与 sprite 近乎纯黑的边缘 中间暗色 亮色 读出来的意思
Final Fantasy VI,Terra 93% 4% 3% 硬朗的纯黑剪影
Breath of Fire II,Ryu 59% 37% 4% 受光一侧把黑描边放柔
Chrono Trigger,Crono 48% 51% 2% 一半黑,一半暗色
Seiken Densetsu 3,Duran 38% 54% 9% 选择性描边;黑色留在接地处
Secret of Mana,Randi 0% 100% 0% 没有黑;描边是更暗的固有色
EarthBound,Ness 0% 100% 0% 没有黑;深棕和藏青的边缘

更柔和的边缘,在 Mana 系列里是明确的意图。石井浩一谈 Seiken Densetsu 3:“阴影之类我们用的是深蓝和紫,而不是黑色的浓淡,为的是带出一种柔软感。”他的 sprite 美术和背景美术也一起工作,好让人物真的坐在场景里:“如果你做 sprite 时完全不管背景,场景的方位感就会彻底乱掉。”33 Chrono Trigger 刻意落在两者之间;开发中把画面的明度保持在 Secret of Mana 和 Final Fantasy 系列“之间”。34 一条规则,贯彻到游戏里每一个 sprite,这才让一群角色看起来像同一套班底。

重制版的教训

Pixel Remaster(2021 至 2022 年)保留了 16×24 的基础尺寸,并在上方和两侧留出余量,好让手臂能伸出去、披风能飘起来;在 FF VI 上,涩谷员子终于拿到了她 1994 年就想要的那一个像素:“当时我拼命希望上面能再多一个像素。这次重制让我如愿了。”35 这批画是“以显示在 LCD 屏幕上为前提”重做的,因为原作是照着 CRT 的晕散去点的。35 随之而来的争议关乎字体而非 sprite:上线时用的是一款纤细的现代字体,后来补上的像素字体,制作时需要做出约 7,500 个日文字符。36 反面教材是 2014 年 FF VI 的移动版,Kotaku 形容那批被抹平重绘的图“像是不小心丢进了洗衣机”。37 照着你真正要出货的那块屏幕作画,并且把字体当成美术来对待。

2. Pokémon 的图块系统,一代一代看过来

Square 的美术手上有 16 种颜色和一张 24 兆位的卡带。Game Freak 的美术手上只有四级灰度和一台 Game Boy,而他们为应付这份约束所建的系统,是这个行当里最清楚的教学案例——因为如今每一代都能在 pret 的反编译里读到。下面这些数字我是从源文件里读出来的,不是从爱好者维基上抄的。38

Game Boy 用每像素 2 位、四级灰度的 8×8 图块画出 160×144 的画面,硬件对象 40 个,每条扫描线最多十个。39 Pokémon Red 载入一套最多 96 块图块的图块集,用 4×4 图块组成的 32×32“区块”搭出世界,并以每区块一字节的方式存一座城镇;游戏里没有任何一套区块集超过 128 个区块。真新镇是 10×9 个区块,也就是 320×288 像素,正好横两屏、竖两屏。40 碰撞是一张你可以站上去的 8×8 图块 ID 清单,引擎只检测一块图块——你正前方那一格的左下角。41 水是单独一块图块,它的十六个字节向右按位旋转一个像素,连做四次,再向左做四次;花是一块图块在三帧存图之间按 1-1-2-3 的顺序换来换去;整套动画系统大约每二十帧触发一次。42 一个角色是四个 8×8 对象,画成六帧:三个朝向各有站立和迈步,朝右的帧由朝左翻转而来;上下方向的行走循环是站、迈、站、迈的翻转,所以画一帧迈步就同时有了两条腿。43 我最喜欢的那个小花招不花一分钱:当 sprite 站在图块集的草地图块上时,引擎会给它下面两个对象置上背景优先级位,草就画到腿上去了。6

观看:Sprite Analysis, Pokémon: Top-Down RPG Pixel Art, Brandon James Greer

Gold、Silver 和 Crystal 沿用了区块格式,把 Game Boy Color 的新硬件花在两件事上。图块集跨两个 VRAM 存储体扩到 192 块,每块图块取八组具名调色板(GRAY、RED、GREEN、WATER、YELLOW、BROWN、ROOF、TEXT)之一。这些调色板针对清晨、白天、夜晚、暗处和室内分别定义,所以城都的昼夜变化只是一次 64 字节的调色板重载,而不是第二套美术。44 碰撞改成每个区块的 16×16 象限各一个带类型的字节(FLOOR、WALL、TALL_GRASS、WATER、DOOR、LADDER 等),这才是第二世代明明存着 32 像素区块、玩起来却像 16 像素游戏的真正原因。44 多样性来自调色板:五组“人物”调色板共用同一种肤色,只差一个颜色,于是同一张图重新上色五次就填满了一座城镇。45

Ruby、Sapphire 和 Emerald 是成熟形态,也是现代引擎该抄的那一版。一套图块集是整个地区共用的 512 块主图块,加上每座城镇 512 块副图块,两者之间共十三组 16 色调色板。一个元图块是十六字节:八个 GBA 屏幕条目,即两层 2×2 图块,每个条目带一个图块 ID、两个翻转位和一组调色板。它的属性字另加一个 8 位行为(高草、台阶、门、电脑,共 240 种取值)和一种层类型:Normal,上层盖住 sprite;Covered,什么都不盖;Split,玩家走在两层之间。2 地图上的一格是十六位——10 位给元图块,2 位给碰撞,4 位给高度,而高度 15 让一座桥既能从上面走也能从下面穿。46 野外用三层硬件背景一起滚动来呈现地图,第四层固定下来放文本,所以屋顶或树冠遮住玩家,靠的是它位于优先级更高的那一层,而不是任何排序。2 未白镇是 20×20 个元图块,橙华市 30×30,橘滨市 40×60,紫堇市 80×40。47

角色变成 16×32,各占一个硬件 sprite,装在一张 144×32 的图里,共九帧:三个朝向、每个方向两步,朝东由朝西翻转而来。行走按迈、站、迈、站播放,每帧八拍,就是人人都记得的那份一颠一颠。48 图块动画跑在一个帧计数器上:每十六拍中的第 0 拍更新花,第 1 拍更新水,第 2 拍更新沙滩边缘,第 3 拍更新瀑布,第 4 拍更新水陆交界,这样五次 DMA 写入永远不会落在同一帧。49 水面倒影是把 sprite 复制一份放到最低优先级,用仿射矩阵翻转,换一组调色板,再按 sprite 高度减二的量下移。影子只在 sprite 腾空时存在——跳下台阶或骑车起跳的时候。高草如今是一个生成在该格上的五帧 sprite,叠在玩家的下半身上。50

第一世代(Game Boy) 第二世代(Game Boy Color) 第三世代(Game Boy Advance)
图块 8×8,2bpp 8×8,2bpp,外加一个调色板半字节 8×8,4bpp
行走格 16×16;碰撞落在一块 8×8 图块上 16×16;每象限一个带类型的字节 16×16 元图块;逐格的碰撞与高度
存储的地图单位 32×32 区块,一字节 同上 16×16 元图块,16 位格内的 10 位 ID
图块集 96 块图块,最多 128 个区块 192 块图块,户外 128 个区块 512+512 块图块,512+512 个元图块
调色板 一组,四级灰度 八组四色,逐图块 十三组十六色,逐图块
层 一层,外加一个 sprite 优先级位 一层,外加逐图块的优先级位 地图三层,文本一层
角色 16×16,六帧 16×16,六帧 16×32,九帧

此表的出处是本节引用的那些 pret 仓库。4044248

从这份记录里再说两件事。那款 Game Boy Color 上的卡牌游戏,是卡牌收藏者世界最近的祖先,它把每张卡的插画都画成 64×48 像素,各自配一组四色调色板,调色板与图块一同嵌入,显示时分配到一个调色板槽位——所以 Charizard 拿到的是米色、橙、红和近乎纯黑,而一张能量卡拿到的是白、两级橄榄灰和近乎纯黑。51 规则不在尺寸;规则是“每张卡一组量化过的调色板、一个固定边框、一个缩放等级”。至于这份自律,该钉在桌前的那句话出自杉森建:“像素画深得不可思议。一个 sprite 里只要挪动一个像素的位置,给人的印象就可能完全不同。”52 用他自己的话说,他的 sprite 是把更复杂的设计化成“容易看懂”的符号,因为屏幕小,存储更小。53 Red 与 Green 出货时大约只有四名程序员和不到十名美术。54

3. 当代的大师们,以及“3A 级像素画”的价钱

2010 年以来,最好的像素艺术游戏出自一到二十五人的团队,跑在毫无限制的硬件上,所以他们保留的每一条约束都是选择。而这些选择是扎堆的。

他们固定一块能整数倍放大的画布。 Celeste 的 320×180 乘以 6 就是 1080p;Pedro Medeiros 说:“这就是我所谓的游戏画布。”3 Sea of Stars 以 640×360 渲染,至于它的“Pixel Perfect”选项,一位玩家在该工作室的 Steam FAQ 帖中解释道,它“会在画面四周加一圈黑边,这样像素看起来就是锐利的而不是糊的”。55 Animal Well 是 320×180,当视口小到画不出诚实的扫描线时,它就把扫描线滤镜关掉。56 Hyper Light Drifter 是 480×270;Alx Preston 说:“我们的游戏是 480p。它是低分辨率的,而且非常刻意如此。”57 Shovel Knight 选了 400×240 以对上 NES 的 240 条可见扫描线,用 Yacht Club 的话说,“Shovel Knight 的一个像素在 1080p 下其实是 4.5×4.5 个像素”。58 Godot 的文档如今推荐以 640×360 为基准,因为它能无黑边地放大到 720p、1080p、1440p 和 4K。59

画布 720p 1080p 4K 采用者
320×180 4 倍 6 倍 12 倍 Celeste、Animal Well
400×240 3 倍 4.5 倍 9 倍 Shovel Knight
480×270 2.67 倍 4 倍 8 倍 Hyper Light Drifter
640×360 2 倍 3 倍 6 倍 Sea of Stars、Godot 的推荐值

他们绝不混用像素密度。 Medeiros 的缩放规则是:“这件事只能按原图的 100% 为增量来做。”而当两种密度实在避不开时,“可以有 100% 的元素和 200% 的元素,但绝不能有 150% 的”。60 Celeste 走得更远,维持三个彼此绝不渗透的“世界”:“Game、UI 和 Map,分别是像素画、高分辨率和 3D。”3 UI 自成一层、自有倍率,等世界放大完了再合成上去。初代 Switch 上的 Octopath Traveler 在掌机模式下以 576p 渲染世界,同时把 UI 保持在 720p,路径不同,分离是一样的。61

他们挑一个光照档位,并付那个价钱。 最底下,Moonlighter 根本没有动态光照;城里的夜晚是“用 sprite 的叠加来制造有光的印象”。10 往上一档,Celeste 把每一盏灯都当作遮罩画进一张 2,048 像素的纹理:64 个槽位的网格,每盏灯占一个颜色通道,所以一张纹理装得下 256 盏灯,而遮挡物会在着色器把颜色乘以遮罩之前,先从聚光里把阴影抠掉。11 再往上,Eastward 是“一款有着 2D 视角的 3D 游戏”,团队为每个资源“一个一个手绘凹凸贴图”,好让真实光源能给平面 sprite 上阴影。12 Animal Well 的 Billy Basso 拒用引擎自带的点光源,因为那种平滑渐变和像素画相冲,他写了自己的边缘光着色器,还为烟和水跑了一套全屏流体模拟。62 Dead Cells 则是把 3D 模型“以极小的尺寸、不开抗锯齿”渲染出来再用卡通着色器上色,等于白得了法线贴图。63 最顶上,Sea of Stars 把头六个月花在打造一套“在视觉上与像素画保持一致”的光照上,而 HD-2D 把 sprite 广告牌放进一个打了光的 Unreal 场景里,再加景深、泛光、调色、镜头光晕和暗角。6465 制作 HD-2D 系列的浅野智也说,它“比你想的更贵”。13 而 Octopath Traveler II 的玩家会把景深和泛光关掉,因为“屏幕边缘会糊掉,把路给挡住”。13

观看:The Making of Sea of Stars, Escapist Documentary

他们用的帧数比你以为的少,转而去动颜色。 Dead Cells 的角色高五十像素,而 Motion Twin 的 3D 动画工作流在更早的原型 ScarKrow 上就已经做到每秒 30 帧,像素化那一步是到 Dead Cells 才加进来的。63 次像素动画是这门手艺安静的武器:想让一个小 sprite 移动一小段距离,教程说“别动 sprite”,“动它的颜色”;在那个 50 像素高的角色身上,六个淡色就足以让人读出一次呼吸。66 Octopath 用 Photoshop 的操控变形批量生产动作,再手工修像素。65 Animal Well 用程序化方式驱动它的生物,每条肢体各走各的轨迹,而 Basso 刻意避开挤压拉伸和屏幕震动。67

他们锁定一套调色板并共用它。 Raymond Schlitter 的方法是每条色阶九个色块、每一级色相偏移 20 度、色阶之间相隔 45 度,并在亮端降低饱和度,否则“你会得到一堆刺眼灼目的颜色”。68 Cassette Beasts 靠“共用同一个约 20 色的色池”让 120 只怪物保持协调,就像一条用料固定的可动人偶产品线。69 Shovel Knight 允许每个 sprite 用四到五色外加透明,而 NES 当年只给三色。58 社区那些固定调色板(Resurrect 64、Apollo、Endesga 32)之所以存在,正是因为这份自律管用。70

他们让美术的体量配得上团队。 Stardew Valley 是一个人加 16×16 的图块;Eric Barone 谈他的下一款游戏:“继续用 16×16 的图块尺寸,能让这么大体量的游戏里美术的量还在可控范围内。”71 Sabotage Studio 从 The Messenger 的七个人长到 Sea of Stars 的约二十五人。72 Animal Well 是一个人、七年、一套自研 C++ 引擎、33 兆字节,以及一个正好 256 个房间的世界——因为房间 ID 只有一字节。73 Eastward 的工作室从三位创始人长到约十二名全职,角色超过 200 个,都用 Aseprite 做动画。74 Switch 2 取消了过去掌机那份妥协:1080p 的掌机屏,以及 1080p 或 4K 的电视输出,所以 320×180 和 640×360 的画布在两种模式下都能是整数倍,只是 4K 输出封顶 60 帧。75

4. 手艺,写成带数字的规则

下面是一座四分之三俯视小镇的语法,按从业者自己的说法整理。凡是我把某条实践折算成数字供我们自己使用的地方,都会注明。

  1. 这个视角是正交投影的倾斜,不是透视。 LPC 的风格指南把相机放在“大约 60 度”且不加透视;Schlitter 把同一个视角描述为从 45 度俯看一栋房子,此时“屋顶和正面各能看到约四分之三”,并补上那条起支配作用的条款:“统一性优先于真实性。”7677 垂直线保持垂直,正面被压缩,屋顶不旋转,而且每一件物体都遵守同一套规则。
  2. 网格是 16,制作的节奏是 32。 Schlitter 说:“16×16 像素大概是最常见的尺寸,拿它来对待你的像素肯定错不了。”78 Stardew 和那几款 GBA 游戏也是这么认的;Pokémon 的 Game Boy 区块和 LPC 的网格则是 32。图块制作和碰撞判定都在 16 上做,房屋和大树则按两块图块一组来设计。
  3. 高图块的问题用分层来解。 Stardew 的地图层由后到前是 Back(地形)、Buildings(碰撞)、Paths、Front(“玩家在其北侧时画在玩家之上,在其南侧时画在玩家之下”)和 AlwaysFront。79 Pokémon 的 Normal、Covered、Split 三种元图块类型是同一个思路,只是把排序交给了硬件优先级。2
  4. 一组地形过渡是 47 块图块。 所谓 blob 集,是“一套二边二角 Wang 图块集的 47 块子集”;位权为北 1、东北 2、东 4、东南 8、南 16、西南 32、西 64、西北 128,而一个角只有在它两侧的边都成立时才计数,这条规则把 256 种掩码塌缩成 47 种剪影。8081 栅栏和绿篱则是 16 块的边缘集。Tiled 的地形集和 LDtk 的规则组都直接实现了这些。8283
  5. 树是树干之上的叶簇,影子就在正下方。 Schlitter 用基本单元为“一个 2×2 像素的小方块”的叶簇堆出树冠,“每簇四到五色”,并把树“摆成交错重叠的行,以形成密实的森林图案”。谈到影子,他先讲实用:“从游戏设计角度,把影子直接放在树的正下方最实用。”尽管他本人更喜欢“让它偏向一侧,看起来更有动感”;影子应当“含蓄,不要朝任何特定方向拉得很长”,而说到墙投下的落影,“它们的长度不应超过一块图块”。84
  6. 颜色是色阶,不是色块。 色阶变亮时色相朝暖偏,变暗时朝冷偏,每级最多 20 度;饱和度在色阶中段达到峰值。68 LPC 的规则三个字:“不要纯色!”阴影“朝最接近的紫”,高光“朝最接近的黄”。76 就单个 sprite 而言,Schlitter 建议在上阴影有把握之前“只用大约 5 种颜色”;而 Cure 的定律成立:“如果你用 4 种颜色做不出一个好 sprite,用 40 种也救不了你。”8586
  7. 一条描边规则,处处适用。 LPC 规定:世界的描边是“当前颜色的更暗版本,或者笼统地说一个暗色,但不是黑色”;角色的描边是“黑色或近乎纯黑,不做选择性描边”。76 第 1 节那张 SNES 表显示了各家选得不同会是什么结果;要点在于选一次。
  8. 给三种错误起名字,然后把它们揪出来。 锯齿(jaggies)是一条线的节奏里跑偏的那个像素;条带(banding)是“相邻像素在底层网格上终止于同一个 x 或 y 坐标”;枕状上色(pillow shading)是无视光照的同心色带。86 抗锯齿只用在又长又缓的台阶上,绝不用在 45 度线或直线上,而且要把柔化限制在 sprite 自己的颜色之内,不要对着背后的东西去柔化,因为决定背景的是游戏。8687 在一个 16 像素的世界里,抖动几乎永远用不上;用 Pixel Parmesan 的话说,有些 sprite“相对于它们可能容纳的细节量来说,根本就小到没法抖动”。88
  9. 角色:画三个方向,四步走路,一个会动的待机。 Stardew 的农夫是 16×32,按固定顺序绘制(身体、裤子、上衣、配饰、头发、帽子、手臂),帽子装在 20×20 的格子里;走路是三张独立帧构成的四步。8990 Pokémon Emerald 的是迈、站、迈、站。48 Schlitter 说:头部“占整个 sprite 的三分之一到一半”,画上、下、侧三面并把侧面镜像;至于待机动作,“它甚至不需要讲得通,动就行”。9192
  10. 文字就是美术。 位图字体只在整数倍下渲染;Daniel Linssen 的 m5x7 页面写着“请使用字号 16、32、48 等等”。93 Pokémon Emerald 的文本框边框是一张 24×24 的图,也就是 3×3 块硬件图块,这就是九宫格;而 Aseprite 的切片会把九宫格的中心区带进导出的 JSON。9495
  11. 在一个平和的世界里,“爽感”就是天气。 那几场关于屏幕震动和顿帧的经典演讲,是围绕一款射击游戏和一个打砖块写的;一座收藏者的小镇要的是 Stardew 那套天气词汇(晴、雨、暴风雨、带花粉或落叶的风、雪),以及由图块属性而非新美术生成的脚步声。969798
  12. 流水线是一道构建步骤。 Aseprite 的命令行会把打包好的图集连同 JSON 一起导出(--sheet-type packed --shape-padding 2 --extrude --format json-array --list-tags --list-slices),那两像素的内边距加上外扩,正好保护每一帧的边缘不被旁边那一帧渗进来。99100

观看:Pixel Art Class, Top Down Style Analysis & Tutorial, AdamCYounis

5. Apple 的路子:三种架构、一套配方,以及那点算术

我们这个问题有两半,彼此往反方向拉。世界这一半要的是整数倍放大、nearest 采样、不受光的纹素稳稳落在整像素上。而其中唯一真实的那件东西——收藏者最心爱的那张卡——要的是成为一件有明暗的 3D 物体,从平面世界里升起来,并且被它所在的那层架子挡住,这意味着它必须和图块待在同一个深度缓冲里。任何把卡当作第二层去合成的设计都会丢掉这份遮挡,把那个瞬间做成假的。能同时装下这两半的 Apple 架构有三种,代价各不相同。

SpriteKit 当作 2D 引擎用的 RealityKit Metal,先低分辨率渲染再做一次整数倍放大
像素采样 给每张纹理设 SKTexture.filteringMode = .nearest,关掉 mipmap101 在材质上给一个完整的 MTLSamplerDescriptor,用 .nearest 和 .notMipmapped;纹理上用 MipmapsMode.none14 你自己的采样器;每一道滤波都归你管111
图块地图 SKTileMapNode:分块处理,所有图块共用一张图集时每个可见块一次绘制调用,支持邻接规则102 整张地图一个 MeshDescriptor,一次绘制调用;自 iOS 26 起道具可用 GPU 实例化109 你自己的顶点缓冲
sprite 帧 图集纹理加 SKAction.animate 每个四边形一组 textureCoordinateTransform 的偏移与缩放(iOS 18)15 逐实例的 UV 矩形
那张 3D 卡 SK3DNode 承载 SceneKit,而 Apple 在 WWDC25 上弃用了它并转入维护模式103 同一场景、同一深度缓冲里的一个普通实体,由一盏不受光的世界会忽略的灯照亮 你自己写的第三趟渲染
渲染器默认值 对像素来说没问题 运动模糊和 HDR 色调映射默认开启;景深、相机颗粒和抗锯齿要显式关掉16 无
帧率 自动适配 ProMotion113 Apple 的性能文章提到 60 fps 的上限114 用 CADisplayLink 和 CADisableMinimumFrameDurationOnPhone 键做到 120 Hz113
面板级精确像素 无法控制视图的缩放滤镜 RealityView 上没有 contentScaleFactor 按 QA1909 设 drawableSize = bounds × nativeScale112
已知的坑 标签无法用 nearest 过滤;iOS 9 曾有一次回归导致 .nearest 被忽略 相机的 scale 只有一行说明且没有单位;有论坛报告称用正交相机做投影会返回错误值104105 图集打包器、文本、输入和场景图都得你自己写

对一款纯 2D 游戏来说,SpriteKit 仍是最快的路,而且它在维护中、没有被弃用。对一个只需要一件真 3D 物体的世界来说,RealityKit 才是对的引擎,而且像素艺术的每一项要求都有写进文档的 API。Metal 是通往 RealityKit 无法承诺的那两件事——120 Hz 和面板级精确缩放——的逃生口;文档里给出的办法是 RealityRenderer,它把同样那些实体渲染进你自己的纹理,供你自己提交的那一趟 nearest 放大使用。110

配方

// One texel is k device pixels, with k a whole number. Pixels, not points.
let pixelsTall = Float(size.height * displayScale)
let k = max(1, (pixelsTall / (20 * 16)).rounded(.down))   // aim for about 20 tiles tall
let worldTall = pixelsTall / k                            // world units are texels
var camera = OrthographicCameraComponent()
camera.scale = worldTall / 2                        // measured: scale is half the view's height
cameraEntity.components.set(camera)

// Nearest sampling, no mipmaps, alpha test instead of blending.
let sampler = MTLSamplerDescriptor()
sampler.minFilter = .nearest
sampler.magFilter = .nearest
sampler.mipFilter = .notMipmapped
let texture = try TextureResource(image: sheet, options: .init(semantic: .color, mipmapsMode: .none))
var material = UnlitMaterial()
material.color = .init(tint: .white, texture: .init(texture, sampler: .init(sampler)))
material.opacityThreshold = 0.5
material.textureCoordinateTransform = .init(
    offset: [Float(col) / Float(cols), 1 - Float(row + 1) / Float(rows)],
    scale: [1 / Float(cols), 1 / Float(rows)], rotation: 0)

// Switch the AR defaults off.
content.renderingEffects.motionBlur = .disabled
content.renderingEffects.depthOfField = .disabled
content.renderingEffects.cameraGrain = .disabled
content.renderingEffects.antialiasing = .none
content.renderingEffects.dynamicRange = .standard

关于这段代码有三点说明。Apple 对 OrthographicCameraComponent.scale 的全部描述只有“相机用来缩放实体的一个浮点值”,而“等于视图高度一半”这层关系是我们自己在模拟器上量出来的(3 倍、每纹素七像素时,320 个世界单位跨越 746.67 点,正是 320 × 7 ÷ 3)。104 opacityThreshold 正是像素画想要的那条镂空路径:“RealityKit 会丢弃不透明度低于 opacityThreshold 的像素”,其余部分完全不透明地渲染,于是既没有边缘混合,也没有排序问题。15 而比任何采样器都更要紧的是默认值:除非你把它们关掉,RealityView 会“施加一种为虚拟物体引入运动模糊的效果”,还会加上“一种高动态范围效果,连同色调映射”。16 在我们这么做之前,走路的角色每迈一步都糊成一片。每个 sprite 的 x、y 和相机都在缓动之后、每一帧取整到整数世界单位,这样就没有纹素卡在像素之间,而深度和那张 3D 卡的运动仍然是连续的;另外,由于论坛报告过的那个投影缺陷,点击的世界坐标是我们用相机位置、k 和显示倍率自己算的,而不是去问 RealityKit。105107

模拟器中,Kiradex 广场铺满展开的 iPhone Duo 内屏:草坪与小径以每纹素六个设备像素绘制,HUD 落在安全区内。

缩放的算术

3 倍这个缩放系数和 16 像素的网格没有任何关系;要紧的是像素数。用 16 纹素的图块、目标是上下约二十块时,k = floor(pixelsTall ÷ 320)。余数决定了两种策略:能放多少块就放多少块(宽屏能看到更多世界,没有黑边),或者严格保持二十块高、把剩下的交给黑边。下表每一行都是从 Apple 的规格页和 Xcode 27 的模拟器配置算出来的。17118

设备与方向 点 像素 k 可见图块数(宽 × 高) 要正好 20 块高所需的黑边
iPhone 18 Pro Max,竖屏 440 × 956 1320 × 2868 8 10.3 × 22.4 308 px
iPhone 18 Pro,竖屏 402 × 874 1206 × 2622 8 9.4 × 20.5 62 px
iPhone Duo 外屏,竖屏 466 × 678 1398 × 2034 6 14.6 × 21.2 114 px
iPhone Duo 内屏,展开(横屏) 951 × 669 2853 × 2007 6 29.7 × 20.9 87 px
iPhone Duo 内屏,竖屏 669 × 951 2007 × 2853 8 15.7 × 22.3 293 px
iPad Pro 13 英寸,横屏 1376 × 1032 2752 × 2064 6 28.7 × 21.5 144 px
Apple TV 4K 1920 × 1080,2 倍 3840 × 2160 6 40.0 × 22.5 240 px

这些高度没有一个能被 320 整除,所以在现行设备上,“正好二十块图块高”永远意味着黑边;18 Pro Max 的 2868 ÷ 320 = 8.96 已是其中最接近整数 9 的一个。HIG 要求游戏“在各种宽高比下都好看且表现得当”并且“按全屏体验来设计”,这就支持了多露出世界而不是加黑边的做法,广场里我们正是这么做的,而需要整体呈现的房间则改为居中。115 在 3 倍显示屏上,k = 8 时五纹素的字体是 13.3 点,k = 6 时是 10 点,低于 HIG 的 11 点下限,所以对话文本活在 SwiftUI 里、按 UI 倍率排布,而不在世界之中。115 至于那层 SwiftUI 外壳里的像素图标和九宫格边框,Image.interpolation(.none) 能让它们保持锐利。116

iPhone Duo 的内屏是这套算术唯一还没算完的地方。Apple 的规格表给出的面板是 1878×2670 像素,而模拟器配置给出的逻辑帧缓冲是 2007×2853、倍率 3.0,也就是说 UIKit 以 3 倍渲染 669×951 点,再由合成器按约 0.936 下采样到玻璃面上——这恰恰是 Apple 技术问答 QA1909 针对 Plus 级机型所描述的行为。这会让 UIScreen.nativeScale 落在 2.807 附近,而每纹素六个逻辑像素到了面板上约为 5.6 个。17112120 模拟器显示的是逻辑帧缓冲,所以广场在那里看着没问题,到真机上会略微发软;唯一能避开它的办法是让 Metal 在 nativeBounds 上自己持有可绘制对象,而第一步是在真机上把 nativeScale 打到日志里。外屏则整除得干干净净(1398 ÷ 466 = 3.0)。

我们找到的两个 bug,和一个采集假象

卡牌查看器第二次和第三次打开时是黑的,而它的场景与第一次逐帧完全一致。原因是我们给包含 RealityView 的 Metal 层的那个 SwiftUI 视图加了不透明度动画;跨越这层边界去动画 .opacity,会让那一层根本没被绘制。修法是不再给视图做动画,改为淡出一层黑色蒙版。在负载较重的模拟器上,首帧仍会迟到,最多可达十二秒,所以我们的 UI 走查读的是一串定时亮度采样中的最后一个,而不是第一个。

第二个问题出在我们的工具上,而不是渲染器。从宿主机采集 Duo 模拟器的内屏时(xcrun simctl io <udid> screenshot --display=primary-1),图像只在 Core Animation 重新合成时才刷新;单靠 RealityKit 的帧不会触发它,于是屏幕上正在走动的玩家,在采集结果里却是僵住的。改从测试包内部用 XCUIScreen.screens[1] 采集,拍到的才是实情。这两件事各花掉我们一天,而且我能找到的任何文档里都没有——这正是它们出现在这里的理由。

在 iPhone 18 Pro Max 上,收藏者最心爱的那张卡从平面广场里升起,是这个不受光的像素世界里唯一一件被打光、有明暗的物体。

6. 案例研究:先审判我们的广场,再按规则把它重建

下面是对 TestFlight 第 18 版出货时的 Kiradex World 所做的诚实审计,对照的是第 1 到第 4 节。地面是 28 块图块,颜色是敲进文本网格里随手定的,平涂、没有色阶、也没有约定好的光。收藏者是一张 48×96 的图,走路两帧,没有待机,没有影子,描边方针一个 sprite 一个样。没有头顶层,所以什么都没法从树冠后面或屋檐下面穿过去;没有自动图块,所以每一道草地到小径的边都是拿尺子画的;也没有高度。底下那套引擎是健全的(整张地图一个网格、nearest 采样、整数倍缩放、卡和图块共用深度缓冲),但压在上面的美术,放到 Game Boy 面前都抬不起头。

放大八倍并叠上网格的旧 Kiradex 图块集与收藏者图:平涂色、从文本网格来的图块、两帧走路。

规格书

下面这份规格是我们自己的,由上文那些有出处的实践推导而来;凡是数字属于建议而非事实的地方,都写明是建议。

  • 投影与网格。 正交四分之三视角,单一光源来自左上,垂直线保持垂直。图块 16×16;房屋和大树按 32 像素的节奏;房间 10×8 到 12×9 块图块;小镇规模介于橙华市的 30×30 和橘滨市的 40×60 之间。
  • 层,按绘制顺序。 地面(自动图块的草坪、小径、广场石板、水)、细节(变体、花、烘焙好的影子)、物体(按底边做 y 排序:人、长椅、路灯、树干、房屋正面,带碰撞)、头顶(屋顶、树冠、栏杆,永远在人之上)、灯光(叠加混合的路灯 sprite,入夜时替换)、天气,以及自有倍率的 UI。就是 Stardew 的五层,再把 Pokémon 的 Normal 情形——上层盖住玩家——拿来当头顶层。
  • 自动图块。 草地到小径、草地到水、草地到崖、广场到小径,各一套 47 块的 blob 集;栅栏和绿篱用 16 块的边缘集;草地三种变体并加权,好让重复藏起来。水四帧、每帧 250 毫秒(Emerald 的十六拍八步是节奏上的参照);花两帧;路灯两种状态外加夜间闪烁。
  • 调色板。 一套主调色板,48 到 64 色分成六到八条色相偏移的色阶,饱和度在中段达峰,不用纯色,室内取自偏冷的那一半。每个 sprite 最多八色,每块图块最多六色。黄昏和夜晚用一层覆盖全世界的正片叠底色调,再加上为路灯、窗户和售货亭招牌手绘的自发光变体。
  • 角色。 16×32 的格子里一个宽 16、高 24 的人形,头部九到十像素,眼睛一像素,不画嘴,双脚落在最下一块图块上好让 y 排序用底边,头顶留八像素给帽子和举起的卡。画三个方向外加一个镜像的第四向;只有举卡这个动作要单独画一套朝右的,因为手里的卡是不对称的。走路四帧、每帧 125 毫秒;待机是两帧、一像素的轻微起伏;举卡三帧(预备、举起、保持)。纸娃娃分层按 Stardew 的顺序,每层都是贴合身体网格的完整图,帽子按方向各设锚点。每个人和每棵树底下一个 12×4 的椭圆影子。
  • 描边。 角色用近乎纯黑,世界用更暗的固有色,绝不画在图块内部。
  • 文字。 m5x7 按整数倍,放在 24×24 的九宫格框里,两行,打字机式显示,两帧的继续箭头。对像素密度唯一一处刻意的例外,就是收藏者那张真卡:引擎早已会把它举到玩家头顶,那是一张有明暗的 3D 卡,三块图块高,和世界同在一个场景里。举起的手中那张小卡是手持层上的一个 sprite,两者从不假装是同一件东西。

锻炉

这批美术我们不打算在图像编辑器里画,也不打算用提示词生成。美国版权局 2025 年 1 月的报告断定,就作者身份而言“提示词本身并不提供足够的控制”,而一套没有作者的图块集,就是一套谁都可以从 app 里顺走的图块集;同一份报告保护“对输出的创造性修改”,以及 AI 起辅助而非替代作用的作品。18 Circular 33 把想法、流程、系统和操作方法排除在著作权之外——投影方式、图块尺寸和分层方案正住在那里;而具体的图块和 sprite 是受保护的表达,名称若受保护,也是作为商标。所以干净的路,是把每一个像素的来历都握在自己手里。19 我们的锻炉是 scripts/forge/ 下的一个小 Python 程序,依据一套主调色板和手工设定的规则画出每一块图块和每一个 sprite。调色板模块用十四条色相偏移的色阶构建 58 种颜色,并导出一个 GIMP 调色板文件以便审阅。栅格是索引式的:一个 sprite 就是一张颜色名称的网格,而一个像素只可能是调色板中的某一项,或者九种由 app 按收藏者替换的标记色之一。地形模块画出草坪、夯土、石板和水,然后沿着一条摇摆的边界,把外层地形盖到内层地形之上,外角做圆、加一圈镶边色,由此生成全部 47 种 blob 过渡。每一次随机选择都是由其位置决定的固定哈希,所以重跑一次会得到逐字节相同的结果;而每一条规则都是某个人写下、并且能够为之辩护的一行代码。

Kiradex 主调色板:十四条色相偏移的色阶共 58 色,阴影偏向紫,高光偏向黄。

草坪中一条小径的 47 块 blob 集,由规则生成:边与角按 cr31 的位掩码索引,边界摇摆,并带一圈深色草镶边。

铺上草坪-小径集的试验田:边缘是摇摆的而不是尺子画出来的,草坪变体打断了重复,柔化后的转角读起来像被踩旧的地面。

第一块试验田证明了这个方法根本上是成立的。第二天早上,角色和引擎所命名的那 28 块图块,在同一个程序里跟了上来:16×32 格子里的一个 16×24 人形,拆成身体、头发、帽子和手持卡四层,并保留 app 为每位收藏者外观替换的标记色,带两帧待机、四帧走路和三帧举卡;树是树干之上的叶簇,影子在下面;一面抹灰墙不带踢脚线,因为同一块图块也要填满房间之外的砌体,而踢脚线会在整个屏幕上拉出一道横纹;水是四帧,地面每秒走完四遍。下面这张截屏,就是和它们一起通过的那次模拟器行走检查。广场目前铺的仍是引擎命名的那 28 块图块,所以在 JSON 地图把 blob 集带进来之前,它的侧边依旧是直的。

用上锻炉之后,iPhone 18 Pro Max 上的 Kiradex 广场:按规则绘制的草坪、小径与石板图块,树下带影子,还有栅栏和池塘,收藏者们有的戴着帽子、各自带一个椭圆影子,以及两户人家的正面。

房间、大厅、道具和更大的小镇,都会由同一个程序接着做,出口是 Aseprite 兼容的图集和 JSON,所以美术怎么变,Swift 那边的加载器都不用动。

这个世界要做什么

美术这套程序是为玩法服务的,而对收集类游戏的调研改变了工作的先后次序。主角是卡:世界保持哑光,只有那张真卡是唯一有明暗的物体——因为在一款下载量超过一亿的游戏 Pokémon TCG Pocket 里,一块单卡展示板和一本三十张的卡册就已经够当展柜了。129 房间的陈设上限是十六件,也就是秘密基地那个数字,因为正是上限把一个架子变成一幅构图;拜访是只读的,点赞每天一次,而房间的总数永远不会减少,这是 Club Penguin 给冰屋定的规矩。122124 访客每间房赢得一面旗,在 30、100 和 500 处升阶,这正是 ORAS 用来把“走进陌生人的秘密基地”变成主要动词的那套等级。125 每周日会送来一份给房间打分的报告,并列出得分来源,这是快乐之家学院的节奏。123 每周的大厅借来的是 Stardew 的农产品展台而不是 Pokémon 的华丽大赛:九个展座、一个基础分、跨年代与系列的多样性加成、来自扫描记录的单品分、三档门槛,以及一套陌生人一眼就能看懂的评判标准。121 聊天只保留一棵预设语句的树(问候、回答、收藏话题、反应),词汇靠游玩解锁,就像 Emerald 里那位追潮流的人每次因记录交换而来访时都会解锁一个流行语;绝不允许自由输入,因为 Club Penguin 的词语过滤器连“mom”都拦,却依然——按它自己的帮助页所承认的——放过了一些冒犯性消息,133124 而且 FTC 2022 年的命令要求 Epic 对儿童和青少年默认关闭语音与文字聊天。126124131 每位好友每天一份小礼物,友谊等级设在 1 天、7 天、30 天和 90 天,这是 Pokémon GO 的那道阶梯。127 赞助者的标识只出现在名牌和房间皮肤上,绝不碰展座名额或评判加成;那篇关于温馨向游戏的论文所警告的“华丽往往会制造社会比较的压力”就是界限。128 任何带随机性的东西一律不卖。

美术之后要做的引擎工作是:从 JSON 载入而非硬编码行的分层图块地图、跑在共享节奏上的动画图块、带 y 排序遮挡的头顶层、逐帧合成的纸娃娃 sprite,以及服务端地图、NPC 和一致性表的同步更新。

核心要点

如果你来画

  • 在画下第一块图块之前,先把格子、调色板和光定死:16×16 的图块、16×32 格子里的 16×24 人形、色相偏移色阶里的 48 到 64 色、光从左上来。这份指南里的每一位大师,都是从约束往外推的。
  • 挑一条描边规则,贯彻到整套班底。FF VI 那 93% 的黑边和 Secret of Mana 的 0%,各自都是自洽的;把两者混在一起的班底则不是。9
  • 把帧花在表现上,把颜色花在运动上:FF VI 的 46 个姿势、Emerald 的迈-站-迈-站,以及动颜色而不动 sprite 的次像素动画。14866
  • 过渡是 47 块,栅栏是 16 块,树是叶簇、影子就在正下方。规则只画一次,剩下的交给编辑器去摆。8084

如果你在 Apple 平台上做

  • 当一件物体必须在平面世界里是真正的 3D 时,就留在 RealityKit:它共用深度缓冲,而且像素艺术的每一项需求都有写进文档的 API。纯 2D 游戏请选 SpriteKit,并把 RealityRenderer 留作通往 120 Hz 和面板级精确像素的 Metal 逃生口。14110
  • 第一天就把 AR 默认项关掉:运动模糊和 HDR 色调映射不关就是开着的,而这份配方连景深、相机颗粒和抗锯齿也一并关掉,因为每一项都会把纹素抹花。16
  • 算术用像素来做:k = floor(pixelsTall ÷ 320),把每个 sprite 的 x、y 和相机取整到整数世界单位,并在相信模拟器之前先在真机上读 UIScreen.nativeScale,在 iPhone Duo 上尤其如此。112118
  • 在我们的 RealityView 里,给外层视图做不透明度动画会让它变黑;改成在上面盖一层蒙版去淡出。采集 Duo 内屏请从测试包内部做,而不是从宿主机。另外记得加上 LSSupportsGameMode,因为 Game Mode 会“尽量减少后台活动,让游戏更流畅、帧率更稳定”。117

如果你在经营工作室

  • 让美术的体量配得上团队:Eric Barone 一直守着 16×16 的图块,好让一个人就能画出 Stardew 那么大的世界;而 Sabotage 在做 Sea of Stars 的过程中从七个人长到约 25 人。7172
  • 除非你有半年的引擎工时可花,否则就在 Moonlighter 到 Celeste 之间挑一个光照档位;HD-2D 那一档“比你想的更贵”,而且连它自己的玩家都会把效果关掉。101113
  • 把每一个像素的来历握在自己手里。纯粹由提示词生成的美术不受保护,这是版权局自己的结论,混合情形则逐案判断;手绘的美术,以及由人所写的规则绘制出来的美术,都保住了人类作者的来历。18
  • 在一个为收藏者而建的世界里,让被收藏的那件东西成为唯一有光泽的物体,给房间设上限,周日评分,点赞只增不减,并且绝不让人打字。Daniel Cook 那句“去掉聊天,你就去掉了 95% 的正向社交行为”是真的,正因如此,预设语句才必须扛起孩子原本想打出来的那些回答。130

常见问题

俯视视角的像素艺术游戏该用多大的图块?

16×16。这是 Pokémon 自 Game Boy 的 16 像素行走格以来一直在用的格子,是 Stardew Valley 立身的格子,也是 Raymond Schlitter 称为“最平衡的工作尺寸”的那个格子。4079132 角色放进 16×32 的格子里,身体约 24 像素高;房屋和大树按两块图块一组来设计。

iOS 上的像素艺术,该用 SpriteKit 还是 RealityKit?

没有 3D 物体的游戏用 SpriteKit:带邻接规则的图块地图、配法线贴图的灯光,再加上 filteringMode = .nearest,药方就这些。101102 当场景里必须有一件东西是和图块共用深度缓冲、有明暗的 3D 时,用 RealityKit:正交相机、带显式混合模式或不透明度阈值的 UnlitMaterial、nearest 采样器、不用 mipmap,全都有文档,而 iOS 26 还加上了实例化和一个后处理钩子。104106108109 SpriteKit 唯一的 3D 桥梁 SK3DNode 架在 SceneKit 上,而 Apple 在 WWDC25 上把 SceneKit 转入了维护模式。103

怎样在 iPhone 屏幕上做到整数倍缩放?

用像素思考。把视图的点数乘以 displayScale,用高度除以 320(二十块十六像素的图块),向下取整,那就是你每纹素的设备像素数:iPhone 18 Pro Max 上是 8,展开的 iPhone Duo、13 英寸 iPad Pro 和 4K Apple TV 上是 6。17119 每一帧都把相机以及每个 sprite 的 x、y 取整到整数世界单位。再决定余数是变成更多可见世界还是变成黑边;现行 iPhone 没有一款高度能被 320 整除。在 iPhone Duo 的内屏上,请到真机上查 UIScreen.nativeScale,因为面板那 1878×2670 像素和模拟器显示的 2007×2853 帧缓冲对不上。112

AI 能替游戏生成像素画吗?

它能生成图像,但光靠提示词并不会让你对生成物拥有著作权。美国版权局 2025 年的报告断定,纯由 AI 生成的材料不受保护,且“提示词本身并不提供足够的控制”,而人对输出所做的创造性修改,以及把 AI 用来“辅助而非替代人类创造力”的情形,则受保护。18 对一款要出货的游戏来说,实际后果是:一套整个从提示词生成、未加入任何人类表达的图块集,没有可供主张的著作权,其训练来历也无从得知;而在人确实加入了表达的地方,版权局会逐案判断其贡献。要么自己画,要么写下那套画它的规则,并且把哪部分是哪部分记录清楚。

一个“受 Pokémon 启发”的世界,法律边界在哪里?

画风、方法和系统不受保护,具体表达才受保护。Circular 33 把“任何想法、程序、过程、系统、操作方法、概念、原理或发现”排除在著作权之外。19 一座 16 像素图块的四分之三视角小镇、双层元图块、迈-站式行走、47 块的水岸线,这些都是方法。真新镇的那些图块、那些生物、精灵球和属性符号则是表达,而名称若受保护,是作为商标。Kiradex 用自己的调色板、按自己的规则画出每一块图块和每一个 sprite,而整个 app 里唯一的 Pokémon 图像,就是用户扫描进来的那张真卡。

一组地形过渡为什么正好需要 47 块图块?

因为一块图块的外观取决于八个邻居(四条边和四个角),共 256 种组合,但一个角只有在它两侧的边也都存在时才有意义。按这条规则把 256 种掩码塌缩之后,剩下 47 种不同的剪影——这正是 Tiled 的文档把“47 块的 Blob 图块集”称作混合集常用精简形式的原因。808182


这份指南是怎么做出来的。 支撑它的六份调研卷宗是 2026 年 10 月 2 日用 Claude 的 agent 汇编的,而文中每一个数字随后都从注释所指的一手来源重新读过一遍:pret 的反编译、Apple 的文档(经由其 JSON 端点)、开发者本人的演讲与文章,以及 Shmuplations、Nova Crystallis 和 Lava Cut Content 上的翻译访谈。sprite 的测量、缩放的算术、RealityKit 相机的实测,以及 Kiradex 的锻炉,都是我自己的工作,文中已如此标注。凡是某项主张只依赖单一来源的,注释里都会说明。

本站相关内容:面向开发者的 iPhone Duo 推导了内屏的点尺寸和上面那张缩放表所依据的 1.42 这个比值;为 iPhone Duo 准备你的 app 是关于折叠、保留区域以及广场如今所遵循的 HUD 规则的实作范例;Xcode 27.1 测试版:在 iPhone Duo 模拟器里跑你的 app 讲的是模拟器,以及本文截图所用的 Device Hub 姿态;RealityKit 与空间心智模型 是第 5 节的 RealityKit 基础;Metal 4 要点 讲的是那个逃生口真要做的话会用到的 API;而在浏览器里重现 MacPaint 是我上一次照着一手资料重写像素渲染器的记录。

参考来源


  1. FF6hacking Wiki,“Sprites (FF3us tutorial)”,2026 年 10 月 2 日访问,https://www.ff6hacking.com/wiki/doku.php?id=ff3%3Aff3us%3Atutorial%3Asprites。 ↩↩↩↩↩

  2. pret,pokeemerald/include/global.fieldmap.h(元图块与地图格布局、层类型)、pokeemerald/include/fieldmap.h(NUM_TILES_IN_PRIMARY 512、NUM_TILES_TOTAL 1024、NUM_PALS_TOTAL 13、NUM_TILES_PER_METATILE 8)以及 pokeemerald/include/constants/metatile_behaviors.h(那 240 种行为),2026 年 10 月 2 日访问,https://github.com/pret/pokeemerald/blob/master/include/global.fieldmap.h、https://github.com/pret/pokeemerald/blob/master/include/fieldmap.h、https://github.com/pret/pokeemerald/blob/master/include/constants/metatile_behaviors.h。 ↩↩↩↩↩

  3. Pedro Medeiros,“Consistency”,Saint11,2026 年 10 月 2 日访问,https://saint11.art/blog/consistency/。 ↩↩↩

  4. Fabien Sanglard,“Why Did the SNES Have Two PPUs?”,2026 年 10 月 2 日访问,https://fabiensanglard.net/snes_ppus_why/。 ↩↩↩

  5. gbdev,“Tile Data”,Pan Docs,2026 年 10 月 2 日访问,https://gbdev.io/pandocs/Tile_Data.html;pret,pokered/gfx/tilesets(96 块图块的集合),https://github.com/pret/pokered/tree/master/gfx/tilesets。 ↩

  6. pret,pokered/engine/gfx/sprite_oam.asm(UNDER_GRASS 优先级位),2026 年 10 月 2 日访问,https://github.com/pret/pokered/blob/master/engine/gfx/sprite_oam.asm。 ↩↩

  7. “Final Fantasy VI Developer Roundtable (1994)”,Shmuplations 译,2026 年 10 月 2 日访问,https://shmuplations.com/ff6rt/。 ↩

  8. “Final Fantasy 35th Anniversary Special Interview, Part 2”,访谈整理稿,Nova Crystallis,2023 年 7 月,2026 年 10 月 2 日访问,https://novacrystallis.com/2023/07/final-fantasy-35th-anniversary-special-interview-part-2-of-2-transcription/。 ↩↩↩↩↩

  9. 作者的测量,2026 年 10 月 2 日,取自 videogamesprites.net 上按动作逐段拆分的素材中、每款游戏一名主角的站立帧(每张均经核实为精确的 2 倍最近邻放大);边缘像素指四邻中存在透明像素的任一不透明像素;“近乎纯黑”指各通道均不超过 255 中的 40。素材库:http://www.videogamesprites.net/。 ↩↩↩

  10. “Moonlighter: Building Pixel Art & Preparing for Switch”,80.lv,2026 年 10 月 2 日访问,https://80.lv/articles/moonlighter-building-pixel-art-preparing-for-switch。 ↩↩↩

  11. Noel Berry,“Remaking Celeste’s Lighting”,2026 年 10 月 2 日访问,https://noelberry.ca/posts/celeste_lighting/。 ↩↩↩

  12. “Eastward’s Creators Share Insights on Making Pixel Art Adventures”,Game Developer,2026 年 10 月 2 日访问,https://www.gamedeveloper.com/art/eastward-s-creators-share-insights-on-making-pixel-art-adventures。 ↩↩

  13. “Triangle Strategy Producers Talk HD-2D and Why Other Devs Haven’t Used It”,Nintendo Life,2022 年 5 月,2026 年 10 月 2 日访问,https://www.nintendolife.com/news/2022/05/triangle-strategy-producers-talk-hd-2d-and-why-other-devs-havent-used-it;Octopath Traveler II 的玩家变通方案讨论帖,Steam Community,https://steamcommunity.com/app/1971650/discussions/0/3777994452130450169/。 ↩↩↩↩

  14. Apple Developer Documentation,“MaterialParameters.Texture.Sampler.init(:)”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/realitykit/materialparameters/texture/sampler-swift.struct/init(:);“TextureResource.MipmapsMode”,https://developer.apple.com/documentation/realitykit/textureresource/mipmapsmode。 ↩↩↩

  15. Apple Developer Documentation,“UnlitMaterial.opacityThreshold”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/realitykit/unlitmaterial/opacitythreshold;“UnlitMaterial.textureCoordinateTransform”,https://developer.apple.com/documentation/realitykit/unlitmaterial/texturecoordinatetransform-swift.property。 ↩↩↩

  16. Apple Developer Documentation,“RealityViewRenderingEffects”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/realitykit/realityviewrenderingeffects。 ↩↩↩↩

  17. 作者依据 Apple 公布的面板尺寸(iPhone Duo:https://www.apple.com/iphone-duo/specs/;iPhone 18 Pro:https://www.apple.com/iphone-18-pro/specs/)与 Xcode 27 模拟器设备配置所做的计算,2026 年 10 月 2 日;完整表格见第 5 节。 ↩↩↩↩

  18. U.S. Copyright Office,Copyright and Artificial Intelligence, Part 2: Copyrightability(2025 年 1 月),2026 年 10 月 2 日访问,https://www.copyright.gov/ai/Copyright-and-Artificial-Intelligence-Part-2-Copyrightability-Report.pdf。 ↩↩↩↩

  19. U.S. Copyright Office,Circular 33: Works Not Protected by Copyright,2026 年 10 月 2 日访问,https://www.copyright.gov/circs/circ33.pdf。 ↩↩↩

  20. SNESdev Wiki,“SNES PPU for NES developers”,2026 年 10 月 2 日访问,https://snes.nesdev.org/wiki/SNES_PPU_for_NES_developers。 ↩↩↩

  21. SNESdev Wiki,“Sprites”,2026 年 10 月 2 日访问,https://snes.nesdev.org/wiki/Sprites。 ↩↩↩↩

  22. SNESdev Wiki,“Backgrounds”,2026 年 10 月 2 日访问,https://snes.nesdev.org/wiki/Backgrounds。 ↩

  23. Wikipedia,“Mode 7”,2026 年 10 月 2 日访问,https://en.wikipedia.org/wiki/Mode_7。 ↩

  24. SuperFamicom.org 卡带数据库中 Final Fantasy IV、V、VI 和 Chrono Trigger 的条目,2026 年 10 月 2 日访问,https://superfamicom.org/info/final-fantasy-4、https://superfamicom.org/info/final-fantasy-5、https://superfamicom.org/info/final-fantasy-6、https://superfamicom.org/info/chrono-trigger;FF V 的 16 兆位亦见于注 26 的 FF V 访谈中 Kokubo 的说法(“这次我们有 16Mb”)。 ↩

  25. “Chrono Trigger Developer Interview (1995)”,Shmuplations 译,2026 年 10 月 2 日访问,https://shmuplations.com/chronotrigger/(时田:“这张卡能塞下四个 FFIV”;Kamata:“我想八兆里大概有六兆用在了图形上”)。 ↩

  26. “Final Fantasy V Developer Interview (1992)”,Shmuplations 译,2026 年 10 月 2 日访问,https://shmuplations.com/ffv/。 ↩

  27. Chrono Compendium 论坛,“Sprite assembly data”,主题 2872,2026 年 10 月 2 日访问,https://www.chronocompendium.com/Forums/index.php?topic=2872.0。 ↩↩

  28. SNESdev Wiki,“Color math”,2026 年 10 月 2 日访问,https://snes.nesdev.org/wiki/Color_math。 ↩

  29. “Kazuko Shibuya”,UT Magazine,优衣库,2026 年 10 月 2 日访问,https://www.uniqlo.com/jp/en/contents/feature/ut-magazine/s134/。 ↩

  30. “Chrono Trigger Developer Interviews (1995), Part 2”,Shmuplations 译,2026 年 10 月 2 日访问,https://shmuplations.com/chronotrigger2/。 ↩

  31. “Tetsuya Nomura on Final Fantasy VI”,Final Fantasy Portal Site,2026 年 10 月 2 日访问,https://na.finalfantasy.com/topics/528。 ↩

  32. “Final Fantasy VI Developer Interviews (1994)”,Shmuplations 译,2026 年 10 月 2 日访问,https://shmuplations.com/ff6/。 ↩

  33. “Seiken Densetsu 3 Developer Interview (1995)”,Shmuplations 译,2026 年 10 月 2 日访问,https://shmuplations.com/seikendensetsu3/。 ↩↩

  34. Wikipedia,“Chrono Trigger”(开发一节,引用 Yasuhiko Kamata),2026 年 10 月 2 日访问,https://en.wikipedia.org/wiki/Chrono_Trigger。 ↩

  35. “Interview: Discussing Final Fantasy Pixel Remaster Sprites and Designs”,Siliconera,2026 年 10 月 2 日访问,https://www.siliconera.com/interview-discussing-final-fantasy-pixel-remaster-sprites-and-designs/。 ↩↩

  36. “Square Enix Details the Considerable Amount of Work That Went into the Fonts of Final Fantasy Pixel Remaster”,GoNintendo,2026 年 10 月 2 日访问,https://gonintendo.com/contents/21170-square-enix-details-the-considerable-amount-of-work-that-went-into-the-fonts-of。 ↩

  37. Jason Schreier,“Oh No, Square Enix, What Have You Done to Final Fantasy”,Kotaku,2026 年 10 月 2 日访问,https://kotaku.com/oh-no-square-enix-what-have-you-done-to-final-fantasy-1502268040。 ↩

  38. pret 的反编译项目(pokered、pokecrystal、pokeemerald、pokefirered、poketcg),截至 2026 年 10 月 2 日的 GitHub master 分支,https://github.com/pret。图块数量是从随后各注所列文件的 PNG 尺寸和字节大小读出来的。 ↩

  39. gbdev,“Graphics”与“Object Attribute Memory (OAM)”,Pan Docs,2026 年 10 月 2 日访问,https://gbdev.io/pandocs/Graphics.html 和 https://gbdev.io/pandocs/OAM.html。 ↩

  40. pret,pokered/data/tilesets/tileset_headers.asm、pokered/gfx/blocksets/ 和 pokered/constants/map_constants.asm,2026 年 10 月 2 日访问,https://github.com/pret/pokered/blob/master/data/tilesets/tileset_headers.asm、https://github.com/pret/pokered/tree/master/gfx/blocksets、https://github.com/pret/pokered/blob/master/constants/map_constants.asm。 ↩↩↩

  41. pret,pokered/data/tilesets/collision_tile_ids.asm 和 pokered/home/overworld.asm,2026 年 10 月 2 日访问,https://github.com/pret/pokered/blob/master/data/tilesets/collision_tile_ids.asm 和 https://github.com/pret/pokered/blob/master/home/overworld.asm。 ↩

  42. pret,pokered/home/vcopy.asm(UpdateMovingBgTiles),2026 年 10 月 2 日访问,https://github.com/pret/pokered/blob/master/home/vcopy.asm。 ↩

  43. pret,pokered/data/sprites/facings.asm 和 pokered/gfx/sprites/,2026 年 10 月 2 日访问,https://github.com/pret/pokered/blob/master/data/sprites/facings.asm 和 https://github.com/pret/pokered/tree/master/gfx/sprites。 ↩

  44. pret,pokecrystal/home/map.asm(LoadTilesetGFX)、pokecrystal/gfx/tilesets/johto_palette_map.asm、pokecrystal/gfx/tilesets/bg_tiles.pal 和 pokecrystal/constants/collision_constants.asm,2026 年 10 月 2 日访问,https://github.com/pret/pokecrystal/blob/master/home/map.asm、https://github.com/pret/pokecrystal/blob/master/gfx/tilesets/johto_palette_map.asm、https://github.com/pret/pokecrystal/blob/master/gfx/tilesets/bg_tiles.pal、https://github.com/pret/pokecrystal/blob/master/constants/collision_constants.asm。 ↩↩↩

  45. pret,pokecrystal/gfx/overworld/npc_sprites.pal,2026 年 10 月 2 日访问,https://github.com/pret/pokecrystal/blob/master/gfx/overworld/npc_sprites.pal。 ↩

  46. pret,pokeemerald/include/global.fieldmap.h;Porymap 手册,“Editing Map Collisions”,2026 年 10 月 2 日访问,https://huderlem.github.io/porymap/manual/editing-map-collisions.html。 ↩

  47. pret,pokeemerald/data/layouts/layouts.json,2026 年 10 月 2 日访问,https://github.com/pret/pokeemerald/blob/master/data/layouts/layouts.json。 ↩

  48. pret,pokeemerald/src/data/object_events/object_event_anims.h 和 pokeemerald/graphics/object_events/pics/people/,2026 年 10 月 2 日访问,https://github.com/pret/pokeemerald/blob/master/src/data/object_events/object_event_anims.h 和 https://github.com/pret/pokeemerald/tree/master/graphics/object_events/pics/people。 ↩↩↩↩

  49. pret,pokeemerald/src/tileset_anims.c,2026 年 10 月 2 日访问,https://github.com/pret/pokeemerald/blob/master/src/tileset_anims.c。 ↩

  50. pret,pokeemerald/src/field_effect_helpers.c(倒影、影子、草地特效的摆放)和 pokeemerald/src/data/field_effects/field_effect_objects.h(五帧的高草 sprite),2026 年 10 月 2 日访问,https://github.com/pret/pokeemerald/blob/master/src/field_effect_helpers.c 和 https://github.com/pret/pokeemerald/blob/master/src/data/field_effects/field_effect_objects.h。 ↩

  51. pret,poketcg/Makefile(那条 rgbgfx --colors embedded --auto-palette 规则)和 poketcg/src/gfx/cards/,2026 年 10 月 2 日访问,https://github.com/pret/poketcg/blob/master/Makefile 和 https://github.com/pret/poketcg/tree/master/src/gfx/cards。调色板取值读自 charizard.png 和 doublecolorlessenergy.png。 ↩

  52. “Pokémon: 2000 Developer Interview with Ken Sugimori and Shigeru Miyamoto”,Shmuplations 译,2026 年 10 月 2 日访问,https://shmuplations.com/pokemon/。 ↩

  53. “Sugimori & Masuda Developer Interview (Nintendo Online Magazine, July 2000)”,Anthony Madry 译,Lava Cut Content,2026 年 10 月 2 日访问,https://lavacutcontent.com/sugimori-masuda-developer-interview/。 ↩

  54. 任天堂,“Iwata Asks: Pokémon HeartGold Version & SoulSilver Version”,第 3 部分,2026 年 10 月 2 日访问,https://www.nintendo.com/en-gb/Iwata-Asks/Iwata-Asks-Pokemon-HeartGold-Version-SoulSilver-Version/Iwata-Asks-Pokemon-HeartGold-Version-SoulSilver-Version/3-Just-Being-President-Was-A-Waste-/3-Just-Being-President-Was-A-Waste–225951.html;杉森关于美术人数的说法(“大概不到十个人”)见“Iwata Asks: Pokémon Black and White”,整理稿见 https://pocketmonsters.net/content/Iwata_Asks_BW。 ↩

  55. Soleil(HylianAngel),在 Sabotage Studio 的 SaboMath 所开 Steam Community 主题“Sea of Stars: Frequently Asked Questions”下的评论,2026 年 10 月 3 日访问,https://steamcommunity.com/app/1244090/discussions/0/5913784177847747164/。640×360 这个数字和对 Pixel Perfect 的描述出自该评论者,而非工作室官方说法。 ↩

  56. Billy Basso,关于内部分辨率与扫描线的回帖,Animal Well Steam Community,2026 年 10 月 2 日访问,https://steamcommunity.com/app/813230/discussions/0/4361250264577867864/。 ↩

  57. “Resolution Doesn’t Matter With 2D Games, Says Hyper Light Drifter Developer”,Nintendo Life,2014 年 11 月,2026 年 10 月 2 日访问,https://www.nintendolife.com/news/2014/11/resolution_doesnt_matter_with_2d_games_says_hyper_light_drifter_developer;480×270 这个数字出自 Preston,见“Road to the IGF: Heart Machine’s Hyper Light Drifter”,Game Developer,https://www.gamedeveloper.com/design/road-to-the-igf-heart-machine-s-i-hyper-light-drifter-i-。 ↩

  58. Yacht Club Games,“Breaking the NES for Shovel Knight”,2026 年 10 月 2 日访问,https://www.yachtclubgames.com/blog/breaking-the-nes/。 ↩↩

  59. Godot Engine 文档,“Multiple resolutions”,2026 年 10 月 2 日访问,https://docs.godotengine.org/en/stable/tutorials/rendering/multiple_resolutions.html。 ↩

  60. Pedro Medeiros,“Scaling”,Saint11,2026 年 10 月 2 日访问,https://saint11.art/blog/scaling/。 ↩

  61. “Video: Octopath Traveler Earns Digital Foundry’s Respect for Blending Old With New”,Nintendo Life,2018 年 7 月,2026 年 10 月 2 日访问,https://www.nintendolife.com/news/2018/07/video_octopath_traveler_earns_digital_foundryrs_respect_for_blending_old_with_new。 ↩

  62. “Why Animal Well’s Home-Brewed Engine Was Key to Its Success”,Game Developer,2026 年 10 月 2 日访问,https://www.gamedeveloper.com/design/why-animal-well-s-home-brewed-engine-was-key-to-its-success。 ↩

  63. Thomas Vasseur,“Art Design Deep Dive: Using a 3D Pipeline for 2D Animation in Dead Cells”,Game Developer,2026 年 10 月 2 日访问,https://www.gamedeveloper.com/production/art-design-deep-dive-using-a-3d-pipeline-for-2d-animation-in-i-dead-cells-i-。 ↩↩

  64. Wikipedia,“Sea of Stars (video game)”,开发一节,引用 The Escapist 的 The Making of Sea of Stars 第 15:00 处,2026 年 10 月 2 日访问,https://en.wikipedia.org/wiki/Sea_of_Stars 和 https://www.youtube.com/watch?v=NvsDBAcKFDw。 ↩

  65. Acquire Corp.,“Octopath Traveler”演讲,UNREAL FEST EAST 2018(Epic Games Japan 幻灯片),2026 年 10 月 2 日访问,https://www.docswell.com/s/EpicGamesJapan/KXPWY5-UE4_UFE2018_ACQUIRE_OCTOPATHTRAVELER;Wikipedia,“HD-2D”,https://en.wikipedia.org/wiki/HD-2D。 ↩↩

  66. “Give Your Sprites Depth with Sub-Pixel Animation”,2D Will Never Die,2026 年 10 月 2 日访问,https://2dwillneverdie.com/tutorial/give-your-sprites-depth-with-sub-pixel-animation/。 ↩↩

  67. “Creature Feature: The Surreal Pixel Art and Animation of Animal Well”,Game Developer,2026 年 10 月 2 日访问,https://www.gamedeveloper.com/art/creature-feature-the-surreal-pixel-art-and-animation-of-animal-well。 ↩

  68. Raymond Schlitter,“Pixelblog 1: Color Palettes”,Slynyrd,2018 年 1 月,2026 年 10 月 2 日访问,https://www.slynyrd.com/blog/2018/1/10/pixelblog-1-color-palettes。 ↩↩

  69. “Cassette Beasts Interview”,Pocket Tactics,2026 年 10 月 2 日访问,https://www.pockettactics.com/cassette-beasts/interview。 ↩

  70. Lospec 上 Resurrect 64、Apollo 和 Endesga 32 的调色板页面,2026 年 10 月 2 日访问,https://lospec.com/palette-list/resurrect-64、https://lospec.com/palette-list/apollo、https://lospec.com/palette-list/endesga-32。 ↩

  71. “Getting Started with Pixel Art: An Interview with Eric Barone”,Mental Nerd,2026 年 10 月 2 日访问,https://mentalnerd.com/blog/getting-started-pixel-art-interview/;Wikipedia,“Stardew Valley”,https://en.wikipedia.org/wiki/Stardew_Valley。 ↩↩

  72. “Sea of Stars: Sabotage Director Thierry Boulanger Interview”,MobileSyrup,2023 年 9 月,2026 年 10 月 2 日访问,https://mobilesyrup.com/2023/09/07/sea-of-stars-sabotage-director-thierry-boulanger-interview/。 ↩↩

  73. “The Scratch Coding and Discipline at the Heart of Animal Well”,Game Developer,2026 年 10 月 2 日访问,https://www.gamedeveloper.com/programming/the-scratch-coding-and-discipline-at-the-heart-of-animal-well;Wikipedia,“Animal Well”,https://en.wikipedia.org/wiki/Animal_Well。 ↩

  74. “Road to the IGF: Pixpil’s Eastward”,Game Developer,2026 年 10 月 2 日访问,https://www.gamedeveloper.com/business/road-to-the-igf-pixpil-s-i-eastward-i-;Wikipedia,“Eastward (video game)”,https://en.wikipedia.org/wiki/Eastward_(video_game)。 ↩

  75. 任天堂,“Nintendo Switch 2: More details about features”,2026 年 10 月 2 日访问,https://www.nintendo.com/en-gb/Hardware/Nintendo-Switch-2/Nintendo-Switch-2-More-details-about-features-2790188.html。 ↩

  76. Liberated Pixel Cup,“LPC Style Guide”,2026 年 10 月 2 日访问,https://lpc.opengameart.org/static/LPC-Style-Guide/build/styleguide.html。 ↩↩↩

  77. Raymond Schlitter,“Pixelblog 3: Graphical Projections, Part 1”,Slynyrd,2018 年 3 月,2026 年 10 月 2 日访问,https://www.slynyrd.com/blog/2018/3/14/pixelblog-3-graphical-projections-1。 ↩

  78. Raymond Schlitter,“Pixelblog 20: Top Down Tiles”,Slynyrd,2019 年 8 月,2026 年 10 月 2 日访问,https://www.slynyrd.com/blog/2019/8/27/pixelblog-20-top-down-tiles。 ↩

  79. Stardew Valley Wiki,“Modding:Maps”,2026 年 10 月 2 日访问,https://stardewvalleywiki.com/Modding:Maps。 ↩↩

  80. cr31(经 Boris the Brave 的镜像),“The Blob Tileset”,2026 年 10 月 2 日访问,http://www.boristhebrave.com/permanent/24/06/cr31/stagecast/wang/blob.html。 ↩↩↩

  81. Boris the Brave,“Classification of Tilesets”,2021 年 11 月,2026 年 10 月 2 日访问,https://www.boristhebrave.com/2021/11/14/classification-of-tilesets/。 ↩↩

  82. Tiled 文档,“Using Terrains”,2026 年 10 月 2 日访问,https://doc.mapeditor.org/en/stable/manual/terrain/。 ↩↩

  83. LDtk 文档,“Auto-layers”,2026 年 10 月 2 日访问,https://ldtk.io/docs/general/auto-layers/。 ↩

  84. Raymond Schlitter,“Pixelblog 44: Top Down Trees”“Pixelblog 21: Top Down Objects”和“Pixelblog 43: Top Down Tiles, Part 2”,Slynyrd,2026 年 10 月 2 日访问,https://www.slynyrd.com/blog/2023/5/22/pixelblog-44-top-down-trees、https://www.slynyrd.com/blog/2019/9/18/pixelblog-21-top-down-objects、https://www.slynyrd.com/blog/2023/3/26/pixelblog-43-top-down-tiles-part-2。 ↩↩

  85. Raymond Schlitter,“Pixelblog 7: Developing Style”,Slynyrd,2018 年 7 月,2026 年 10 月 2 日访问,https://www.slynyrd.com/blog/2018/7/14/pixelblog-7-developing-style。 ↩

  86. Cure,“The Pixel Art Tutorial”,PixelJoint 论坛,2026 年 10 月 2 日访问,https://pixeljoint.com/forum/forum_posts.asp?TID=11299。 ↩↩↩

  87. Pedro Medeiros,“Anti-Alias and Banding”,Saint11,2026 年 10 月 2 日访问,https://saint11.art/pixel_art_articles/article5/。 ↩

  88. “Dithering for Pixel Artists”,Pixel Parmesan,2026 年 10 月 2 日访问,https://pixelparmesan.com/blog/dithering-for-pixel-artists。 ↩

  89. Stardew Valley Wiki,“Modding:Farmer sprite”,2026 年 10 月 2 日访问,https://stardewvalleywiki.com/Modding:Farmer_sprite。 ↩

  90. Stardew Valley Wiki,“Modding:Hats”,2026 年 10 月 2 日访问,https://stardewvalleywiki.com/Modding:Hats。 ↩

  91. Raymond Schlitter,“Pixelblog 22: Top Down Character Sprites”,Slynyrd,2019 年 10 月,2026 年 10 月 2 日访问,https://www.slynyrd.com/blog/2019/10/21/pixelblog-22-top-down-character-sprites。 ↩

  92. Raymond Schlitter,“Pixelblog 8: Intro to Animation”,Slynyrd,2018 年 8 月,2026 年 10 月 2 日访问,https://www.slynyrd.com/blog/2018/8/19/pixelblog-8-intro-to-animation。 ↩

  93. Daniel Linssen,“m5x7”,itch.io,2026 年 10 月 2 日访问,https://managore.itch.io/m5x7。 ↩

  94. pret,pokeemerald/graphics/text_window/(边框 1.png,24×24 像素),2026 年 10 月 2 日访问,https://github.com/pret/pokeemerald/tree/master/graphics/text_window。 ↩

  95. Aseprite 文档,“Slices”,2026 年 10 月 2 日访问,https://www.aseprite.org/docs/slices/。 ↩

  96. Jan Willem Nijman(Vlambeer),“The Art of Screenshake”,INDIGO Classes 2013,2026 年 10 月 2 日访问,https://www.youtube.com/watch?v=AJdEqssNZ-U。 ↩

  97. Martin Jonasson 与 Petri Purho,“Juice It or Lose It”,GDC Europe 2012,2026 年 10 月 2 日访问,https://www.youtube.com/watch?v=Fy0aCDmgnxg。 ↩

  98. Stardew Valley Wiki,“Weather”,以及“Modding:Maps”中的 Type 图块属性,2026 年 10 月 2 日访问,https://stardewvalleywiki.com/Weather 和 https://stardewvalleywiki.com/Modding:Maps。 ↩

  99. Aseprite 文档,“Command Line Interface”,2026 年 10 月 2 日访问,https://www.aseprite.org/docs/cli/。 ↩

  100. CodeAndWeb,“TexturePacker: Texture Settings”,2026 年 10 月 2 日访问,https://www.codeandweb.com/texturepacker/documentation/texture-settings。 ↩

  101. Apple Developer Documentation,“SKTexture.filteringMode”与“SKTextureFilteringMode”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/spritekit/sktexture/filteringmode 和 https://developer.apple.com/documentation/spritekit/sktexturefilteringmode。 ↩↩

  102. Apple Developer Documentation,“SKTileMapNode”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/spritekit/sktilemapnode;Apple,“What’s New in SpriteKit”,WWDC16 第 610 场(文字稿镜像),https://nonstrict.eu/wwdcindex/wwdc2016/610/。 ↩↩

  103. Apple,“Bring your SceneKit project to RealityKit”,WWDC25 第 288 场,2026 年 10 月 2 日访问,https://developer.apple.com/videos/play/wwdc2025/288/。 ↩↩

  104. Apple Developer Documentation,“OrthographicCameraComponent”与“OrthographicCameraComponent.scale”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/realitykit/orthographiccameracomponent 和 https://developer.apple.com/documentation/realitykit/orthographiccameracomponent/scale。“等于高度一半”这层关系是作者 2026 年 10 月在 Kiradex 渲染器中测得的。 ↩↩↩

  105. Apple Developer Forums,第 768467 号主题(在 macOS 15.0 上报告的一例 RealityView 在添加正交相机时崩溃,Apple 工程师称应已在 .2 系列版本中修复;2025 年 2 月的跟帖报告投影返回了错误值),2026 年 10 月 2 日访问,https://developer.apple.com/forums/thread/768467。 ↩↩

  106. Apple Developer Documentation,“UnlitMaterial”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/realitykit/unlitmaterial。 ↩

  107. Apple Developer Documentation,“RealityView”与“SceneEvents.Update”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/realitykit/realityview 和 https://developer.apple.com/documentation/realitykit/sceneevents/update。 ↩

  108. Apple Developer Documentation,“PostProcessEffect”与“PostProcessEffectContext”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/realitykit/postprocesseffect 和 https://developer.apple.com/documentation/realitykit/postprocesseffectcontext。 ↩

  109. Apple Developer Documentation,“MeshInstancesComponent”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/realitykit/meshinstancescomponent;Apple,“What’s new in RealityKit”,WWDC25 第 287 场,https://developer.apple.com/videos/play/wwdc2025/287/;Apple Developer Forums,第 694561 号主题(iOS 26 之前没有实例化),https://developer.apple.com/forums/thread/694561。 ↩↩

  110. Apple Developer Documentation,“RealityRenderer”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/realitykit/realityrenderer。 ↩↩

  111. Apple Developer Documentation,“MTLSamplerMinMagFilter”以及示例“Customizing render pass setup”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/metal/mtlsamplerminmagfilter 和 https://developer.apple.com/documentation/metal/customizing-render-pass-setup。 ↩

  112. Apple,技术问答 QA1909,“Supporting native screen scale in your graphics application”,以及 Metal Best Practices Guide,“Native Screen Scale”,2026 年 10 月 2 日访问,https://developer.apple.com/library/archive/qa/qa1909/_index.html 和 https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/NativeScreenScale.html。 ↩↩↩↩

  113. Apple Developer Documentation,“Optimizing iPhone and iPad apps to support ProMotion displays”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/quartzcore/optimizing-iphone-and-ipad-apps-to-support-promotion-displays。 ↩↩

  114. Apple Developer Documentation,“Improving the Performance of a RealityKit App”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/realitykit/improving-the-performance-of-a-realitykit-app。 ↩

  115. Apple Human Interface Guidelines,“Designing for games”,2025 年 6 月 9 日更新,2026 年 10 月 2 日访问,https://developer.apple.com/design/human-interface-guidelines/designing-for-games。 ↩↩

  116. Apple Developer Documentation,“Image.interpolation(:)”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/swiftui/image/interpolation(:)。 ↩

  117. Apple Developer Documentation,“LSSupportsGameMode”,2026 年 10 月 2 日访问,https://developer.apple.com/documentation/bundleresources/information-property-list/lssupportsgamemode。 ↩

  118. Xcode 27 模拟器设备配置(/Library/Developer/CoreSimulator/Profiles/DeviceTypes/ 下的 capabilities.plist),作者于 2026 年 10 月 2 日读取:iPhone Duo 的两块显示屏为 1398 × 2034 和 2007 × 2853,倍率 3.0;iPhone 18 Pro Max 为 1320 × 2868,倍率 3.0;iPad Pro 13 英寸(M5)为 2064 × 2752,倍率 2.0。 ↩↩

  119. Apple,“iPad Pro: Tech Specs”,2026 年 10 月 2 日访问,https://www.apple.com/ipad-pro/specs/。 ↩

  120. Blake Crosley,“iPhone Duo for Developers”,blakecrosley.com,2026 年 9 月,https://blakecrosley.com/blog/iphone-duo-for-developers。 ↩

  121. Stardew Valley Wiki,“Stardew Valley Fair”(农产品展台评分),2026 年 10 月 2 日访问,https://stardewvalleywiki.com/Stardew_Valley_Fair。 ↩

  122. Serebii,“Pokémon Ruby & Sapphire: Secret Bases”,2026 年 10 月 2 日访问,https://www.serebii.net/rubysapphire/secretbase.shtml。 ↩

  123. Nookipedia,“Happy Home Academy”,2026 年 10 月 2 日访问,https://nookipedia.com/wiki/Happy_Home_Academy。 ↩

  124. That Penguin Game,“Your Igloo”与“Chat Modes”(Club Penguin 帮助文档存档),2026 年 10 月 2 日访问,https://thatpenguingame.com/club-penguin-help/game-help/your-igloo/ 和 https://thatpenguingame.com/club-penguin-help/safety/chat-modes/。 ↩↩↩

  125. Serebii,“Pokémon Omega Ruby & Alpha Sapphire: Super-Secret Bases”,2026 年 10 月 2 日访问,https://www.serebii.net/omegarubyalphasapphire/supersecretbases.shtml。 ↩

  126. pret,pokeemerald/src/data/easy_chat/easy_chat_groups.h 及各组词表,2026 年 10 月 2 日访问,https://github.com/pret/pokeemerald/blob/master/src/data/easy_chat/easy_chat_groups.h;流行语的解锁规则(每当追潮流的人因记录交换而到来时解锁一个词)见 pokeemerald/src/easy_chat.c,https://github.com/pret/pokeemerald/blob/master/src/easy_chat.c。 ↩

  127. Serebii,“Pokémon GO: Friends”,2026 年 10 月 2 日访问,https://www.serebii.net/pokemongo/friends.shtml。 ↩

  128. Project Horseshoe,“Cozy Games”(2017 年),转载于 Lost Garden,2026 年 10 月 2 日访问,http://lostgarden.com/2018/01/24/cozy-games/。 ↩

  129. “Pokémon TCG Pocket: Binder and Card Showcase Guide”,Game Rant,2026 年 10 月 2 日访问,https://gamerant.com/pokemon-tcg-pocket-binder-card-showcase-album-guide/;Wikipedia,“Pokémon Trading Card Game Pocket”,https://en.wikipedia.org/wiki/Pok%C3%A9mon_Trading_Card_Game_Pocket。 ↩

  130. Daniel Cook,“Game design patterns for building friendships”,Lost Garden,2017 年 1 月,2026 年 10 月 2 日访问,https://lostgarden.com/2017/01/27/game-design-patterns-for-building-friendships/;以及“Kind Games: Designing for Prosocial Multiplayer”,2023 年 7 月,https://lostgarden.com/2023/07/08/kind-games-designing-for-prosocial-multiplayer/。 ↩

  131. U.S. Federal Trade Commission,“Fortnite Video Game Maker Epic Games to Pay More Than Half a Billion Dollars over FTC Allegations”,2022 年 12 月,2026 年 10 月 2 日访问,https://www.ftc.gov/news-events/news/press-releases/2022/12/fortnite-video-game-maker-epic-games-pay-more-half-billion-dollars-over-ftc-allegations。 ↩

  132. Raymond Schlitter,“Pixelblog 35: Top Down Interiors”,Slynyrd,2021 年 11 月,2026 年 10 月 3 日访问,https://www.slynyrd.com/blog/2021/11/30/pixelblog-35-top-down-interiors。 ↩

  133. Wikipedia,“Lane Merrifield”(Club Penguin 的过滤器“会过滤掉诸如‘mom’这类看似无害的词,并同时屏蔽电话号码和电子邮件地址”),2026 年 10 月 3 日访问,https://en.wikipedia.org/wiki/Lane_Merrifield。 ↩

相关文章

让应用为 iPhone Duo 做好准备:一个完整的实例

为 iPhone Duo 准备并提交应用:决定布局的 SDK 标记、一款真实应用走完每种姿态的过程、两块屏的截图,以及 App Store 的规则。

36 分钟阅读

Xcode 27.1 beta:把应用放进 iPhone Duo 模拟器

Xcode 27.1 beta 带来了第一个 iOS 27.1 SDK 和一台 iPhone Duo 模拟器:SDK 新增了什么,设备配置文件怎么写这两块屏,以及探针在每种姿态下报告了什么。

21 分钟阅读

为 iPhone Duo 做设计:什么会移动,什么会分栏,什么保持不动

把 Apple 的 iPhone Duo 设计指南和三场 Tech Talk 当作规则来读:用两个尺寸类别取代逐一适配的姿态、折痕处的位移、arrangement,以及侧边栏。

16 分钟阅读