先试试看
打开数字熔炉 Demo,点几下「锻造」,攒够 15 锭就买一个学徒工坊。放着不管它也会自己产锭,攒到 100 万锭可以「重铸」换永久倍率,从头再堆一轮更大的数字。进度只保存在当前浏览器。
我是怎样描述需求的
这个题目的关键词是「建造经营」「消磨时间」「堆叠巨大数字」,我把这三层需求拆成具体的机制写进提示词:
请创建 number-forge 静态 Web Demo,一个放置类数字增长游戏。核心循环:点击按钮产出「锭」,用锭购买工坊,工坊自动持续产锭;工坊有多个等级,购买成本随持有数量指数增长;数字要能堆到非常大,需要 K/M/B/T 等单位换算显示。加入重铸机制:消耗当前进度换取永久产出倍率,可无限循环重置堆叠。用原生 HTML、CSS、JavaScript,不引入后端,用 localStorage 存档,并支持关闭页面后按真实经过时间结算离线收益。视觉延续米白纸张、深墨色文字的风格,加一个熔炉暖色调强调色,支持深色模式和手机适配。完成后重点检查大数字换算在整数进位处是否正确,以及购买按钮是否会随收入实时变成可用状态。
这段描述基本对应了游戏的八座工坊、重铸公式和存档逻辑。我特意在最后一句提了两个容易出错的地方——后来也确实在这两处发现了问题。
使用时你会看到什么
点开页面先看到一个大大的锭数和「锻造一下」按钮,每次点击会弹出一个飘字反馈。买下第一座「学徒」后,右侧速率会显示「+0.10 / 秒」,此后工坊清单会持续解锁:风箱、熔炉、锻造机、传送带、精炼厂、熔铸塔、星辰锻炉,越往后单座产出越高,购买成本也涨得更快。攒够百万锭,侧栏的「熔炉重铸」会点亮,点下去清空当前锭和工坊,但换来的余烬会让此后的产出和点击收益永久提高 2% 每枚,可以一直重铸下去,数字理论上没有上限。关掉页面几分钟再回来,会看到一条播报告诉你离线期间按 70% 效率烧了多少锭。
从一个小需求开始
这个 Demo 没有多货币系统、没有科技树、没有成就墙,只有「点击 → 自动化 → 重铸」这一条循环,够消磨时间,但边界很清楚。想把想法落成页面,可以先读做第一个 Demo 前,先把需求写清楚,把谁来玩、最短循环、技术约束和验收方式写清楚,再让它动手。
先定体验,再选技术
放置类游戏最容易走偏的地方是把系统设计得太复杂——货币太多、公式太绕,反而让「越堆越大」的爽感变得模糊。我先只画了一条循环:点击攒第一笔钱 → 买自动化 → 攒够重铸 → 数字重新起跑但基数更高。所有界面元素都服务这条线,没有额外的菜单或页面。
技术上继续沿用原生 HTML、CSS、JavaScript,一个 setInterval 驱动的主循环,配合 localStorage 存档。状态只有四类:当前锭数、本轮已赚总量(用于计算重铸收益)、余烬数量、以及八座工坊各自的持有数量,没有引入任何框架或状态管理库。
大数字如何堆叠
「堆叠巨大数字」是这个题目的核心,所以数字格式化单独写成一个函数,按千分位分级换算成 K、M、B、T…直到 No(10³⁰),超出预设单位后自动生成 aa、ab、ac 这样的双字母后缀继续往上叠:
function formatNumber(num, keepDecimals) {
const n = Math.max(0, num);
if (!isFinite(n)) return '∞';
if (n < 1000) {
if (keepDecimals && n > 0) return n < 10 ? n.toFixed(2) : n.toFixed(1);
return Math.floor(n).toString();
}
let tier = Math.floor(Math.log10(n) / 3);
let scaled = n / Math.pow(1000, tier);
if (Number(scaled.toFixed(scaled < 10 ? 2 : 1)) >= 1000) {
tier += 1;
scaled = n / Math.pow(1000, tier);
}
return scaled.toFixed(scaled < 10 ? 2 : 1) + suffixFor(tier);
}
第一版实现里,999999 会被显示成 1000.0K——四舍五入把三位数顶到了千位却没有跳到下一级单位。我让它专门检查了这个进位边界,加了一段「如果四舍五入后满千,就把单位再往上提一级」的修正,问题才消失。这类边界错误在数字堆叠类游戏里很容易被忽略,却直接影响「看数字变大」这件事本身给不给人爽感。
工坊与重铸如何构成经济循环
八座工坊按等级排列,购买成本按每次购入乘以 1.15 的指数增长,产出则线性叠加:
function buildingCost(i) {
return BUILDINGS[i].baseCost * Math.pow(1.15, state.buildings[i]);
}
function rawPerSecond() {
return BUILDINGS.reduce((sum, b, i) => sum + b.rate * state.buildings[i], 0);
}
重铸的收益按本轮总收入的平方根计算,floor(sqrt(本轮总收入 / 1,000,000)) 枚余烬,每枚余烬让产出和点击收益永久 ×1.02。这个公式保证早期重铸门槛低、能很快感受到「重来一次却更强」的反馈,后期则需要指数级更多的收入才能换到下一枚余烬,配合工坊成本的指数增长,构成一个可以无限延伸但节奏递减的循环。
点击收益也不是固定值,而是 Math.max(1, 本轮每秒产出 × 0.05) × 余烬倍率——前期点击是主要收入来源,后期自动化跑起来后点击依然有意义,不会变成纯粹的摆设。
存档与离线收益
每 5 秒自动写入 localStorage,并在页面关闭前补写一次。重新打开时,读取存档里的时间戳和当前时刻的差值,按 70% 效率、最多 4 小时结算离线产出:
function applyOfflineProgress(lastSave) {
const elapsed = Math.min((Date.now() - lastSave) / 1000, OFFLINE_CAP_S);
if (elapsed < 5) return;
const gain = rawPerSecond() * multiplier() * elapsed * OFFLINE_RATE;
state.ingots += gain;
state.runEarned += gain;
}
70% 效率和 4 小时上限是刻意留出的策略空间:完全放着不管也会有收获,但回来看一眼、手动买点工坊,效率仍然更高,这也是这类游戏「值得时不时回来点开」的设计意图。
验证与边界
除了在浏览器里实际点击、购买、重铸、切换深色模式和窄屏之外,我还写了一段基于 jsdom 的无头脚本,把真实的 index.html 和 app.js 加载进模拟 DOM,逐步验证:点击攒锭、购买后费率显示是否正确、存档写入与读取、快进到百万锭后重铸能否拿到预期的余烬数量、以及手动伪造一次「十分钟前的存档」重新加载后离线收益是否符合公式计算——四组场景全部对上预期数字,才确认发布。
当前版本有三个明确边界:单机存档不跨设备同步,没有成就或排行榜,购买只能一次一座(没有「买到下一个整十」之类的批量购买)。这些都是可以独立叠加的增强项,不影响核心循环已经成立。
下一步可以怎么做
第一步是加入批量购买(买 10 座、买到刚好花完当前锭),减少后期反复点击。第二步是给每座工坊加一个「升级」——花费更多锭把单座产出翻倍,让工坊数量不是唯一变量。第三步是把余烬倍率之外再加一层「传承科技树」,让重铸不只是数字变倍率,还能解锁新的工坊类型。
这个 Demo 最适合用来验证一件事:一条「点击、自动化、重铸」的循环加上足够扎实的大数字显示,就足够让人愿意时不时点开看一眼。至于要不要往上叠更多系统,可以等真实玩家的反馈说话。