You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
5.8 KiB
190 lines
5.8 KiB
import pygame
|
|
import random
|
|
|
|
# 初始化 Pygame
|
|
pygame.init()
|
|
|
|
# 设置窗口尺寸
|
|
cell_size = 20 # 单元格大小
|
|
grid_width = 30 # 网格宽度
|
|
grid_height = 20 # 网格高度
|
|
window_width = grid_width * cell_size
|
|
window_height = grid_height * cell_size
|
|
window = pygame.display.set_mode((window_width, window_height))
|
|
pygame.display.set_caption("迷宫游戏")
|
|
|
|
# 设置颜色
|
|
WHITE = (255, 255, 255)
|
|
BLACK = (0, 0, 0)
|
|
RED = (255, 0, 0)
|
|
GREEN = (0, 255, 0)
|
|
|
|
# 设置时钟
|
|
clock = pygame.time.Clock()
|
|
|
|
|
|
# 生成随机迷宫
|
|
def generate_maze(width, height):
|
|
# 初始化迷宫,所有单元格都是墙壁
|
|
maze = [[1 for _ in range(width)] for _ in range(height)]
|
|
|
|
# 确保入口和出口是通道
|
|
maze[0][0] = 0
|
|
maze[height - 1][width - 1] = 0
|
|
|
|
# 使用深度优先搜索生成迷宫
|
|
def carve_passages(x, y):
|
|
# 随机选择方向
|
|
directions = [(0, 2), (2, 0), (0, -2), (-2, 0)]
|
|
random.shuffle(directions)
|
|
|
|
for dx, dy in directions:
|
|
nx, ny = x + dx, y + dy
|
|
|
|
# 检查是否在边界内
|
|
if 0 <= nx < width and 0 <= ny < height:
|
|
# 如果目标单元格是墙壁
|
|
if maze[ny][nx] == 1:
|
|
# 打通墙壁
|
|
maze[ny][nx] = 0
|
|
# 打通中间的墙壁
|
|
maze[y + dy // 2][x + dx // 2] = 0
|
|
# 递归处理下一个单元格
|
|
carve_passages(nx, ny)
|
|
|
|
# 从入口开始生成迷宫
|
|
carve_passages(0, 0)
|
|
|
|
# 确保出口附近有通道
|
|
maze[height - 2][width - 1] = 0
|
|
maze[height - 1][width - 2] = 0
|
|
|
|
return maze
|
|
|
|
|
|
# 生成迷宫
|
|
maze = generate_maze(grid_width, grid_height)
|
|
|
|
|
|
# 定义小人类
|
|
class Character:
|
|
def __init__(self, grid_x, grid_y):
|
|
self.grid_x = grid_x # 小人的网格 x 坐标
|
|
self.grid_y = grid_y # 小人的网格 y 坐标
|
|
self.x = grid_x * cell_size + cell_size // 2 # 小人的像素 x 坐标
|
|
self.y = grid_y * cell_size + cell_size // 2 # 小人的像素 y 坐标
|
|
self.radius = cell_size // 3 - 1 # 稍微减小半径,避免卡住
|
|
self.speed = 3 # 移动速度
|
|
self.collision_margin = 2 # 碰撞检测的边缘余量,减小这个值可以让小球更容易通过狭窄通道
|
|
|
|
def move(self, dx, dy):
|
|
# 计算目标位置
|
|
new_x = self.x + dx
|
|
new_y = self.y + dy
|
|
|
|
# 检测是否与墙壁碰撞
|
|
if self.will_collide(new_x, new_y):
|
|
# 尝试单独移动 X 或 Y 方向
|
|
if dx != 0 and not self.will_collide(new_x, self.y):
|
|
new_y = self.y # 只移动 X 方向
|
|
elif dy != 0 and not self.will_collide(self.x, new_y):
|
|
new_x = self.x # 只移动 Y 方向
|
|
else:
|
|
return # 两个方向都不能移动
|
|
|
|
# 更新位置
|
|
self.x = new_x
|
|
self.y = new_y
|
|
self.grid_x = self.x // cell_size
|
|
self.grid_y = self.y // cell_size
|
|
|
|
def will_collide(self, x, y):
|
|
# 计算碰撞检测的实际半径
|
|
collision_radius = self.radius - self.collision_margin
|
|
|
|
# 检测小球是否会与墙壁碰撞
|
|
# 计算小球边缘的四个点
|
|
points = [
|
|
(x - collision_radius, y), # 左
|
|
(x + collision_radius, y), # 右
|
|
(x, y - collision_radius), # 上
|
|
(x, y + collision_radius) # 下
|
|
]
|
|
|
|
# 检测每个点是否在墙壁内
|
|
for px, py in points:
|
|
# 计算点所在的网格位置
|
|
grid_x = int(px // cell_size)
|
|
grid_y = int(py // cell_size)
|
|
|
|
# 检测是否超出边界
|
|
if grid_x < 0 or grid_x >= grid_width or grid_y < 0 or grid_y >= grid_height:
|
|
return True
|
|
|
|
# 检测是否与墙壁碰撞
|
|
if maze[grid_y][grid_x] == 1:
|
|
return True
|
|
|
|
return False
|
|
|
|
def draw(self, window):
|
|
# 绘制小人(红色小球)
|
|
pygame.draw.circle(window, RED, (self.x, self.y), self.radius)
|
|
|
|
|
|
# 创建小人对象(初始位置在左上角)
|
|
character = Character(0, 0)
|
|
|
|
# 设置出口位置
|
|
exit_grid_x = grid_width - 1
|
|
exit_grid_y = grid_height - 1
|
|
|
|
# 主循环
|
|
running = True
|
|
while running:
|
|
# 处理事件
|
|
for event in pygame.event.get():
|
|
if event.type == pygame.QUIT: # 检测窗口关闭事件
|
|
running = False
|
|
|
|
# 检测键盘持续按下状态
|
|
keys = pygame.key.get_pressed()
|
|
if keys[pygame.K_UP]: # 按下上箭头键
|
|
character.move(0, -character.speed)
|
|
if keys[pygame.K_DOWN]: # 按下下箭头键
|
|
character.move(0, character.speed)
|
|
if keys[pygame.K_LEFT]: # 按下左箭头键
|
|
character.move(-character.speed, 0)
|
|
if keys[pygame.K_RIGHT]: # 按下右箭头键
|
|
character.move(character.speed, 0)
|
|
|
|
# 清空屏幕
|
|
window.fill(WHITE)
|
|
|
|
# 绘制迷宫
|
|
for i in range(grid_height):
|
|
for j in range(grid_width):
|
|
if maze[i][j] == 1: # 绘制墙壁
|
|
pygame.draw.rect(window, BLACK, (j * cell_size, i * cell_size, cell_size, cell_size))
|
|
|
|
# 绘制出口
|
|
exit_x = exit_grid_x * cell_size + cell_size // 2
|
|
exit_y = exit_grid_y * cell_size + cell_size // 2
|
|
pygame.draw.circle(window, GREEN, (exit_x, exit_y), cell_size // 3)
|
|
|
|
# 绘制小人
|
|
character.draw(window)
|
|
|
|
# 检测是否到达出口
|
|
if abs(character.x - exit_x) < cell_size // 2 and abs(character.y - exit_y) < cell_size // 2:
|
|
print("胜利!")
|
|
running = False
|
|
|
|
# 更新屏幕
|
|
pygame.display.flip()
|
|
|
|
# 控制帧率
|
|
clock.tick(60)
|
|
|
|
# 退出 Pygame
|
|
pygame.quit() |