← 返回主页
小游戏 可破坏地形 净室复刻 原生 JS CORS

粉碎任意网页:把整个互联网变成射击关卡

2026.09 · by Easin

输入一个网址,它的标题、文字、图片、盒子全部变成可破坏的像素关卡——拿枪一路向下轰,把整个页面打成渣。这篇是开发实录:怎么扒闭源原作的设计、怎么用「掩码+画布」双层结构做出 Worms 式可破坏地形、怎么在公共跨域代理全军覆没的国内网络里活下去,以及「出生龛」「击杀顿帧」这些我踩出来/偷出来的小聪明。

🎮 线上开玩:bayshier.github.io/destroy · 📦 源码:github.com/bayshier/destroy(全中文注释)

一、扒原版:闭源,所以只能净室

原版 Destroy Any Website 是 Sprite Fusion 出品的爆款小游戏:输入网址 → 网站变成可破坏像素关卡 → 一路打穿。我把它 187KB 的主 chunk 拆开分析了一遍,确认两件事:没有开源仓库;但它的架构完全可以靠行为反推——

环节原版实现我的复刻
网页抓取自有服务端 /api/page?url= 代理公共 CORS 代理链(见第四节,惨烈)
页面转关卡服务端处理 + 前端排版前端 DOMParser 按文档流重排
破坏系统自研 canvas 引擎掩码+画布双层(见第二节)
武器pistol/smg/shotgun/launcher/railgun + grenade手枪/冲锋枪/霰弹枪/火箭筒 + 手雷
联机WebSocket 六位房间码❌ 静态托管做不了,单机

武器参数都是真扒的:原版弹速 2000~2300 px/s(≈35px/帧)、smg 散布 0.07、火箭带子母弹(bomblets:8)。我的第一版弹速只给了 7px/帧,被自己人吐槽「打不出去」——对齐量级之后手感立刻正常了。复刻一件事,数值量级比机制还原更容易漏。

二、可破坏地形:掩码 + 画布双层

整个游戏的核心只有一个念头:网页是一张纸,纸上所有墨水都是地形。实现是《百战天虫》的经典套路——

破坏率是增量累计的(erase 返回本次毁掉的像素数),全程不需要任何全图统计。

三、网页 → 像素关卡的映射规则

不是截图,是解析 DOM 后重新排版——打碎的是内容本身:

网页元素关卡形态
h1~h626px→14px 标题大字(打碎最解压)
p / li / td 等正文11~13px 文字平台,逐行断行
img经代理取回真实图(防画布污染),失败画「小山太阳」占位框
pre / code灰底代码块
a 链接蓝字+下划线,并记录为敌人「链接虫」出生点
纯 SPA 空壳检测内容过少,自动补占位盒子保证可玩

四、国内网络实测:公共代理全军覆没

这是整个项目最绝望的一节。浏览器同源策略不允许直接 fetch 别人的网页,原版用自有服务端代理;GitHub Pages 是静态托管,只能靠公共 CORS 代理。实测结果:

代理国内直连备注
api.cors.lol⚠️ 能通但无 CORS 头curl 测通是假象,浏览器照样拒
api.allorigins.win❌ 超时主站通,API 子域不通
corsproxy.io❌ 401转向收费
thingproxy / r.jina.ai❌ 死/被墙—
codetabs / cors.eu.org⚠️ 时好时坏 / 假代理—

三个应对:① 内置演示关卡升为一等公民(标题页黄色大按钮,零网络 100% 可玩);② 自定义代理输入框——填 https://你的代理/?url={url} 存 localStorage 自动插到链首;③ README 提供 10 行 Node 自建代理,有服务器的一劳永逸。网址模式诚实降级为「网络允许时的进阶玩法」。

五、出生龛:向页面索要一块确定的安全区

最阴的 bug 藏在出生点上。直觉做法是扫描页面找「净空+地面」——但密集文字页里根本不存在 13px 高的净空。扫描失败走兜底坐标,那个点恰好落在标题文字内部,物理引擎把角色逐帧顶出屏幕上边缘(y=-22):角色看不见、跳跃没有地面、左右移动在画面外——玩家视角就是「这游戏没法玩」。

修复思路反转:不求页面给出生点,关卡生成时强行造一个「出生龛」——在版心中部 clearRect 清出一条竖井(身体区+跳跃空间),铺一根绿色出生平台,之后掩码扫描自动生效。任何页面(包括纯图片页)都有确定可站的起点。顺手给角色加了白描边+红帽子,在深浅不一的页面上永不难找。

六、手感三件套:全向瞄准、武器量级、打击感

七、CSS 文字墙:解析器容错的恶意

上线后第一反馈:输入 baidu.com,整个页面被一堵 CSS 代码墙糊满。原因:代理传坏的 HTML 会让 DOMParser 的容错把 <style> 内容当成正文文本节点排出。两层防御:

  1. junkText 启发式过滤:文本含标签碎片(<style/<div),或花括号 ≥6 + 含 :; + 开头非中文段落 → 拒画。4 样本单测全过,正常中英文段落零误杀。
  2. 转义自动重解析:解析后探针发现标签碎片 → 反转义 HTML 再解析一次。

用同款坏 HTML 离线复现:CSS 墙消失,标题/导航/正文正常成关卡,稀疏处自动补占位盒子。另修了图片抓取无超时的隐患(单图 8 秒强制放弃)。

八、踩坑清单

坑现象解法
出生点落在文字里角色被顶出屏幕外,玩家以为无法操控出生龛:清竖井+铺平台,向关卡索要确定安全区
画布扩容重置画笔排版后字号全变默认ensure() 后必须重设 ctx.font
外链图片污染画布getImageData 抛安全异常图片走代理取 blob 再解码
弹速对不上量级「子弹打不出去」的观感对齐原版 2000+px/s 量级
rAF 被遮挡暂停自动化测试全 0,以为游戏坏了测试时截图强制渲染帧(人玩不受影响)
junkText 误杀花括号多的正常技术段落被拒要求开头 40 字非中文 + 括号密度双条件

九、小结

这个项目加起来不到一千五百行,没有一个依赖。做完最大的感受有两层:技术层面,「像素即地形」这个单一念头像种子一样长出了整套玩法——碰撞、破坏、敌人生成、通关判定全部从它推导;产品层面,原版把「浏览网页」这个最无聊的日常翻转成了「摧毁网页」,好的创意不需要复杂的技术,需要的是一次足够狠的视角转换。

后续待办都写在仓库的 AGENT.md 里:自建代理、轨道炮与子母火箭、Boss 战、以及原版最核心的联机合作。

Easin's Code Lab · 作者:Easin 🎮 玩一下 · ← 返回主页 · 源码 ↗