【游戏制作】使用Python创建一个美观的贪吃蛇游戏,附完整代码

2024-08-02 08:00:31 浏览数 (3)

前言

贪吃蛇游戏是一款经典的电脑游戏,许多人都曾经玩过。今天我们将使用Python和ttkbootstrap库来实现一个具有美观界面的贪吃蛇游戏,并添加一些额外的功能,使其更具吸引力。

项目运行结果

项目简介

我们的贪吃蛇游戏将包括以下功能:

  1. 游戏场地是一片矩形区域,蛇可以在这片区域中自由移动。
  2. 使用tkinterCanvas控件来绘制蛇、食物和游戏区域。
  3. 游戏开始时会随机生成一条蛇和一个食物,蛇会自动移动。
  4. 通过方向键控制蛇的移动方向。
  5. 当蛇吃到食物时,蛇身长度增加,并重新生成一个食物。
  6. 当蛇撞到墙壁、石块或自己时,游戏结束。
  7. 随着得分增加,游戏速度逐渐加快。
  8. 添加游戏菜单,包括暂停、继续、退出等功能。
  9. 添加查看历史记录、查看当前日期和时间、查看开发者信息、修改主题和窗口大小等功能。
  10. 使用ttkbootstrap来美化游戏界面。

环境配置

在开始编写代码之前,我们需要确保安装了必要的库。我们将使用tkinterttkbootstrap库。

代码语言:javascript复制
pip install ttkbootstrap

代码实现

主体结构

我们首先创建一个SnakeGame类,包含所有游戏逻辑和界面设置。以下是完整的代码实现:

代码语言:javascript复制
import tkinter as tk
from tkinter import messagebox, Menu, Toplevel, Text, simpledialog, StringVar
import random
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
import datetime

