首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >我用AI养了一只赛博龙虾:一个售前打工人不正经副业的诞生

我用AI养了一只赛博龙虾:一个售前打工人不正经副业的诞生

原创
作者头像
君子不器
修改2026-04-22 11:34:42
修改2026-04-22 11:34:42
1590
举报

这是一篇不太正经的技术文章。

如果你期待的是"如何提升工作效率"——出门左转,我之前写了两篇正经的,总共三万多字,够你看一晚上。

这篇要讲的是一个售前打工作之余做的、跟效率毫无关系、甚至有点浪费时间的东西——

🦞 一只住在桌面上的赛博龙虾。


一、缘起:一个加班到深夜的疯狂念头

那是去年冬天的一个晚上,大概11点半。

我刚改完一份方案的第7版PPT,眼睛酸得像泡过醋。关掉PPT的那一刻,屏幕暗了一下——macOS桌面空荡荡的,Dock栏安静地缩在底部,就剩几个冷冰冰的文件图标和一张已经看了两年的壁纸。

就在那一瞬间,脑子里突然蹦出一个莫名其妙的想法:

"如果我的桌面上能有个小东西就好了。不用干什么正事,就是……待在那儿。我累了的时候它能动一下,我开心了它能跟着开心一下。"

然后第二个念头紧跟着来了:

"等等,我不是正在搞WorkBuddy吗?这玩意儿能不能帮我做一个?"

那天晚上我没继续改PPT。

我打开编辑器,写下了这个项目的第一行代码:

代码语言:python
复制
# 龙虾宠物 v0.0.1
# 一个疯狂的深夜决定
print("🦞 Hello, World!")

当时的我完全没想到,这个"深夜摸鱼产物",半年后会被我写成一篇参赛文章。


二、它长什么样?

先上主菜。

🎨 它以前的样子

这是我在腾讯云轻量服务器部署的龙虾,过去的使用方式是网页+钉钉,说实话有点生硬

龙虾以前的对话框
龙虾以前的对话框

🎨 现在的样子:赛博霓虹龙虾

现在它就默默呆在我电脑角落里,随时唤醒他

原谅我的直男审美,当然了,可以随时调用workbuddy的专家中心的设计师给他重新设计一套皮肤

龙虾宠物桌面截图
龙虾宠物桌面截图

核心视觉特征:

元素

设计

为什么这么设计

主体

一只Q版熊猫(非写实,偏科技)

it从业者要炫酷

配色

霓虹色系(青色/品红/电光蓝)

赛博朋克感 + 桌面上够显眼

光效

边缘发光 + 呼吸灯效果

"活着"的感觉

大小

约 120×120 像素

不遮挡工作内容,但足够可爱

透明背景

PNG透明通道

融入桌面,不是悬浮窗口

其实workbuddy的设计专家还给我处理很多效果图,我可以随时更换

1.0的设计图找不到了,这是我的2.0
1.0的设计图找不到了,这是我的2.0

其实

设计理念一句话:它是你桌面上的一个小生命,不是一个软件窗口。

🖥️ 它在桌面上的样子

每个状态都有独立的动画序列。 不是贴图切换——是真正的逐帧动画,带缓动曲线,看着很自然。


三、它有什么本事?(高能预警⚡)

好,外观介绍完了。现在讲最好玩的部分——这只赛博龙虾到底能干什么。

📋 状态一览表(完整版)

状态名

触发条件

行为表现

音效/特效

1

🦞 空闲(Idle)

无操作超过3分钟

桌面随机漫步+观察四周

轻轻的脚步声

2

💼 工作(Working)

检测到键盘/鼠标活跃

安静待机+探头看进度

打字音(轻微)

3

😊 开心(Happy)

完成任务 / 收到正面反馈

转圈+吐泡泡+发光

欢快的音效

4

😵 错误(Error)

命令执行失败/报错

翻白眼+冒烟+抖动

"duang~" 失败音

5

😴 困倦(Sleepy)

凌晨以后还在工作

打哈欠+眼皮打架+倒下

哈欠声

6

🔥 兴奋(Excited)

连续完成多个任务

高速转圈+烟花粒子

燃烧音效+BGM

7

⏰ 提醒(Reminder)

设定的提醒时间到了

弹窗挡住屏幕(很欠揍)

提示音

8

❤️ 撒娇(Clingy)

你太久没理它了

追着鼠标跑+弹气泡求关注

"嗯~"的声音

8个状态,每个都是独立设计的动画和行为逻辑。 不是简单的A/B切换,而是有过渡动画、有随机变化、有"性格"在里面。

下面挑几个最有意思的展开讲:


而且每次开心的"激烈程度"是不一样的:

情绪等级

触发条件

表现差异

⭐ 微笑

完成一个小任务

微微发光+小幅度摇摆

