☰
零依赖的 ASCII 海洋模拟器 ascii-sharks:用字符画出会游泳鲨鱼的完整指南
2026/10/30 8:24:56 网站建设 项目流程

【免费下载链接】ascii-sharks

ascii shark components in typescript

项目地址:https://gitcode.com/gh_mirrors/as/ascii-sharks
点击查看免费下载

ascii-sharks 是一个零依赖的 ASCII 海洋模拟器:它用 TypeScript 在浏览器 canvas 上,把鱼群和鲨鱼渲染成一格一格的字符,模拟出一片会游动、会逃散、会捕猎的"字符海洋"。整个项目没有任何运行时第三方库,核心只有 7 个源文件,两条命令即可跑起来。

;' %%' .t;. .oooo S;:S% %8S8. ;:tt%t '.. XX%%S t' ''XSSS8SSX%XX8#. %XSX% :;' ;.''X8%8XX%%S%%S%SStt%tSX8S#X8't%ttt. ::%' ''8XXXSSt%Stttttt%8@%%@%8@8%Sttt%%%%SSSSS%tt. 'SXXtt%t%%%S%:;StS%ttSS%tSXSt88@@%8%@8%tStS%%X%SS%%S%;;t .@##88#@...'@@@@#@8@88X88#XXXSX8SX88SX8%SS%S%%S88St%t%%%. %;%t :. '.'##@###@X#888XX##8@@@#.X%XS%. .%t ;%%%#@@##@@@. SXS%% t. .%;%%%. %%XXS '%t:t .SXSS' '::. ooooo .S'

这就是 README.md 里展示的"主角":由# @ % S 8 X等字符按明暗分层拼出的鲨鱼,在黑色网格上缓缓游过,身后拖着青色的尾迹光点 🌊

两分钟快速上手:克隆、安装并运行演示

无需任何构建配置,Vite + TypeScript 已经写好。克隆仓库后两条命令即可看到全屏海洋:

git clone https://gitcode.com/gh_mirrors/as/ascii-sharks cd ascii-sharks npm install && npm run dev

运行后打开本地地址,你会看到 4 条不同"景深"的 classic 鲨鱼在屏幕里巡游,背景里数百条小鱼组成鱼群。

互动小技巧:

  • 🖱️ 移动鼠标:鱼群会把光标当作天敌四散逃开;
  • 💥 点击页面:制造一次"水花",附近的鱼瞬间炸开;
  • 🔗 切换鲨鱼阵容:在 URL 后追加?sharks=参数,例如?sharks=thresher,hammerhead,mako,nurse(第一条最大,其余依次递减),不传参数则默认 4 条 classic。参数解析逻辑见 demo.ts。

内置生态一览:8 种鲨鱼与 5 种鱼类

8 种可选择的鲨鱼种类

鲨鱼种类定义在 src/world.ts 的SharkKind类型中,每种都有独立的体型轮廓、皮肤色调和花纹:

种类特征
classic经典纺锤形,冷调蓝灰皮肤(默认主角)
hammerhead宽铲形头翼,眼睛长在头翼两端
greathammer更宽的锤头,镰刀状背鳍,板岩色皮肤
tiger方头重身,背部带虎斑纹
zebra短圆头 + 缎带状长尾,沙色皮肤带斑点
mako细长锥形吻部,金属靛蓝色背部
thresher上半截尾鳍长过整个身体,青铜紫皮肤
nurse扁宽的头和身体,双背鳍靠后,土黄色

每种鲨鱼的"体型函数"(背鳍位置、胸鳍弧度、尾叉形状等)都在 src/renderer.ts 的SHAPES表中用"体长的比例"描述,所以同一套渲染管线可以画出所有种类。

5 种鱼群物种

鱼群物种配置在 src/species.ts,每种鱼有独立的巡游速度、群规模、"个人空间"和行为权重:

  • sardine(沙丁鱼):喜欢围成旋转的"饵球"(bait ball),mill值最高;
  • anchovy(凤尾鱼):高度一致化,游出长长的"缎带";
  • silverside:中等一致性的稳定鱼群;
  • mackerel(鲭鱼):小规模、保持距离的松散群;
  • goby(虾虎鱼):几乎不看邻居、随机乱窜的"蜂群"。

这些行为差异来自经典的 Couzin 模型(见 src/species.ts 的注释):对齐(align)强就形成极化鱼群和缎带,弱则形成蜂群,再加上切向力(mill)就旋转成饵球。

核心原理:字符网格上的鱼群与猎手

鱼群:带"恐惧传染"的 boids

模拟核心是 src/world.ts 注释里写明的方案——Reynolds boids(分离 / 对齐 / 内聚)加上几个让它"像真的"的细节:

  1. 盲点:每条鱼正后方约 127° 看不到邻居,逃散不会 180° 完美掉头;
  2. 恐惧传染:看到鲨鱼的鱼会把自己的alarm值传染给邻鱼(每跳衰减 14%),于是整群鱼即使只有边缘看到了猎手也会一起炸开,形成真实的"惊波";
  3. 喷泉水效应:逃跑的鱼会朝鲨鱼路径的侧方分流,重现自然界 bait ball 的喷泉形态;
  4. 空间哈希:鱼被分进网格桶(rebuildHash),让数百条鱼的邻居查询保持 O(n),60fps 轻松运行。

