下载 App

【《上帝的球》开发者日志 #03】—— 光被墙卡住了 249 帧

10/1551 浏览综合 包含 AI 合成内容

日期:2026.10.14 | 开发第 3 天 | 距投稿截止还有 6 天
昨天那篇末尾我列了三条待办:补多语言、跑真机、加引导。今天一件都没做。
今天一整天都在跟光较劲。起因很小——我自己随手在球里摆了两面镜子想让一束光来回弹,结果光粘在玻璃上了,一动不动。我盯着看了半分钟,然后意识到:这不是摆法的问题,是我写的光子逻辑从根上就错了。
这篇只讲一件事:把一个元素修到"我敢说它是对的"。

先说结论

光子这一块,我数出来四个独立的毛病,一个比一个隐蔽:
#症状我最后查到的地方
1光撞到玻璃就被"吸"住,永远停在玻璃表面穿透明介质时只改了坐标变量,没真的把粒子挪过去
2光飞出球的边界后不消失,变成一颗永远停在网格边缘的幽灵销毁条件是"寿命 > 0 才递减",而我在边界上把寿命直接设成了 0
3光撞墙反射一次,寿命就短一截反射分支里顺手砍了寿命,纯属我写的时候想当然
4贴着球壁的曲面飞,会在同一个格子里原地反射到天荒地老对角方向走不通时没有退路,整条光卡在楼梯口
第 4 个我是用"最长原地停留帧数"这个指标抓出来的。修之前,同一个场景里最长的一次停留是 249 帧——八秒多,一束光贴在球壁上抖了八秒。
修完是 2 帧。

一个一个说

① 玻璃反而成了唯一能粘住光的材质。
这条最讽刺。我把"透明"理解成"光能穿过去",于是写了:光碰到玻璃就把折射后的新方向算出来,赋值给循环里的坐标变量,然后接着往下走。
问题是那只是三个局部变量。粒子对象本身还在原来的格子里。下一次移动拿着一个错误的原点去做交换,把同一个粒子对象写进了两个格子——33 个格子下标指向同一个粒子。数组一坏,后面的演化结果全部不可信。
修法:穿透明介质时老老实实走一次真正的位移。另外在移动函数最底下加了一道安全阀——if (格子里的对象 !== 我要移动的对象) 直接放弃这次移动。宁可少动一格,也绝不把数组写坏。
② 幽灵光子。
飞出边界的处理,我原来的写法是"把寿命设成 0,让它自然消亡"。但粒子引擎的销毁条件是"寿命大于 0 时才每帧递减",寿命已经是 0 的粒子永远不递减、永远不回收。于是它变成一颗停在网格最边上、不吃不喝也不动的光子,你还能看见它。
改成飞出边界直接回收——不啰嗦。
③ 反射不该扣寿命。
这条纯粹是我偷懒。撞墙反射的时候我顺手把寿命截短了,写的时候想的是"光撞墙总得损耗点吧"。但这是错的:镜子反射的光不会因为反射而从世界上消失得更快。光飞多久,只该由它自己的寿命决定。
④ 249 帧——曲面上的楼梯口。
这条最有意思,也花了我最久。
球的边界在整数网格上不是一个光滑的圆,是一圈楼梯。一束光斜着撞上楼梯的拐角时,它想去的那个对角格恰好是墙壁,于是原地反射;反射后的方向又指向另一个对角格,还是墙,再反射回来……
我原来的反射法线只有一种取法:从球心指向外。在楼梯拐角上这个法线会把光又推回墙里,配合整数坐标就成了死锁。
修法是给移动加"退路":对角走不通,就先试试只走 x 那一轴;还走不通,再试只走 y 那一轴。光于是不撞死在拐角上,而是沿着墙滑开。
这个思路其实很朴素——现实里你贴着墙走路,撞到东西也不会原地弹回来,你会侧一下身绕过去。我把它写进了移动里。
修完之后我单独试了一颗贴着壁飞的光子:300 帧里它飞了 92 格,一路顺着球壁滑过去,没有一次停顿。

顺手修掉的三个别的东西

