一个跑在终端里的 ASCII art 虚拟宠物。喂、玩、睡、治病、洗澡,看它升级、变胖、变瘦、变老——纯 Node.js,无任何外部服务。
✦ ASCII 宠物乐园 ✦
╔══════════════════════════════════════════════════╗
║ /\_/\ ║
║ ( ^.^ ) ║
║ > ♡ < ║
║ /_____\ ║
║ 小猫 · xx ║
║ 心情: 非常开心 ♡ ║
╚══════════════════════════════════════════════════╝
╔══════════════════════════════════════════════════╗
║ — 状态栏 — ║
║ 等级 Lv.1 经验 5/50 ║
║ 年龄 0 分钟 体重 正常 ║
║ 饱食度 ████████████████████ 100% ║
║ 快乐值 █████████████████░░░ 85% ║
║ 精力值 █████████████████░░░ 85% ║
║ 健康值 ████████████████████ 100% ║
╚══════════════════════════════════════════════════╝
─────────────────────────────────────────────
[1] 喂食 [2] 玩耍 [3] 睡觉 [4] 治疗
[5] 洗澡 [r] 领养 [q] 退出
─────────────────────────────────────────────
▶ xx开心地吃了普通饭!
| 类型 | 称呼 | 表情 |
|---|---|---|
cat |
小猫 | 🐱 |
dog |
小狗 | 🐶 |
bunny |
小兔 | 🐰 |
每只宠物有 9 种动画帧:happy / idle / hungry / sad / sick / sleeping / playing / eating / dead,根据当前属性自动切换。
| 属性 | 范围 | 说明 |
|---|---|---|
| 饱食度 (hunger) | 0–100 | 0 = 全饱,100 = 饿死边缘 |
| 快乐值 (happiness) | 0–100 | 低于 20 会陷入 sad 状态 |
| 精力值 (energy) | 0–100 | 低于 15 自动 sleeping,低于 10 拒绝玩耍 |
| 健康值 (health) | 0–100 | 归零即死亡;低于 30 进入 sick |
| 体重 (weight) | 0–100 | 偏瘦 (<20) / 偏胖 (>80) 会显示警告 |
| 年龄 | 分钟 | 自动累加,达到 60 分钟 / 24 小时切换为"小时 / 天" |
| 按键 | 动作 | 效果 | 经验 |
|---|---|---|---|
1 |
喂食 | 弹出子菜单选食物(见下) | +5 |
2 |
玩耍 | 快乐 +20、精力 −20、饥饿 +10、体重 −2 | +8 |
3 |
睡觉 | 精力 +40、健康 +5 | +3 |
4 |
治疗 | 健康 +30 | +10 |
5 |
洗澡 | 快乐 +10、健康 +5 | +3 |
每个指令都有防呆判定:吃太饱、太累、不困、已经很健康都会被拒绝并给出友好提示。
| 食物 | 饱食 | 快乐 | 精力 | 体重 |
|---|---|---|---|---|
| 普通饭 | −25 | +5 | +5 | +3 |
| 零食 | −10 | +15 | +2 | +5 |
| 蔬菜 | −20 | 0 | +8 | −2 |
| 肉类 | −35 | +10 | +15 | +8 |
想长肌肉吃肉、想减肥吃菜、零食最哄它开心但最容易胖。
哪怕你关掉程序,宠物也会按现实时间"活着":
- 饥饿 +2 / 分钟
- 快乐 −1 / 分钟
- 精力 −1.5 / 分钟
- 饿到 90 以上 → 健康开始扣
- 快乐低于 10 → 健康扣
- 状态都不错(饿<50、快乐>60、精力>30)→ 健康缓慢恢复
- 体重根据进食 / 饥饿动态浮动
- 离开超过 8 小时按 8 小时算——避免一周不开就饿死
health <= 0,或者hunger >= 100且持续超过 60 分钟
死亡后主菜单变成 [R] 收养新宠物 / [Q] 退出,状态被冻结,记录会保留以提醒你"曾经的它"。
- 每个动作给经验
expNeeded = level × 50- 升级时屏幕弹出
★ 升级了!现在是 Lv.X !★
- 存档位置:
./.save/pet.json - 每次按键操作后自动写盘
- 每 10 秒自动 tick 一次(应用衰减 + 存档 + 重绘)
- 退出 / Ctrl+C / SIGTERM 均会优雅保存
- 离开 5 分钟以上回来,会显示 "你离开了 X 分钟,xx 好想你!"
- 用
chalk上色:状态值 >60 绿、>30 黄、≤30 红 - 进度条用
█/░拼出 20 格 - 主面板 + 状态栏 + 菜单 + 消息四区分块
- 子菜单(喂食 / 领养)专门走单独的输入处理,全程 raw‑mode 单键响应,无需按 Enter
- Node.js ≥ 18(用了 ESM、
??、可选链;项目本机用的是 Node 22) - 支持 ANSI 颜色 + UTF-8 的终端(macOS Terminal / iTerm2 / Windows Terminal / 任何现代终端均可)
npm install
npm start # 或 node src/index.js开发时可以用:
npm run dev # node --watch,源码改动自动重启会进入领养流程:
- 选宠物类型(
1猫 /2狗 /3兔) - 给它取个名字
- 进入主界面
| 键 | 含义 |
|---|---|
1–5 |
五大动作 |
r / R |
领养新宠物(旧的存档会被覆盖) |
q / Q |
保存并退出 |
Ctrl+C |
同上,优雅退出 |
直接删掉存档:
rm -rf .save下次启动会重新进入领养流程。
ascll-pet-ao/
├── src/
│ ├── index.js # 入口:游戏循环、按键分发、自动 tick
│ ├── pet.js # 领域模型 Pet 类(属性、衰减、动作、状态机)
│ ├── ui.js # 渲染、菜单、键盘输入、子菜单 prompt
│ ├── ascii.js # 三种宠物 × 九种状态的 ASCII 帧
│ └── storage.js # JSON 存档读写
├── .save/
│ └── pet.json # 存档(自动生成,已 gitignore)
└── package.json
| 模块 | 行数 | 职责 |
|---|---|---|
index.js |
~210 | 主循环、handleAction 路由、startAutoRefresh 定时器、adoptNewPet 流程、quit 收尾 |
pet.js |
~210 | Pet 类、applyTimeDecay、feed/play/sleep/heal/clean、gainExp、getState、getMood、toJSON |
ui.js |
~290 | renderPet / renderMenu / renderMessage / renderLevelUp / renderFeedMenu / renderAdoptScreen、单键 prompt、setupKeyInput |
ascii.js |
~200 | PETS 字典 + getFrame(type, state) 查询 |
storage.js |
~40 | loadPet / savePet / deleteSave(基于 fs) |
- 单一 stdin 通路:领养、喂食两个子菜单都复用主 keypress 流(
subMenuKeyHandler让步机制),不再并行起readline.Interface,避免 raw‑mode 与行模式互抢导致输入失灵。 - 纯函数化属性变更:所有动作返回
{ success, msg },index.js统一拿到结果再 render,便于测试和扩展。 - 时间驱动 ≠ 帧驱动:所有衰减都基于
Date.now() - lastSaved,因此关掉再开也能正确推进;定时器只是触发刷新,不是计时器。
目前没有自动化测试,但 Pet 类是纯逻辑,非常容易补测:
import { Pet } from './src/pet.js';
const p = new Pet({ type: 'cat', name: 'test' });
p.feed('meat');
console.assert(p.hunger < 20);如果想加冒烟测试,可以模拟 process.stdin 为 PassThrough、写入按键序列驱动整套流程。
在 src/ascii.js 的 PETS 里新增一项,给齐 9 个状态的 frames,再到 renderAdoptScreen 的 typeMap 加一行即可,其他模块零改动。
- 在
Pet类加一个返回{ success, msg }的方法 - 在
src/index.js的handleActionswitch 里加一个 case - 在
src/ui.js的renderMenuactions数组里加一项
{
"chalk": "^5.3.0"
}仅此一个 runtime 依赖,其余全是 Node 标准库(fs / path / url / readline)。
未指定。项目 v1,作者自留地实验。
灵感来自上世纪的 Tamagotchi 和命令行 ASCII 艺术传统。