贪吃蛇是一款经典的游戏,它操作简单但乐趣无穷,也是初学者练习编程的绝佳项目。在这篇博客中,我们将使用 Python 和 pygame 库开发一个完整的贪吃蛇游戏。通过这个项目,你可以学习到游戏开发的基础知识,比如事件处理、动画渲染和游戏逻辑设计。


1. 为什么选择 pygame

pygame 是一个基于 Python 的跨平台 2D 游戏开发库。它提供了游戏开发中常用的功能,比如处理键盘输入、绘制图形、播放音效等,非常适合构建小游戏。

安装 pygame

pip install pygame

2. 游戏设计思路

贪吃蛇的核心逻辑包括以下几点:

  1. 游戏界面:绘制蛇、食物和游戏背景。
  2. 蛇的移动:通过方向键控制蛇的移动。
  3. 食物逻辑:蛇吃到食物后,身体长度增加,分数也随之提升。
  4. 游戏结束:当蛇撞墙或碰到自己时,游戏结束。

3. 实现代码

3.1 基本游戏结构

首先,我们构建一个基本的游戏窗口。

import pygame
import sys

# 初始化 Pygame
pygame.init()

# 设置游戏窗口大小
WIDTH, HEIGHT = 600, 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("贪吃蛇游戏")

# 定义颜色
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)

# 游戏主循环
def main():
    clock = pygame.time.Clock()  # 控制游戏帧率

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        screen.fill(BLACK)  # 填充背景
        pygame.display.flip()  # 更新屏幕
        clock.tick(30)  # 每秒最多 30 帧

if __name__ == "__main__":
    main()

运行上述代码后,你会看到一个黑色窗口,这是我们游戏的基础界面。


3.2 绘制贪吃蛇和食物

接下来,我们在窗口中绘制贪吃蛇和食物。

import random

def draw_snake(snake_body):
    for block in snake_body:
        pygame.draw.rect(screen, GREEN, pygame.Rect(block[0], block[1], 20, 20))

def draw_food(food_position):
    pygame.draw.rect(screen, (255, 0, 0), pygame.Rect(food_position[0], food_position[1], 20, 20))

