科学休息,我用AI写了个vscode养鱼插件:DevFish发布
1、前言
程序员这个职业,真是个全能的职业,上的厨房下的机房。每天的“运动”就是手指从 A 键挪到 Z 键。每天的常态是不断 Ctrl+C、Ctrl+V ,越忙越粘键盘,效率反而掉成狗。
于是我把“摸鱼”两个字正经写进了 OKR,目标很单纯:把划水变成合法行为,定时休息,bug 减半。
但是一旦陷入头脑休息期间,就会发现脑袋空空,手指不知道干嘛。于是就用AI帮我写了个vscode插件,名副其实的摸鱼插件。
这里全程近乎没有自己手撸的代码,只是给到了AI创意想法,AI帮我实现。不得不感叹,危已~
2、项目到底干啥
Dev Fish 就是一款把“休息”包装成“养鱼”的插件。装完之后,VSCode 侧边栏会多一个鱼缸:
- 里头的鱼会围观你写代码,你敲得快它们就加速游,Debug 时集体装死。
- 番茄钟到点,鱼会冒泡提醒你“该起来倒水了”。
- 通过Ctrl+Shift+p,可以键入指令,添加鱼苗,喂养,或清洁鱼缸等互动。
3、演示下效果图(装个13)
首页图:

Ctrl+shift+P唤起指令输入框:

添加鱼:

智慧信息流:

4、技术栈一句话说完前端
TypeScript + VSCode Webview + Canvas
4.1、核心代码
4.1.1、MVC
Model (数据层)├── Fish.ts - 鱼的数据和行为├── Tank.ts - 水缸的数据和管理└── StorageService - 数据持久化View (视图层)├── AquariumProvider - Webview 提供者├── HTML/CSS - UI 结构和样式└── Canvas - 动画渲染Controller (控制层)├── fishCommands - 鱼的命令处理├── breakCommands - 休息的命令处理└── wisdomCommands - 智慧的命令处理
4.1.2、 鱼的运动算法
class Fish {private baseVelocityX: number;private baseVelocityY: number;private speedMultiplier: number = 1.0;update(deltaTime: number): void {// 计算实际速度 = 基础速度 × 状态乘数const actualVelocityX = this.baseVelocityX * this.speedMultiplier;const actualVelocityY = this.baseVelocityY * this.speedMultiplier;// 更新位置this.x += actualVelocityX * deltaTime;this.y += actualVelocityY * deltaTime;// 边界检测和反弹this.handleBoundaryCollision();// 更新状态this.updateHappiness(deltaTime);this.updateHunger(deltaTime);this.updateBubble();}private handleBoundaryCollision(): void {const tankWidth = 800;const tankHeight = 600;if (this.x < 0 || this.x > tankWidth) {this.velocityX *= -1;this.x = Math.max(0, Math.min(tankWidth, this.x));}if (this.y < 0 || this.y > tankHeight) {this.velocityY *= -1;this.y = Math.max(0, Math.min(tankHeight, this.y));}}
}
4.1.3、泡泡显示算法
class BubbleStateMachine {private state: 'showing' | 'hiding' = 'hiding';private lastStateChangeTime: number = Date.now();private showDuration: number = 3000; // 显示 3 秒private hideDuration: number = 5000; // 隐藏 5 秒update(): void {const now = Date.now();const elapsed = now - this.lastStateChangeTime;if (this.state === 'showing') {if (elapsed > this.showDuration) {this.state = 'hiding';this.lastStateChangeTime = now;}} else {if (elapsed > this.hideDuration) {this.state = 'showing';this.lastStateChangeTime = now;this.bubble = this.getRandomBubble();}}}isVisible(): boolean {return this.state === 'showing';}
}
4.1.4、事件节流
// 防止事件处理过于频繁
class EventThrottler {private lastExecutionTime: number = 0;private throttleInterval: number = 100; // 100msthrottle(callback: () => void): void {const now = Date.now();if (now - this.lastExecutionTime >= this.throttleInterval) {callback();this.lastExecutionTime = now;}}
}// 使用
const throttler = new EventThrottler();vscode.workspace.onDidChangeTextDocument(() => {throttler.throttle(() => {tank.fish.forEach(fish => fish.onTyping());});
});
5、开始养鱼吧
插件已经发布到vscode插件市场,目前支持最新版vscode 1.105版本以上。

5.1、下一步计划
- 把成就数据扔 GitHub Gist,换电脑也能同步。
- 给鱼写个最原始的 FSM,让它偶尔自己发呆、偶尔追鼠标。
- 欢迎提 PR,最好顺带给我写单元测试,我实在懒得动。
记住:Ctrl+S 之前,先喂鱼。
