街头霸王 II 开发探秘:纸上追踪

若说探究CPS-1系统的工程奥秘令人着迷,那么开发者用纸张与剪刀追踪ROM预算的幕后故事同样引人入胜。

90年代末,卡普空在街机界崭露头角。这家总部位于大阪的公司似乎接连推出爆款:1988年的《恶灵古堡》,1989年的《最终决战》,1991年的《街头霸王II》,以及众多其他优秀作品。

彼时,游戏爱好者踏入街机厅必见成排的卡普空机柜,这既是玩家青睐的明证,亦是运营商追捧的实证。

过去半年间,我利用闲暇研究卡普空的成功案例,尤其聚焦《街头霸王II》的诞生历程。若说探究CPS-1系统的工程奥秘令人着迷,那么开发者用纸张与剪刀追踪ROM预算的幕后故事同样引人入胜。

元素周期表

CP-SYSTEM 101


1988年问世的CPS-1(当时称为CP-System)是卡普空统一的街机平台。其众多创新中,最突出的是强大的图形渲染管道。

虽然仍采用图层概念,但CPS-1摒弃了矩形精灵的限制。OBJ图层由称为“贴图”的16×16像素单元构成。在《街头霸王II》中,通过组合贴图形成角色姿势。这种设计赋予美术师极大自由度,使其能设计任意尺寸和形状的“对象”。

Ryu’s victory pose (29 tiles) Sagat’s Tiger Uppercut pose (30 tiles) Honda’s Jump pose (45 tiles) Chun-li being awesome pose (25 tiles)

除水平/垂直翻转等基础操作外,CPS-1无法对瓦片进行旋转或缩放处理。其真正突破在于每帧可操控的瓦片数量——据称高达256个。

在当时实现如此大规模的画面动态效果堪称技术奇迹。这种“震撼效果”极大推动了游戏的成功。以《惩罚者》为例,最终BOSS“金皮纳”的动作序列竟由多达80个贴图构成。

《惩罚者》画面几乎被精灵图覆盖(来源:rq87.flyingomelette.com)

ROM预算


CPS-1的强大性能虽是美术人员的福音,却让项目经理头疼不已。在ROM芯片价格高昂的年代,游戏开发初期便需设定不可逾越的ROM预算。

CPS-1问世前,预算控制只需简单计算:美术团队可用的精灵数量=ROM容量÷矩形精灵尺寸。但自由形态的引入带来了追踪难题。

纸张系统


解决方案竟来自纸张与剪刀。

为最大化利用现有容量,我们把ROM容量写在白板上,再像拼贴画般剪贴像素角色。

白板留白处即代表ROM剩余容量。于是我们像拼图般从留白处开始填充。

有件趣事:我们把结局设计留到最后,结果完成时容量已告罄。正束手无策时,我们在桌底发现了遗失的电路板。

我们称之为“奇迹记忆板”。

– 西谷彰,《街霸2》开发访谈

空白画布

由于CPS-1采用16色索引(每像素4位),16×16像素的贴图占用空间为16x16x16x16 / 2 = 32 KiB。以《街头霸王II:世界战士》为例,开发团队在6 MiB的ROM预算中为精灵分配了4.6 MiB,因此共打印了144张纸质贴图。

图纸考古学


该系统为软件考古学家提供了绝佳研究机会。其中可辨识后期添加的功能(这些功能利用剩余空间实现,因此切割得不够工整)。

遗憾的是,我仅发现两张图纸。在《最终决战开发者访谈》一文[1]中发现了达尔西姆,而在《如何制作卡普空格斗角色》[2]一书中发现了隆。

Sheet 0x3300 Sheet 0x4500

请注意每张贴图表左上角的贴图寻址系统(达尔西姆0x3300与隆0x4500)。前两位十六进制字符表示贴图表ID(取值范围[0-255]),后两位则是该贴图表内的具体贴图ID。