⭐⭐ 高兴

完成中等任务 / 被夸奖

转圈+吐少量泡泡

⭐⭐⭐ 超级开心

完成大项目 / 连续夸奖

全套连招+粒子烟花+变色

⭐⭐⭐⭐ 狂欢

(隐藏触发)连续工作后准时下班

全屏庆祝动画+特殊BGM

是的,它有一个隐藏的"狂欢模式"。 触发条件嘛——留个悬念,后面讲。


为什么这么设计?

因为我觉得——AI工具最让人抓狂的不是报错本身,而是报错时的冷漠。

终端里一行红色的 ERROR,冷冰冰的,没有任何情感。但如果你桌上有个小龙虾,它在帮你执行命令,失败了之后翻白眼、冒黑烟、还抖两下——

你就不那么想砸键盘了。

甚至会笑出来:"哎呀,小龙虾也翻车了哈哈哈。"

然后心情好一点,重新试一次。

这就是情绪价值。 一个会跟你一起翻车的宠物,比一个永远正确的工具有温度得多。


⏰ 状态详解:那个"很欠揍"的提醒功能

这是龙虾被吐槽最多的功能——也是我个人觉得最实用的功能。

背景: 我设置了"连续工作90分钟自动提醒休息"。

然后某天下午我在赶方案,完全忘记了时间。写到投入处,忽然——

因为那天晚上忘记截图了,写文章时候顺便截个图示意下
因为那天晚上忘记截图了,写文章时候顺便截个图示意下

你的所有工作内容被一只龙虾盖住了。什么都干不了。

除非你点"去休息"或者"稍后再说"。

第一次看到这个的时候我愣了两秒,然后笑喷了——这也太霸道了吧?!

但说实话——真的有效。 因为普通的系统提示你可以无视、可以最小化、可以让它在角落里自生自灭。但当整只龙虾跳到你屏幕中央的时候,你不得不停下来跟它交互。

而一旦你停下来点了"稍后再说"——哪怕只是这几秒钟的中断——你的大脑就已经从"深度沉浸模式"里被拽出来了。

这时候你会意识到:"哦,确实坐了好久了。站起来走走吧。"

这就是设计意图:用一种有趣但不失强制力的方式打断你的沉浸式工作循环。

后来我还加了一些细节:

提醒时机

龙虾台词

备注

工作90分钟

"该休息了!你已经工作很久了!"

标准提醒

工作120分钟

"你还不累吗??我都困了 💤"

加重语气

工作180分钟

"大哥/大姐……你是铁打的吗"

语气开始无奈

凌晨0点后

"……你确定还要继续吗"

不再霸道,变成温柔关心

凌晨2点后

直接播放一段轻音乐 + 屏幕色调变暖

强制温柔模式

越晚越温柔。 因为我深知凌晨两点还在工作的售前不需要一个聒噪的宠物——需要的是一句安静的"早点休息吧"。



四、语音交互:对着电脑说话的感觉有多爽

如果说前面的动画让龙虾好看,那语音交互让它好用

🔑 快捷键唤醒

全局快捷键 Cmd+Shift+L(L = Lobster,很好记):

我的赛博龙虾-小熊猫开始跳动起来,并且出现happy的表情

虽然是熊猫但是毕竟是赛博龙虾
虽然是熊猫但是毕竟是赛博龙虾

然后你说话。说完松开快捷键,它开始处理。

💬 实际对话案例

来,感受一下日常使用场景:

场景1:查待办

代码语言:markdown
复制
你:(按下 Cmd+Shift+L)我今天还有什么待办?
龙虾:(停顿1秒处理)好的老板!你今天的待办有这些:

  🔴 [高优先] XX集团方案初稿 —— 截止今天下午6点
  🟡 [中] 给客户回邮件确认演示时间
  🟢 [低] 团队周报(周五再写也行)

一共3件事,最重要的是方案初稿哦~ 要加油!💪

注意那个语气词"哦~"和"💪"——这是龙虾的人设。它不是一个冷冰冰的语音助手,它是一个有点话痨的小助手

场景2:快速记录灵感

代码语言:markdown
复制
你:(按下 Cmd+Shift+L)记一下,客户说他们想要一个
     能在手机上看的实时大屏
龙虾:记下来啦!

  📝 新增备忘:
  · 内容:客户需求 - 移动端实时大屏查看
  · 时间:刚刚
  · 关联客户:XX集团(自动识别上下文)

已写入记忆系统 ✅

场景3:纯粹聊天(摸鱼时刻)

代码语言:markdown
复制
你:(按下 Cmd+Shift+L)我好累啊
龙虾:(沉默0.5秒……)
  
  那给你讲个冷笑话吧?
  
  问:龙虾最喜欢的数学符号是什么?
  ……
  答:是"夹"(夹角)!因为龙虾有大大的钳子呀~ 🫠
  
  (龙虾说完自己吐了个泡泡,像是在为自己的冷笑话感到尴尬)

  ……不好笑吗?那我再来一个?