光修光了,但既然已经在这儿了,就把我先前记录下的几个"看着不对劲"的地方一起处理了:
植物和水在一起,水瞬间就没了。 原来是"相邻即反应",一帧就把整片水推成氧气。改成按接触面积缓慢消耗——植物慢慢把周围的水分解掉,变成氧气冒出去,水面是慢慢下去的,不是一刀切。
氧气和二氧化碳直接往底下坠。 这个是物理上就不对:气体凭什么被重力像石头一样拽到球底?改成上浮、扩散、往上走。现在球里的气体是分层的,重的在下面、轻的在上面。
火柴人会滑到固体下方,甚至穿出球外。 补了两道约束:与固体的碰撞、以及球壁的硬边界。火柴人现在站在沙面上,不会整个人钻进地里。

然后是那一整晚的测试

我不敢只靠肉眼。写了一个专门盯光子的检查脚本,23 条断言:穿透、折射、全内反射、撞墙、出界回收、以及"不许原地卡住"。
这里踩了一个我自己的坑,值得写下来:
"原地卡住"这个指标我一开始写错了。
我的第一版是这样统计的:看某一个格子下标连续多少帧是光子。跑出来一堆误报——一个明明在正常飞行的光束被判成"卡住"。
原因是我忘了自己写的东西:**光子沿直线每帧走 3 格,整排光点的格子下标集合根本不变。**第 0 帧占了 3、6、9…,第 1 帧还占 3、6、9…,因为整排一起平移了一格。集合不变,但那是在飞。
改成按粒子对象的身份追踪——谁是谁,这才是"同一个东西停了多久"。改完误报清零。
同样的错我还犯了一次:另一个探针只比较 x 坐标,结果把"在沙柱里竖直弹跳"的光子判成原地卡住(它 x 没变,其实在上下飞)。改成比较完整坐标之后,各元素的停滞帧数全部归零。
这两件事让我确认了一件事:测出来的"异常",先怀疑度量,再怀疑代码。
到凌晨的结果:
  • 光子检查 23 / 23 全过
  • 全元素冒烟(166 种 × 多场景)全过,1500 帧混战单帧 30.12 ms
  • 生态长跑:四组场景,最长的一组跑满 6000 帧没崩,另外两组分别在 96.3 秒和 56.4 秒走到终点
  • 火柴人碰撞、设备旋转、DOM/输入集成 —— 全过

今天的一个片段

这段片子是用游戏本身一帧一帧渲出来的(900 帧、1080×1920、30 fps),过程中撞出来的坑比写游戏还密:
  • 一格只能放一颗光子。想画一条实心光束,只在一个位置每帧投一颗是不够的——光子每帧前进 3 格,光点间距正好等于步长,整条光带变成一把梳子。得沿光束方向错开 1 格同时投三颗,三组相位首尾相接才接得上。我一开始还自作聪明地"并排投三行",结果只加粗不填缝,白忙。
  • 斜着飞的一串光子会互相顶住。所以光束必须是轴对齐的。为了让"屏幕上的水平"在世界坐标里也是水平,我得先把球的自转倒回 0。
  • **两条光束绝不能交叉。**交叉点上双方各顶一下,1 格间距的光带会被连锁推到整条僵死。
  • **Math.sin(Math.PI) 不是精确的 0。**一个 1e-16 的正数会让"竖直光束"被判成斜向——因为方向判断写的是 vy > 0 ? 1 : vy < 0 ? -1 : 0。我现在会在投光之前把 1e-15 量级的残差掐成 0。
  • 自转的单位是弧度/帧,不是角度。我一开始误当成角度,填了 0.16,等于 9°/帧,几百帧就把球里的东西搅成一锅均匀的糊。另外粒子会滞后于球体的转动:实测 0.0064 rad/帧还能保住沙堆,再快整团被搅散。片子最后定在 0.0012。

问题与风险

  1. **真机还是没跑过。**这是第一天就欠的债,今天第三天,还欠着。这是我现在最大的风险。
  2. 光子的斜向飞行仍然不可靠:单颗没问题,一串就会互顶。我这次的绕法是"只用轴对齐光路",也就是说游戏里用激光器随便斜着打一束光,很可能还是糊的。这是下一件必须解决的事。
  3. 生态平衡偏紧:四组长跑里有两组会走到终点(96.3 秒 / 56.4 秒)。不是崩,是耗尽了。这是设计问题,不是 bug,但得调。
  4. 审计证明的是"物理正确",证明不了"好玩"。手感只能人来判断。