另需注意贴图采用矩形而非正方形设计。CP系统采用384×224分辨率,其宽高比与CRT显示器的4:3比例存在差异。若设计师绘制正方形贴图,显示效果将被压缩变形。通过矩形绘制,他们实质上实现了视觉素材的反向拉伸,确保贴图以原始绘制形态呈现。这种非正方形像素系统曾让美术团队苦不堪言。

在制作《遗忘世界》时,我发现了这个纵横比问题。“像素不是正方形的!”我告诉老板。

“不可能,我要求的是正方形!”他当场回应并联系了硬件部门。

“像素是正方形的!”他最终承认道。

后来我再次提出抗议,老板却回应说是计算错误。

——安田彰,SF2制作人[3])

虽然只成功提取出两张ROM片令人失望,但通过ROM内部残留的压痕信息仍可实现重建。得益于mame和sf2platinium提供的GFX-ROM格式解析工具[4],我们开发了自动化重建程序。待所有图层还原完毕,分析与推测阶段正式开启。

图层解析探索


CPS-1采用四层架构。《街头霸王II》的OBJ层由144张图层构成,总计4.6MiB。剩余1.4MiB分配给背景层与前景层,即SCROL1(16张)、SCROL2(8张)和SCROL3(23张)。

占用字节量最大的角色依次为:扎吉夫(19张)、本田(15张)、达尔西姆(14张,身材虽瘦但伸展幅度惊人!)、布兰卡(15张)、隆(13.5张)、盖尔(11张)、春丽(10张)、 迪克塔托(9,斗篷独占整张贴图!)、沙加特(6)、拳师(6)、克劳(6)和肯(3)。

首张贴图主角自然是主角隆。

注意隆在0x69/0x6A的顶部头发被移至0x6F/0x9F以保持布局完整。左上姿势头发偏移的原因不明,是否因GFX ROM地址0x0000不可用?分析其他游戏也证实图块0x0000从未被使用。

肯是叠加层


Ryu palette
Ken palette

观察饼图可见,肯角色仅占用了三个图层的极小空间。

这是因为肯是叠加在隆贴图上的补丁。隆的调色板经过特殊设计以匹配肯的肤色,仅服装和面部颜色存在差异。

在贴图表0x0100中,隆的胜利姿势0x76紧邻肯的2×2补丁0x70,补丁痕迹尤为明显。

肯的胜利姿势以隆的姿势为基础,通过调色板转换并替换差异贴图实现。注意隆牙齿的白色来自其服装纹理,而肯因道服为红色,美术师不得不复用部分肤色纹理。

碎片追踪


在贴图表0x4700(“肯的补丁区”)的0xC0处,可见一张非格斗角色的小型肖像。这实为开发团队的合影,他们在游戏结尾的制作名单中出现。值得注意的是,这些照片既非真实肖像也未使用真实姓名——此举很可能是为避免人才挖角。

趣闻:“NIN”是卡普空制作人西谷明(Akira Nishitani)的代号。他参与制作的所有游戏(包括《Forgotten Worlds》《Final Fight》《街头霸王2》)的高分榜均使用此署名。

ROM空间捉襟见肘


开发者似乎严重缺乏ROM存储空间,甚至采用了局部姿势对称技术。在0x4E00处,萨加特的左腿在0xBA位置缺失。为补全该部位,CPS-1主板被指令调用右腿贴图并进行水平翻转。

达尔西姆(0X3300)贴图差异


达尔西姆重建图层几乎完全吻合。但可见红色标注的姿势未被采用,该姿势为让出空间给春丽的“百裂腿”而被舍弃,表明这是后期追加内容。在0x4C处可见为布兰卡预留的碎片空间。

隆(0X4500)图层差异


隆的角色图层同样存在类似差异。两个姿势(位于0xC20xCC处)在正式版前被删除,以腾出空间容纳春丽的“旋风脚”(该招式是否也是开发后期追加?)及团队致谢肖像。

图层系统使用了多久?


考虑到当时已有X68000等强大工作站,我始终好奇图层系统究竟使用了多久才被图形资源编译工具取代。通过查阅其他游戏的图层文件,可以进行粗略推测。