def main():
    clock = pygame.time.Clock()

    # 初始化蛇和食物
    snake_body = [[100, 50], [80, 50], [60, 50]]  # 初始蛇的身体
    snake_direction = "RIGHT"  # 初始方向
    change_to = snake_direction
    food_position = [random.randrange(1, (WIDTH // 20)) * 20,
                     random.randrange(1, (HEIGHT // 20)) * 20]
    food_spawn = True

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP and not snake_direction == "DOWN":
                    change_to = "UP"
                if event.key == pygame.K_DOWN and not snake_direction == "UP":
                    change_to = "DOWN"
                if event.key == pygame.K_LEFT and not snake_direction == "RIGHT":
                    change_to = "LEFT"
                if event.key == pygame.K_RIGHT and not snake_direction == "LEFT":
                    change_to = "RIGHT"

        # 更新蛇的方向
        snake_direction = change_to

        # 更新蛇头的位置
        if snake_direction == "UP":
            snake_body[0][1] -= 20
        if snake_direction == "DOWN":
            snake_body[0][1] += 20
        if snake_direction == "LEFT":
            snake_body[0][0] -= 20
        if snake_direction == "RIGHT":
            snake_body[0][0] += 20

        # 增加新头,移除尾巴
        snake_body.insert(0, list(snake_body[0]))
        if snake_body[0] == food_position:
            food_spawn = False
        else:
            snake_body.pop()

        if not food_spawn:
            food_position = [random.randrange(1, (WIDTH // 20)) * 20,
                             random.randrange(1, (HEIGHT // 20)) * 20]
        food_spawn = True

        # 绘制界面
        screen.fill(BLACK)
        draw_snake(snake_body)
        draw_food(food_position)
        pygame.display.flip()

        # 检测游戏结束条件
        if (snake_body[0][0] < 0 or snake_body[0][0] >= WIDTH or
            snake_body[0][1] < 0 or snake_body[0][1] >= HEIGHT):
            pygame.quit()
            sys.exit()

        clock.tick(10)

if __name__ == "__main__":
    main()

3.3 游戏逻辑优化

增加碰撞检测:

  • 如果蛇头碰到自己的身体,游戏结束。
# 检测是否撞到自己
if snake_body[0] in snake_body[1:]:
    pygame.quit()
    sys.exit()

显示分数:

  • 在屏幕上显示当前得分。
def show_score(score):
    font = pygame.font.SysFont("arial", 24)
    score_surface = font.render(f"Score: {score}", True, WHITE)
    screen.blit(score_surface, (10, 10))

# 在游戏主循环中调用
show_score(len(snake_body) - 3)

4. 游戏扩展功能

  1. 难度提升:随着得分增加,蛇的移动速度逐渐提高。
  2. 排行榜:记录玩家的最高得分。
  3. 主题切换:允许玩家切换不同的蛇和背景颜色。
  4. 多种模式:加入障碍物或限时模式。

5. 完整代码

以下是完整的贪吃蛇游戏代码:

import pygame
import random
import sys

# 初始化 Pygame
pygame.init()

# 设置窗口大小和颜色
WIDTH, HEIGHT = 600, 400
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
RED = (255, 0, 0)

# 初始化屏幕
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("贪吃蛇游戏")

def draw_snake(snake_body):
    for block in snake_body:
        pygame.draw.rect(screen, GREEN, pygame.Rect(block[0], block[1], 20, 20))

def draw_food(food_position):
    pygame.draw.rect(screen, RED, pygame.Rect(food_position[0], food_position[1], 20, 20))

def show_score(score):
    font = pygame.font.SysFont("arial", 24)
    score_surface = font.render(f"Score: {score}", True, WHITE)
    screen.blit(score_surface, (10, 10))

def main():
    clock = pygame.time.Clock()

    # 初始化蛇和食物
    snake_body = [[100, 50], [80, 50], [60, 50]]
    snake_direction = "RIGHT"
    change_to = snake_direction
    food_position = [random.randrange(1, (WIDTH // 20)) * 20,
                     random.randrange(1, (HEIGHT // 20)) * 20]
    food_spawn = True

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_UP and not snake_direction == "DOWN":
                    change_to = "UP"
                if event.key == pygame.K_DOWN and not snake_direction == "UP":
                    change_to = "DOWN"
                if event.key == pygame.K_LEFT and not snake_direction == "RIGHT":
                    change_to = "LEFT"
                if event.key == pygame.K_RIGHT and not snake_direction == "LEFT":
                    change_to = "RIGHT"

        snake_direction = change_to

        if snake_direction == "UP":
            snake_body[0][1] -= 20
        if snake_direction == "DOWN":
            snake_body[0][1] += 20
        if snake_direction == "LEFT":
            snake_body[0][0] -= 20
        if snake_direction == "RIGHT":
            snake_body[0][0] += 20

        snake_body.insert(0, list(snake_body[0]))
        if snake_body[0] == food_position:
            food_spawn = False
        else:
            snake_body.pop()

        if not food_spawn:
            food_position = [random.randrange(1, (WIDTH // 20)) * 20,
                             random.randrange(1, (HEIGHT // 20)) * 20]
        food_spawn = True

        screen.fill(BLACK)
        draw_snake(snake_body)
        draw_food(food_position)
        show_score(len(snake_body) - 3)

        if (snake_body[0][0] < 0 or snake_body[0][0] >= WIDTH or
            snake_body[0][1] < 0 or snake_body[0][1] >= HEIGHT or
            snake_body[0] in snake_body[1:]):
            pygame.quit()
            sys.exit()

        pygame.display.flip()
        clock.tick(10 + len(snake_body) // 5)

if __name__ == "__main__":
    main()

6. 总结

通过本文,我们从零开发了一个简单的贪吃蛇游戏,并逐步扩展了功能,如得分统计、速度变化和游戏结束条件。这是一个学习 Python 基础和游戏开发的绝佳项目。如果你感兴趣,可以继续扩展功能,比如增加关卡、音效或网络多人模式。

希望你喜欢这个项目!如果有任何问题或建议,欢迎在评论区留言讨论!🎮