class SnakeGame:
    def __init__(self, root):
        self.root = root
        self.root.title("贪吃蛇游戏")
        self.root.geometry("600x400")

        # 使用ttkbootstrap主题
        self.style = ttk.Style("cosmo")

        self.canvas = tk.Canvas(self.root, bg="white", height=400, width=600)
        self.canvas.pack()

        self.snake = [(20, 20), (20, 40), (20, 60)]
        self.food = None
        self.direction = "Down"
        self.running = True
        self.score = 0
        self.level = 1
        self.speed = 200

        self.create_menu()
        self.create_food()
        self.bind_keys()
        self.update()

    def create_menu(self):
        menubar = Menu(self.root)
        self.root.config(menu=menubar)

        game_menu = Menu(menubar, tearoff=0)
        menubar.add_cascade(label="游戏", menu=game_menu)
        game_menu.add_command(label="暂停", command=self.pause)
        game_menu.add_command(label="继续", command=self.resume)
        game_menu.add_separator()
        game_menu.add_command(label="退出", command=self.root.quit)

        help_menu = Menu(menubar, tearoff=0)
        menubar.add_cascade(label="帮助", menu=help_menu)
        help_menu.add_command(label="游戏帮助", command=self.show_help)

        # 历史记录菜单
        history_menu = Menu(menubar, tearoff=0)
        history_menu.add_command(label="查看历史记录", command=self.show_history)
        menubar.add_cascade(label="历史记录", menu=history_menu)

        # 查看菜单
        view_menu = Menu(menubar, tearoff=0)
        view_menu.add_command(label="查看日期", command=self.show_date)
        view_menu.add_command(label="查看开发者", command=self.show_developer)
        menubar.add_cascade(label="查看", menu=view_menu)

        # 修改菜单
        edit_menu = Menu(menubar, tearoff=0)

        # 修改主题子菜单
        theme_menu = Menu(edit_menu, tearoff=0)
        style = ttk.Style()
        theme_names = style.theme_names()  # 以列表的形式返回多个主题名
        for theme_name in theme_names:
            theme_menu.add_command(label=theme_name, command=lambda t=theme_name: self.change_theme(t))
        edit_menu.add_cascade(label="修改主题", menu=theme_menu)

        # 修改窗口大小功能
        edit_menu.add_command(label="修改窗口大小", command=self.change_window_size)
        menubar.add_cascade(label="修改", menu=edit_menu)

    def change_theme(self, theme_name):
        style = ttk.Style()
        style.theme_use(theme_name)

    def change_window_size(self):
        size = simpledialog.askstring("设置窗口大小", "请输入窗口大小(如800x600):")
        if size:
            self.root.geometry(size)

    def create_food(self):
        if self.food:
            self.canvas.delete(self.food)
        x = random.randint(0, 29) * 20
        y = random.randint(0, 19) * 20
        self.food = self.canvas.create_rectangle(x, y, x 20, y 20, fill="red")

    def bind_keys(self):
        self.root.bind("<Up>", self.go_up)
        self.root.bind("<Down>", self.go_down)
        self.root.bind("<Left>", self.go_left)
        self.root.bind("<Right>", self.go_right)
        self.root.bind("<space>", self.pause_resume)
        self.root.bind("j", self.speed_up)

    def go_up(self, event):
        if self.direction != "Down":
            self.direction = "Up"

    def go_down(self, event):
        if self.direction != "Up":
            self.direction = "Down"

    def go_left(self, event):
        if self.direction != "Right":
            self.direction = "Left"

    def go_right(self, event):
        if self.direction != "Left":
            self.direction = "Right"

    def pause_resume(self, event):
        if self.running:
            self.pause()
        else:
            self.resume()

    def speed_up(self, event):
        if self.speed > 50:
            self.speed -= 50

    def pause(self):
        self.running = False

    def resume(self):
        self.running = True
        self.update()

    def show_help(self):
        messagebox.showinfo("游戏帮助", "这是一个贪吃蛇游戏。使用方向键来控制蛇的移动,吃到豆子增加分数和长度。避免撞到墙壁或蛇身。")

    def show_history(self):
        history_window = Toplevel(self.root)
        history_window.title("历史记录")
        history_window.geometry("320x420")
        
        history_text = Text(history_window, wrap="word")
        history_text.pack(expand=1, fill="both")
        
        for record in self.history:
            history_text.insert("end", record   "n")

    def show_date(self):
        current_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        messagebox.showinfo("当前日期和时间", current_date)

    def show_developer(self):
        messagebox.showinfo("开发者信息", "开发者: B站 优秀稳妥的小光")

    def update(self):
        if self.running:
            self.move_snake()
            self.check_collisions()
            self.check_food()
            self.root.after(self.speed, self.update)

    def move_snake(self):
        head_x, head_y = self.snake[0]
        if self.direction == "Up":
            new_head = (head_x, head_y - 20)
        elif self.direction == "Down":
            new_head = (head_x, head_y   20)
        elif self.direction == "Left":
            new_head = (head_x - 20, head_y)
        elif self.direction == "Right":
            new_head = (head_x   20, head_y)
        
        self.snake = [new_head]   self.snake[:-1]
        self.canvas.delete("snake")
        for segment in self.snake:
            self.canvas.create_rectangle(segment[0], segment[1], segment[0]   20, segment[1]   20, fill="green", tags="snake")

    def check_collisions(self):
        head_x, head_y = self.snake[0]
        if head_x < 0 or head_x >= 600 or head_y < 0 or head_y >= 400 or len(self.snake) != len(set(self.snake)):
            self.game_over()

    def check_food(self):
        if self.canvas.coords(self.food) == [self.snake[0][0], self.snake[0][1], self.snake[0][0]   20, self.snake[0][1]   20]:
            self.snake.append(self.snake[-1])
            self.score  = 1
            if self.score % 5 == 0:
                self.level  = 1
                self.speed -= 20
            self.create_food()

    def game_over(self):
        self.running = False
        messagebox.showinfo("游戏结束", f"你的得分是 {self.score}")
        self.root.quit()

if __name__ == "__main__":
    root = ttk.Window(themename="cosmo")
    game = SnakeGame(root)
    root.mainloop()