首要目标是梳理该团队所有作品,从《街头霸王2》《遗忘世界》《最终决战》之前的早期作品开始。虽然未专门定位调色板而采用默认灰度模式,但仍能清晰辨认图形轮廓。

Forgotten World sheet (1988) Final Fight sheet (1989)

不出所料,发现结构完全一致。后续作品如《街头霸王2:冠军版》和《街头霸王2:超激斗》也进行了核查。GFX仅获得微小改进[5],图层结构始终未变。

Street Fighter 2: Champion Edition (1992) Street Fighter 2: Hyper Fighting sheet (1992)

其他卡普空团队


卡普空曾由不同团队并行开发多款作品。经查证负责《恶灵古堡》与《忍者龙剑传》的团队,其制作流程虽略显宽松,但本质上仍遵循相同模式。

Ghouls ‘n Ghosts sheet (1988) Strider sheet (1989)

非卡普空游戏


部分CPS-1游戏并非卡普空出品,例如Mitchell公司开发的《Pang-3》。同样未见任何改动。

CPS-2与《超级街头霸王2》


似乎CPS-1平台的大多数(若非全部)游戏都采用了角色表系统。而CPS-2游戏则稍难分析,因为卡普空添加了诸多保护机制。虽然68000指令集和Z-80指令集均经过加密处理,但图形ROM仅被重新排列,仍可轻松查看。

在首款CPS-2作品《超级街头霸王2》(1993年)中,原有十二名角色阵容新增了四位角色。原有角色的角色表布局保持不变。

Super Street Fighter 2 Ryu sheet (1993) Super Street Fighter 2 Cammy sheet (1993)

但观察卡米角色图层(0x9000)可发现布局显然非手工制作,似乎采用了自上而下、左至右的分配系统。卡普空大约在1992年开始使用工具构建《街头霸王2》的新GFX ROM,是否使用x68000工作站仍未可知。

街头霸王Alpha


在CPS-2平台后续作品中,《街头霸王Alpha》(1995)与《街头霸王Alpha 3》(1998)均呈现出工具生成的结构特征。所有角色贴图如同压碎的土豆般紧密排列,毫无空余像素空间。这表明CPS-2平台可能从未采用过原始的贴图系统。

Street Fighter Alpha sheet (1995) Street Fighter Alpha 3 sheet (1998)

征集访谈对象


本人多次尝试联系参与CPS-1/CPS-2系统开发的程序员,迄今均未成功。本人旨在记录并保存这些机器的编程方式,尤其关注X68000计算机的应用细节。若您具备亲身经历或能引荐相关人士,敬请邮件联系 🙂 !

参考文献


^ [1] Final Fight Developer’s Interview
^ [2] How To Make Capcom Fighting Characters
^ [3] Akiman’s Twitter account
^ [4] Tool CPSheet
^ [5] Differences Between SF2 World Warrior and SF2 Champion Edition
元素周期表抱枕

本文由 TecHug 分享,英文原文及文中图片来自 STREET FIGHTER II, PAPER TRAILS

