parent
e7d594fbdb
commit
ecdc84e44a
@ -0,0 +1,256 @@
|
||||
import pygame
|
||||
import random
|
||||
import os
|
||||
|
||||
# 初始化 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()
|
||||
|
||||
# 加载胜利动画帧
|
||||
frames = []
|
||||
frame_folder = "frames" # 确保这个文件夹存在并包含PNG图片
|
||||
if os.path.exists(frame_folder):
|
||||
for frame_file in sorted(os.listdir(frame_folder)):
|
||||
if frame_file.endswith(".png"):
|
||||
frame = pygame.image.load(os.path.join(frame_folder, frame_file))
|
||||
# 等比例缩放帧图片
|
||||
frame_width, frame_height = frame.get_size()
|
||||
scale_factor = min(window_width / frame_width, window_height / frame_height) * 0.8 # 缩小一点以便显示文字
|
||||
scaled_frame = pygame.transform.scale(frame,
|
||||
(int(frame_width * scale_factor), int(frame_height * scale_factor)))
|
||||
frames.append(scaled_frame)
|
||||
else:
|
||||
print(f"警告: 文件夹 '{frame_folder}' 不存在,将不显示胜利动画")
|
||||
|
||||
# 设置字体(使用支持中文的字体文件)
|
||||
try:
|
||||
font_path = "c:/Windows/Fonts/simhei.ttf" # 替换为你的中文字体文件路径
|
||||
font = pygame.font.Font(font_path, 36) # 使用中文字体,字号 36
|
||||
except:
|
||||
print("无法加载指定字体,使用默认字体")
|
||||
font = pygame.font.Font(None, 36) # 使用默认字体
|
||||
|
||||
|
||||
# 生成随机迷宫
|
||||
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
|
||||
|
||||
# 游戏状态
|
||||
game_state = "playing" # "playing", "victory"
|
||||
current_frame = 0
|
||||
victory_time = 0
|
||||
|
||||
# 主循环
|
||||
running = True
|
||||
while running:
|
||||
# 处理事件
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT: # 检测窗口关闭事件
|
||||
running = False
|
||||
elif event.type == pygame.KEYDOWN and game_state == "victory":
|
||||
if event.key == pygame.K_RETURN: # 按回车键重新开始游戏
|
||||
game_state = "playing"
|
||||
maze = generate_maze(grid_width, grid_height)
|
||||
character = Character(0, 0)
|
||||
|
||||
# 游戏逻辑
|
||||
if game_state == "playing":
|
||||
# 检测键盘持续按下状态
|
||||
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)
|
||||
|
||||
# 检测是否到达出口
|
||||
exit_x = exit_grid_x * cell_size + cell_size // 2
|
||||
exit_y = exit_grid_y * cell_size + cell_size // 2
|
||||
if abs(character.x - exit_x) < cell_size // 2 and abs(character.y - exit_y) < cell_size // 2:
|
||||
print("胜利!")
|
||||
game_state = "victory"
|
||||
victory_time = pygame.time.get_ticks()
|
||||
current_frame = 0
|
||||
|
||||
# 清空屏幕
|
||||
window.fill(WHITE)
|
||||
|
||||
if game_state == "playing":
|
||||
# 绘制迷宫
|
||||
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)
|
||||
|
||||
elif game_state == "victory":
|
||||
# 绘制胜利动画
|
||||
if frames: # 如果有加载动画帧
|
||||
# 将帧居中显示
|
||||
frame_width, frame_height = frames[current_frame].get_size()
|
||||
x = (window_width - frame_width) // 2
|
||||
y = (window_height - frame_height) // 2
|
||||
window.blit(frames[current_frame], (x, y))
|
||||
|
||||
# 更新帧索引
|
||||
if pygame.time.get_ticks() - victory_time > 100: # 每100毫秒更新一次帧
|
||||
current_frame = (current_frame + 1) % len(frames)
|
||||
victory_time = pygame.time.get_ticks()
|
||||
|
||||
# 绘制胜利文字
|
||||
victory_text = font.render("胜利!", True, (255, 0, 0)) # 红色文字
|
||||
text_rect = victory_text.get_rect(center=(window_width // 2, window_height - 50))
|
||||
window.blit(victory_text, text_rect)
|
||||
|
||||
# 绘制提示文字
|
||||
restart_text = font.render("按回车键重新开始", True, (0, 0, 0)) # 黑色文字
|
||||
restart_rect = restart_text.get_rect(center=(window_width // 2, window_height - 20))
|
||||
window.blit(restart_text, restart_rect)
|
||||
|
||||
# 更新屏幕
|
||||
pygame.display.flip()
|
||||
|
||||
# 控制帧率
|
||||
clock.tick(60)
|
||||
|
||||
# 退出 Pygame
|
||||
pygame.quit()
|
Loading…
Reference in new issue