From 74ded43dd5dc2f9d66c50510168411971fc5f07f Mon Sep 17 00:00:00 2001 From: pa3r2yevq <2602324141@qq.com> Date: Tue, 2 Jan 2024 11:57:54 +0800 Subject: [PATCH] ADD file via upload --- tuixiangzi.py | 347 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 tuixiangzi.py diff --git a/tuixiangzi.py b/tuixiangzi.py new file mode 100644 index 0000000..62533f7 --- /dev/null +++ b/tuixiangzi.py @@ -0,0 +1,347 @@ +import pgzrun +from pgzero.actor import Actor +from pgzero.clock import clock +from pgzero.loaders import sounds + + +GRID_SIZE = 48 # 格子尺寸 +WIDTH = GRID_SIZE * 11 # 屏幕宽度 +HEIGHT = GRID_SIZE * 9 # 屏幕高度 +size=WIDTH,HEIGHT + + + +level = 1 # 游戏关卡值 +level_images=[] #关卡图片 +level_complete = False # 游戏过关标记 +MAX_LEVEl = 3 +game_over = False +display_game_over = False +start=False#开始游戏按钮 +level_num_flag=False#选关窗口判定 + +ui_game_over = Actor("pushbox_game_over",(WIDTH//2,HEIGHT//2)) + +# 方向字典,存储各方向对应的坐标偏移值 +dirs = {"right":(1, 0), "left":(-1, 0), + "up":(0, -1), "down":(0, 1), "none":(0, 0)} + +# 游戏界面元素 +ui_level_up = Actor("pushbox_level_up", (WIDTH//2, HEIGHT//2)) +#开始界面 +gui_background_image=Actor("gui_background",topleft=(0,0)) +btn_start_game=Actor("start",(WIDTH-290, HEIGHT-160)) +btn_exit_game=Actor("finish",(WIDTH-275,HEIGHT-60)) +#绘制关卡 +for i in range(3): + level_image=Actor("level"+str(i + 1), (0, HEIGHT // 2 + 80 * i)) + level_images.append(level_image) + +# 从文件读取地图数据 +def load_map(map_file): + map_array =[] + with open(map_file, "r") as map_file: + lines = map_file.readlines() + for line in lines: + line = line.replace(" ", "") # 去掉空格 + line = line.split(",") # 将文本行转换为字符列表 + line = list(map(int, line)) # 将字符转化成整数 + map_array.append(line) + return map_array + + +# 初始化地图,生成游戏角色 +def setup_screen(mapdata): + global walls, floors, boxes, targets, player + walls = [] # 墙壁列表 + floors= [] # 地板列表 + boxes = [] # 箱子列表 + targets = [] # 目标点列表 + for row in range(len(mapdata)): + for col in range(len(mapdata[row])): + x = col * GRID_SIZE + y = row * GRID_SIZE + floors.append(Actor("pushbox_floor", topleft=(x, y))) + if mapdata[row][col] == 1: + walls.append(Actor("pushbox_wall", topleft=(x, y))) + elif mapdata[row][col] == 2: + box = Actor("pushbox_box", topleft=(x, y)) + box.placed = False + boxes.append(box) + elif mapdata[row][col] == 3: + player = Actor("pushbox_down", topleft=(x, y)) + elif mapdata[row][col] == 4: + targets.append(Actor("pushbox_target", topleft=(x, y))) + elif mapdata[row][col] == 6: + targets.append(Actor("pushbox_target", topleft=(x, y))) + box = Actor("pushbox_box_hit", topleft=(x, y)) + box.placed = True + boxes.append(box) + + +# 加载地图,初始化关卡 +def setup_level(level): + if level<=0: + return + mapdata = load_map("maps/map" + str(level) + ".txt") + setup_screen(mapdata) + + +# 处理键盘按下事件 +def on_key_down(key): + if level_complete or game_over: + return + if key==keys.C: + undo() + return + if key == keys.O: + setup_level(level) + return + if key == keys.RIGHT: + player.direction = "right" + player.image = "pushbox_right" + elif key == keys.LEFT: + player.direction = "left" + player.image = "pushbox_left" + elif key == keys.DOWN: + player.direction = "down" + player.image = "pushbox_down" + elif key == keys.UP: + player.direction = "up" + player.image = "pushbox_up" + else: + player.direction = "none" + player_move() + player_collision() + +#按钮点击 +def on_mouse_down(pos): + global start,level_num_flag,level + if btn_start_game.collidepoint(pos): + start=True + level_num_flag = True + elif btn_exit_game.collidepoint(pos): + exit() + else: + for i in range(len(level_images)): + if level_images[i].collidepoint(pos) and level_num_flag and level: + if i == 0: + level_num1() + setup_level(level) + if i == 1: + level_num2() + setup_level(level) + elif i == 2: + level_num3() + setup_level(level) + level_num_flag = False + + +#游戏关卡绘制 +level_image_bg=Actor("gui_background",topleft=(0,0)) +def level_draw(): + level_image_bg.draw() +#关卡1、2、3 +def level_num1(): + global level + level = 1 +def level_num2(): + global level + level = 2 +def level_num3(): + global level + level = 3 + +# 移动玩家角色 +moves=[] +box_moves = [] +def player_move(): + player.oldx = player.x + player.oldy = player.y + if player.direction is None: + dx, dy = 0, 0 + else: + dx, dy = dirs[player.direction] + player.x += dx * GRID_SIZE + player.y += dy * GRID_SIZE + moves.append((player.direction, -dx * GRID_SIZE, -dy * GRID_SIZE)) + # 记录箱子移动前的位置 + for box in boxes: + box.oldx = box.x + box.oldy = box.y + +# 撤销最后一次移动操作 +def undo(): + global moves, box_moves, boxes + if moves: + last_move = moves.pop() + direction, dx, dy = last_move + player.direction = opposite_dir(direction) + player.x += dx + player.y += dy + player_collision() # 处理碰撞 + # 检查是否有箱子的移动记录,如果有,则撤销箱子的移动 + if box_moves: + last_box_move = box_moves.pop() + box,bx, by = last_box_move + box.x += bx + box.y += by + box_collision(box) # 重新处理箱子碰撞 +# 获取相反的方向 +def opposite_dir(direction): + if direction == "right": + return "left" + elif direction == "left": + return "right" + elif direction == "up": + return "down" + elif direction == "down": + return "up" + +# 玩家角色的碰撞检测与处理 +def player_collision(): + # 玩家与墙壁的碰撞 + if player.collidelist(walls) != -1: + player.x = player.oldx + player.y = player.oldy + return + # 检测玩家与箱子的碰撞 + index = player.collidelist(boxes) + # 如果玩家没有碰到箱子,返回 + if index == -1: + return + # 如果玩家碰到箱子,箱子先移动一格 + box = boxes[index] + box.oldx = box.x + box.oldy = box.y + dx, dy = dirs[player.direction] + box.x += dx * GRID_SIZE + box.y += dy * GRID_SIZE + current_box = box + # 记录箱子的移动 + box_moves.append((current_box, -dx * GRID_SIZE, -dy * GRID_SIZE)) + # 如果箱子碰到了墙壁或者其他箱子,玩家和箱子都退回原来的位置 + if box_collision(box) == True: + box.x = box.oldx + box.y = box.oldy + player.x = player.oldx + player.y = player.oldy + return + sounds.fall.play() + + +# 箱子角色的碰撞检测与处理 +def box_collision(box): + # 箱子与墙壁的碰撞,返回True + if box.collidelist(walls) != -1: + return True + # 箱子与其他箱子的碰撞,返回True + if box_collision_check(box): + return True + for bx in boxes: + if box == bx: + continue + if box.colliderect(bx): + return True + check_target(box) + return False + +def box_collision_check(box): + for bx in boxes: + if box == bx: + continue + if box.colliderect(bx): + return True + return False + +# 检测箱子是否放置在目标点上 +def check_target(box): + if box.collidelist(targets) != -1: + box.image = "pushbox_box_hit" + box.placed = True + else: + box.image = "pushbox_box" + box.placed = False + + +# 判断是否过关 +def check_level_up(): + for box in boxes: + if not box.placed: + return False + return True + + +# 设置新的关卡 +def set_next_level(): + global level_complete, level + level_complete = False + level += 1 + setup_level(level) + + +# 更新游戏逻辑 +def update(): + global level_complete,game_over + if level_complete or game_over: + return + if check_level_up(): + if level == MAX_LEVEl: + game_over = True + sounds.win.play() + clock.schedule(set_game_over,1) + else: + level_complete = True + sounds.win.play() + clock.schedule(set_next_level, 2) + + +# 绘制游戏图像 +def draw(): + screen.fill((255, 255, 255)) + if not start: + # screen.clear() + gui_background_image.draw() + btn_start_game.draw() + btn_exit_game.draw() + return + elif level_num_flag and start: + # screen.clear() + level_draw() + level_menu_draw() + for level_image in level_images: + level_image.draw() + return + if game_over & display_game_over: + ui_game_over.draw() + return + for floor in floors: + floor.draw() + for wall in walls: + wall.draw() + for target in targets: + target.draw() + for box in boxes: + box.draw() + screen.draw.text("Level " + str(level), topleft=(20, 20), + fontsize=30, color="black") + player.draw() + if level_complete: + ui_level_up.draw() + +def set_game_over(): + global display_game_over + display_game_over = True + +def level_menu_draw(): + if level_num_flag: + for level_image in level_images: + level_image.x=WIDTH//2 + else: + for level_image in level_images: + level_image.x=-50 + + + +setup_level(level) +pgzrun.go() \ No newline at end of file