主要功能详解
界面和菜单

我们使用了ttkbootstrap来创建美观的界面和菜单。菜单栏包含了游戏控制、查看信息、修改主题等功能。以下是创建菜单的代码:

代码语言:javascript复制
def create_menu(self):
    menubar = Menu(self.root)
    self.root.config(menu=menubar)

    game_menu = Menu(menubar, tearoff=0)
    menubar.add_cascade(label="游戏", menu=game_menu)
    game_menu.add_command(label="暂停", command=self.pause)
    game_menu.add_command(label="继续", command=self.resume)
    game_menu.add_separator()
    game_menu.add_command(label="退出", command=self.root.quit)

    help_menu = Menu(menubar, tearoff=0)
    menubar.add_cascade(label="帮助", menu=help_menu)
    help_menu.add_command(label="游戏帮助", command=self.show_help)

    # 历史记录菜单
    history_menu = Menu(menubar, tearoff=0)
    history_menu.add_command(label="查看历史记录", command=self.show_history)
    menubar.add_cascade(label="历史记录", menu=history_menu)

    # 查看菜单
    view_menu = Menu(menubar, tearoff=0)
    view_menu.add_command(label="查看日期", command=self.show_date)
    view_menu.add_command(label="查看开发者", command=self.show_developer)
    menubar.add_cascade(label="查看", menu=view_menu)

    # 修改菜单
    edit_menu = Menu(menubar, tearoff=0)

    # 修改主题子菜单
    theme_menu = Menu(edit_menu, tearoff=0)
    style = ttk.Style()
    theme_names = style.theme_names()  # 以列表的形式返回多个主题名
    for theme_name in theme_names:
        theme_menu.add_command(label=theme_name, command=lambda t=theme_name: self.change_theme(t))
    edit_menu.add_cascade(label="修改主题", menu=theme_menu)

    # 修改窗口大小功能
    edit_menu.add_command(label="修改窗口大小", command=self.change_window_size)
    menubar.add_cascade(label="修改", menu=edit_menu)
控制蛇的移动

通过绑定键盘事件来控制蛇的移动方向:

代码语言:javascript复制
def bind_keys(self):
    self.root.bind("<Up>", self.go_up)
    self.root.bind("<Down>", self.go_down)
    self.root.bind("<Left>", self.go_left)
    self.root.bind("<Right>", self.go_right)
    self.root.bind("<space>", self.pause_resume)
    self.root.bind("j", self.speed_up)
食物生成和碰撞检测

在游戏中,蛇需要不断地吃到食物来增加长度。以下是生成食物和检测碰撞的代码:

代码语言:javascript复制
def create_food(self):
    if self.food:
        self.canvas.delete(self.food)
    x = random.randint(0, 29) * 20
    y = random.randint(0, 19) * 20
    self.food = self.canvas.create_rectangle(x, y, x 20, y 20, fill="red")

def check_food(self):
    if self.canvas.coords(self.food) == [self.snake[0][0], self.snake[0][1], self.snake[0][0]   20, self.snake[0][1]   20]:
        self.snake.append(self.snake[-1])
        self.score  = 1
        if self.score % 5 == 0:
            self.level  = 1
            self.speed -= 20
        self.create_food()
游戏结束

当蛇撞到墙壁或自身时,游戏结束:

代码语言:javascript复制
def game_over(self):
    self.running = False
    messagebox.showinfo("游戏结束", f"你的得分是 {self.score}")
    self.root.quit()
运行游戏

将上述代码保存为一个Python文件并运行,即可开始玩贪吃蛇游戏。通过菜单栏可以进行暂停、继续、退出等操作,也可以查看历史记录、当前日期和开发者信息等。

总结

通过本项目,我们不仅实现了一个功能完整的贪吃蛇游戏,还学会了如何使用ttkbootstrap来美化界面。希望这个项目对你有所帮助,享受编程的乐趣吧!

0 人点赞