为迷宫墙壁添加碰撞
Adding collision to maze walls
谁能帮我给精灵添加碰撞点。我有一个过去的代码,我在图像上分层了一个位图,但相同的代码不能很好地集成物理绘制线而不是检测 black/grey 在图像上的位置
import random
import pygame
pygame.init()
WHITE = (255,255,255)
GREY = (20,20,20)
BLACK = (0,0,0)
PURPLE = (100,0,100)
RED = (255,0,0)
size = (701,701)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Maze Generator")
done = False
clock = pygame.time.Clock()
width = 25
cols = int(size[0] / width)
rows = int(size[1] / width)
stack = []
pos = (0,0)
class Player(pygame.sprite.Sprite):
def __init__(self, image, pos, background):
super().__init__()
self.image = image
self.pos = pygame.Vector2(pos)
self.rect = self.image.get_rect(center=self.pos)
self.background = background
def update(self, events, dt):
pressed = pygame.key.get_pressed()
move = pygame.Vector2((0, 0))
if pressed[pygame.K_w]: move += (0, -1)
if pressed[pygame.K_a]: move += (-1, 0)
if pressed[pygame.K_s]: move += (0, 1)
if pressed[pygame.K_d]: move += (1, 0)
#if move.length() > 0: move.normalise_ip()
self.pos = self.pos + move*(dt/5)
self.rect.center = self.pos
if self.background:
new_rect.clamp_ip(self.background.get_rect())
new_pos = new_rect.center
hit_box = self.background.subsurface(new_rect)
for x in range(new_rect.width):
for y in range(new_rect.height):
if sum(hit_box.get_at((x, y))) < 500:
return
def load_background(filename=None):
name = filename if filename else "background.jpg"
background = pygame.image.load(name)
background = pygame.transform.rotate(background, -90)
background = pygame.transform.scale(background, (800,600))
return background
def load_player(background):
pimg = pygame.Surface((10, 10))
pimg.fill((200, 20, 20))
return Player(pimg, (25, 325), background)
class Cell():
def __init__(self,x,y):
global width
self.x = x * width
self.y = y * width
self.visited = False
self.current = False
self.walls = [True,True,True,True] # top , right , bottom , left
# neighbors
self.neighbors = []
self.top = 0
self.right = 0
self.bottom = 0
self.left = 0
self.next_cell = 0
def draw(self):
if self.current:
pygame.draw.rect(screen,RED,(self.x,self.y,width,width))
elif self.visited:
pygame.draw.rect(screen,WHITE,(self.x,self.y,width,width))
if self.walls[0]:
pygame.draw.line(screen,BLACK,(self.x,self.y),((self.x + width),self.y),1) # top
if self.walls[1]:
pygame.draw.line(screen,BLACK,((self.x + width),self.y),((self.x + width),(self.y + width)),1) # right
if self.walls[2]:
pygame.draw.line(screen,BLACK,((self.x + width),(self.y + width)),(self.x,(self.y + width)),1) # bottom
if self.walls[3]:
pygame.draw.line(screen,BLACK,(self.x,(self.y + width)),(self.x,self.y),1) # left
def checkNeighbors(self):
#print("Top; y: " + str(int(self.y / width)) + ", y - 1: " + str(int(self.y / width) - 1))
if int(self.y / width) - 1 >= 0:
self.top = grid[int(self.y / width) - 1][int(self.x / width)]
#print("Right; x: " + str(int(self.x / width)) + ", x + 1: " + str(int(self.x / width) + 1))
if int(self.x / width) + 1 <= cols - 1:
self.right = grid[int(self.y / width)][int(self.x / width) + 1]
#print("Bottom; y: " + str(int(self.y / width)) + ", y + 1: " + str(int(self.y / width) + 1))
if int(self.y / width) + 1 <= rows - 1:
self.bottom = grid[int(self.y / width) + 1][int(self.x / width)]
#print("Left; x: " + str(int(self.x / width)) + ", x - 1: " + str(int(self.x / width) - 1))
if int(self.x / width) - 1 >= 0:
self.left = grid[int(self.y / width)][int(self.x / width) - 1]
#print("--------------------")
if self.top != 0:
if self.top.visited == False:
self.neighbors.append(self.top)
if self.right != 0:
if self.right.visited == False:
self.neighbors.append(self.right)
if self.bottom != 0:
if self.bottom.visited == False:
self.neighbors.append(self.bottom)
if self.left != 0:
if self.left.visited == False:
self.neighbors.append(self.left)
if len(self.neighbors) > 0:
self.next_cell = self.neighbors[random.randrange(0,len(self.neighbors))]
return self.next_cell
else:
return False
def removeWalls(current_cell,next_cell):
x = int(current_cell.x / width) - int(next_cell.x / width)
y = int(current_cell.y / width) - int(next_cell.y / width)
if x == -1: # right of current
current_cell.walls[1] = False
next_cell.walls[3] = False
elif x == 1: # left of current
current_cell.walls[3] = False
next_cell.walls[1] = False
elif y == -1: # bottom of current
current_cell.walls[2] = False
next_cell.walls[0] = False
elif y == 1: # top of current
current_cell.walls[0] = False
next_cell.walls[2] = False
grid = []
for y in range(rows):
grid.append([])
for x in range(cols):
grid[y].append(Cell(x,y))
current_cell = grid[0][0]
next_cell = 0
# -------- Main Program Loop -----------
def main():
global current_cell
player = None
initialized = False
current_maze = None
dt = 0
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
sprites = pygame.sprite.Group()
if not initialized:
#current_maze = 0
background = load_background()
background = None
player = load_player(background)
sprites.add(player)
initialized = True
play = False
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
for y in range(rows):
for x in range(cols):
grid[y][x].draw()
if play == True:
pygame.init()
while not done:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
player_x = player.pos[0]
player_y = player.pos[1]
sprites.update(None, dt)
#screen.fill(pygame.Color('grey'))
#screen.blit(background, (0, 0))
sprites.draw(screen)
pygame.display.flip()
dt = clock.tick(60)
else:
current_cell.visited = True
current_cell.current = True
next_cell = current_cell.checkNeighbors()
if next_cell != False:
current_cell.neighbors = []
stack.append(current_cell)
removeWalls(current_cell,next_cell)
current_cell.current = False
current_cell = next_cell
elif len(stack) > 0:
current_cell.current = False
current_cell = stack.pop()
else:
play = True
pygame.display.flip()
main()
pygame.quit()
如果有人能帮助我或指出正确的方向,我会很高兴。
end_rect = pygame.draw.rect(screen, RED, (800-width, 600-width, width, width))
if player.rect.colliderect(end_rect):
screen.fill(BLACK)
end = True
确保 Player
对象位于 grid
的单元格中心。例如计算 player
:
的随机位置
def load_player(background):
pimg = pygame.Surface((10, 10))
pimg.fill((200, 20, 20))
px = random.randint(0, rows-1) * width + width//2
py = random.randint(0, cols-1) * width + width//2
return Player(pimg, (px, py), background)
要跟踪玩家,但突出显示玩家位置,当前玩家位置必须在玩家更新和重绘之前用不同的颜色着色:
pygame.draw.rect(screen, (255, 164, 164), player.rect)
sprites.update(None, dt)
sprites.draw(screen)
碰撞测试:
- 必须确定
grid
中玩家的当前位置。
- 必须确定玩家新的可能的新位置,具体取决于运动。
- 如果从当前位置到新位置的轨道上有一堵墙,则必须跳过该移动
class Player(pygame.sprite.Sprite):
def __init__(self, image, pos, background):
super().__init__()
self.image = image
self.pos = pygame.Vector2(pos)
self.rect = self.image.get_rect(center=self.pos)
self.background = background
def update(self, events, dt):
pressed = pygame.key.get_pressed()
move = pygame.Vector2((0, 0))
# calculate maximum movement and current cell position
testdist = dt // 5 + 2
cellx = self.rect.centerx // width
celly = self.rect.centery // width
minx = self.rect.left // width
maxx = self.rect.right // width
miny = self.rect.top // width
maxy = self.rect.bottom // width
# test move up
if minx == maxx and pressed[pygame.K_w]:
nexty = (self.rect.top-testdist) // width
if celly == nexty or (nexty >= 0 and not grid[celly][cellx].walls[0]):
move += (0, -1)
# test move right
elif miny == maxy and pressed[pygame.K_d]:
nextx = (self.rect.right+testdist) // width
if cellx == nextx or (nextx < cols and not grid[celly][cellx].walls[1]):
move += (1, 0)
# test move down
elif minx == maxx and pressed[pygame.K_s]:
nexty = (self.rect.bottom+testdist) // width
if celly == nexty or (nexty < rows and not grid[celly][cellx].walls[2]):
move += (0, 1)
# test move left
elif miny == maxy and pressed[pygame.K_a]:
nextx = (self.rect.left-testdist) // width
if cellx == nextx or (nextx >= 0 and not grid[celly][cellx].walls[3]):
move += (-1, 0)
self.pos = self.pos + move*(dt/5)
self.rect.center = self.pos
如果你想重新开始迷宫,你必须摆脱嵌套的游戏循环。使用 1 个游戏循环和一个条件,即游戏是否处于 play
状态或正在初始化迷宫。
检查玩家是否到达目标可以通过pygame.Rect.colliderect()
完成:
finished = pygame.Rect(0, 0, width, width).colliderect(player.rect)
要重新启动,您必须重置 grid
:
grid = []
for y in range(rows):
grid.append([])
for x in range(cols):
grid[y].append(Cell(x,y))
current_cell = grid[0][0]
将播放器设置到新的随机位置:
px = random.randint(0, rows-1) * width + width//2
py = random.randint(0, cols-1) * width + width//2
player.pos = pygame.Vector2(px, py)
player.rect = player.image.get_rect(center=player.pos)
清除后台并重置状态play
:
screen.fill(0)
play = False
完整 main
代码:
def main():
global current_cell, grid
player = None
initialized = False
current_maze = None
dt = 0
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
sprites = pygame.sprite.Group()
if not initialized:
#current_maze = 0
background = load_background()
background = None
player = load_player(background)
sprites.add(player)
initialized = True
play = False
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if play == True:
pygame.draw.rect(screen, (255, 164, 164), player.rect)
sprites.update(None, dt)
sprites.draw(screen)
dt = clock.tick(60)
finished = pygame.Rect(0, 0, width, width).colliderect(player.rect)
if finished:
# init new grid
grid = []
for y in range(rows):
grid.append([])
for x in range(cols):
grid[y].append(Cell(x,y))
current_cell = grid[0][0]
# create new random player positon
px = random.randint(0, rows-1) * width + width//2
py = random.randint(0, cols-1) * width + width//2
player.pos = pygame.Vector2(px, py)
player.rect = player.image.get_rect(center=player.pos)
# clear screen
screen.fill(0)
play = False
else:
current_cell.visited = True
current_cell.current = True
next_cell = current_cell.checkNeighbors()
if next_cell != False:
current_cell.neighbors = []
stack.append(current_cell)
removeWalls(current_cell,next_cell)
current_cell.current = False
current_cell = next_cell
elif len(stack) > 0:
current_cell.current = False
current_cell = stack.pop()
else:
play = True
for y in range(rows):
for x in range(cols):
grid[y][x].draw()
pygame.display.flip()
谁能帮我给精灵添加碰撞点。我有一个过去的代码,我在图像上分层了一个位图,但相同的代码不能很好地集成物理绘制线而不是检测 black/grey 在图像上的位置
import random
import pygame
pygame.init()
WHITE = (255,255,255)
GREY = (20,20,20)
BLACK = (0,0,0)
PURPLE = (100,0,100)
RED = (255,0,0)
size = (701,701)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Maze Generator")
done = False
clock = pygame.time.Clock()
width = 25
cols = int(size[0] / width)
rows = int(size[1] / width)
stack = []
pos = (0,0)
class Player(pygame.sprite.Sprite):
def __init__(self, image, pos, background):
super().__init__()
self.image = image
self.pos = pygame.Vector2(pos)
self.rect = self.image.get_rect(center=self.pos)
self.background = background
def update(self, events, dt):
pressed = pygame.key.get_pressed()
move = pygame.Vector2((0, 0))
if pressed[pygame.K_w]: move += (0, -1)
if pressed[pygame.K_a]: move += (-1, 0)
if pressed[pygame.K_s]: move += (0, 1)
if pressed[pygame.K_d]: move += (1, 0)
#if move.length() > 0: move.normalise_ip()
self.pos = self.pos + move*(dt/5)
self.rect.center = self.pos
if self.background:
new_rect.clamp_ip(self.background.get_rect())
new_pos = new_rect.center
hit_box = self.background.subsurface(new_rect)
for x in range(new_rect.width):
for y in range(new_rect.height):
if sum(hit_box.get_at((x, y))) < 500:
return
def load_background(filename=None):
name = filename if filename else "background.jpg"
background = pygame.image.load(name)
background = pygame.transform.rotate(background, -90)
background = pygame.transform.scale(background, (800,600))
return background
def load_player(background):
pimg = pygame.Surface((10, 10))
pimg.fill((200, 20, 20))
return Player(pimg, (25, 325), background)
class Cell():
def __init__(self,x,y):
global width
self.x = x * width
self.y = y * width
self.visited = False
self.current = False
self.walls = [True,True,True,True] # top , right , bottom , left
# neighbors
self.neighbors = []
self.top = 0
self.right = 0
self.bottom = 0
self.left = 0
self.next_cell = 0
def draw(self):
if self.current:
pygame.draw.rect(screen,RED,(self.x,self.y,width,width))
elif self.visited:
pygame.draw.rect(screen,WHITE,(self.x,self.y,width,width))
if self.walls[0]:
pygame.draw.line(screen,BLACK,(self.x,self.y),((self.x + width),self.y),1) # top
if self.walls[1]:
pygame.draw.line(screen,BLACK,((self.x + width),self.y),((self.x + width),(self.y + width)),1) # right
if self.walls[2]:
pygame.draw.line(screen,BLACK,((self.x + width),(self.y + width)),(self.x,(self.y + width)),1) # bottom
if self.walls[3]:
pygame.draw.line(screen,BLACK,(self.x,(self.y + width)),(self.x,self.y),1) # left
def checkNeighbors(self):
#print("Top; y: " + str(int(self.y / width)) + ", y - 1: " + str(int(self.y / width) - 1))
if int(self.y / width) - 1 >= 0:
self.top = grid[int(self.y / width) - 1][int(self.x / width)]
#print("Right; x: " + str(int(self.x / width)) + ", x + 1: " + str(int(self.x / width) + 1))
if int(self.x / width) + 1 <= cols - 1:
self.right = grid[int(self.y / width)][int(self.x / width) + 1]
#print("Bottom; y: " + str(int(self.y / width)) + ", y + 1: " + str(int(self.y / width) + 1))
if int(self.y / width) + 1 <= rows - 1:
self.bottom = grid[int(self.y / width) + 1][int(self.x / width)]
#print("Left; x: " + str(int(self.x / width)) + ", x - 1: " + str(int(self.x / width) - 1))
if int(self.x / width) - 1 >= 0:
self.left = grid[int(self.y / width)][int(self.x / width) - 1]
#print("--------------------")
if self.top != 0:
if self.top.visited == False:
self.neighbors.append(self.top)
if self.right != 0:
if self.right.visited == False:
self.neighbors.append(self.right)
if self.bottom != 0:
if self.bottom.visited == False:
self.neighbors.append(self.bottom)
if self.left != 0:
if self.left.visited == False:
self.neighbors.append(self.left)
if len(self.neighbors) > 0:
self.next_cell = self.neighbors[random.randrange(0,len(self.neighbors))]
return self.next_cell
else:
return False
def removeWalls(current_cell,next_cell):
x = int(current_cell.x / width) - int(next_cell.x / width)
y = int(current_cell.y / width) - int(next_cell.y / width)
if x == -1: # right of current
current_cell.walls[1] = False
next_cell.walls[3] = False
elif x == 1: # left of current
current_cell.walls[3] = False
next_cell.walls[1] = False
elif y == -1: # bottom of current
current_cell.walls[2] = False
next_cell.walls[0] = False
elif y == 1: # top of current
current_cell.walls[0] = False
next_cell.walls[2] = False
grid = []
for y in range(rows):
grid.append([])
for x in range(cols):
grid[y].append(Cell(x,y))
current_cell = grid[0][0]
next_cell = 0
# -------- Main Program Loop -----------
def main():
global current_cell
player = None
initialized = False
current_maze = None
dt = 0
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
sprites = pygame.sprite.Group()
if not initialized:
#current_maze = 0
background = load_background()
background = None
player = load_player(background)
sprites.add(player)
initialized = True
play = False
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
for y in range(rows):
for x in range(cols):
grid[y][x].draw()
if play == True:
pygame.init()
while not done:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
player_x = player.pos[0]
player_y = player.pos[1]
sprites.update(None, dt)
#screen.fill(pygame.Color('grey'))
#screen.blit(background, (0, 0))
sprites.draw(screen)
pygame.display.flip()
dt = clock.tick(60)
else:
current_cell.visited = True
current_cell.current = True
next_cell = current_cell.checkNeighbors()
if next_cell != False:
current_cell.neighbors = []
stack.append(current_cell)
removeWalls(current_cell,next_cell)
current_cell.current = False
current_cell = next_cell
elif len(stack) > 0:
current_cell.current = False
current_cell = stack.pop()
else:
play = True
pygame.display.flip()
main()
pygame.quit()
如果有人能帮助我或指出正确的方向,我会很高兴。
end_rect = pygame.draw.rect(screen, RED, (800-width, 600-width, width, width))
if player.rect.colliderect(end_rect):
screen.fill(BLACK)
end = True
确保 Player
对象位于 grid
的单元格中心。例如计算 player
:
def load_player(background):
pimg = pygame.Surface((10, 10))
pimg.fill((200, 20, 20))
px = random.randint(0, rows-1) * width + width//2
py = random.randint(0, cols-1) * width + width//2
return Player(pimg, (px, py), background)
要跟踪玩家,但突出显示玩家位置,当前玩家位置必须在玩家更新和重绘之前用不同的颜色着色:
pygame.draw.rect(screen, (255, 164, 164), player.rect)
sprites.update(None, dt)
sprites.draw(screen)
碰撞测试:
- 必须确定
grid
中玩家的当前位置。 - 必须确定玩家新的可能的新位置,具体取决于运动。
- 如果从当前位置到新位置的轨道上有一堵墙,则必须跳过该移动
class Player(pygame.sprite.Sprite):
def __init__(self, image, pos, background):
super().__init__()
self.image = image
self.pos = pygame.Vector2(pos)
self.rect = self.image.get_rect(center=self.pos)
self.background = background
def update(self, events, dt):
pressed = pygame.key.get_pressed()
move = pygame.Vector2((0, 0))
# calculate maximum movement and current cell position
testdist = dt // 5 + 2
cellx = self.rect.centerx // width
celly = self.rect.centery // width
minx = self.rect.left // width
maxx = self.rect.right // width
miny = self.rect.top // width
maxy = self.rect.bottom // width
# test move up
if minx == maxx and pressed[pygame.K_w]:
nexty = (self.rect.top-testdist) // width
if celly == nexty or (nexty >= 0 and not grid[celly][cellx].walls[0]):
move += (0, -1)
# test move right
elif miny == maxy and pressed[pygame.K_d]:
nextx = (self.rect.right+testdist) // width
if cellx == nextx or (nextx < cols and not grid[celly][cellx].walls[1]):
move += (1, 0)
# test move down
elif minx == maxx and pressed[pygame.K_s]:
nexty = (self.rect.bottom+testdist) // width
if celly == nexty or (nexty < rows and not grid[celly][cellx].walls[2]):
move += (0, 1)
# test move left
elif miny == maxy and pressed[pygame.K_a]:
nextx = (self.rect.left-testdist) // width
if cellx == nextx or (nextx >= 0 and not grid[celly][cellx].walls[3]):
move += (-1, 0)
self.pos = self.pos + move*(dt/5)
self.rect.center = self.pos
如果你想重新开始迷宫,你必须摆脱嵌套的游戏循环。使用 1 个游戏循环和一个条件,即游戏是否处于 play
状态或正在初始化迷宫。
检查玩家是否到达目标可以通过pygame.Rect.colliderect()
完成:
finished = pygame.Rect(0, 0, width, width).colliderect(player.rect)
要重新启动,您必须重置 grid
:
grid = []
for y in range(rows):
grid.append([])
for x in range(cols):
grid[y].append(Cell(x,y))
current_cell = grid[0][0]
将播放器设置到新的随机位置:
px = random.randint(0, rows-1) * width + width//2
py = random.randint(0, cols-1) * width + width//2
player.pos = pygame.Vector2(px, py)
player.rect = player.image.get_rect(center=player.pos)
清除后台并重置状态play
:
screen.fill(0)
play = False
完整 main
代码:
def main():
global current_cell, grid
player = None
initialized = False
current_maze = None
dt = 0
screen_rect = screen.get_rect()
clock = pygame.time.Clock()
sprites = pygame.sprite.Group()
if not initialized:
#current_maze = 0
background = load_background()
background = None
player = load_player(background)
sprites.add(player)
initialized = True
play = False
while not done:
# --- Main event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
if play == True:
pygame.draw.rect(screen, (255, 164, 164), player.rect)
sprites.update(None, dt)
sprites.draw(screen)
dt = clock.tick(60)
finished = pygame.Rect(0, 0, width, width).colliderect(player.rect)
if finished:
# init new grid
grid = []
for y in range(rows):
grid.append([])
for x in range(cols):
grid[y].append(Cell(x,y))
current_cell = grid[0][0]
# create new random player positon
px = random.randint(0, rows-1) * width + width//2
py = random.randint(0, cols-1) * width + width//2
player.pos = pygame.Vector2(px, py)
player.rect = player.image.get_rect(center=player.pos)
# clear screen
screen.fill(0)
play = False
else:
current_cell.visited = True
current_cell.current = True
next_cell = current_cell.checkNeighbors()
if next_cell != False:
current_cell.neighbors = []
stack.append(current_cell)
removeWalls(current_cell,next_cell)
current_cell.current = False
current_cell = next_cell
elif len(stack) > 0:
current_cell.current = False
current_cell = stack.pop()
else:
play = True
for y in range(rows):
for x in range(cols):
grid[y][x].draw()
pygame.display.flip()