敲鸡蛋 · 怒气值爆表版:一个程序员的自我救赎
🎮 一款解压又好玩的 Python 小游戏 ——《敲鸡蛋:怒气值爆表版》用 pygame 打造的小游戏,每点击一下鸡蛋,就能触发爆裂粒子 + 弹幕吐槽 + 功德增长。敲够 50 次,鸡蛋颜色变黑、体积膨胀,怒气值同步上升,右侧还会显示怒气计量尺!支持:背景音乐 🎵(自动播放 + M键静音)本地记录 🧾(最高敲击数)吐槽老板金句 🎯(24 句循环弹出)快捷键操作 🖱️(敲蛋 / 截图 /
🥚 故事从一次“远程会议”开始……
“各位,我们下个季度的目标要更具挑战性!”
“虽然资金紧张,但我们要相信团队的力量!”
“目前工资暂时不动,但后续会有绩效激励!”
听着老板在会议里激情澎湃地画着饼,我默默关掉摄像头,打开了……egg_tapper.py
。
“工资不动?那我就把这颗蛋敲裂!”
💡 项目简介
这是一个由 Python + pygame 打造的 解压小游戏 ——《敲鸡蛋:怒气值爆表版》。
它不仅能模拟真实敲击,还有 爆裂粒子、怒气条成长、吐槽弹幕、成就系统,一边敲蛋一边爽快吐槽,极大缓解打工精神内耗!
🌟 核心功能亮点
功能项 | 说明 |
---|---|
✅ 鸡蛋敲击反馈 | 每点一下,粒子飞溅、功德+1 |
🎧 背景音乐 | 自动播放本地 mp3/ogg 文件,可静音 |
🐣 鸡蛋成长机制 | 每敲 50 下变黑变大,视觉反馈拉满 |
📈 怒气值条 | 右侧实时展示鸡蛋“发黑程度” |
🗯️ 吐槽老板金句 | 每敲一下弹一句爆笑吐槽,24 句循环 |
📊 历史记录保存 | 保留最高敲击记录(显示于左上角) |
🖱️ 快捷键控制 | 空格/鼠标敲、M 静音、S 截图、Q 退出 |
🧪 如何运行
1. 安装依赖
pip install pygame
2. 资源准备(可选)
将以下文件放到脚本同目录下:
-
egg.png
:鸡蛋图片(建议 512×512) -
crack.wav
:敲击音效(每次点击触发) -
bgm.mp3
/bgm.ogg
:背景音乐 -
font.ttf
:支持中文的字体文件(推荐 NotoSansCJK)
3. 启动游戏
python egg_tapper.py
⌨️ 快捷键说明
快捷键 | 功能 |
---|---|
鼠标点击 / 空格键 | 敲蛋! |
M | 开/关背景音乐 |
S | 截图保存 |
Q / Esc | 退出游戏 |
项目结构
egg_tapper/
├── egg_tapper.py # 主程序(核心逻辑代码)
├── assets/ # 资源目录(建议集中管理)
│ ├── egg.png # 鸡蛋图片(可替换)
│ ├── crack.wav # 敲击音效(每次点击)
│ ├── bgm.mp3 # 背景音乐(支持 mp3 / ogg)
│ └── font.ttf # 中文字体(避免乱码)
├── egg_save.json # 本地保存文件(自动生成)
egg_tapper.py 的完整代码
"""
敲鸡蛋 (Egg Tapper) — v5 美化·持久纪录版
========================================
本版亮点
--------
1. **历史最高分持久化** (`egg_save.json`)
* 每次启动 `本局` 计数从 0 开始;`最高` 会读取并刷新本地最高纪录。
2. **界面排版优化**
* 统计区左右居中、怒气尺标题完整、吐槽条移至底部居中。
3. 原有功能全保留:怒气升级、颜色变深、体积增大、音效、弹幕、粒子、背景音乐、截图等。
运行
----
```bash
pip install pygame
python egg_tapper.py
```
"""
from __future__ import annotations
import json, math, random, sys
from pathlib import Path
from dataclasses import dataclass
from typing import List
import pygame
# -------------------- 基础常量 -------------------- #
BASE_W, BASE_H = 560, 720 # 窗口尺寸
GAUGE_W = 60 # 右侧怒气尺宽度
GAUGE_X = BASE_W - GAUGE_W
SAVE_FILE = Path("egg_save.json")
WHITE, BLACK = (255, 255, 255), (0, 0, 0)
DEFAULT_COLOR = (237, 229, 216) # 蛋壳初始 RGB
PARTICLE_COLS = [(255,199,44), (255,82,82), (69,210,252), (138,201,38)]
MAX_PARTICLES = 600 # 控制粒子总量
# -------------------- 文本资源 -------------------- #
PHRASES = [
"越敲越强!", "功不唐捐", "鸡你太美", "再来亿下", "蛋·行不行", "我裂开了", "狂敲不止",
"蛋定如山", "燃烧吧小宇宙", "再来一打!",
]
BOSS_LINES = [
"老板总喊着冲刺目标,工资却像蜗牛在爬道",
"老板画的大饼飘啊飘,钱包瘪瘪心发焦",
"老板说要一起向前跑,自己却在后方享逍遥",
"老板口才赛过脱口秀,兑现承诺却没个头",
"老板天天喊着要突破,员工钱包原地没挪窝",
"老板描绘前景似仙境,实际收入让人泪满襟",
"老板决策好似捉迷藏,员工跟着晕头又转向",
"老板豪言壮志震天响,工资待遇悄悄往下放",
"老板总说公司是大家,可好处都往自己抓",
"老板指挥若定有方略,员工累成陀螺钱不多",
"老板谈起理想滔滔不绝,说到加薪哑口无言",
"老板规划未来头头是道,当下工资让人想吐槽",
"老板说要共享胜利果,最后只有苦劳没收获",
"老板总把困难轻松说,员工加班加点没处躲",
"老板描绘愿景美如画,工资现实惨不忍察",
"老板决策频繁像翻书,员工适应无力心添堵",
"老板鼓励大家要拼搏,奖励却像星星一颗颗",
"老板说着公司前景阔,自己钱包鼓得像秤砣",
"老板夸赞员工都很棒,升职加薪却没影光",
"老板总是信心超级满,员工待遇原地打转转",
"老板规划宏图似星汉,工资涨幅细若游丝般",
"老板强调团队力量强,利益分配却不均当",
"老板说要一起创辉煌,员工只剩疲惫心迷茫",
"老板说起未来眼放光,工资现状不如从前样",
]
# -------------------- 字体加载 -------------------- #
CANDIDATE_FONTS = [
"PingFang SC", "Hiragino Sans GB", "Heiti SC", "Songti SC",
"STHeiti", "Arial Unicode MS", "AppleGothic",
]
def load_font(size: int) -> pygame.font.Font:
"""优先使用同目录 font.ttf,其次系统常见中文字体。"""
if Path("font.ttf").exists():
return pygame.font.Font("font.ttf", size)
for name in CANDIDATE_FONTS:
path = pygame.font.match_font(name)
if path:
return pygame.font.Font(path, size)
return pygame.font.SysFont(None, size)
# -------------------- 工具函数 -------------------- #
def load_img(path: str, scale: float = 1.0):
if not Path(path).exists():
return None
try:
img = pygame.image.load(path).convert_alpha()
if scale != 1.0:
w, h = img.get_size()
img = pygame.transform.smoothscale(img, (int(w * scale), int(h * scale)))
return img
except Exception:
return None
def play_sound(path: str):
if Path(path).exists():
try:
pygame.mixer.Sound(path).play()
except pygame.error:
pass
# -------- 持久化:只保存最高纪录 -------- #
def load_best() -> int:
if SAVE_FILE.exists():
try:
return json.loads(SAVE_FILE.read_text()).get("best", 0)
except Exception:
pass
return 0
def save_best(best: int):
try:
SAVE_FILE.write_text(json.dumps({"best": best}))
except Exception:
pass
# -------------------- 数据类 -------------------- #
@dataclass
class Particle:
pos: pygame.Vector2
vel: pygame.Vector2
r: float
col: tuple[int, int, int]
life: int = 40
def update(self):
self.pos += self.vel
self.vel *= 0.92
self.r *= 0.96
self.life -= 1
def draw(self, surf):
if self.life > 0 and self.r > 0:
pygame.draw.circle(surf, self.col, self.pos, max(1, int(self.r)))
@dataclass
class FloatingText:
txt: str
pos: pygame.Vector2
font: pygame.font.Font
alpha: int = 255
def update(self):
self.pos.y -= 1
self.alpha -= 3
def draw(self, surf):
if self.alpha <= 0:
return
im = self.font.render(self.txt, True, BLACK)
im.set_alpha(self.alpha)
surf.blit(im, self.pos)
@dataclass
class Egg:
base_rect: pygame.Rect
rect: pygame.Rect
image: pygame.Surface | None
color: tuple[int, int, int] = DEFAULT_COLOR
growth: int = 0 # 怒气值 / 成长次数
scale: float = 1.0
pulse_dir: int = 1
def draw(self, surf):
if self.image:
surf.blit(self.image, self.rect)
else:
pygame.draw.ellipse(surf, self.color, self.rect)
def pulse(self):
self.scale, self.pulse_dir = 1.2, -1
def animate(self):
if self.scale == 1.0:
return
self.scale += 0.02 * self.pulse_dir
if self.scale <= 0.9:
self.scale, self.pulse_dir = 0.9, 1
if abs(self.scale - 1.0) < 0.02:
self.scale = 1.0
self._apply_transform()
def level_up(self):
self.growth += 1
# 壳色加深
self.color = tuple(max(0, int(c * 0.85)) for c in self.color)
# 尺寸放大
self.base_rect.inflate_ip(int(self.base_rect.w * 0.1), int(self.base_rect.h * 0.1))
if self.image:
self.image = pygame.transform.smoothscale(self.image, self.base_rect.size)
self._apply_transform()
def _apply_transform(self):
w0, h0 = self.base_rect.size
w, h = max(2, int(w0 * self.scale)), max(2, int(h0 * self.scale))
self.rect.size = (w, h)
self.rect.center = self.base_rect.center
# -------------------- 主游戏类 -------------------- #
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((BASE_W, BASE_H))
pygame.display.set_caption("敲鸡蛋 — 吐槽老板 🐣")
self.big_font = load_font(36)
self.small_font = load_font(24)
img = load_img("egg.png", 0.7)
center_x = (BASE_W - GAUGE_W) // 2
base_rect = (img.get_rect(center=(center_x, BASE_H // 2 - 60)) if img else
pygame.Rect(center_x - 80, BASE_H // 2 - 120, 160, 200))
self.egg = Egg(base_rect.copy(), base_rect.copy(), img)
# 背景音乐
self.music_on = False
for mf in ("bgm.mp3", "bgm.ogg"):
if Path(mf).exists():
pygame.mixer.music.load(mf)
pygame.mixer.music.set_volume(0.6)
pygame.mixer.music.play(-1)
self.music_on = True
break
# 计数器
self.taps = 0 # 本局计数
self.best = load_best() # 历史最佳
self.particles: List[Particle] = []
self.texts: List[FloatingText] = []
self.boss_idx = 0
self.boss_line = ""
self.clock = pygame.time.Clock()
self.running = True
# ---------- 输入处理 ---------- #
def tap(self):
self.taps += 1
if self.taps > self.best:
self.best = self.taps
save_best(self.best)
play_sound("crack.wav")
self.egg.pulse()
# 粒子效果
center = self.egg.rect.center
if len(self.particles) < MAX_PARTICLES:
for _ in range(10):
ang = random.uniform(0, 2 * math.pi)
spd = random.uniform(2, 6)
self.particles.append(
Particle(
pygame.Vector2(center),
pygame.Vector2(math.cos(ang) * spd, math.sin(ang) * spd),
random.uniform(3, 6),
random.choice(PARTICLE_COLS)
)
)
# 弹幕文字
msg = random.choice(PHRASES)
w, _ = self.small_font.size(msg)
self.texts.append(FloatingText(msg, pygame.Vector2(center[0] - w // 2, center[1] - 40), self.small_font))
# 底部吐槽
self.boss_line = BOSS_LINES[self.boss_idx]
self.boss_idx = (self.boss_idx + 1) % len(BOSS_LINES)
# 怒气升级
if self.taps % 50 == 0:
self.egg.level_up()
def handle_events(self):
for e in pygame.event.get():
if e.type == pygame.QUIT:
self.running = False
elif e.type == pygame.MOUSEBUTTONDOWN and self.egg.rect.collidepoint(e.pos):
self.tap()
elif e.type == pygame.KEYDOWN:
if e.key in (pygame.K_ESCAPE, pygame.K_q):
self.running = False
elif e.key == pygame.K_SPACE:
self.tap()
elif e.key == pygame.K_m:
if self.music_on:
pygame.mixer.music.pause()
else:
pygame.mixer.music.unpause()
self.music_on = not self.music_on
elif e.key == pygame.K_s:
pygame.image.save(self.screen, "screenshot.png")
self.texts.append(FloatingText("📸 已截图", pygame.Vector2(BASE_W // 2 - 40, BASE_H - 80), self.small_font))
# ---------- 更新 ---------- #
def update(self):
self.egg.animate()
for p in self.particles[:]:
p.update()
if p.life <= 0 or p.r <= 0:
self.particles.remove(p)
for t in self.texts[:]:
t.update()
if t.alpha <= 0:
self.texts.remove(t)
# ---------- 绘制 ---------- #
def draw_gauge(self):
seg_h = 40
levels = 10
y0 = 140
x_inner = GAUGE_X + 15
# 标题
title = self.small_font.render(f"怒气值 {self.egg.growth}", True, BLACK)
self.screen.blit(title, (GAUGE_X + (GAUGE_W - title.get_width()) // 2, 90))
for lv in range(levels):
col = tuple(max(0, int(c * (0.85 ** lv))) for c in DEFAULT_COLOR)
rect = pygame.Rect(x_inner, y0 + lv * seg_h, GAUGE_W - 30, seg_h - 2)
pygame.draw.rect(self.screen, col, rect)
if lv == self.egg.growth:
pygame.draw.rect(self.screen, BLACK, rect, 2)
def render(self):
self.screen.fill(WHITE)
# 主蛋 + 粒子
self.egg.draw(self.screen)
for p in self.particles:
p.draw(self.screen)
for t in self.texts:
t.draw(self.screen)
# 顶部统计
sess_txt = self.small_font.render(f"本局: {self.taps}", True, BLACK)
best_txt = self.small_font.render(f"最高: {self.best}", True, BLACK)
self.screen.blit(sess_txt, (10, 10))
self.screen.blit(best_txt, (10, 35))
# 中央标题
cnt_surface = self.big_font.render(f"敲蛋数: {self.taps}", True, BLACK)
self.screen.blit(cnt_surface, ((BASE_W - GAUGE_W) // 2 - cnt_surface.get_width() // 2, 40))
# 底部吐槽
if self.boss_line:
bl_surf = self.small_font.render(self.boss_line, True, BLACK)
self.screen.blit(bl_surf, (((BASE_W - GAUGE_W) // 2) - bl_surf.get_width() // 2, BASE_H - 70))
# 怒气计量尺
self.draw_gauge()
pygame.display.flip()
# ---------- 主循环 ---------- #
def run(self):
while self.running:
self.handle_events()
self.update()
self.render()
self.clock.tick(60)
pygame.quit()
sys.exit()
# -------------------- 入口 -------------------- #
if __name__ == "__main__":
Game().run()
❤️ 彩蛋 · 吐槽弹幕(部分节选)
老板画的大饼飘啊飘,钱包瘪瘪心发焦
老板谈起理想滔滔不绝,说到加薪哑口无言
老板总说公司是大家,可好处都往自己抓
老板豪言壮志震天响,工资待遇悄悄往下放
老板夸赞员工都很棒,升职加薪却没影光
🧠 结语
写这个小游戏其实一开始只是为了吐槽。但做到后面,敲蛋、变色、怒气条……它成了我一种情绪调节的出口。
如果你也在被 KPI、需求、996 压得喘不过气,不妨敲几个蛋,放一首歌,笑一笑:
“人生不是打工打到底,也可以是……把蛋敲裂,然后重启。”
如果你喜欢这个项目,欢迎评论、点赞、收藏,或者来 GitHub 一起玩花样!😉
如需源码打包、版本拓展或移植 App,我也很乐意继续开发~

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)