内置了一个笑话库。 专门用于用户明确表示"我很累""我不开心""烦死了"这类情绪低谷时刻。

而且笑话的质量——怎么说呢——以"让人无语到忘记烦恼"为核心KPI。有时候烂到你会忍不住笑出声:"这什么破笑话哈哈哈哈。"

然后你就真的没那么累了。

这就是设计哲学:与其试图真正解决你的疲劳(它做不到),不如用一种轻松的方式让你从负面情绪里抽离出来一分钟。这一分钟可能就够了。


🎙️ 语音交互技术简述

我设置了快捷键唤醒语音,直接调用mac语音
我设置了快捷键唤醒语音,直接调用mac语音

(不想看技术细节的同学可以跳过这节)

语音交互的技术栈:

代码语言:markdown
复制
你的声音
  ↓
macOS 系统语音识别(Speech Framework)
  ↓
文字文本
  ↓
WorkBuddy AI 处理(理解意图 + 生成回复)
  ↓
回复文本
  ↓
macOS TTS 文字转语音(系统自带语音包)
  ↓
龙虾"说话" + 同步口型动画

关键设计决策:

决策点

选择

原因

语音识别引擎

macOS原生Speech Framework

免费无需网络延迟低

唤醒方式

全局快捷键(非语音唤醒)

避免误触+"龙虾"这个词太难发音一致

语音合成

系统TTS + 自定义语速/音调

让声音听起来更像"角色"而非机器

口型动画

基于音素级别的简单映射

不需要精确对口型,只要嘴巴在动就行

离线能力

识别+基础回复可离线

网络断了也能用基础功能

整个语音交互的响应延迟大约在1-2秒。 按下快捷键到龙虾开始"说话",差不多就是自然对话中的停顿节奏——不会让你觉得等了很久,也不会快得不自然。


五、技术架构:一只龙虾的解剖学

好了,好玩的部分展示完了。现在来点有料的部分

(放心,不会变成枯燥的技术文档。我会用人话讲。)


🏗️ 整体架构一览

代码语言:markdown
复制
┌─────────────────────────────────────────────┐
│            🦞 龙虾宠物系统架构                │
├─────────────────────────────────────────────┤
│                                             │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  │
│  │ 渲染层   │  │ 状态机   │  │ 交互层   │  │
│  │ (View)   │  │ (State)  │  │(Input)   │  │
│  ├──────────┤  ├──────────┤  ├──────────┤  │
│  │·动画系统 │  │·8种状态  │  │·快捷键   │  │
│  │·粒子特效 │  │·状态转换 │  │·语音识别 │  │
│  │·透明窗口 │  │·情绪模型 │  │·鼠标事件 │  │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘  │
│       │             │             │         │
│  ┌────▼─────────────▼─────────────▼─────┐  │
│  │            核心调度器 (Core)          │  │
│  │  · 主循环 60fps                     │  │
│  │  · 状态协调                         │  │
│  │  · 事件总线                         │  │
│  └──────────────────┬──────────────────┘  │
│                     │                     │
│  ┌──────────────────▼──────────────────┐  │
│  │         WorkBuddy Skill 接口层        │  │
│  │  · memory-manager 记忆读写            │  │
│  │  · 命令执行代理                      │  │
│  │  · oepnclaw-Gateway 接口             │  │
│  └──────────────────────────────────────┘  │
│                                             │
└─────────────────────────────────────────────┘

三层架构,各管各的事:

  • 渲染层:负责"长得什么样"——动画、特效、透明窗口
  • 状态机:负责"现在是什么心情"——8种状态之间的转换规则
  • 交互层:负责"怎么跟人打交道"——快捷键、语音、鼠标

三层之间通过事件总线通信,互不直接耦合。

为什么要分层? 因为一开始我没分层。

最开始所有的逻辑都塞在一个文件里——渲染代码旁边就是状态判断,状态判断旁边就是键盘监听。能跑,但是加第三个功能的时候就开始乱了。

后来重构成了现在的架构,每加一个新功能只需要:

  1. 在渲染层加动画资源
  2. 在状态机加一个状态节点
  3. 在交互层加一个触发入口

三层各改各的,互不影响。


🧠 状态机:龙虾的"大脑"

这是整个系统最核心也最有趣的部分。

代码语言:markdown
复制
# 伪代码:状态机简化示意

