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

本教程将介绍在迷宫中创建精灵和列表(不是精灵)之间的冲突的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。

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

问题描述

我一直在做一个随机生成的迷宫游戏,游戏中的敌人穿过迷宫向玩家移动。然而,我遇到了玩家能够穿过迷宫的墙壁的问题,我的问题是迷宫的墙壁不是精灵,因此不能使用精灵碰撞或垂直碰撞。有什么其他方法可以阻止球员穿过围墙?我能想到的唯一选择是得到每一面墙的位置,并防止球员进入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_SIZEcol_r = player.rect.right // CELL_SIZE
row_t = player.rect.top // CELL_SIZErow_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 walls和How 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()

好了关于在迷宫中创建精灵和列表(不是精灵)之间的冲突的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。