为什么贪吃蛇就要上下左右移动,直接跟随鼠标移动不是更好

上代码

import pygame
import sys
import random
import math

# 初始化pygame
pygame.init()

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (213, 50, 80)
GREEN = (0, 255, 0)
BLUE = (50, 153, 213)
BUTTON_COLOR = (100, 100, 255)
BUTTON_HOVER_COLOR = (150, 150, 255)

# 屏幕设置
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('贪吃蛇游戏 - 可穿透自己版')

# 游戏时钟
clock = pygame.time.Clock()

# 蛇的参数
SNAKE_SIZE = 15
SNAKE_SPEED = 20

# 字体设置
font_small = pygame.font.SysFont("simhei", 25)
font_medium = pygame.font.SysFont("simhei", 35)
font_large = pygame.font.SysFont("simhei", 50)


# 按钮类
class Button:
    def __init__(self, x, y, width, height, text):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.is_hovered = False

    def draw(self, surface):
        color = BUTTON_HOVER_COLOR if self.is_hovered else BUTTON_COLOR
        pygame.draw.rect(surface, color, self.rect, border_radius=10)
        pygame.draw.rect(surface, BLACK, self.rect, 2, border_radius=10)

        text = font_medium.render(self.text, True, BLACK)
        text_rect = text.get_rect(center=self.rect.center)
        surface.blit(text, text_rect)

    def check_hover(self, pos):
        self.is_hovered = self.rect.collidepoint(pos)
        return self.is_hovered

    def is_clicked(self, pos, event):
        if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            return self.rect.collidepoint(pos)
        return False


# 显示分数
def show_score(score):
    score_text = font_medium.render(f"得分: {score}", True, BLACK)
    screen.blit(score_text, [10, 10])


# 绘制蛇
def draw_snake(snake_body):
    for i, segment in enumerate(snake_body):
        color = BLUE if i == 0 else GREEN  # 蛇头蓝色,身体绿色
        pygame.draw.rect(screen, color, [segment[0], segment[1], SNAKE_SIZE, SNAKE_SIZE])


# 显示消息
def show_message(text, color, y_offset=0, font=font_medium):
    msg = font.render(text, True, color)
    screen.blit(msg, [SCREEN_WIDTH // 2 - msg.get_width() // 2, SCREEN_HEIGHT // 3 + y_offset])


# 计算两点距离
def get_distance(x1, y1, x2, y2):
    return math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)


# 主菜单
def show_menu():
    start_button = Button(SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2, 200, 50, "开始游戏")

    while True:
        screen.fill(WHITE)
        mouse_pos = pygame.mouse.get_pos()

        # 显示标题
        title = font_large.render("贪吃蛇游戏", True, BLACK)
        screen.blit(title, [SCREEN_WIDTH // 2 - title.get_width() // 2, 100])

        # 显示游戏说明
        show_message("用鼠标控制蛇的移动", BLACK, -50, font_small)
        show_message("吃到红色食物增加长度", BLACK, -10, font_small)
        show_message("可以穿过自己的身体", BLACK, 30, font_small)

        # 更新按钮状态
        start_button.check_hover(mouse_pos)
        start_button.draw(screen)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if start_button.is_clicked(mouse_pos, event):
                return  # 开始游戏

        pygame.display.update()
        clock.tick(60)


# 游戏主循环
def game_loop():
    game_active = True

    # 初始化蛇的位置
    snake_x = SCREEN_WIDTH // 2
    snake_y = SCREEN_HEIGHT // 2

    # 蛇的身体
    snake_body = []
    snake_length = 1

    # 食物位置
    food_x = round(random.randrange(0, SCREEN_WIDTH - SNAKE_SIZE) / SNAKE_SIZE) * SNAKE_SIZE
    food_y = round(random.randrange(0, SCREEN_HEIGHT - SNAKE_SIZE) / SNAKE_SIZE) * SNAKE_SIZE

    while game_active:
        mouse_pos = pygame.mouse.get_pos()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    return  # 返回菜单

        # 计算蛇向鼠标移动的方向
        dx = mouse_pos[0] - snake_x
        dy = mouse_pos[1] - snake_y
        dist = get_distance(snake_x, snake_y, mouse_pos[0], mouse_pos[1])

        if dist > 5:  # 如果距离够远才移动
            # 标准化方向向量
            dx /= dist
            dy /= dist

            # 更新蛇头位置
            snake_x += dx * SNAKE_SIZE * 0.5
            snake_y += dy * SNAKE_SIZE * 0.5

            # 确保不会超出屏幕
            snake_x = max(0, min(SCREEN_WIDTH - SNAKE_SIZE, snake_x))
            snake_y = max(0, min(SCREEN_HEIGHT - SNAKE_SIZE, snake_y))

        # 更新蛇身
        snake_head = [snake_x, snake_y]
        snake_body.append(snake_head)

        if len(snake_body) > snake_length:
            del snake_body[0]


        # 绘制游戏
        screen.fill(WHITE)

        # 绘制食物
        pygame.draw.rect(screen, RED, [food_x, food_y, SNAKE_SIZE, SNAKE_SIZE])

        # 绘制蛇
        draw_snake(snake_body)

        # 显示分数
        show_score(snake_length - 1)

        pygame.display.update()

        # 检查是否吃到食物
        if (abs(snake_x - food_x) < SNAKE_SIZE and abs(snake_y - food_y) < SNAKE_SIZE):
            food_x = round(random.randrange(0, SCREEN_WIDTH - SNAKE_SIZE) / SNAKE_SIZE) * SNAKE_SIZE
            food_y = round(random.randrange(0, SCREEN_HEIGHT - SNAKE_SIZE) / SNAKE_SIZE) * SNAKE_SIZE
            snake_length += 1

            clock.tick(SNAKE_SPEED)

        # 游戏结束画面
    while not game_active:
        screen.fill(WHITE)
        show_message("游戏结束!", RED, -50, font_large)
        show_message(f"得分: {snake_length - 1}", BLACK, 0)
        show_message("按ESC键返回主菜单", BLACK, 50)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    return

        pygame.display.update()
        clock.tick(60)


# 游戏主循环
while True:
    show_menu()
    game_loop()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大家一起学编程(python)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值