class LobsterStateMachine:
    
    # 状态定义
    states = ["idle", "working", "happy", "error", 
              "sleepy", "excited", "reminder", "clingy"]
    
    # 状态转换规则(关键!)
    transitions = {
        # 从 idle(空闲)可以转到:
        "idle": {
            "user_active": "working",      # 用户开始操作 → 工作状态
            "long_idle": "clingy",         # 太久没理 → 撒娇模式
            "task_done": "happy",          # 任务完成 → 开心
            "late_night": "sleepy",        # 深夜了 → 困了
        },
        # 从 working(工作)可以转到:
        "working": {
            "user_stop": "idle",           # 用户停手了 → 空闲
            "task_success": "happy",       # 任务成功 → 开心
            "task_error": "error",         # 任务失败 → 翻车
            "work_90min": "reminder",      # 工作90分 → 强制提醒
        },
        # 从 error(错误)可以转到:
        "error": {
            "retry_success": "excited",    # 重试成功 → 超级开心(补偿心理)
            "retry_error": "idle_depressed",  # 继续失败 → 颓废
            "timeout": "idle",             # 超时恢复 → 空闲
        },
        # ... 其他状态的转换规则
    }
    
    # 还有"情绪强度"参数
    emotion_intensity = 0.0  # 0.0 ~ 1.0
    
    # 影响行为表现的剧烈程度
    # 比如 happy 状态下:
    # intensity 0.3 → 微微发光
    # intensity 0.7 → 转圈+泡泡
    # intensity 1.0 → 全套连招+烟花

状态机的精髓在于"转换规则"。 不是任何状态都能转到任何其他状态的——必须符合逻辑:

  • 不能从"开心"直接跳到"错误"(中间得经过某个事件触发)
  • 不能从"困倦"直接跳到"兴奋"(除非有特殊的惊喜事件)
  • "撒娇"只有从"长时间空闲"触发(不能随便跳进去)

这样龙虾的行为才是可预测但又带点意外的。 你大致知道它下一步会做什么,但具体什么时候做什么又有随机性。这种感觉——很像养真宠物。


🎨 动画系统:怎么让龙虾"活"起来

很多人问:"你的动画是怎么做的?帧动画?骨骼动画?还是实时渲染?"

答案可能让你失望:最简单的方式——Sprite Sheet(精灵图帧动画)。

代码语言:markdown
复制
制作流程:

1. 用设计工具(Figma/Illustrator)画出龙虾的每一帧
   · idle状态:8帧(一个完整的呼吸+微移动循环)
   · walk状态:12帧(迈步动画)
   · happy状态:24帧(转圈+泡泡的完整连招)
   · error状态:16帧(翻白眼→冒烟→抖动→恢复)
   · ...每种状态独立的帧序列

2. 导出为 Sprite Sheet(精灵图集)
   ┌────────────────────────────────────┐
   │ frame1 │ frame2 │ frame3 │ frame4 │  ← 一张大图
   │ frame5 │ frame6 │ frame7 │ frame8 │     包含所有帧
   │ frame9 │ frame10│ ...    │ ...    │
   └────────────────────────────────────┘

3. 代码中按固定间隔切换帧(60fps下约每2-3帧切换一张sprite)
   
4. 加入缓动曲线(easing)让动作不那么机械
   · 不是匀速播放 → 而是"快-慢-快"的自然节奏
   · 起步加速 → 中间均速 → 结束减速

为什么不用更高级的技术?

原因很朴实:

方案

优点

缺点

我的评估

实时3D渲染

最灵活

开发量大,性能消耗高

杀鸡用牛刀

骨骼动画(Spine)

流畅自然

需要额外工具链和学习成本

对当前规模过剩

Lottie矢量动画

缩放不失真

复杂动画支持有限

可考虑未来迁移

Sprite Sheet帧动画

简单可靠

帧数多时文件略大

✅ 当前最佳选择

对于一只120×120像素的桌面宠物来说,帧动画完全够了。 每个状态十几到二十几帧,全部加起来的图片资源不到2MB。

做得好≈用最合适的技术,而不是最新的技术。


六、开发踩坑实录:那些让我凌晨两点还在debug的事

这部分可能是全文最有共鸣的章节。

因为——谁做开发没踩过坑呢?区别只在于:有的人踩完了忘了,我把它们全记下来了。


坑 1:透明窗口的"隐形杀手"

预期:龙虾显示在一个透明背景的窗口上,完美融入桌面。

现实:窗口是透明了——但点击事件也被透明了。也就是说龙虾"后面"的桌面区域仍然可以接收鼠标点击,导致你经常点穿了龙虾点到后面的图标。

代码语言:markdown
复制
现象:
你想拖动龙虾到另一个位置
  → 点击龙虾
  → 点穿了!!点到了龙虾后面的文件夹!!
  → 文件夹打开了
  → 你:???

解决方案:macOS 的 NSWindow 有一个属性叫 ignoresMouseEvents——但我们要的反过来的效果。最终通过设置透明的 hitTest 区域解决了:

代码语言:markdown
复制
// 只让龙虾本体区域接收鼠标事件,透明部分穿透
override func hitTest(_ point: NSPoint) -> NSView? {
    // 检测点击位置是否在龙虾图像的非透明区域内
    if lobstersBodyFrame.contains(point) {
        return self  // 点到龙虾本体 → 响应
    }
    return nil  // 点到透明区域 → 穿透到下层窗口
}

耗时排查:3小时。 其中2小时在怀疑人生。


坑 2:全局快捷键被系统抢占

预期Cmd+Shift+L 全局生效,在任何App中都能唤醒龙虾。

现实:在某些应用中快捷键完全无效。尤其是终端和一些IDE。

代码语言:markdown
复制
调试过程:
Day 1:在自己写的测试App里 → ✅ 正常
Day 2:在Safari里 → ✅ 正常  
Day 3:在VS Code里 → ❌ 没反应
Day 4:在终端里 → ❌ 还是没有
Day 5:发现有些App会注册相同或相似的快捷键
Day 6:改成 Cmd+Ctrl+Shift+L(四个键!)→ ✅ 全局生效
Day 7:四个键太难按了,换了个思路
最终方案:使用 macOS 的 CGEvent tap 机制
        + 选择一个极少冲突的组合键
        + 失败时提供备用方案(菜单栏图标点击)

教训:全局快捷键是个"看似简单实则巨坑"的功能。如果你的应用也需要全局快捷键——一定要充分测试各种App场景,不要只在自已的应用里测。


坑 3:语音识别的"尴尬 silence"

预期:按下快捷键 → 说话 → 松开 → 龙虾回应。

现实:很多时候按下快捷键后环境噪音被当成语音输入了——键盘声、窗外车声、甚至是呼吸声。

代码语言:markdown
复制
翻车现场:

你:(按下快捷键)(敲击键盘搜索资料)
龙虾:(认真听...)
龙虾:你刚才说的是 "嗒嗒嗒嗒嗒-回车-嗒嗒" 吗?
你:......

解决方案

  1. 增加静音阈值过滤:低于一定音量的输入直接忽略
  2. 加入"确认机制":当识别结果看起来不像正常语言时,龙虾会说"不好意思,你刚才是要说什么?没听清呢~"
  3. 视觉反馈增强:录音时龙虾做一个明显的"倾听"动画+波形显示,让用户知道它正在录

第三条改动之后,误触发率下降了大概80%。 因为用户能看到龙虾在"录音",就不会在按住快捷键的时候顺便敲键盘了。


坑 4:内存泄漏——龙虾越长越大

预期:长期运行稳定,内存占用恒定。

现实:运行一天之后,内存占用从 50MB 涨到了 800MB

代码语言:markdown
复制
排查过程:

打开 Instruments(macOS性能分析工具)
  → 发现 Animation Layer 在不断创建但不释放
  → 每次状态转换都新建一组 Layer
  → 但旧的状态 Layer 没有正确销毁
  
原因:Swift 的 ARC(引用计数)在某些循环引用场景下
     不会自动释放内存
     
修复:手动管理动画层的生命周期
     + 在状态切换时主动清理旧的动画资源
     + 使用对象池(Object Pool)复用常用动画元素

修复后:连续运行48小时,内存稳定在60-80MB ✅

这个坑教会我一个道理:即使是"小程序",也要关注内存管理 桌面宠物是那种用户开了就不关的应用——可能连续运行几天甚至几周。这种场景下的内存泄漏比普通应用致命得多。


坑 5:那个"意外诞生"的追鼠标功能

这个不算bug算feature,但确实是从一个bug演变来的(前面第三章讲过)。

原始设计意图:空闲状态时龙虾应该在屏幕上均匀随机漫步

实际情况:有一版代码里的"随机目标点选择算法"有个偏差——它选择目标点的时候,鼠标当前位置的权重被错误地设高了(本意是让龙虾偶尔对鼠标产生好奇,结果权重太高导致一直在追)。

发现之后的第一反应是修bug。

但看着它追鼠标跑了二十秒——我突然觉得这特有意思。

于是没有修。而是把这个"bug"正规化了:

代码语言:python
复制
# 最终版的"好奇心算法"

def select_target_position(current_pos, mouse_pos, curiosity_level):
    """
    curiosity_level: 0.0 ~ 1.0
      0.0 = 完全随机漫步(不关心鼠标)
      1.0 = 100%追鼠标(撒娇模式满级)
      
    正常情况 curiosity_level = 0.1(偶尔瞥一眼鼠标)
    长时间无交互后逐渐升至 0.8(开始追着跑)
    用户有任何操作后立即降回 0.1
    """
    
    if random() < curiosity_level:
        # 有概率选择鼠标方向
        return add_noise(mouse_pos, noise_radius=50)
    else:
        # 正常随机
        return random_point_on_screen()

