当你为三岁小孩写一个画图软件——Mr. Baby Paint 与偶然发现的细胞自动机
目录
- 一个芬兰程序员,和他坐在腿上的三岁孩子
- 为幼儿设计软件:核心是「没有任何操作是错的」
- 边缘即 UI:用屏幕边缘替代菜单栏
- 意外的细胞自动机:当填充工具开始互相打架
- 像素膨胀:一个像素引发的算法狂欢
- 所以这一切值吗
凌晨三点看到 Hacker News 上有个 101 分的帖子,标题叫「Mr. Baby Paint 与偶然发现的细胞自动机」。
点进去之前我以为又是一篇「我用 AI 做了什么」的 Show HN。点进去之后发现,是一个芬兰程序员 Heikki 给自己的三岁孩子写了款画图软件,然后顺手发现了新细胞自动机、写了十几种像素膨胀算法,还把自己做的字体渲染管线开源了。
一篇文章里塞了三条完全独立但每条都很好的故事线。这 101 分是实至名归的。
一个芬兰程序员,和他坐在腿上的三岁孩子
Heikki 的三岁孩子想参与爸爸的一切活动——包括他坐在电脑前做的事。小孩子喜欢按弹簧键盘、晃动鼠标、转滚轮听咔哒声。但按一个三岁小孩的操作精度,在普通软件里什么都做不了。
他们试了 Wordpad 和 MS Paint。结果是什么呢?小孩子随意一甩鼠标就把画图模式切到了菜单栏,或者点歪了工具栏,软件就进入了一个完全不同的「模式」。爸爸得不停地把鼠标从孩子手里拿回来,把模式调回画图状态。
孩子觉得被打断很不爽。爸爸觉得这个流程根本不可持续。
Heikki 的总结很到位:「这孩子不操作电脑的时候对鼠标键盘完全没兴趣。」——意思是,孩子想做的不是「玩鼠标」,而是「玩电脑上的画图」这件事本身。这是一个重要的设计前提。
为幼儿设计软件:核心是「没有任何操作是错的」
Heikki 给自己的要求是:用做正经项目的认真态度来对待这个幼儿画图软件。
MVP 极其简单:全屏空白画布,没有菜单栏,没有工具栏。孩子坐在爸爸腿上操控鼠标,爸爸用左手按键盘快捷键。CMD+S 保存,CMD+E 清空画布。整个屏幕就是画图区域,孩子就算猛砸键盘也不会跳出任何东西。
但 Heikki 不满足于做一个「被阉割的 MS Paint」。他想让每一次操作都有反馈——无论是左键画图、滚轮撒沙、还是右键填充。「没有任何操作是错的」是这个软件的设计哲学。每次点击都产生痕迹、音效、或视觉反馈。
有一个细节让我很喜欢:幼童的鼠标移动速度极快,两帧之间的跨度可能是几十甚至几百像素。普通画图软件用直线连接采样点,但在这种场景下会画出非常生硬的折线。Heikki 用了 Catmull-Rom 样条插值来让曲线保持平滑,然后在曲线上每 1px 盖一个笔刷纹理。
对于一个「给两岁小孩画的画图软件」来说,这个技术投入已经远超「将就一下」的标准了。
边缘即 UI:用屏幕边缘替代菜单栏
Mr. Baby Paint 没有菜单栏,没有工具栏,没有调色板。它的 UI 设计在屏幕的四条边上——光标碰到不同边缘触发不同功能。
左边缘分成 16 段:控制笔刷大小和字体选择
底边缘分成 16 段:16 种颜色
顶边缘分成 64 段:64 个字符(A-Z a-z 0-9 !? 和一些符号)
右边缘分成 2 段:圆形笔刷和方形笔刷
这个设计确实聪明。幼童的鼠标操作是随机的,但屏幕边缘是一个永远可以命中的目标。你不需要精确地点击一个小图标——甩到边缘就能切换功能。而且因为分段较大(每段在 1080p 屏幕上大约 67px 宽),孩子自己乱动鼠标也可能「碰巧」换到新颜色,然后产生一种「我做到了」的兴奋感。
意外的细胞自动机:当填充工具开始互相打架
这是整篇文章里我最喜欢的段落。
Heikki 受《Mario Paint》启发,让填充工具不是瞬间完成的,而是一行一行慢慢扩展——看着颜色从点击位置向四周「生长」的过程本身就有观赏性。但和 Mario Paint 不同,Heikki 不想让填充阻塞其他操作。他允许多个填充同时进行,也允许用户在填充过程中继续画图。
然后有趣的事情发生了。
他意识到,因为所有活动的填充共享同一个「生长预算」(每帧总增长上限 1000px),新填充比旧填充生长得更快(因为它们更小)。小填充开始碰撞旧填充还在生长的边缘。当他把两个同色的填充放在一起时,它们开始互相合并、吞并、振荡——
一个基于洪泛填充的细胞自动机,就这样被撞了出来。
「它半稳定:可以运行几千代才进入稳定的振荡模式,有时候一个填充『赢了』,其他的就消失了。这是一个有趣的 bug,所以我把它留下来了。」
Heikki 试了 GPU 版本的实现——更快,无延迟——但他觉得 GPU 版本更无聊。CPU 版的「固有缓慢」成了设计的一部分。这种选择在性能优先的软件世界里几乎不可想象,但在这个为幼儿画的画图软件里,它确实是对的。
像素膨胀:一个像素引发的算法狂欢
故事还没完。
Mr. Baby Paint 内置了 16 种位图字体,大部分来自老计算机(如初代 Macintosh)。Heikki 想自己画几个,但他的单线矢量字体渲染器只生成 1px 宽的笔画——太细了。他想要更粗的版本。
正常人会怎么做?手动描一遍。
Heikki 做了什么事?他写了12 种不同的像素膨胀算法,从最暴力的「每个黑像素原地放大成方块」开始,一路尝试了跳种距离场、角隙检测、中轴骨架、签名距离场、16 方向射线投射、Meijster 精确欧几里得距离变换、带碰撞检测的迭代膨胀……最终在第 12 个版本后回到了第 4 版,在 Aseprite 里手动清理了一下,作为最终方案。
那 11 个「失败」版本呢?「它们其实也都能用,只是没达到我心里的标准。」
他把这个位图字体管线直接集成到了 Mr. Baby Paint 里。现在可以轻松从同一份源文件生成不同粗细和风格的字重。
所以这一切值吗
Mr. Baby Paint 在 itch.io 上卖 4.99 美元。到目前为止卖了大约 30 份。
30 份 × 4.99 = 149.7 美元。去掉平台抽成,可能到手一百出头。如果按工时算,他写这篇博客的功夫就已经远超这个数了。
但我在想的是另一个问题:这个项目里的每一个产出——幼儿画图软件、细胞自动机发现、12 种像素膨胀算法、位图字体管线——全都是因为「我三岁的孩子想玩鼠标,而 MS Paint 对他来说太难了」这个最开始的原点触发的。
那些算法狂欢不是为了发表论文或拿投资,只是因为一个爸爸想让坐在他腿上的孩子能开心地画画。
这 30 份销量不是指标。孩子画出了什么才是。
封面图:用文生图模型为这篇文章生成了一张极简儿童画风格的概念图。
评论(0)
暂无评论,来写第一条吧~