小白中文Python-db_桌面小黄鸭宠物
这是一个使用Python的tkinter库开发的桌面小黄鸭宠物游戏。宠物具有饥饿度、能量、健康和快乐度等状态,玩家可通过右键菜单进行喂食、休息、 sot治疗和玩耍等互动。 ["DesktopPet"类] 实现了宠物的绘制、动画效果和状态管理,支持窗口拖动和透明背景。 游戏采用多线程处理状态更新和动画,使用pygame播放音频。 代码结构清晰,适合初学者学习图形界面开发和简单游戏设计。
下面是中文Python游戏全部源代码。在【小白中文Python软件】上开发,【转为西文关键字】。可以在Vscode和Pychram等软件上运行。
python
导入 tkinter 作为 tk
从 tkinter 导入 messagebox, simpledialog
导入 random
导入 math
导入 threading
导入 time
从 pygame 导入 mixer
导入 sys
类 DesktopPet:
定义 __init__(self):
# 初始化pygame音频系统
mixer.init()
# 宠物状态
self.hunger = 50 # 0-100,越高越饿
self.energy = 100 # 0-100,越低越累
self.health = 100 # 0-100,越低越不健康
self.happiness = 50 # 0-100,越低越不开心
self.is_resting = 假
# 创建主窗口
self.root = tk.Tk()
self.root.title("桌面宠物 - 小黄鸭")
self.root.overrideredirect(真) # 无边框窗口
self.root.attributes("-alpha", 0.95) # 透明度
self.root.attributes("-topmost", 真) # 窗口置顶
self.root.attributes("-transparentcolor", "white") # 白色透明
# 窗口大小和初始位置
self.width = 150
self.height = 150
self.root.geometry(f"{self.width}x{self.height}+500+300")
# 创建画布
self.canvas = tk.Canvas(self.root, width=self.width, height=self.height, bg="white", highlightthickness=0)
self.canvas.pack()
# 鼠标事件变量
self.x = 0
self.y = 0
self.dragging = 假
# 绑定鼠标事件
self.canvas.bind("<Button-1>", self.on_drag_start)
self.canvas.bind("<B1-Motion>", self.on_drag_motion)
self.canvas.bind("<ButtonRelease-1>", self.on_drag_release)
self.canvas.bind("<Button-3>", self.show_menu)
# 创建右键菜单
self.menu = tk.Menu(self.root, tearoff=0)
self.menu.add_command(label="喂食", command=self.feed)
self.menu.add_command(label="休息", command=self.toggle_rest)
self.menu.add_command(label="吃药", command=self.heal)
self.menu.add_command(label="玩耍", command=self.play)
self.menu.add_separator()
self.menu.add_command(label="查看状态", command=self.show_status)
self.menu.add_separator()
self.menu.add_command(label="退出", command=self.quit_game)
# 绘制小黄鸭
self.draw_duck()
# 启动状态更新线程
self.running = 真
self.status_thread = threading.Thread(target=self.update_status, daemon=真)
self.status_thread.start()
# 启动动画线程
self.animation_thread = threading.Thread(target=self.animate, daemon=真)
self.animation_thread.start()
定义 draw_duck(self, angle=0):
"""绘制小黄鸭,angle参数用于动画效果"""
self.canvas.delete("all")
# 小黄鸭身体
body_radius = 30
body_x = self.width // 2
body_y = self.height // 2 + 10
# 身体(椭圆)
self.canvas.create_oval(
body_x - body_radius, body_y - body_radius//1.5,
body_x + body_radius, body_y + body_radius//1.5,
fill="#FFD700", outline=""
)
# 头部
head_radius = 20
head_x = body_x + body_radius * math.cos(angle)
head_y = body_y - body_radius//1.5 * math.sin(angle)
self.canvas.create_oval(
head_x - head_radius, head_y - head_radius,
head_x + head_radius, head_y + head_radius,
fill="#FFD700", outline=""
)
# 眼睛
eye_offset = 5
eye_x = head_x + head_radius//2
eye_y = head_y - eye_offset
self.canvas.create_oval(
eye_x - 3, eye_y - 3,
eye_x + 3, eye_y + 3,
fill="black", outline=""
)
# 嘴巴
beak_length = 15
beak_x1 = head_x + head_radius
beak_y1 = head_y
beak_x2 = beak_x1 + beak_length
beak_y2 = beak_y1 - 5
beak_x3 = beak_x1 + beak_length
beak_y3 = beak_y1 + 5
self.canvas.create_polygon(
beak_x1, beak_y1,
beak_x2, beak_y2,
beak_x3, beak_y3,
fill="#FFA500", outline=""
)
# 翅膀
wing_radius = 15
wing_x = body_x - body_radius//2
wing_y = body_y
self.canvas.create_oval(
wing_x - wing_radius, wing_y - wing_radius,
wing_x + wing_radius, wing_y + wing_radius,
fill="#FFC107", outline=""
)
# 脚
foot_length = 15
foot_x1 = body_x - body_radius//2
foot_y1 = body_y + body_radius//1.5
foot_x2 = foot_x1 - foot_length
foot_y2 = foot_y1 + foot_length
foot_x3 = body_x + body_radius//2
foot_y3 = body_y + body_radius//1.5
foot_x4 = foot_x3 + foot_length
foot_y4 = foot_y3 + foot_length
self.canvas.create_line(foot_x1, foot_y1, foot_x2, foot_y2, width=3, fill="#FFA500")
self.canvas.create_line(foot_x3, foot_y3, foot_x4, foot_y4, width=3, fill="#FFA500")
定义 on_drag_start(self, event):
"""开始拖动窗口"""
self.x = event.x
self.y = event.y
self.dragging = 真
self.play_sound("drag")
定义 on_drag_motion(self, event):
"""拖动窗口过程"""
如果 self.dragging:
x = self.root.winfo_x() + event.x - self.x
y = self.root.winfo_y() + event.y - self.y
self.root.geometry(f"+{x}+{y}")
定义 on_drag_release(self, event):
"""结束拖动窗口"""
self.dragging = 假
定义 show_menu(self, event):
"""显示右键菜单"""
self.menu.post(event.x_root, event.y_root)
定义 play_sound(self, sound_type):
"""播放合成的声音"""
# 停止当前播放的声音
如果 mixer.music.get_busy():
mixer.music.stop()
# 根据不同操作生成不同频率的简单声音
尝试:
如果 sound_type == "feed":
# 喂食声音 - 中等频率
self.generate_tone(440, 0.3)
否则如果 sound_type == "heal":
# 吃药声音 - 高低交替
self.generate_tone(660, 0.2)
time.sleep(0.2)
self.generate_tone(880, 0.2)
否则如果 sound_type == "play":
# 玩耍声音 - 欢快的旋律
对于 freq 在 [523, 659, 784, 1047]:
self.generate_tone(freq, 0.15)
time.sleep(0.15)
否则如果 sound_type == "rest":
# 休息声音 - 低频
self.generate_tone(220, 0.5)
否则如果 sound_type == "drag":
# 拖动声音 - 短音
self.generate_tone(330, 0.1)
否则如果 sound_type == "happy":
# 开心声音
self.generate_tone(660, 0.2)
time.sleep(0.2)
self.generate_tone(784, 0.2)
否则如果 sound_type == "sad":
# 难过声音
self.generate_tone(330, 0.2)
time.sleep(0.2)
self.generate_tone(220, 0.3)
捕获:
跳过 # 忽略音频错误
定义 generate_tone(self, frequency, duration):
"""生成简单的正弦波音调"""
导入 numpy 作为 np
从 pygame.sndarray 导入 make_sound
# 采样率
sample_rate = 44100
# 生成正弦波
n_samples = int(sample_rate * duration)
buf = np.zeros((n_samples, 2), dtype=np.int16)
max_amplitude = 2**15 - 1
对于 s 在 range(n_samples):
t = float(s) / sample_rate
buf[s][0] = int(max_amplitude * math.sin(2 * math.pi * frequency * t))
buf[s][1] = buf[s][0] # 立体声,左右声道相同
# 播放声音
sound = make_sound(buf)
sound.play()
定义 feed(self):
"""喂食功能"""
self.hunger = max(0, self.hunger - 30)
self.happiness = min(100, self.happiness + 10)
messagebox.showinfo("喂食", "小黄鸭开心地吃了食物!")
self.play_sound("feed")
定义 toggle_rest(self):
"""切换休息状态"""
self.is_resting = 非 self.is_resting
如果 self.is_resting:
messagebox.showinfo("休息", "小黄鸭开始休息了...")
否则:
messagebox.showinfo("醒来", "小黄鸭醒来了!")
self.play_sound("rest")
定义 heal(self):
"""治疗功能"""
self.health = min(100, self.health + 40)
self.happiness = max(0, self.happiness - 10) # 吃药会不开心
messagebox.showinfo("吃药", "小黄鸭吃了药,感觉好多了!")
self.play_sound("heal")
定义 play(self):
"""玩耍功能"""
self.happiness = min(100, self.happiness + 30)
self.energy = max(0, self.energy - 20)
self.hunger = min(100, self.hunger + 10)
messagebox.showinfo("玩耍", "你和小黄鸭玩得很开心!")
self.play_sound("play")
定义 show_status(self):
"""显示宠物状态"""
status_text = (f"饥饿度: {self.hunger}/100\n"
f"精力: {self.energy}/100\n"
f"健康度: {self.health}/100\n"
f"开心度: {self.happiness}/100")
messagebox.showinfo("小黄鸭状态", status_text)
定义 update_status(self):
"""定期更新宠物状态"""
当 self.running:
如果 非 self.is_resting:
# 非休息状态下,饥饿度增加,精力减少
self.hunger = min(100, self.hunger + 1)
self.energy = max(0, self.energy - 1)
# 饥饿影响健康
如果 self.hunger > 80:
self.health = max(0, self.health - 0.5)
否则:
# 休息状态下,精力恢复
self.energy = min(100, self.energy + 2)
# 健康影响开心度
如果 self.health < 30:
self.happiness = max(0, self.happiness - 1)
# 精力影响开心度
如果 self.energy < 20:
self.happiness = max(0, self.happiness - 1)
# 状态过低时提示
如果 self.hunger >= 90 且 random.random() < 0.1:
messagebox.showwarning("提示", "小黄鸭好饿啊,快喂点食物吧!")
self.play_sound("sad")
如果 self.energy <= 10 且 random.random() < 0.1 且 非 self.is_resting:
messagebox.showwarning("提示", "小黄鸭好累啊,让它休息一下吧!")
self.play_sound("sad")
如果 self.health <= 20 且 random.random() < 0.1:
messagebox.showwarning("提示", "小黄鸭不舒服,需要治疗!")
self.play_sound("sad")
如果 self.happiness >= 90 且 random.random() < 0.05:
messagebox.showinfo("开心", "小黄鸭今天特别开心!")
self.play_sound("happy")
# 每3秒更新一次
time.sleep(3)
定义 animate(self):
"""宠物动画效果"""
angle = 0
direction = 0.05
当 self.running:
# 根据状态调整动画速度
如果 self.is_resting:
speed_factor = 0.3
否则如果 self.happiness < 30:
speed_factor = 0.5
否则:
speed_factor = 1
# 更新角度
angle += direction * speed_factor
如果 angle > 0.5 或 angle < -0.5:
direction *= -1
# 绘制动画帧
self.root.after(0, 匿名函数 a=angle: self.draw_duck(a))
# 控制动画帧率
time.sleep(0.1)
定义 quit_game(self):
"""退出游戏"""
self.running = 假
self.status_thread.join()
self.animation_thread.join()
mixer.quit()
self.root.destroy()
定义 run(self):
"""运行主循环"""
self.root.mainloop()
如果 __name__ == "__main__":
# 确保中文显示正常
尝试:
pet = DesktopPet()
pet.run()
捕获 Exception 作为 e:
print(f"程序出错: {e}")
sys.exit(1)
点赞和关注我的博客!
超越自己是我的每一步,我的进步就是你的进步!