问题描述
我正在编写Bomberman游戏,现在我没有任何精灵,但我使用矩形。 这是我的代码:
import pygame
pygame.init()
WinWidth = 800
WinHeight = 608
p1x = 32
p1y = 32
vel = 1
clock = pygame.time.Clock()
win = pygame.display.set_mode((WinWidth,WinHeight))
def player():
pygame.draw.rect(win,(0,200,200),(p1x,p1y,32,32))
player_rect = pygame.Rect(p1x,tlw,tlh)
class Wall:
def __init__(self,x,y):
self.x = x
self.y = y
pygame.draw.rect(win,(50,50,50),(x,y,32))
class Breakable:
def __init__(self,(200,150,100),32))
game_map1 = [[0,0],[0,10,2,0]]
run = True
while run:
pygame.init()
clock.tick(100)
win.fill((0,255,200))
y = 0
for layer in game_map1:
x = 0
for tile in layer:
if tile == 0:
Wall(x * 32,y * 32)
wall_rect = pygame.Rect(x * 32,y * 32,tlh)
if tile == 10:
pygame.Rect(x * 32,32)
if tile == 2:
Breakable(x * 32,y * 32)
x += 1
y += 1
player()
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
if player_rect.colliderect(wall_rect):
p1x *= -1
p1y *= -1
else:
p1x += vel
elif event.key == pygame.K_a:
if player_rect.colliderect(wall_rect):
p1x *= -1
p1y *= -1
else:
p1x -= vel
if event.key == pygame.K_s:
if player_rect.colliderect(wall_rect):
p1x *= -1
p1y *= -1
else:
p1y += vel
elif event.key == pygame.K_w:
if player_rect.colliderect(wall_rect):
p1x *= -1
p1y *= -1
else:
p1y -= vel
pygame.display.update()
x
和y
在播放器矩形的左上方-它们分别是p1x
和p1y
。
宽度和高度分别为tlw
和tlh
。
Wall和Breakable也使用tlw
和tlh
,它们没有播放器所具有的特定坐标。
如此...我看了一个教程(https://www.youtube.com/watch?v=HCWI2f7tQnY&t=2s),甚至试图自己进行碰撞检测。但是我做不到。我在tilemap中没有矩形的坐标,并且tilemap中也有很多矩形。如何使用无坐标且有多个矩形的图块进行碰撞检测?是的,该游戏目前还没有太多内容……我用pygame.Rect的player_rect
和wall_rect
进行了尝试,然后使用了(colliderect)
,但没有工作,如何使player_rect与所有wall_rect碰撞,而不仅仅是与之碰撞。
我的问题是: 如何对碰撞发生的图块进行碰撞检测?
解决方法
我重构了整个代码,因为您发布的代码会引发错误,并且我无法测试我的代码。我们在这里实现冲突检测的方法是可行的,但并不是很有效。如果您想知道哪一方正在发生冲突,以便可以实施游戏逻辑,那么colliderect
毫无意义。我建议您问一个有关如何构建自定义碰撞检测的新问题,因为它是一个全新的主题,但是以下代码解决了有关如何使用colliderect实现碰撞检测的原始问题。下面的示例还显示了draw函数应如何是一种单独的方法,这是更好的实现方法。顺便说一句,如果您将tile == 10
放在您的问题中,而该问题基本上什么也没做,所以我将pygame.Rect(x * 32,y * 32,32,32)
放在了问题中。如果希望将其用作新型墙,则可以创建类似于pass
和Breakable
的新类。最终答案,希望对您有所帮助:)。
Wall
关于您的最后一个问题:
import pygame
pygame.init()
WinWidth = 800
WinHeight = 608
clock = pygame.time.Clock()
win = pygame.display.set_mode((WinWidth,WinHeight))
class Player:
def __init__(self):
self.x = 32
self.y = 32
self.width = 20
self.height = 20
self.vel = 0.1
def draw(self):
pygame.draw.rect(win,(0,200,200),(self.x,self.y,32))
def getRect(self):
return pygame.Rect(self.x,self.width,self.height)
class Wall:
def __init__(self,rect):
self.rect = rect
self.x = rect.x
self.y = rect.y
def draw(self):
pygame.draw.rect(win,(50,50,50),self.rect)
def getRect(self):
return pygame.Rect(self.x,32)
class Breakable:
def __init__(self,rect):
self.rect = rect
self.x = rect.x
self.y = rect.y
def draw(self):
pygame.draw.rect(win,(200,150,100),32)
game_map1 = [[0,0],[0,10,2,0]]
walls = []
y = 0
for layer in game_map1:
x = 0
for tile in layer:
if tile == 0:
walls.append(Wall(pygame.Rect([x*32,y*32,32])))
if tile == 10:
pass
if tile == 2:
walls.append(Breakable(pygame.Rect([x*32,32])))
x += 1
y += 1
player = Player()
pygame.init()
run = True
while run:
clock.tick(100)
win.fill((0,255,200))
for i in range(len(walls)):
walls[i].draw()
player.draw()
for wall in walls:
if player.getRect().colliderect(wall.getRect()): #getRect is the method we added to wall class earlier
print("they are colliding")
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
run = False
if event.type == pygame.KEYDOWN:
for wall in walls:
wall_rect = wall.getRect()
if event.key == pygame.K_d:
if player.getRect().colliderect(wall_rect):
player.x *= -1
player.y *= -1
else:
player.x += player.vel
elif event.key == pygame.K_a:
if player.getRect().colliderect(wall_rect):
player.x *= -1
player.y *= -1
else:
player.x -= player.vel
if event.key == pygame.K_s:
if player.getRect().colliderect(wall_rect):
player.x *= -1
player.y *= -1
else:
player.y += player.vel
elif event.key == pygame.K_w:
if player.getRect().colliderect(wall_rect):
player.x *= -1
player.y *= -1
else:
player.y -= player.vel
pygame.display.update()
这些是您可以使用的自定义冲突检测功能。我还没有一位球员(rect1)的左边,但我会稍后再尝试制作,或者您也可以尝试做成一位。您也可以尝试改进我提供的内容以适合您的游戏。使用这些,您可以准确地找出发生冲突的那一侧,并添加有用的逻辑。示例:
#Checks if right side of rect1 is colliding with left side of rect2
def rightCheck(rect1,rect2):
if rect1.x + rect1.width > rect2.x:
if (rect1.y > rect2.y and rect1.y < rect2.y + rect2.height) or (rect1.y + rect1.height < rect2.y + rect2.height and rect1.y + rect1.height> rect2.y):
if rect1.x < rect2.x:
return True
return False
#Checks if top side of rect1 is colliding with bottom side of rect2
def topCheck(rect1,rect2):
if rect1.y < rect2.y + rect2.height:
if (rect1.x > rect2.x and rect1.x < rect2.x + rect2.width) or (rect1.x + rect1.width > rect2.x and rect1.x + rect1.width < rect2.x + rect2.width):
if rect1.y > rect2.y:
return True
return False
#Checks if bottom side of rect1 is colliding with top side of rect2
def botCheck(rect1,rect2):
if rect1.y + rect1.height > rect2.y:
if (rect1.x > rect2.x and rect1.x < rect2.x + rect2.width) or (rect1.x + rect1.width > rect2.x and rect1.x + rect1.width < rect2.x + rect2.width):
if rect1.y < rect2.y:
return True
return False