所以这确实是一个"把bug变成feature"的真实案例。 而且变成了最受欢迎的功能之一。


七、手把手教你做一个(最小可行版本)

好,看了这么多——你可能手痒了。

这一章教你自己造一个。 不用龙虾,不用赛博朋克风——就从最简单的东西开始:

一只会在桌面上来回走的小猫/小狗/任何你喜欢的东西。

🛠️ 技术栈选择

我们用 Python + PyQt6 来实现。原因:

  • Python 语法简单,容易理解和修改
  • PyQt6 跨平台(macOS/Windows/Linux都能跑,但本教程以 macOS 为主)
  • 社区资源丰富,遇到问题好搜

Step 1:环境准备(3分钟)

代码语言:python
复制
# 安装PyQt6
pip install PyQt6

# 确认安装成功
python -c "from PyQt6.QtWidgets import QApplication; print('OK')"

如果输出 OK 就说明环境没问题。

Step 2:第一个透明窗口(5分钟)

创建文件 my_pet.py

代码语言:python
复制
import sys
from PyQt6.QtWidgets import QApplication, QLabel, QWidget
from PyQt6.QtCore import Qt, QTimer
from PyQt6.QtGui import QPixmap, QColor

class DesktopPet(QWidget):
    def __init__(self):
        super().__init__()
        
        # === 窗口基本设置 ===
        self.setWindowTitle("我的桌面宠物")
        
        # 设置窗口为无边框 + 始终置顶 + 透明背景
        self.setWindowFlags(
            Qt.WindowType.FramelessWindowHint |      # 无边框
            Qt.WindowType.WindowStaysOnTopHint |     # 置顶
            Qt.WindowType.Tool                       # 不在任务栏显示
        )
        
        # 透明背景(关键!)
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
        
        # 窗口大小
        self.setFixedSize(120, 120)
        
        # 初始位置(屏幕右下角)
        from PyQt6.QtWidgets import QApplication
        screen = QApplication.primaryScreen().geometry()
        self.move(screen.width() - 150, screen.height() - 150)
        
        # === 创建标签显示内容 ===
        self.label = QLabel("🐱", self)
        self.label.setStyleSheet("""
            font-size: 80px;
            background-color: transparent;
        """)
        self.label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.label.setGeometry(0, 0, 120, 120)
        
        # === 移动相关变量 ===
        self.dx = 2   # x方向移动速度
        self.dy = 1   # y方向移动速度
        
        # === 定时器:每30ms更新一次位置(约33fps)===
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_position)
        self.timer.start(30)
        
        # 显示窗口
        self.show()
    
    def update_position(self):
        """更新宠物位置(实现来回走的动画)"""
        # 获取当前位置
        x = self.x()
        y = self.y()
        
        # 获取屏幕尺寸
        from PyQt6.QtWidgets import QApplication
        screen = QApplication.primaryScreen().geometry()
        max_x = screen.width() - 120  # 减去窗口宽度
        max_y = screen.height() - 120 # 减去窗口高度
        
        # 更新位置
        new_x = x + self.dx
        new_y = y + self.dy
        
        # 边界检测:撞墙就反弹
        if new_x <= 0 or new_x >= max_x:
            self.dx = -self.dx  # 反转X方向
            new_x = max(0, min(new_x, max_x))
        
        if new_y <= 0 or new_y >= max_y:
            self.dy = -self.dy  # 反转Y方向
            new_y = max(0, min(new_y, max_y))
        
        # 移动窗口
        self.move(new_x, new_y)


# === 启动应用 ===
if __name__ == "__main__":
    app = QApplication(sys.argv)
    pet = DesktopPet()
    sys.exit(app.exec())

Step 3:运行!(见证奇迹的时刻)

代码语言:python
复制
python my_pet.py

你应该能看到:

代码语言:markdown
复制
┌──────────────┐
│              │
│      🐱       │  ← 一只Emoji小猫!
│              │     在你的桌面上!
│              │     来回走!
│              │     碰到边就反弹!
└──────────────┘

恭喜!你刚刚用不到70行代码做出了一个桌面宠物的雏形! 🎉

Step 4:进阶改进(可选)

有了基础版之后,你可以逐步添加功能:

改进1:换成自己的图片
代码语言:python
复制
# 把 Emoji 替换为自定义图片
self.label = QLabel(self)
pixmap = QPixmap("my_cat.png")  # 你的宠物图片,建议PNG透明背景
self.label.setPixmap(pixmap.scaled(120, 120))
self.label.setGeometry(0, 0, 120, 120)
改进2:添加鼠标拖拽
代码语言:python
复制
# 在类中添加以下方法

def mousePressEvent(self, event):
    """鼠标按下:记录起始位置"""
    if event.button() == Qt.MouseButton.LeftButton:
        self.drag_start_pos = event.globalPosition().toPoint() - self.frameGeometry().topLeft()

