如何在迷宫墙中添加碰撞以防止物体穿过迷宫墙?

2022-04-10 00:00:00 python pygame collision-detection

问题描述

所以我做一个重复的Pac-Man游戏项目已经有一段时间了,我一直试图在我的圆形对象和迷宫的墙壁之间添加碰撞,但遇到了困难--here is an imaged example.

我曾尝试将Player类中的冲突检测放在与Main不同的文件中,方法是将网格的位置设置为等于迷宫的墙,然后返回语句FALSE以指示对象撞到了墙,否则返回TRUE以指示不同的情况。

我做错了什么或丢失了什么?以下是我的主文件和播放器文件的内容:

请注意,我的网格的单元格宽度和高度为:

宽度=448-60/19,其中19是单元格的列周长 高度=576-60/21,其中21是单元格的行长

我存储在文本文件中的迷宫墙壁坐标是:

1111111111111111111
1000000001000000001
1011011101011101101
1000000000000000001
1011011111111101101
1000010001000100001
1111011101011101111
0001010000000101000
1111010110110101111
0000000100010000000
1111010111110101111
0001010000000101000
1111010111110101111
1000000001000000001
1011011101011101101
1001000000000001001
1101010111110101011
1000010001000100001
1011111101011111101
1000000000000000001
1111111111111111111

我的主.py文件:

from pygame.locals import (KEYDOWN, K_UP, K_DOWN, K_LEFT, K_RIGHT, 
K_RETURN, K_BACKSPACE, K_ESCAPE, QUIT)

from Pac_Mans_Main_Menu_State_Machine import *
from the_players_class import *


class ItsElements:

        pygame.init()
        pygame.display.set_caption("Pac-Man")
        self.the_screens_width, self.the_screens_height = 448, 576
        self.the_screens_perimeter = pygame.Surface((self.the_screens_width, self.the_screens_height))
        self.the_screens_perimeter_window = pygame.display.set_mode(size=(self.the_screens_width, self.the_screens_height))
        self.the_maze_image_surface = pygame.image.load("Maze_Background.png")
        self.the_maze_image_surface = pygame.transform.scale(self.the_maze_image_surface, size=(448 - 60, 576 - 60))
        self.the_mazes_walls = []

        with open("The_Mazes_Walls_Coordinates.txt", 'r') as the_maze_images_surface:
            for the_maze_image_surfaces_y_index, the_maze_image_surfaces_walls_coordinates in enumerate(the_maze_images_surface):
                for the_maze_image_surfaces_x_index, the_characters_type in enumerate(the_maze_image_surfaces_walls_coordinates):
                    if the_characters_type == "1":
                    self.the_mazes_walls.append(The_Vector(the_maze_image_surfaces_x_index, the_maze_image_surfaces_y_index))

        self.THE_UP_KEY, self.THE_DOWN_KEY, self.THE_LEFT_KEY, self.THE_RIGHT_KEY, self.THE_START_KEY, self.THE_BACK_KEY = 
            False, False, False, False, False, False

        self.the_player = ThePlayer(self, The_Vector(9, 9))

    def display_the_maze_background(self):
        self.the_screens_perimeter.blit(self.the_maze_image_surface, (30, 30))

    def draw_the_maze_backgrounds_pre_defined_walls_coordinates_using_the_screens_grid(self):
        for the_walls in self.the_mazes_walls:
            pygame.draw.rect(self.the_maze_image_surface, "Purple", (the_walls.x * ((448 - 60) / 19) + 1,
                                                                 the_walls.y * ((576 - 60) / 21) + 1,
                                                                 ((448 - 60) / 19), ((576 - 60) / 21)))

    def draw_the_screens_grid(self):
        for x in range(self.the_screens_width // 2):
            pygame.draw.line(self.the_maze_image_surface, "Gray", (x * ((448 - 60) / 19), 0),
                         (x * ((448 - 60) / 19), 576))
        for y in range(self.the_screens_height // 2):
            pygame.draw.line(self.the_maze_image_surface, "Gray", (0, y * ((576 - 60) / 21)),
                         (448, y * ((576 - 60) / 21)))

    def check_the_events(self):
        for the_event in pygame.event.get():
            if the_event.type == KEYDOWN:
                if the_event.key == K_UP:
                    self.THE_UP_KEY = True
                    if self.the_programs_playing_status is True:
                       self.the_player.move_the_circular_surfaces_position(The_Vector(0, -1))

                if the_event.key == K_DOWN:
                    self.THE_DOWN_KEY = True
                    if self.the_programs_playing_status is True:
                       self.the_player.move_the_circular_surfaces_position(The_Vector(0, 1))

                if the_event.key == K_LEFT:
                    self.THE_LEFT_KEY = True
                    if self.the_programs_playing_status is True:
                      self.the_player.move_the_circular_surfaces_position(The_Vector(-1, 0))

                if the_event.key == K_RIGHT:
                    self.THE_RIGHT_KEY = True
                    if self.the_programs_playing_status is True:
                       self.the_player.move_the_circular_surfaces_position(The_Vector(1, 0))

                if the_event.key == K_RETURN:
                    self.THE_START_KEY = True

                if the_event.key == K_BACKSPACE:
                    self.THE_BACK_KEY = True

                if the_event.key == K_ESCAPE:
                    self.the_programs_running_status, self.the_programs_playing_status = False, False
                    self.the_current_menu.run_the_display = False

            elif the_event.type == QUIT:
                self.the_programs_running_status, self.the_programs_playing_status = False, False
                self.the_current_menu.run_the_display = False

    def reset_the_pressed_keys(self):
        self.THE_UP_KEY, self.THE_DOWN_KEY, self.THE_LEFT_KEY, self.THE_RIGHT_KEY, self.THE_START_KEY, self.THE_BACK_KEY = 
            False, False, False, False, False, False

    def the_programs_main_loop(self):
       while self.the_programs_playing_status:

           # "'Check' the ''player's 'inputs'' 'in the 'events:''"
           self.check_the_events()

           #  Did the "'player' 'hit' the ''Enter' key' on their 'keyboard?'" "If so," then "'Stop' 'playing' the program but
           #  'continue' 'running' it:"
           if self.THE_START_KEY:
               self.the_programs_playing_status = False

           # "'Fill' the screen's 'surface' 'black:'"
           self.the_screens_perimeter.fill("Black")

           # "'Display' the 'game's 'background:''"
           self.display_the_maze_background()

           # "'Display' the ''manually' drawn' ''maze background' image:'"
           self.draw_the_maze_backgrounds_pre_defined_walls_coordinates_using_the_screens_grid()

           # "'Display' the 'screen's 'grid:''"
           self.draw_the_screens_grid()

           # "'Display' the 'player's ''current' score:''"
           self.display_the_current_score_text()

           # "'Display' the 'player's ''high' score:''"
           self.display_the_high_score_text()

           self.the_screens_perimeter_window.blit(self.the_screens_perimeter, (0, 0))

           self.the_player.draw_the_players_circles_surface()

           self.the_player.update()

           # "'Calling' 'flip()' will 'update the 'screen's 'display'' 'with the 'newly drawn surface''' or else 'nothing will
           # change:'"
           pygame.display.flip()

           self.reset_the_pressed_keys()

我的player.py文件包含我的播放器的类:

import pygame

from pygame.math import Vector2 as The_Vector

class ThePlayer(pygame.sprite.Sprite):
    def __init__(self, pac_man, the_grids_position):
        super(ThePlayer, self).__init__()
        self.pac_man = pac_man
        self.the_grids_position = the_grids_position

        self.the_pixels_position = 
            The_Vector((self.the_grids_position.x * (448 - 60) / 19) + ((60 / 2) + ((448 - 60) / 19) / 1.9),
                       (self.the_grids_position.y * (576 - 60) / 21) + ((60 / 2) + ((576 - 60) / 21) / 1.9))

        self.the_circular_surfaces_direction = The_Vector(0, 0)

        # print(self.the_grids_position, self.the_pixels_position)

    def draw_the_players_circles_surface(self):
        pygame.draw.circle(self.pac_man.the_screens_perimeter_window, "Yellow",
                           (int(self.the_pixels_position.x), int(self.the_pixels_position.y)), 7)

        # This block will be used to "'track' the ''player's 'position:''"

        # pygame.draw.rect(self.pac_man.the_screens_perimeter_window, "Red",
        #                 (self.the_pixels_position.x - (448 - 60) / 19 + (60 / 5.7),
        #                  self.the_pixels_position.y - (576 - 60) / 21 + (60 / 4.7),
        #                  (448 - 60) / 19, (576 - 60) / 21), 1)
        #                                     OR:
        pygame.draw.rect(self.pac_man.the_screens_perimeter_window, "Red",
                         (self.the_grids_position.x * (448 - 60) / 19 + (60 / 1.95),
                          self.the_grids_position.y * (576 - 60) / 21 + (60 / 1.95),
                          (448 - 60) / 19, (576 - 60) / 21), 1)

    def move_the_circular_surfaces_position(self, the_circular_surfaces_direction):
        self.the_circular_surfaces_direction = the_circular_surfaces_direction

    def the_circular_surface_collides_with_a_wall(self):

        for the_walls in self.pac_man.the_mazes_walls:
            if The_Vector(self.the_grids_position + self.the_circular_surfaces_direction) == the_walls:
                return False
            else:
                return True

    def update(self):
        # "'Move' the 'circular surface' 'relative to' the 'pixel's 'x's' and 'y's' positions' ''on' the 'screen:''"
        self.the_pixels_position += self.the_circular_surfaces_direction

        # "'Set' the 'grid's 'position'' 'relative to' the 'pixel's 'x:'"
        self.the_grids_position.x = (self.the_pixels_position.x - 60 + ((448 - 60) / 19) // 2) // ((448 - 60) / 19) + 1

        # "'Set' the 'grid's 'position'' 'relative to' the 'pixel's 'y:'"
        self.the_grids_position.y = (self.the_pixels_position.y - 60 + ((576 - 60) / 21) // 2) // ((576 - 60) / 21) + 1

请原谅我的问题太长了,非常感谢您的时间和对相关人员的帮助。我希望这个问题可以正确重现。


解决方案

正如另一个用户所指出的,我不确定您移动的逻辑在哪里。然而,这是我通常编程冲突的方式:

# Suppose you know what direction you want the player to move in 
currentPosition = # (row, column) tuple of current position
newPosition = # (row, column) tuple of new position  
              # e.g. (currentPosition[0] + rowDelta, currentPosition[1] + rowDelta)

if ("""newPosition collides with a wall in your maze"""):
   # Player's position remains the same
else:
   # Move the player's current position to newPosition
   # and call whatever code you need to render it.

相关文章