feat(main): 增加魔法宠物聊天功能

- 集成 DeepSeek API 实现宠物聊天功能
- 添加用户输入框和聊天历史显示区域
- 优化宠物生成逻辑,增加宠物性格属性
- 调整界面布局和样式,提升用户体验
This commit is contained in:
sairate 2025-04-23 15:21:52 +08:00
parent 073c6692ad
commit 539e83f96a
2 changed files with 145 additions and 31 deletions

View File

@ -3,7 +3,9 @@
<component name="MaterialThemeProjectNewConfig"> <component name="MaterialThemeProjectNewConfig">
<option name="metadata"> <option name="metadata">
<MTProjectMetadataState> <MTProjectMetadataState>
<option name="userId" value="1a843db6:196430267ac:-7ffa" /> <option name="migrated" value="true" />
<option name="pristineConfig" value="false" />
<option name="userId" value="21c1c7ee:193388d497c:-7ff9" />
</MTProjectMetadataState> </MTProjectMetadataState>
</option> </option>
</component> </component>

172
main.py
View File

@ -1,68 +1,84 @@
import tkinter as tk #gui模块 主要共功能是创建窗口 import tkinter as tk
from tkinter import messagebox from tkinter import messagebox, scrolledtext
from PIL import Image, ImageTk from PIL import Image, ImageTk
import os import os
import random import random
import pygame import pygame
import requests
import threading
# 初始化 pygame 播放器 # DeepSeek API配置
pygame.mixer.init() DEEPSEEK_API_KEY = "sk-ef8d5c251461489e86e9b9f6bf136900" # 替换为您的实际API密钥
DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat/completions"
# 宠物信息(名字 + 描述 + 图像路径 + 声音路径) try:
pygame.mixer.init()
print("pygame音频初始化成功")
except Exception as e:
print("pygame音频初始化失败:", e)
# 宠物信息(名字 + 描述 + 图像路径 + 声音路径 + 性格)
pets = { pets = {
"fire": { "fire": {
"name": "小火星", "name": "小火星",
"desc": "热情似火的小精灵,像火焰一样跳跃,能照亮黑暗的角落!", "desc": "热情似火的小精灵,像火焰一样跳跃,能照亮黑暗的角落!",
"personality": "热情活泼,充满能量,乐于助人",
"image": "./images/fire_pet.png", "image": "./images/fire_pet.png",
"sound": "./sounds/fire.mp3" "sound": "./sounds/fire.mp3"
}, },
"water": { "water": {
"name": "小水灵", "name": "小水灵",
"desc": "爱在水中嬉戏的小可爱,总能带来清凉和欢乐的气息!", "desc": "爱在水中嬉戏的小可爱,总能带来清凉和欢乐的气息!",
"personality": "温柔亲切,聪明伶俐,喜欢玩耍",
"image": "./images/water_pet.png", "image": "./images/water_pet.png",
"sound": "./sounds/water.mp3" "sound": "./sounds/water.mp3"
}, },
"thunder": { "thunder": {
"name": "小电闪", "name": "小电闪",
"desc": "全身带电的小家伙,跑得飞快,一不小心就“嗞啦”一下!", "desc": "全身带电的小家伙,跑得飞快,一不小心就“嗞啦”一下!",
"personality": "调皮捣蛋,反应灵敏,喜欢恶作剧",
"image": "./images/thunder_pet.png", "image": "./images/thunder_pet.png",
"sound": "./sounds/thunder.mp3" "sound": "./sounds/thunder.mp3"
}, },
"wind": { "wind": {
"name": "小风灵", "name": "小风灵",
"desc": "像风一样自由自在,轻盈地守护着大家,还会吹走烦恼哦!", "desc": "像风一样自由自在,轻盈地守护着大家,还会吹走烦恼哦!",
"personality": "自由洒脱,爱冒险,安静细腻",
"image": "./images/wind_pet.png", "image": "./images/wind_pet.png",
"sound": "./sounds/wind.mp3" "sound": "./sounds/wind.mp3"
}, },
"earth": { "earth": {
"name": "小土地", "name": "小土地",
"desc": "稳重又强壮的大地守护者,是伙伴们最坚实的后盾!", "desc": "稳重又强壮的大地守护者,是伙伴们最坚实的后盾!",
"personality": "可靠沉稳,忠诚守护,有安全感",
"image": "./images/earth_pet.png", "image": "./images/earth_pet.png",
"sound": "./sounds/earth.mp3" "sound": "./sounds/earth.mp3"
}, },
"dark": { "dark": {
"name": "小黑星", "name": "小黑星",
"desc": "神秘的黑夜精灵,能在安静中保护大家不受惊吓!", "desc": "神秘的黑夜精灵,能在安静中保护大家不受惊吓!",
"personality": "神秘低调,冷静敏锐,喜欢黑夜",
"image": "./images/dark_pet.png", "image": "./images/dark_pet.png",
"sound": "./sounds/dark.mp3" "sound": "./sounds/dark.mp3"
}, },
"light": { "light": {
"name": "小光星", "name": "小光星",
"desc": "闪闪发光的光明使者,总能把温暖和希望带给大家!", "desc": "闪闪发光的光明使者,总能把温暖和希望带给大家!",
"personality": "阳光开朗,善解人意,充满正能量",
"image": "./images/light_pet.png", "image": "./images/light_pet.png",
"sound": "./sounds/light.mp3" "sound": "./sounds/light.mp3"
}, },
} }
# 创建主窗口 # 创建主窗口
root = tk.Tk() root = tk.Tk()
root.title("魔法宠物生成器") root.title("魔法宠物伙伴")
root.geometry("400x500") root.geometry("600x700")
root.config(bg="lightyellow") root.config(bg="lightyellow")
# 标题标签 # 标题标签
title_label = tk.Label(root, text="🎉 你的魔法宠物诞生啦!", font=("Arial", 16, "bold"), bg="lightyellow") title_label = tk.Label(root, text="🎉 你的魔法宠物伙伴", font=("Arial", 16, "bold"), bg="lightyellow")
title_label.pack(pady=10) title_label.pack(pady=10)
# 图像显示标签 # 图像显示标签
@ -73,38 +89,134 @@ image_label.pack(pady=10)
info_label = tk.Label(root, text="", font=("Arial", 12), wraplength=300, justify="center", bg="lightyellow") info_label = tk.Label(root, text="", font=("Arial", 12), wraplength=300, justify="center", bg="lightyellow")
info_label.pack(pady=10) info_label.pack(pady=10)
# 保存照片引用(避免垃圾回收) # 对话历史显示区域
current_photo = None chat_frame = tk.Frame(root, bg="lightyellow")
chat_frame.pack(pady=10, fill=tk.BOTH, expand=True)
chat_history = scrolledtext.ScrolledText(chat_frame, width=60, height=10, font=("Arial", 10), wrap=tk.WORD)
chat_history.pack(fill=tk.BOTH, expand=True)
chat_history.insert(tk.END, "系统: 欢迎来到魔法宠物世界!点击按钮召唤你的宠物伙伴吧!\n")
chat_history.config(state=tk.DISABLED)
# 用户输入框
input_frame = tk.Frame(root, bg="lightyellow")
input_frame.pack(pady=5)
user_input = tk.Entry(input_frame, width=50, font=("Arial", 12))
user_input.pack(side=tk.LEFT, padx=5)
# 当前宠物和图像引用
current_photo = None
current_pet = None
def chat_with_pet(message):
if not current_pet:
return "请先召唤一只宠物伙伴吧!点击'召唤宠物'按钮~"
pet_info = pets[current_pet['type']]
prompt = f"""
你是一只名叫{pet_info['name']}的魔法宠物你的性格特点是{pet_info['personality']}
你现在正在和主人对话请用可爱活泼的语气回应可以适当使用表情符号和语气词~
当前对话内容{message}
"""
headers = {
"Authorization": f"Bearer {DEEPSEEK_API_KEY}",
"Content-Type": "application/json"
}
data = {
"model": "deepseek-chat",
"messages": [{"role": "user", "content": prompt}],
"temperature": 0.8,
"max_tokens": 150
}
try:
response = requests.post(DEEPSEEK_API_URL, headers=headers, json=data)
if response.status_code == 200:
return response.json()["choices"][0]["message"]["content"]
return f"{pet_info['name']}好像有点困惑... (API错误: {response.status_code})"
except Exception as e:
return f"哎呀,{pet_info['name']}暂时无法回应... ({str(e)})"
def send_message():
message = user_input.get()
if not message:
return
chat_history.config(state=tk.NORMAL)
chat_history.insert(tk.END, f"\n你: {message}\n")
chat_history.config(state=tk.DISABLED)
chat_history.see(tk.END)
user_input.delete(0, tk.END)
def run_chat():
response = chat_with_pet(message)
chat_history.config(state=tk.NORMAL)
pet_name = pets[current_pet['type']]['name'] if current_pet else "系统"
chat_history.insert(tk.END, f"{pet_name}: {response}\n")
chat_history.config(state=tk.DISABLED)
chat_history.see(tk.END)
threading.Thread(target=run_chat).start()
user_input.bind("<Return>", lambda event: send_message())
# 生成宠物的函数
def generate_pet(): def generate_pet():
global current_photo global current_photo, current_pet
# 随机选择宠物类型
pet_type = random.choice(list(pets.keys())) pet_type = random.choice(list(pets.keys()))
pet = pets[pet_type] pet = pets[pet_type]
current_pet = {"name": pet["name"], "type": pet_type}
# 显示宠物描述 # 更新UI显示
info_label.config(text=f"名字:{pet['name']}\n\n介绍:{pet['desc']}") info_label.config(text=f"名字:{pet['name']}\n\n介绍:{pet['desc']}")
image_label.config(image='') # 清除旧图片
# 加载并显示图像(使用 Pillow # 显示宠物图像
img_path = pet['image'] if os.path.exists(pet['image']):
if os.path.exists(img_path): img = Image.open(pet['image']).resize((200, 200))
img = Image.open(img_path).convert("RGB") current_photo = ImageTk.PhotoImage(img)
img = img.resize((200, 200)) image_label.config(image=current_photo)
photo = ImageTk.PhotoImage(img)
image_label.config(image=photo)
current_photo = photo # 避免图像被回收
else:
image_label.config(image='')
# 播放声音 # 播放宠物声音
sound_path = pet['sound'] if os.path.exists(pet['sound']):
if os.path.exists(sound_path): pygame.mixer.music.stop()
pygame.mixer.music.load(sound_path) pygame.mixer.music.load(pet['sound'])
pygame.mixer.music.play() pygame.mixer.music.play()
# 在聊天框显示欢迎语
chat_history.config(state=tk.NORMAL)
chat_history.insert(tk.END, f"\n{pet['name']}出现了!\n")
chat_history.insert(tk.END, f"{pet['name']}: {random.choice(['你好呀主人!我是你的新伙伴~','哇!见到你好开心!','准备好和我一起冒险了吗?'])}\n")
chat_history.config(state=tk.DISABLED)
chat_history.see(tk.END)
# 按钮 # 按钮
generate_button = tk.Button(root, text="🎲 生成魔法宠物", font=("Arial", 14), command=generate_pet, bg="skyblue") button_frame = tk.Frame(root, bg="lightyellow")
generate_button.pack(pady=20) button_frame.pack(pady=10)
generate_button = tk.Button(
button_frame,
text="✨ 召唤宠物",
font=("Arial", 14),
command=generate_pet,
bg="skyblue",
fg="white"
)
generate_button.pack(side=tk.LEFT, padx=10)
send_button = tk.Button(
button_frame,
text="💌 发送",
font=("Arial", 14),
command=send_message,
bg="pink",
fg="white"
)
send_button.pack(side=tk.LEFT, padx=10)
# 启动主循环 # 启动主循环
root.mainloop() root.mainloop()