def mouseMoveEvent(self, event):
    """鼠标移动:拖拽窗口"""
    if hasattr(self, 'drag_start_pos'):
        new_pos = event.globalPosition().toPoint() - self.drag_start_pos
        self.move(new_pos)
改进3:右键菜单(退出功能)
代码语言:python
复制
def mousePressEvent(self, event):
    """鼠标点击事件"""
    if event.button() == Qt.MouseButton.RightButton:
        # 右键弹出菜单
        from PyQt6.QtWidgets import QMenu, QAction
        menu = QMenu(self)
        exit_action = QAction("退出 🐱", self)
        exit_action.triggered.connect(app.quit)  # 注意:app要是全局可访问的
        menu.addAction(exit_action)
        menu.exec(event.globalPosition().toPoint())
    elif event.button() == Qt.MouseButton.LeftButton:
        self.drag_start_pos = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
改进4:双击切换表情
代码语言:python
复制
def mouseDoubleClickEvent(self, event):
    """双击切换不同表情"""
    import random
    emojis = ["🐱", "😸", "😹", "🙀", "😻"]
    current = random.choice(emojis)
    self.label.setText(current)

🗺️ 从MVP到完整版的进化路线

代码语言:markdown
复制
你现在在这里(刚做完的MVP):
  🐱 透明窗口 + 来回走 + 可拖拽
        ↓
  下一步(花一个周末):
  🐱💬 加上状态切换 + 多组表情 + 右键菜单
        ↓
  再下一步(花一到两周):
  🐱🎤 加上语音交互 + 快捷键 + 基础命令处理
        ↓
  进阶(持续迭代):
  🐱✨ 粒子特效 + 完整动画系统 + 个性化皮肤
        ↓
  最终形态(也就是我现在的龙虾):
  🦞🌟 完整8状态 + 语音交互 + WorkBuddy集成 + 自动化联动

关键心得:每一步都能用。 不用等到"最终形态"才发布——第一版只有来回走的猫咪就已经可以在朋友圈装一波了 😎


八、扩展想象:桌面宠物的未来可能

这部分纯属脑洞。但万一哪天有人想做"桌面宠物2.0"呢——这里有一些方向可以参考。

🔮 可能性1:多人宠物社交

你的龙虾能跟别人的龙虾"认识"。

代码语言:markdown
复制
场景设想:
  你和同事都在用龙虾宠物
  两台电脑在同一个WiFi下
  两只龙虾可以互相"看到"对方(在屏幕边缘冒个头)
  
互动方式:
  · 你的龙虾可以走到屏幕边缘"拜访"同事的龙虾
  · 可以一起"玩"(同步做一些动画)
  · 可以"传递消息"(一只龙虾吐泡泡给另一只)
  · 同事不在座位时,他的龙虾会显得"孤单"

技术上可行性很高——局域网UDP广播就能实现基本的"存在感知"。剩下的就是创意问题了。

🔮 可能性2:宠物技能插槽

让龙虾学会"技能",就像游戏里那样。

代码语言:markdown
复制
概念:
  龙虾本体 = 基础框架(动画+状态+语音)
  技能插件 = 可安装的功能扩展包
  
示例技能:
  ├── skill-github     → GitHub通知(有PR/Issue时龙虾告诉你)
  ├── skill-calendar    → 日程提醒(会议前15分钟龙虾提醒你)
  ├── skill-weather     → 天气播报(每天早上龙虾告诉你今天天气)
  ├── skill-music       → 音乐控制(语音说"放首歌"龙虾调用音乐App)
  ├── skill-pomodoro    → 番茄钟(龙虾陪你专注25分钟+休息5分钟)
  └── skill-custom      → 用户自己写的任意技能...
  
安装方式:
  "帮我的龙虾安装天气播报技能"
  → 自动下载skill-weather
  → 龙虾学会了一项新本领

本质上就是把 WorkBuddy 的 Skill 系统移植到了桌面宠物上。 龙虾不只是宠物——它是你桌面上所有AI能力的统一交互入口

🔮 可能性3:宠物"成长"系统

龙虾随着使用时间推移会"长大"、"进化"。

代码语言:markdown
复制
成长维度:

📈 等级系统
  Lv.1 卵(刚出生)     → 只有一个呆萌的蛋
  Lv.2 幼虾            → 会走会看
  Lv.3 成虾(当前)     → 全部功能解锁
  Lv.4 ????            → 待设计...

🎨 外观进化
  使用时长 > 7天   → 解锁新的配色方案
  使用时长 > 30天  → 解锁装饰配件(小帽子/围巾/眼镜框)
  使用时长 > 90天  → 解锁稀有皮肤(全金龙虾???)