下期计划

  • 把斜向光束彻底修掉——这是今天绕过去的,不是我解决的。要查的是"每帧一步、粒子在扫描过程中被重复更新"这条路径。
  • 真机跑一遍(安卓 + iOS),重点验触摸和声音解锁。

最后说个事

今天最爽的一刻,不是那 23 条断言全绿。
是我把"对角走不通就退而走单轴"那三行加进去、重新跑那个 249 帧停滞的场景——2 帧。
然后我让那颗光子贴着球壁飞。它顺着那圈楼梯滑下去,一格一格,一路滑到对面。屏幕上就是一条弧线,干干净净。
一束光贴着一个圆的内壁走,这件事在数学上没什么了不起。但那一瞬间我脑子里想的是另一件事:这个球是我写的。
它里面的每一条规矩——光会拐弯、会弹回来、会在墙上滑一下——都是我一条条定下来、又一条条验过的。所以那条弧线不是"看起来像",它就是。
另外,官方要求开发期内至少更 5 篇日志,这是第 3 篇。AI 使用说明我会在投稿时一并附上:哪些是它写的、哪些是我改的、哪些是我推翻它自己重写的,都会写清楚。
猜你想搜
聚光灯游戏创作挑战 开发者日志
00:34
《荒原复苏指南》开发日志④:关卡演示堂堂袭来!!截图
《荒原复苏指南》开发日志④:关卡演示堂堂袭来!!
- 人类曾因掌握元素合成技术而一度辉煌,又因滥用元素能量而逐渐从内里衰败。 - 30世纪80年代。社会文化充斥着激进乐观主义与庞大机械美学,在这里,污染和能源共生,幸福与痛苦并存。官方广播和宣传画里依旧在宣扬“科学将战胜一切”、“元素能量将再造新农田”的口号,而世界主城却已经因为污染过度而濒临崩溃、空间挤压严重。为了寻找新的生存空间与无污染能源,官方启动了“重构拓荒计划”。 - 玩家将作为前线拓展
18 赞
6 回复
【童谣镇】聚光灯第二次开发日志截图
【童谣镇】聚光灯第二次开发日志
开发进度: 美术 1、主角人物立绘已细化完成 2、所有NPC的QQ人形象与呼吸动画已设计完成 3、大部分UI界面已设计完成 4、面包房建模与树屋建模以及基础房屋、路灯、树木模型已完成。 5、制作过场动效,制作通用动效材质ing 6、广场资产替换、永续桥和植被的资产替换、房屋资产替换,河流制作 7、学校模型的材质完成 8、石墩子、小道具模型制作ing 9、NPC正比胸像绘制ing 策划 1、任务系统
16 赞
10 回复
【涌现符】开发日志#1截图
【涌现符】开发日志#1
大家好,我们是电子织机队,核心成员都来自同一个学校社团。 经过了五天的设计大烧烤终于把玩法大概定了下来。虽然题目一出大家立刻都想到了涌现式玩法,但是在这么短的时间内设计出优秀好玩的涌现式玩法对于没有太多经验的学生还是难度颇高,涌现式叙事对于没有专门编剧的我们队也难以达到理想的效果。 皮尔斯提出的"Symbols grow"是一个很有趣的概念,也即一个符号在使用中产生解释,解释引导预期和行动,经验又
4 赞
2 回复
01:21
【开发日志07】《我记得》|Windows 里的光与细节截图
【开发日志07】《我记得》|Windows 里的光与细节
第七篇日志,想带大家重新看一遍《我记得》的世界。 最近把录制切到了 Windows,也把 DLSS 加进了这次画面展示。以前日志里放出的主要是 Mac 开发版,这次可以换个角度看看:屋顶追逐时掠过的建筑、第四章跳跃后展开的另一重世界,还有 Boss 战里不断变化的光影和攻击。比起只看静态截图,我更想看看这些细节在奔跑、转场和战斗中能不能保持清楚。 这次实录使用 RTX 4060,开启 DLSS 质
5 赞
5 回复
00:30
《涌》第一次30秒实机演示截图
《涌》第一次30秒实机演示
整段都是游戏实机录的,没有单独做动画,中间夹着几段打精英怪和 Boss 的镜头,封面就是片子最后那一帧——血写的「涌」。 声音分两层:打斗声全是游戏里的真实音效,背景音乐是后面加的。 30 秒不长,希望大家喜欢。还有更多内容后面做好了也会录视频! #聚光灯gamejam开发者日志
4 赞
6 回复
00:07
雨天決行 开发者日志02-人工智能的自我修养截图
雨天決行 开发者日志02-人工智能的自我修养
又和大家见面啦!第二篇日志,说实话一开始不知道该怎么编排,但团队里惊喜的成果越来越多,我们已经迫不及待把更新的内容端上来给大家啦!那么事不宜迟,快来看看都有什么新情报吧ദ്ദി˶ー̀֊ー́ )✧ 一.美术(重磅升级) 以主美小为的生命力作为燃料(bushi)本次美术组取得了大进程!首先是各个ui界面的优化和细化,上次大家看到时还只是初具雏形的草稿,现在大多都完整起来了哦! 同时,随着配色的补全,手
43 赞
39 回复
01:12
屏息3:涌现,开发日志04截图
屏息3:涌现,开发日志04
无数只飞蛾,每一只都只遵循简单的规则,但当它们聚集在一起,却可能产生意想不到的行为,甚至形成某种意识。 这也是我想通过游戏探讨的问题: 当 AI 学会了人类所有的知识,它是否真的能够理解人类? 目前游戏还在持续开发中,希望能在恐怖与解谜之外,加入一些关于 AI、意识和人性的思考 #聚光灯游戏创作挑战 #TapTap聚光灯游戏创作挑战 #聚光灯gamejam开发者日志
2 赞
00:07
首曝!来《灵栖工坊》探索灵魂和魔法涌现的故事~【开发日志01】截图
首曝!来《灵栖工坊》探索灵魂和魔法涌现的故事~【开发日志01】
【游戏介绍】扮演魔女栖栖,从魔女之家出发,去不同的世界结识不同的友人,学习和组合各种魔法,开办自己的工坊,创造、满足生灵们的需求,体验各种故事~ 是不是想到了Noita? 当然,玩法还没做出来呢,所以,先看看美术吧。这一次,我们实现了2DHD的效果,spine小人的动画也更加丰富了——就是手搓起来好累好累就是了。(策划:累嘛……还有有十几个NPC) 伊迪雅克,一所建造在人和灵两个世界之间位面的魔法
13 赞
6 回复
个人向TapTap聚光灯GameJam经验分享截图
个人向TapTap聚光灯GameJam经验分享
首先简单介绍下我们的项目。 《机类Botkind》,名字借鉴于人类humankind。 核心玩法:编辑指令来控制机器人个体行为,进而在工厂中实现自动化产线 游戏类型:模拟经营,自动化,增量(存疑),编程启蒙(雾) 如题所示,这是一篇个人向GJ经验分享,面向对GJ流程好奇想要尝试或已经在尝试的同学,可能会包含很多主观见解。笔者在这次GJ里作为新人队长和主策划带领了一支十一人的新人为主的学生队伍完成了
4 赞
1 回复
【开发者日志 #01】从玩游戏到做游戏:我们用记忆诠释「涌现」截图
【开发者日志 #01】从玩游戏到做游戏:我们用记忆诠释「涌现」
大家好呀,我们是【肝完就是胜利】组合! 最开始我们只是刷刷作品、玩玩游戏。万万没想到,现在居然能和一群三观契合、热爱创作的小伙伴一起,从“玩游戏的人”,变成了“做游戏的人”。在TapTap打磨属于我们自己的作品,真的是一件奇妙又幸运的事。 Gamejam【涌现】主题公布后,我们几个人陷入沉思。 好抽象!好哲学!我们反复挠头:玩家能看到什么?感受到什么?又能在游戏里收获什么全新的体验?让我们一时无从
5 赞
4 回复