1. 简介
贪吃蛇是一款非常经典的游戏,玩家需要操控蛇吃食物,并且随着吃的食物越来越多,蛇的身体也会越来越长。本篇文章将介绍如何使用Python实现一个经典的贪吃蛇游戏,并且增加双人对战的功能,让游戏更加有趣。
2. 游戏规则
首先,我们需要了解贪吃蛇游戏的基本规则。在游戏中,有一个蛇和一些食物。蛇的初始长度为1个单位,每当蛇吃到一个食物,它的长度就会加1个单位。玩家需要控制蛇向上、向下、向左或向右移动,如果蛇的头部碰到了墙壁或者蛇的身体,游戏就结束了。
2.1 单人模式
在单人模式下,游戏只有一个玩家操控一条蛇,游戏流程如下:
随机将食物放置在游戏地图上。
玩家操作蛇进行移动,如果蛇吃到了食物,则蛇的长度加1。
如果蛇的头部碰到了墙壁或者蛇的身体,游戏就结束了。
当游戏结束时,显示玩家得分。
2.2 双人模式
在双人模式下,两个玩家分别操控一条蛇,游戏流程如下:
随机将食物放置在游戏地图上。
玩家1操控蛇1移动,如果蛇1吃到了食物,则蛇1的长度加1。
玩家2操控蛇2移动,如果蛇2吃到了食物,则蛇2的长度加1。
如果蛇1的头部碰到了蛇2的身体或蛇2的头部碰到了蛇1的身体,游戏就结束了。
如果蛇1的头部碰到了墙壁或者蛇1的身体,玩家2获胜,游戏结束。
如果蛇2的头部碰到了墙壁或者蛇2的身体,玩家1获胜,游戏结束。
当游戏结束时,显示双方得分。
3. 开始编写代码
了解了游戏规则之后,我们可以开始编写代码实现贪吃蛇游戏了。首先需要安装Pygame库,它是Python编写游戏的常用库。
pip install pygame
3.1 创建游戏窗口
我们可以使用Pygame来创建一个游戏窗口,并且设置窗口的大小和标题。
import pygame
# 定义窗口大小
WIDTH, HEIGHT = 640, 480
# 初始化游戏
pygame.init()
# 创建游戏窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
# 设置窗口标题
pygame.display.set_caption("贪吃蛇双人大战")
上述代码中,我们导入了Pygame库,并且定义了窗口的宽度和高度。然后我们初始化游戏,创建了一个游戏窗口,并设置了窗口标题为“贪吃蛇双人大战”。接下来我们需要在游戏循环中实现游戏的各种逻辑。
3.2 创建游戏地图和蛇
接下来我们需要创建游戏地图和两条蛇,并且将食物随机放置在地图上。
import pygame
import random
# 定义窗口大小
WIDTH, HEIGHT = 640, 480
# 定义游戏地图大小和格子大小
MAP_WIDTH, MAP_HEIGHT = 600, 440
CELL_SIZE = 20
# 定义颜色常量
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
# 初始化游戏
pygame.init()
# 创建游戏窗口
screen = pygame.display.set_mode((WIDTH, HEIGHT))
# 设置窗口标题
pygame.display.set_caption("贪吃蛇双人大战")
# 创建游戏地图
map_surface = pygame.Surface((MAP_WIDTH, MAP_HEIGHT))
map_surface.fill(WHITE)
# 随机放置食物
food_pos = (random.randint(0, MAP_WIDTH // CELL_SIZE - 1) * CELL_SIZE,
random.randint(0, MAP_HEIGHT // CELL_SIZE - 1) * CELL_SIZE)
# 创建蛇
snake1 = Snake(GREEN, (MAP_WIDTH // CELL_SIZE // 4 * CELL_SIZE, MAP_HEIGHT // 2))
snake2 = Snake(RED, (MAP_WIDTH // CELL_SIZE // 4 * CELL_SIZE * 3, MAP_HEIGHT // 2))
上述代码中,我们定义了游戏地图的大小和格子大小,并且创建了一个游戏地图的Surface,并将它填充为白色。我们随机放置了一个食物,使用了Python的random模块将食物放在地图上的一个随机位置。然后我们创建了两条蛇,一条是绿色的,另一条是红色的,并且将它们初始放置在地图上的中心点位置。
3.3 实现蛇的移动
接下来,我们要实现蛇的移动。在每个游戏循环中,我们需要根据键盘的输入修改蛇的移动方向,并且在新的位置上绘制蛇的身体。我们还需要检查蛇是否吃到了食物,并且根据蛇的长度创建新的食物。
# 游戏循环
clock = pygame.time.Clock()
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:
snake1.change_direction("UP")
elif event.key == pygame.K_DOWN:
snake1.change_direction("DOWN")
elif event.key == pygame.K_LEFT:
snake1.change_direction("LEFT")
elif event.key == pygame.K_RIGHT:
snake1.change_direction("RIGHT")
elif event.key == pygame.K_w:
snake2.change_direction("UP")
elif event.key == pygame.K_s:
snake2.change_direction("DOWN")
elif event.key == pygame.K_a:
snake2.change_direction("LEFT")
elif event.key == pygame.K_d:
snake2.change_direction("RIGHT")
# 清空屏幕
screen.fill(BLACK)
# 绘制游戏地图
map_surface.fill(WHITE)
for x in range(0, MAP_WIDTH, CELL_SIZE):
for y in range(0, MAP_HEIGHT, CELL_SIZE):
pygame.draw.rect(map_surface, BLACK, (x, y, CELL_SIZE, CELL_SIZE), 1)
# 绘制食物
pygame.draw.rect(map_surface, GREEN, (food_pos[0], food_pos[1], CELL_SIZE, CELL_SIZE))
# 移动蛇
snake1.move()
snake2.move()
# 绘制蛇和得分
for snake in [snake1, snake2]:
for idx, pos in enumerate(snake.body):
color = snake.color
if idx == 0:
color = (255, 255, 255)
pygame.draw.rect(map_surface, color, (pos[0], pos[1], CELL_SIZE, CELL_SIZE))
# 检查是否吃到食物
if snake.body[0] == food_pos:
snake.eat(food_pos)
food_pos = (random.randint(0, MAP_WIDTH // CELL_SIZE - 1) * CELL_SIZE,
random.randint(0, MAP_HEIGHT // CELL_SIZE - 1) * CELL_SIZE)
# 检查是否碰到墙壁和蛇身体
if snake.is_dead(MAP_WIDTH, MAP_HEIGHT):
if snake == snake1:
print("玩家2获胜!")
else:
print("玩家1获胜!")
pygame.quit()
sys.exit()
# 将游戏地图添加到窗口上
screen.blit(map_surface, (20, 20))
# 更新窗口
pygame.display.update()
# 控制游戏帧率
clock.tick(10)
3.4 实现双人对战
在上述代码中,我们实现了蛇的移动以及碰撞检测,但是还没有实现双人对战的规则。我们需要修改蛇的移动方向判断和碰撞检测的条件,在检测到蛇的头部碰到对手的身体时,游戏结束。
class Snake:
def __init__(self, color, pos):
self.color = color
self.dir = [CELL_SIZE, 0]
self.body = [pos]
def move(self):
for i in range(len(self.body) - 1, 0, -1):
self.body[i] = self.body[i - 1]
self.body[0] = (self.body[0][0] + self.dir[0], self.body[0][1] + self.dir[1])
def change_direction(self, direction):
if direction == "UP" and self.dir[1] != CELL_SIZE:
self.dir = [0, -CELL_SIZE]
elif direction == "DOWN" and self.dir[1] != -CELL_SIZE:
self.dir = [0, CELL_SIZE]
elif direction == "LEFT" and self.dir[0] != CELL_SIZE:
self.dir = [-CELL_SIZE, 0]
elif direction == "RIGHT" and self.dir[0] != -CELL_SIZE:
self.dir = [CELL_SIZE, 0]
def eat(self, food_pos):
self.body.insert(0, food_pos)
def is_dead(self, map_width, map_height, opponent_body=None):
if self.body[0][0] < 0 or self.body[0][0] >= map_width \
or self.body[0][1] < 0 or self.body[0][1] >= map_height:
return True
if opponent_body is not None and self.body[0] in opponent_body:
return True
for pos in self.body[1:]:
if pos == self.body[0]:
return True
return False
在蛇的类中,我们增加了一个新的参数opponent_body,用于保存对手的身体坐标。如果蛇的头部碰到了对手的身体,is_dead方法需要返回True。
我们还需要在游戏循环中获取对手的身体坐标,并且在每次检测碰撞时传递给is_dead方法。
# 游戏循环
clock = pygame.time.Clock()
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:
snake1.change_direction("UP")
elif event.key == pygame.K_DOWN:
snake1.change_direction("DOWN")
elif event.key == pygame.K_LEFT:
snake1.change_direction("LEFT")
elif event.key == pygame.K_RIGHT:
snake1.change_direction("RIGHT")
elif event.key == pygame.K_w:
snake2.change_direction("UP")
elif event.key == pygame.K_s:
snake2.change_direction("DOWN")
elif event.key == pygame.K_a:
snake2.change_direction("LEFT")
elif event.key == pygame.K_d:
snake2.change_direction("RIGHT")
# 清空屏幕
screen.fill(BLACK)
# 绘制游戏地图
map_surface.fill(WHITE)
for x in range(0, MAP_WIDTH, CELL_SIZE):
for y in range(0, MAP_HEIGHT, CELL_SIZE):
pygame.draw.rect(map_surface, BLACK, (x, y, CELL_SIZE, CELL_SIZE), 1)
# 绘制食物
pygame.draw.rect(map_surface, GREEN, (food_pos[0], food_pos[1], CELL_SIZE, CELL_SIZE))
# 移动蛇
snake1.move()
snake2.move()
# 绘制蛇和得分
for snake in [snake1, snake2]:
for idx, pos in enumerate(snake.body):
color = snake.color
if idx == 0:
color = (255, 255, 255)
pygame.draw.rect(map_surface, color, (pos[0], pos[1], CELL_SIZE, CELL_SIZE))
# 检查是否吃到食物
if snake.body[0] == food_pos:
snake.eat(food_pos)
food_pos = (random.randint(0, MAP_WIDTH // CELL_SIZE - 1) * CELL_SIZE,
random.randint(0, MAP_HEIGHT // CELL_SIZE - 1) * CELL_SIZE)
# 检查是否碰到墙壁和蛇身体
opponent_body = snake2.body if snake == snake1 else snake1.body
if snake.is_dead(MAP_WIDTH, MAP_HEIGHT, opponent_body):
if snake == snake1:
print("玩家2获胜!")
else:
print("玩家1获胜!")
pygame.quit()
sys.exit()
# 将游戏地图添加到窗口上
screen.blit(map_surface, (20, 20))
# 更新窗口
pygame.display.update()
# 控制游戏帧率
clock.tick(10)
4. 总结
本篇文章中,我们使用Python实现了一个经典的贪吃蛇游戏,并且增加了双人对战的功能。我们介绍了贪吃蛇游戏的基本规则,创建了游戏窗口和游戏地图,并且实现了蛇的移动和吃食物的功能。最后,我们修改了碰撞检测的条件,使游戏可以进行双人对战,并且在游戏结束时显示得分。