🧠 性格养成
  如果你经常在夜间工作 → 龙虾变成"夜猫子"型(白天懒洋洋晚上精神)
  如果你经常让它执行任务 → 龙虾变成"工作狂"型(催你干活)
  如果你经常跟它闲聊    → 龙虾变成"话痨"型(更多随机台词)

让每只龙虾都不一样。 你的龙虾就是你的龙虾——带着你的使用习惯和个人印记。


九、写在最后:为什么一个售前要做这件事

回到最开始的问题:

"一个天天写标书做方案的售前,为什么花了半年时间做一只桌面宠物?"

正经的回答是:这是学习 WorkBuddy Skill系统和 macOS 开发的绝佳练手项目。 过程中掌握的技术点(状态机设计、动画系统、快捷键全局监听、语音集成)后来都用在了正经的工作Skill上。

不正经的回答是:

因为工作是一场马拉松,不是百米冲刺。

我们这些人——做售前的、做实施的、做开发的、做产品经理的——每天都在高强度运转。赶方案、见客户、回邮件、开会、写周报、填报表……

有时候真的很累。不是身体累——是心累。是一种"今天干了好多事情但又好像什么都没推进"的无力感。

在这种时候,如果桌面上有个小东西——

在你连续工作了两个小时之后弹出来说该休息了

在你命令执行失败的时候陪你一起翻白眼冒黑烟

在你深夜还在赶工的时候不再霸道催你而是温柔地放一首轻音乐

在你实在撑不住的时候给你讲一个烂到让人笑出来的冷笑话——

哪怕只是一只虚拟的龙虾,哪怕它什么都不懂,但它在那里。

这就够了。

"工作是给人看的。宠物是给自己看的。"

偶尔让自己开心一下,不丢人。


🦞 如果你也想做属于自己的桌面宠物——

今天就可以开始。 复制第七章的那70行代码,跑起来,然后一点一点地加上你自己的想法。

不必做成龙虾。做一只猫、一条狗、一只史莱姆、一个像素小人、甚至一团会变形的果冻——随你喜欢。

重要的是开始


如果这篇让你笑了至少一次,欢迎 点赞👍 在看⭐ 转发🔄!

评论区留言 "🦞我也想要" ,我把完整的龙虾宠物源码整理出来分享给大家!(目前还在整理中,感兴趣的话人多我就加快进度~)

有问题评论区交流,每一个我都会回~

如果你读到最后,在告诉你一个小彩蛋,你可以直接把我这篇文章发给你的workbuddy,他会直接帮你搭建一个属于你自己的赛博龙虾。


> 写到这里,我的桌上的龙虾刚好从睡眠状态醒来,伸了个懒腰,吐了个泡泡。

> 它好像在说:"写完了?该休息了吧。"

> 好的。晚安,小家伙。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 🦞 一只住在桌面上的赛博龙虾。
    • 一、缘起:一个加班到深夜的疯狂念头
    • 二、它长什么样?
      • 🎨 它以前的样子
      • 🎨 现在的样子:赛博霓虹龙虾
      • 🖥️ 它在桌面上的样子
    • 三、它有什么本事?(高能预警⚡)
      • 📋 状态一览表(完整版)
      • ⏰ 状态详解:那个"很欠揍"的提醒功能
    • 四、语音交互:对着电脑说话的感觉有多爽
      • 🔑 快捷键唤醒
      • 💬 实际对话案例
      • 🎙️ 语音交互技术简述
    • 五、技术架构:一只龙虾的解剖学
      • 🏗️ 整体架构一览
      • 🧠 状态机:龙虾的"大脑"
      • 🎨 动画系统:怎么让龙虾"活"起来
    • 六、开发踩坑实录:那些让我凌晨两点还在debug的事
      • 坑 1:透明窗口的"隐形杀手"
      • 坑 2:全局快捷键被系统抢占
      • 坑 3:语音识别的"尴尬 silence"
      • 坑 4:内存泄漏——龙虾越长越大
      • 坑 5:那个"意外诞生"的追鼠标功能
    • 七、手把手教你做一个(最小可行版本)
      • 🛠️ 技术栈选择
      • Step 1:环境准备(3分钟)
      • Step 2:第一个透明窗口(5分钟)
      • Step 3:运行!(见证奇迹的时刻)
      • Step 4:进阶改进(可选)
      • 🗺️ 从MVP到完整版的进化路线
    • 八、扩展想象:桌面宠物的未来可能
      • 🔮 可能性1:多人宠物社交
      • 🔮 可能性2:宠物技能插槽
      • 🔮 可能性3:宠物"成长"系统
    • 九、写在最后:为什么一个售前要做这件事
  • 如果你读到最后,在告诉你一个小彩蛋,你可以直接把我这篇文章发给你的workbuddy,他会直接帮你搭建一个属于你自己的赛博龙虾。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档