共有{77}精彩评论

  1. 我非常欣赏法比安·桑格拉德的作品。我读过他关于《毁灭战士》和《德军总部》的著作,却从未想过他会开始研究《街头霸王II》的精灵图。

    这些资料实在精彩,我认为它们作为“开发者考古学”具有重要价值。80年代和90年代在我们这代人看来并不遥远,但很容易忘记当时的人们并没有如今这些精密工具。话虽如此,他们确实拥有自己的工具——能一窥当年开发者的工作流程实在令人振奋。

    1. 这位传奇人物总让我犹豫是否该放弃FE转投游戏开发。看到这些资料实在太酷了!

  2. 我痴迷于探索那些诞生于极端资源限制环境的巧妙技巧及其深远影响——当硬件特性激发创意时,往往催生出令人惊叹的创新性滥用方案。

    这篇文章太精彩了!

  3. 我曾是90年代这款游戏的开发者之一:

    https://www.youtube.com/watch?v=lubyi79e6SY

    游戏原本计划采用100% 2D设计,开发团队在编程和美术方向上投入数月后才意识到:当时的个人电脑内存根本不足以存储角色所有旋转角度的精灵图。当拥有四位主角时,数据量便迅速失控——每位角色可朝8或16个方向行走,还能奔跑、爬楼梯、攀爬梯子、匍匐前进、使用20种不同枪械等。等距背景均采用2D贴图拼贴,布局方式与《街头霸王》等所有精灵图游戏如出一辙。

    因此开发数月后,团队决定将所有角色改为3D建模以节省内存。我仅用两周就完成了全游戏转换,包括创建从3D Studio转换的工具链——管它是什么格式,毕竟当年根本没有标准规范。当时几乎没有3D加速器,我甚至记不清是否需要专用SDK支持。我记得我们的游戏无法使用这些加速器,可能是因为帧内3D与2D的合成方式非常特殊——当时多数游戏要么纯2D要么纯3D,很少混合使用。

    《街霸II》的精灵图里藏着彩蛋吗?《Abomination》里倒是不少,主要写在城市里的涂鸦里。

    还有像这样(TFT)不能公开讨论的:https://www.reddit.com/r/gaming/comments/3ylmm4/a_staggering

    1. 若您错过了博文最后一段,其中写道:“我曾多次尝试联系参与CPS-1/CPS-2系统开发的工程师,但至今均告失败。”欢迎随时联系他,为传承您的伟大成就与造福人类尽一份力 🙂

  4. 开发DMG模拟器时,我注意到这些微型精灵图往往高度相似。每个精灵图本质上是由起始地址指向的一系列字节序列。

    这让我想到:是否存在能识别字节重叠、重新打包精灵图并调整地址的压缩算法?

    进而引发思考:是否存在无需解压的压缩算法?只需打包一次,后续直接指向数据片段即可。

    接着我又想到:这不正是解压机制的原理吗?只不过更积极主动?

    1. 这正是基础Lempel-Ziv压缩的运作方式——数据压缩两大核心技术之一。它会记录已解压内容的历史,当遇到重复数据时,直接编码指向该数据的指针。其变体(LZW、LZ77、LZSS以及无数定制版本——毕竟游戏开发者总爱重新发明压缩算法)已被应用于无数游戏中。

      另一种是熵编码,即将字节和指针编码重写为基于频率优化的可变长度值:高频代码用更少位数,低频代码用更多位数。最基础的方法是霍夫曼编码,类似于可变长度的二进制电话号码。

      这两种技术共同构成了DEFLATE压缩的核心原理,该算法被zip、gzip和zlib广泛采用。而zlib又被应用于PNG、PDF等众多格式。

      在构建C代码时,简单的“查找重复项和子集并仅修改指针”压缩已成标准操作。若程序包含“foobar”和“bar”两条字符串,链接器会将“foobar”存储在字符串区,并为“bar”指向其后3字节处——前提是编译/链接选项配置正确。

    2. 在Commodore 64游戏中压缩背景时也采用了类似的技巧。

      压缩器会创建一种特殊字体(C64的“字符集”为8×8像素),并将图片切分成8×8的图块,每个图块对应一个ASCII字符。尽管C64的高分辨率为320×200(多色模式下为160×200),但由于重复块的存在,实际使用的字符通常少于256个。最终背景会通过特殊字体中的这些字符进行绘制。该过程不涉及预先解压操作。

    3. 多年前我曾开发过一款N64 ROM压缩器,能推导出游戏变种的粗略谱系树。其工作原理如下:

      通过暴力比对所有ROM文件,找出与其他版本差异最小的“祖先”版本。

      选定该祖先后,对剩余所有ROM与之进行差异性重新暴力比对。

      这种方法计算上既愚蠢又浪费,但能将40种卡带变体压缩至50MB存储空间,而非1GB。

      1. 你还记得如何确定“祖先”版本吗?

        1. 对于第n+1个卡带,总是选择n与剩余卡带间差异最小的那个。

          筛选前n个则更复杂。关键线索在于ROM名称是否包含“Japan”变体。否则以4张图像为例:16种差异组合中,半数是镜像关系——即ROM 2→4的差异与ROM 4→2的差异互为反转。

          因此理想的初始祖先图像是拥有最多最小子图的图像。

    4. 岩田聪在《口袋妖怪 金/银》中著名的RLE实现方案,仅靠消除空白区域就轻松压缩了50%。

      哈夫曼编码虽是压缩精灵重复图案的最简算法,但即便在旧系统上加载字典进行解压,恐怕也会遭遇内存限制。至少会导致画面卡顿。

    5. 没错。建议研究紧凑数据结构,它们与压缩算法密切相关。前述压缩算法(包括熵压缩及所有LZ变体)都需要解压步骤。虽然它们可能通过分块处理提升解压速度并牺牲存储空间,但解压环节不可或缺。这与它们如何从数据中消除冗余信息(例如使用指针)无关。紧凑数据结构则完全避免解压操作。同样需以存储空间为代价,但某些操作可直接在磁盘上的紧凑数据上执行。

    6. 例如向量量化。听起来很复杂,但压缩本质上是k均值聚类,解压则是查找表操作。

  5. 记得另篇文章提到,主开发者在编码初期就预留了大量内存空间。临近截止日期时,当项目面临内存不足危机,他直接清空这块预留区,项目便顺利交付。

    我认为这种做法值得推广——设定内存预算并严格遵守。

    1. 约一年前曾有人提及类似做法,建议在服务器上常驻10GB空白文件。

      此举在后续空间不足引发问题时屡次救场,即便只是更新操作等场景。

      1. 我记得这是为应对“磁盘满载”导致系统瘫痪的情况,因为此时日志文件也无法写入。

    2. > 我认为这正是当下我们更应践行的做法:设定内存预算并严格遵守。

      构思起来很有趣,但不确定对多数项目是否是合理的权衡?

  6. 我深爱着我们能挖掘三十年前的ROM镜像,重现那些为我们文化重要组成部分而手绘的精灵图集。更令我欣喜的是Fabien真正付诸实践并向我们展示具体方法。

    1. 后期作品被加密导致他无法访问,这让我有些难过。DRM思维又在作祟了。

      1. 卡普空当年为打击山寨街霸2主板费尽心力。虽然对游戏保存工作很遗憾,但能理解他们为何选择DRM路线。话说回来,那些ROM不都解密了?

      2. CPS-2的画面并未加密,只是进行了打乱处理。代码加密技术也早已被破解。

  7. 超爱这篇文章。13到20岁那会儿《街霸II》风靡一时…这款游戏的生命周期实在太长了。初次见到它时简直震撼到不行——毕竟那时见过的游戏只有NES和286电脑上的PC游戏。

    有趣的是,如今我完全不想从事商业游戏开发,但当年却渴望投身其中。那个时代的开发者能在限制中迸发惊人创造力,他们倾注心血让游戏充满乐趣。如今却充斥着成瘾机制、氪金陷阱、过度追求画面而忽视玩法等乱象,简直毁了一切。

    1. >如今却充斥着成瘾机制、氪金陷阱、过度追求画面而忽视玩法等乱象,简直毁了一切。

      这话大错特错,尤其说到《街头霸王》系列… 如今人们抱怨微交易,却从未意识到街机本身就是最早的微交易形式。当年游戏专门设计成每小时从玩家身上榨取固定金额,难度调整也旨在维持这种榨取率。

      当今时代堪称游戏开发者的黄金时期。可用的平台数量、分发渠道、工作室/发行商的多样性都远超历史任何时期。

      1. > 如今人们抱怨微交易,却从未想过街机才是微交易的鼻祖

        我完全不同意。当年街机根本不像微交易,我们乐意投币畅玩。如今即便收入远超童年,微交易仍令人感到赤裸裸的剥削!

        若人们“根本不愿思考”,说明两者相似性微乎其微

  8. 若Fabien能实现这点,将堪称奇迹。

    日本电子游戏开发始终笼罩着神秘面纱,尤其8位与16位时代。我对当时像素画的制作工艺深感兴趣——据说他们使用特殊键盘和CRT显示器绘制。

    整个互联网上仅有一页资料简要提及过这个过程。

    1. 根据我在Akiman推特上了解到的信息,他们是在16×16的方格纸上绘制,然后用手动方式通过键盘的箭头键和0-F键转换成像素。

      仅此而已。

  9. Fabien的又一篇精彩文章 🙂

    令我惊讶的是,在ROM容量如此受限的情况下,美术团队竟未被要求进一步压缩资源。某些贴图除角落或边缘的零星像素外基本空白;我本以为开发者会要求美术师微调姿势以节省整张贴图的空间。

    或者这些贴图集本身就是“精打细算”的成果——在确保游戏能塞进现有ROM容量的前提下,已无需再节省额外贴图?

    1. 我推测开发者优先考虑了更大幅度的优化,比如将隆的身体贴图复用给肯,或是镜像萨加特的腿部贴图。若这些优化已达目标,就无需再四处调整边缘的零散贴图了。

      此外,考虑到贴图集是手工编排的,任何被保留的贴图在整体布局中可能都未能实现最佳压缩效果。

  10. >> 注意Ryu在0x69/0x6A的顶部头发被放置在0x6F/0x9F位置以避免破坏布局。左上姿势头发偏移的原因不明。是否因为GFX ROM地址0x0000无法使用?分析其他游戏也发现该贴图地址从未被使用。

    我猜想,使用空白瓦片进行编码和操作比指定那些非矩形精灵的奇特形状更简单。只需告知硬件瓦片尺寸,再提供包含空白瓦片的瓦片集即可。一旦找到ROM中指定如何组合瓦片形成精灵的区域,就能验证或推翻这种推测。

    听起来完整精灵必须完全位于单一页面内,因此必然存在由图块编号组成的精灵序列表,且每个编号占用1字节。既然已知部分姿势的图块布局,开发者本应能记录该字节序列,在ROM中定位后检查是否存在零图块区域。或者直接查阅MAME源代码——这类细节在该项目中很早就被彻底解析清楚了 🙂

    1. > 似乎完整精灵必须完全位于单一页面内

      实际情况并非如此。达尔西姆贴图页中就包含春丽和布兰卡的碎片。

  11. 我正在为Neo Geo[1]开发精灵贴图打包工具,其图形处理方式与CPS1极为相似。手动拼贴这些贴图简直难以想象,堪称浩大工程。

    Neo Geo硬件提供若干图形特性,其运作前提是贴图必须按特定顺序排列。满足这些要求实属有趣的挑战。

    [1] https://github.com/city41/sromcrom

    1. 完成CPS-1文档后,我正考虑着手整理Neo Geo资料。目前尚未找到优质文档,不知您能否推荐相关资源?

      欢迎发邮件至 fabiensanglard.net@gmail.com

  12. 文章引人入胜,但有个疑问:

    既然能将图像拆分成不同地址的多块图块(正如文中示例所示),难道只需关注总图块数量即可?为何还要费心将这些姿势(或多或少)完整地排列在贴片上,甚至制作这些贴片?

    1. 因为贴片布局是手工绘制设计的。若采用CPS-2游戏那样的自动化流程,他们本可以(也确实)实现自动化。

  13. 《街头霸王II》是我童年最常玩的游戏。始终是这款杰作的忠实拥趸。

    1. 它对我们这代人产生了深远的文化影响。SFII问世时我正值青春期,至今仍珍藏着在街机厅和便利店与朋友对战的美好回忆。那时我刚开始学编程,早期代码大多是尝试制作《街头霸王》游戏(通常只是用QBasic重现游戏美术和动画)。

    2. 没错,《街霸II》的超激版和涡轮版也占据了我青春岁月的重要篇章。多么美好的年代啊!真怀念那段游戏时光

  14. 我可能记错了,但如果是《街头霸王II》或其他类似游戏,在PC平台(DOS时代)的实现方式是:角色贴图并非以矩形(含透明度)存储,而是采用跑长编码——即“从这里到那里有一行像素”。因此代码只需用“movsb”指令,无需耗费资源检测透明度。

    …也可能是其他游戏,但尝试解码图像的过程很有趣 🙂

    (我记得这种方式还能简化像素碰撞检测,但细节记不清了——这可能是《星际控制II》的特性,我们小时候常用来解码图像/模组的游戏)

      1. 你说得可能没错(就我情况而言)。我玩过的版本(!!!)大概是1991-1996年间(?)——那时我刚开始研究这个格式(同时也在研究《星际争霸2》等游戏)。可能更晚些,但毕竟是老游戏了。真没想到这是个自制版本 🙂

  15. 这让我想起给《雷神之锤》自制模型做贴图展开。练习后发现,把面部、头部和前侧区域放大以容纳更多细节效果更佳。其余部分则可压缩或镜像处理,从而最大化利用256×256像素的贴图空间。

  16. 他们竟在6MiB内存里创造出如此精彩的游戏。限制反而激发了创造力,而非扼杀它。

  17. 海量的精灵图使其成为当时超级任天堂平台最大的ROM——足足16兆位!这也导致游戏定价高达75美元,简直离谱。

    不知他们在超级任天堂平台是否采用了相同的技术方案。

  18. 必须称赞这个网站的呈现效果。它完美复刻了老式打字机输出的简洁质感。

    视觉舒适且不干扰阅读——这才是网页应有的模样。

    1. 任何网站都不该使用两端对齐排版,我为此甘愿战至最后一刻。

      1. 此言极是。移动端尚可忽略,但桌面端绝无必要。

        若身处每个抉择都残酷二分的宇宙,我宁可选择低调的两端对齐,也不愿忍受JavaScript的狂轰滥炸。

    2. 设计确实精妙。唯独文字对齐方式值得调整。

  19. 记得看过他们软件设置的视频,用游戏手柄代替鼠标绘制精灵图。

  20. 话说这些图案做极客风包装纸应该很带感。

    1. 绘图部分采用SVG格式,其余均为基础HTML。

      1. 谢谢Fabien。我知道世界计数器的新冠图表使用SVG技术,所以不太清楚具体原因。

        但现在我收到“访问被拒。您的IP地址已被列入黑名单”的提示,只能等上几周再通过普通网络查看了。

        1. 我完全没想到用户会有这个需求。结果发现只需添加“user-scalable=yes”属性即可。我已重新生成网站,现在应该能正常缩放了。

          1. 我以前也不这么认为,直到有段时间主要用手机阅读。屏幕尺寸与视力匹配度,或是单纯追求可读性比例,这些因素都值得考虑。

        2. 遇到这种情况最烦人了,我直接切换到桌面版。真烦人。这个网站也存在同样问题,我用手机浏览时也经常遇到。

          1. 抱歉,我完全没意识到。我认为问题已修复,请告知是否正常。

            1. 不必在意。您愿意查看问题就够了。真的不必道歉!我非常欣赏您的工作,您道歉反而让我过意不去!我表达不清了,“这个网站”指的是Hacker News…唉。

              请带着我的谢意共度佳节!

    2. 结构相当基础。除了文章中段驱动4张图片的画廊需要一点JS外,几乎全是HTML、CSS、文本和图片(PNG及SVG格式)

      1. 谢谢!填写验证码后就能用了。真奇怪,我在Fabien的页面上等了很久,以为SVG已经渲染完毕了。我会再回来看看我的出口是否旋转了,IP封锁是否消失了。

  21. 《街头霸王》是我唯一买过的游戏之一…另一个是Kali(游戏相关应用)。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

你也许感兴趣的: