在迷宫中创建精灵和列表(不是精灵)之间的冲突

本文介绍了在迷宫中创建精灵和列表(不是精灵)之间的冲突的处理方法,对大家解决问题具有一定的参考价值

问题描述

我一直在做一个随机生成的迷宫游戏,游戏中的敌人穿过迷宫向玩家移动。然而,我遇到了玩家能够穿过迷宫的墙壁的问题,我的问题是迷宫的墙壁不是精灵,因此不能使用精灵碰撞或垂直碰撞。有没有其他方法可以阻止球员穿过围墙?我能想到的唯一选择是得到每一面墙的位置,并防止球员进入x或y的值。下面是我想要发生的事情的直观表示:

迷宫代码

class Cell(object):
    def __init__(self, x, y, cell_size, screen, black, white, red, blue):
        # position in matrix
        self.x = x
        self.y = y
        # keeps track of which walls are still visible
        self.walls = [True, True, True, True]
        # checks if cell has been visited during generation
        self.generated = False
        # checks if cell is on path during solving
        self.on_path = False
        # checks if cell has been visited during solving
        self.visited = False
        self.cell_size = cell_size
        self.screen = screen
        self.black = black
        self.white = white
        self.red = red
        self.blue = blue

    def draw_cell(self):
        # coordinates on screen
        x = self.x * self.cell_size
        y = self.y * self.cell_size
        # draws a wall if it still exists
        if self.walls[0]:
            pygame.draw.line(self.screen, self.black, (x, y), (x + self.cell_size, y), 5)

        if self.walls[1]:
            pygame.draw.line(self.screen, self.black,
                             (x, y + self.cell_size), (x + self.cell_size, y + self.cell_size), 5)
        if self.walls[2]:
            pygame.draw.line(self.screen, self.black,
                             (x + self.cell_size, y), (x + self.cell_size, y + self.cell_size), 5)
        if self.walls[3]:
            pygame.draw.line(self.screen, self.black, (x, y), (x, y + self.cell_size), 5)
        # marks out white if generated during generation
        if self.generated:
            pygame.draw.rect(self.screen, self.white, (x, y, self.cell_size, self.cell_size))


class Maze():
    def __init__(self, screen, cell_size, rows, cols, white, black, red, blue):
        self.screen = screen
        self.cell_size = cell_size
        self.rows = rows
        self.cols = cols
        self.state = None
        self.maze = []
        self.stack = []
        self.current_x = 0
        self.current_y = 0
        self.row = []
        self.neighbours = []
        self.black = black
        self.white = white
        self.red = red
        self.blue = blue
        self.cell = None
        self.maze_generated = False

    def on_start(self):
        # maintains the current state
        # maze matrix of cell instances
        self.maze = []
        # stack of current cells on path
        self.stack = []
        self.current_x, self.current_y = 0, 0

        self.maze.clear()
        self.stack.clear()
        for x in range(self.cols):
            self.row = []
            for y in range(self.rows):
                self.cell = Cell(x, y, self.cell_size, self.screen,
                                 self.black, self.white, self.red, self.blue)
                self.row.append(self.cell)
            self.maze.append(self.row)

    def in_bounds(self, x, y):
        return 0 <= x < self.cols and 0 <= y < self.rows
    # if x and y are within the bounds of the walls

    def find_next_cell(self, x, y):
        # keeps track of valid neighbors
        self.neighbours = []

        # loop through these two arrays to find all 4 neighbor cells
        dx, dy = [1, -1, 0, 0], [0, 0, 1, -1]
        for d in range(4):
            # add cell to neighbor list if it is in bounds and not generated
            if self.in_bounds(x + dx[d], y + dy[d]):
                if not self.maze[x + dx[d]][y + dy[d]].generated:
                    self.neighbours.append((x + dx[d], y + dy[d]))
        # returns a random cell in the neighbors list, or -1 -1 otherwise
        if len(self.neighbours) > 0:
            return self.neighbours[random.randint(0, len(self.neighbours) - 1)]
        else:
            return -1, -1

    def remove_wall(self, x1, y1, x2, y2):
        # x distance between original cell and neighbor cell
        xd = self.maze[x1][y1].x - self.maze[x2][y2].x
        # to the bottom
        if xd == 1:
            self.maze[x1][y1].walls[3] = False
            self.maze[x2][y2].walls[1] = False
        # to the top
        elif xd == -1:
            self.maze[x1][y1].walls[1] = False
            self.maze[x2][y2].walls[3] = False
        # y distance between original cell and neighbor cell
        xy = self.maze[x1][y1].y - self.maze[x2][y2].y
        # to the right
        if xy == 1:
            self.maze[x1][y1].walls[0] = False
            self.maze[x2][y2].walls[2] = False
        # to the left
        elif xy == -1:
            self.maze[x1][y1].walls[2] = False
            self.maze[x2][y2].walls[0] = False

    def create_maze(self):
        # if self.maze_generated == False:
        self.maze[self.current_x][self.current_y].generated = True
        # self.maze[self.current_x][self.current_y].draw_current()
        next_cell = self.find_next_cell(self.current_x, self.current_y)
        # checks if a neighbor was returned
        if next_cell[0] >= 0 and next_cell[1] >= 0:
            self.stack.append((self.current_x, self.current_y))
            self.remove_wall(self.current_x, self.current_y, next_cell[0], next_cell[1])
            self.current_x = next_cell[0]
            self.current_y = next_cell[1]
        # no neighbor, so go to the previous cell in the stack
        elif len(self.stack) > 0:
            previous = self.stack.pop()
            self.current_x = previous[0]
            self.current_y = previous[1]
        # else:
        self.maze_generated = True

推荐答案

计算球员矩形角点的行数和列数。

col_l = player.rect.left // CELL_SIZE  
col_r = player.rect.right // CELL_SIZE
row_t = player.rect.top // CELL_SIZE  
row_b = player.rect.bottom // CELL_SIZE  

如果玩家移动,则测试玩家是否正在进入新的单元格。如果当前单元格和新单元格之间有墙,则跳过移动:

keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
    new_rect = player.rect.move(-1, 0)
    next_col = new_rect.left // CELL_SIZE
    if col_l == next_col or not (m.maze[col_l][row_t].walls[3] or m.maze[col_l][row_b].walls[3]):
        player.rect = new_rect
if keys[pygame.K_RIGHT]:
    new_rect = player.rect.move(1, 0)
    next_col = new_rect.right // CELL_SIZE
    if col_r == next_col or not (m.maze[col_r][row_t].walls[1] or m.maze[col_r][row_b].walls[1]):
        player.rect = new_rect
if keys[pygame.K_UP]:
    new_rect = player.rect.move(0, -1)
    next_row = new_rect.top // CELL_SIZE
    if row_t == next_row or not (m.maze[col_l][row_t].walls[0] or m.maze[col_r][row_t].walls[0]):
        player.rect = new_rect
if keys[pygame.K_DOWN]:
    new_rect = player.rect.move(0, 1)
    next_row = new_rect.bottom // CELL_SIZE
    if row_b == next_row or not (m.maze[col_l][row_b].walls[2] or m.maze[col_r][row_b].walls[2]):
        player.rect = new_rect

另请参阅Adding collision to maze wallsHow to implement barriers to stop the player moving through walls


根据上一个问题How to generate my maze instantly so I don't have to watch it Generate?完成示例:

import pygame
import random

class Cell(object):
    def __init__(self, x, y, cell_size, screen, black, white, red, blue):
        # position in matrix
        self.x = x
        self.y = y
        # keeps track of which walls are still visible
        self.walls = [True, True, True, True]
        # checks if cell has been visited during generation
        self.generated = False
        # checks if cell is on path during solving
        self.on_path = False
        # checks if cell has been visited during solving
        self.visited = False
        self.cell_size = cell_size
        self.screen = screen
        self.black = black
        self.white = white
        self.red = red
        self.blue = blue

    def draw_cell(self):
        # coordinates on screen
        x = self.x * self.cell_size
        y = self.y * self.cell_size
        # draws a wall if it still exists
        if self.walls[0]:
            pygame.draw.line(self.screen, self.black, (x, y), (x + self.cell_size, y), 5)
        if self.walls[1]:
            pygame.draw.line(self.screen, self.black,
                             (x, y + self.cell_size), (x + self.cell_size, y + self.cell_size), 5)
        if self.walls[2]:
            pygame.draw.line(self.screen, self.black,
                             (x + self.cell_size, y), (x + self.cell_size, y + self.cell_size), 5)
        if self.walls[3]:
            pygame.draw.line(self.screen, self.black, (x, y), (x, y + self.cell_size), 5)
        # marks out white if generated during generation
        if self.generated:
            pygame.draw.rect(self.screen, self.white, (x, y, self.cell_size, self.cell_size))


class Maze:
    def __init__(self, screen, cell_size, rows, cols, white, black, red, blue):
        self.screen = screen
        self.cell_size = cell_size
        self.rows = rows
        self.cols = cols
        self.state = None
        self.maze = []
        self.stack = []
        self.current_x = 0
        self.current_y = 0
        self.row = []
        self.neighbours = []
        self.black = black
        self.white = white
        self.red = red
        self.blue = blue
        self.cell = None

    def on_start(self):
        # maintains the current state
        # maze matrix of cell instances
        self.maze = []
        # stack of current cells on path
        self.stack = []
        self.current_x, self.current_y = 0, 0

        self.maze.clear()
        self.stack.clear()
        for x in range(self.cols):
            self.row = []
            for y in range(self.rows):
                self.cell = Cell(x, y, self.cell_size, self.screen, self.black, self.white, self.red, self.blue)
                self.row.append(self.cell)
            self.maze.append(self.row)

    def in_bounds(self, x, y):
        return 0 <= x < self.cols and 0 <= y < self.rows

    def find_next_cell(self, x, y):
        # keeps track of valid neighbors
        self.neighbours = []

        # loop through these two arrays to find all 4 neighbor cells
        dx, dy = [1, -1, 0, 0], [0, 0, 1, -1]
        for d in range(4):
            # add cell to neighbor list if it is in bounds and not generated
            if self.in_bounds(x + dx[d], y + dy[d]):
                if not self.maze[x + dx[d]][y + dy[d]].generated:
                    self.neighbours.append((x + dx[d], y + dy[d]))
        # returns a random cell in the neighbors list, or -1 -1 otherwise
        if len(self.neighbours) > 0:
            return self.neighbours[random.randint(0, len(self.neighbours) - 1)]
        else:
            return -1, -1

    def remove_wall(self, x1, y1, x2, y2):
        # x distance between original cell and neighbor cell
        xd = self.maze[x1][y1].x - self.maze[x2][y2].x
        # to the bottom
        if xd == 1:
            self.maze[x1][y1].walls[3] = False
            self.maze[x2][y2].walls[1] = False
        # to the top
        elif xd == -1:
            self.maze[x1][y1].walls[1] = False
            self.maze[x2][y2].walls[3] = False
        # y distance between original cell and neighbor cell
        xy = self.maze[x1][y1].y - self.maze[x2][y2].y
        # to the right
        if xy == 1:
            self.maze[x1][y1].walls[0] = False
            self.maze[x2][y2].walls[2] = False
        # to the left
        elif xy == -1:
            self.maze[x1][y1].walls[2] = False
            self.maze[x2][y2].walls[0] = False

    def create_maze(self):
        self.maze[self.current_x][self.current_y].generated = True
        # self.maze[self.current_x][self.current_y].draw_current()
        next_cell = self.find_next_cell(self.current_x, self.current_y)
        # checks if a neighbor was returned
        if next_cell[0] >= 0 and next_cell[1] >= 0:
            self.stack.append((self.current_x, self.current_y))
            self.remove_wall(self.current_x, self.current_y, next_cell[0], next_cell[1])
            self.current_x = next_cell[0]
            self.current_y = next_cell[1]
        # no neighbor, so go to the previous cell in the stack
        elif len(self.stack) > 0:
            previous = self.stack.pop()
            self.current_x = previous[0]
            self.current_y = previous[1]


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.Surface((20, 20))
        self.image.fill((255, 0, 0))
        self.rect = self.image.get_rect(center = (20, 20))

def main():
    WIDTH, HEIGHT = 800, 800
    CELL_SIZE = 40
    ROWS, COLUMNS = int(HEIGHT / CELL_SIZE), int(WIDTH / CELL_SIZE)

    # color variables
    WHITE = (255, 255, 255)
    BLACK = (0, 0, 0)
    RED = (255, 0, 0)
    BLUE = (0, 0, 255)

    # initialize pygame
    pygame.init()
    SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("Maze Gen")
    CLOCK = pygame.time.Clock()
    FPS = 60

    m = Maze(SCREEN, CELL_SIZE, ROWS, COLUMNS, WHITE, BLACK, RED, BLUE)
    m.on_start()
    while True:
        m.create_maze()
        if len(m.stack) == 0:
            break

    player = Player()
    all_sprites = pygame.sprite.Group(player)

    running = True
    while running:
        CLOCK.tick(FPS)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        col_l = player.rect.left // CELL_SIZE  
        col_r = player.rect.right // CELL_SIZE
        row_t = player.rect.top // CELL_SIZE  
        row_b = player.rect.bottom // CELL_SIZE  

        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            new_rect = player.rect.move(-1, 0)
            next_col = new_rect.left // CELL_SIZE
            if col_l == next_col or not (m.maze[col_l][row_t].walls[3] or m.maze[col_l][row_b].walls[3]):
                player.rect = new_rect
        if keys[pygame.K_RIGHT]:
            new_rect = player.rect.move(1, 0)
            next_col = new_rect.right // CELL_SIZE
            if col_r == next_col or not (m.maze[col_r][row_t].walls[1] or m.maze[col_r][row_b].walls[1]):
                player.rect = new_rect
        if keys[pygame.K_UP]:
            new_rect = player.rect.move(0, -1)
            next_row = new_rect.top // CELL_SIZE
            if row_t == next_row or not (m.maze[col_l][row_t].walls[0] or m.maze[col_r][row_t].walls[0]):
                player.rect = new_rect
        if keys[pygame.K_DOWN]:
            new_rect = player.rect.move(0, 1)
            next_row = new_rect.bottom // CELL_SIZE
            if row_b == next_row or not (m.maze[col_l][row_b].walls[2] or m.maze[col_r][row_b].walls[2]):
                player.rect = new_rect

        SCREEN.fill(WHITE)
        for i in range(m.cols):
            for j in range(m.rows):
                m.maze[i][j].draw_cell()
        all_sprites.draw(SCREEN)
        pygame.display.flip()

if __name__ == "__main__":
    main()
pygame.quit()

这篇关于在迷宫中创建精灵和列表(不是精灵)之间的冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,WP2

admin_action_{$_REQUEST[‘action’]}

do_action( "admin_action_{$_REQUEST[‘action’]}" )动作钩子::在发送“Action”请求变量时激发。Action Hook: Fires when an ‘action’ request variable is sent.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$_REQUEST['action']引用从GET或POST请求派生的操作。源码(Source)更新版本源码位置使用被使用2.6.0 wp-admin/admin.php:...

日期:2020-09-02 17:44:16 浏览:1169

admin_footer-{$GLOBALS[‘hook_suffix’]}

do_action( "admin_footer-{$GLOBALS[‘hook_suffix’]}", string $hook_suffix )操作挂钩:在默认页脚脚本之后打印脚本或数据。Action Hook: Print scripts or data after the default footer scripts.目录锚点:#说明#参数#源码说明(Description)钩子名的动态部分,$GLOBALS['hook_suffix']引用当前页的全局钩子后缀。参数(Parameters)参数类...

日期:2020-09-02 17:44:20 浏览:1070

customize_save_{$this->id_data[‘base’]}

do_action( "customize_save_{$this-&gt;id_data[‘base’]}", WP_Customize_Setting $this )动作钩子::在调用WP_Customize_Setting::save()方法时激发。Action Hook: Fires when the WP_Customize_Setting::save() method is called.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_data...

日期:2020-08-15 15:47:24 浏览:806

customize_value_{$this->id_data[‘base’]}

apply_filters( "customize_value_{$this-&gt;id_data[‘base’]}", mixed $default )过滤器::过滤未作为主题模式或选项处理的自定义设置值。Filter Hook: Filter a Customize setting value not handled as a theme_mod or option.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分,$this->id_date['base'],指的是设置...

日期:2020-08-15 15:47:24 浏览:898

get_comment_author_url

过滤钩子:过滤评论作者的URL。Filter Hook: Filters the comment author’s URL.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/comment-template.php:32610...

日期:2020-08-10 23:06:14 浏览:930

network_admin_edit_{$_GET[‘action’]}

do_action( "network_admin_edit_{$_GET[‘action’]}" )操作挂钩:启动请求的处理程序操作。Action Hook: Fires the requested handler action.目录锚点:#说明#源码说明(Description)钩子名称的动态部分$u GET['action']引用请求的操作的名称。源码(Source)更新版本源码位置使用被使用3.1.0 wp-admin/network/edit.php:3600...

日期:2020-08-02 09:56:09 浏览:876

network_sites_updated_message_{$_GET[‘updated’]}

apply_filters( "network_sites_updated_message_{$_GET[‘updated’]}", string $msg )筛选器挂钩:在网络管理中筛选特定的非默认站点更新消息。Filter Hook: Filters a specific, non-default site-updated message in the Network admin.目录锚点:#说明#参数#源码说明(Description)钩子名称的动态部分$_GET['updated']引用了非默认的...

日期:2020-08-02 09:56:03 浏览:864

pre_wp_is_site_initialized

过滤器::过滤在访问数据库之前是否初始化站点的检查。Filter Hook: Filters the check for whether a site is initialized before the database is accessed.目录锚点:#源码源码(Source)更新版本源码位置使用被使用 wp-includes/ms-site.php:93910...

日期:2020-07-29 10:15:38 浏览:833

WordPress 的SEO 教学:如何在网站中加入关键字(Meta Keywords)与Meta 描述(Meta Description)?

你想在WordPress 中添加关键字和meta 描述吗?关键字和meta 描述使你能够提高网站的SEO。在本文中,我们将向你展示如何在WordPress 中正确添加关键字和meta 描述。为什么要在WordPress 中添加关键字和Meta 描述?关键字和说明让搜寻引擎更了解您的帖子和页面的内容。关键词是人们寻找您发布的内容时,可能会搜索的重要词语或片语。而Meta Description则是对你的页面和文章的简要描述。如果你想要了解更多关于中继标签的资讯,可以参考Google的说明。Meta 关键字和描...

日期:2020-10-03 21:18:25 浏览:1723

谷歌的SEO是什么

SEO (Search Engine Optimization)中文是搜寻引擎最佳化,意思近于「关键字自然排序」、「网站排名优化」。简言之,SEO是以搜索引擎(如Google、Bing)为曝光媒体的行销手法。例如搜寻「wordpress教学」,会看到本站的「WordPress教学:12个课程…」排行Google第一:关键字:wordpress教学、wordpress课程…若搜寻「网站架设」,则会看到另一个网页排名第1:关键字:网站架设、架站…以上两个网页,每月从搜寻引擎导入自然流量,达2万4千:每月「有机搜...

日期:2020-10-30 17:23:57 浏览:1308