鲨鱼:follow-the-leader 脊椎 + 饥饿捕猎

每条鲨鱼是一根 20 节点的"脊椎"(src/world.ts),头部驱动、后续节点以关节刚度限制跟随——所以身体最多弯成 C 形,永远不会"折叠"。行为上:

  • 饥饿系统:hunger随时间增长,吃鱼后下降;
  • 猎物选择:优先盯"落单"的鱼——密集鱼群反而会迷惑捕食者(findPrey按桶内拥挤度打分,见 src/world.ts);
  • 被吃的小鱼不会消失:几秒后它们组成新的鱼群从屏幕边缘游回来,生态保持动态平衡。

渲染:把世界"光栅化"成字符格子

src/renderer.ts 的AsciiRenderer是视觉效果的关键,每帧分四步:

  1. 铺一层黑色底 + 细白网格(paintGrid);
  2. 计算尾迹场:鱼和鲨鱼尾部在格网中"沉积"能量,再扩散衰减,能量高的格子亮起青色小方块——这就是游过后的水波痕迹;
  3. 鱼渲染成单格字符-,按景深分 5 档亮度,急转弯和受惊的鱼会"闪银光";
  4. 鲨鱼逐格超采样(每个格子取 5 个采样点判断覆盖率):内部格子画实心色块 + 按明暗选:;t%SX8#@字符(亮处字符稀疏、暗处字符密集,纹理强化光影),边缘格子用.',等轻字符做抗锯齿轮廓。

鲨鱼皮肤还会以错峰的时钟重新掷色,产生"鳞片闪光";背鳍被"左上方的光"照亮,鳃裂、眼睛、虎纹/斑点全部用字符和色块区分。

集成到你的项目:一行 React 组件或一个 Engine 类

方式一:React 组件(推荐)

src/react.tsx 导出一个AsciiOcean组件,挂载时自动创建引擎、卸载时自动清理:

<AsciiOcean className="ocean" sharks={[{ kind: "hammerhead", size: 1 }]} />

注意:字符来自 canvas 的font-family,记得给组件(或父级)设置等宽字体(如Geist Mono、Menlo)。

方式二:直接用 OceanEngine(无框架)

src/index.ts 导出OceanEngine、AsciiRenderer和paintGrid。只要有一个 canvas 就能跑:

import { OceanEngine } from "./src"; const engine = new OceanEngine(canvas, [{ kind: "hammerhead", size: 1 }]);

OceanEngine内部已经处理了固定时间步长(60Hz)、resize、指针输入、页面不可见时暂停,甚至系统"减少动态效果"偏好——开启prefers-reduced-motion时它会让生态先"静置"4 秒,然后只渲染一帧静态画面(src/engine.ts),对动效敏感的用户也很友好。

源码地图:7 个文件的阅读路线

文件职责
src/index.ts对外导出入口(OceanEngine / AsciiRenderer / World)
src/world.ts生态模拟:鱼群 boids、鲨鱼追踪、进食与重生
src/species.ts5 种鱼的物种参数与加权随机选择
src/engine.ts引擎:固定时间步、resize、指针事件、动效偏好
src/renderer.ts字符渲染:尾迹扩散、鲨鱼光栅化、鱼群分桶绘制
src/react.tsxReact 封装组件<AsciiOcean />
src/math.ts工具函数:clamp、smoothstep、hash3、无散度洋流

辅助文件:demo.ts(Vite 演示入口 + 鲨鱼阵容参数)、index.html(全屏 canvas + Geist Mono 字体)、tsconfig.json、LICENSE(MIT)。

常见问题

Q:真的零依赖吗?是。package.json 中运行时依赖为零,typescript和vite仅是 devDependencies。

Q:想要更小的鱼群或单条鱼?World构造函数接受可选的fishCount参数覆盖按面积计算的默认数量(默认 85~340 条,按画布面积自适应)。

Q:字符显示成方块?canvas 未加载等宽字体。给 canvas 或父级设置font-family: ui-monospace, Menlo, monospace即可,引擎会在字体就绪后重绘。


ascii-sharks 证明了"字符 + 物理感"的组合能带来意想不到的沉浸感:不需要一张贴图,几十个 ASCII 符号加上尾迹扩散,就足以让鲨鱼"游起来"。如果你想给自己的站点加一段有记忆点的背景动画,它是个几乎零成本的选择——MIT 协议,代码量小到一晚上能读完,值得克隆下来把玩 🦈

【免费下载链接】ascii-sharks

ascii shark components in typescript

项目地址:https://gitcode.com/gh_mirrors/as/ascii-sharks
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询