如何检测一个矩形与另一个矩形的先前位置之间的碰撞? Pygame
How do I detect collisions between one rectangle and a previous position of another rectangle? Pygame
我不熟悉 Python 和一般的编程,所以我决定制作一个有 2 个玩家的 Tron 的基本克隆。澄清一下,Tron 是一款玩家骑自行车的游戏,在他们身后形成 path/trail。如果一个玩家撞到另一个玩家的path/trail,他们就输了。我试图通过使用 pygame 中的矩形来检测我的代码中的这种类型的碰撞。
我对如何实现这个想法有一个大致的想法:每次玩家移动时,他们都会在他们身后制作连续的矩形,这些矩形会附加到名为 tron_path_1 或 [=19= 的列表中].因此,如果玩家 1 的矩形与对方玩家 (tron_path_2) 列表中的矩形发生碰撞,我想检测该碰撞。但是在我的代码中,如果每个玩家的两个头相互碰撞,我只能检测到碰撞。所以我的问题是:如何检测玩家的矩形与对方玩家之前的矩形的碰撞?
import pygame
import sys
class Player():
def __init__(self, screen, x, y, w, h, dx, dy, tron_path, color):
"""Create player's tron bike."""
self.screen = screen
self.screen_rect = screen.get_rect()
self.x = x
self.y = y
self.w = w #width
self.h = h #height
self.dx = dx
self.dy = dy
self.tron_path = tron_path
self.color = color
self.player_rect = pygame.Rect(self.x, self.y, self.w, self.h)
def update_position(self):
self.player_rect[0] += self.dx #changes rect's x-coordinate
self.player_rect[1] += self.dy #changes rect's y-coordinate
self.tron_path.append(self.player_rect)
def draw_player(self):
pygame.draw.rect(self.screen, self.color, self.player_rect)
# Initialize pygame settings.
pygame.init()
screen = pygame.display.set_mode((1200,700))
pygame.display.set_caption("Tron")
# Player settings
p1_color = ((219,62,177)) #pink
p2_color = ((255,255,255)) #white
players = []
tron_path_1 = [] # List to keep track of rectangles for each player
tron_path_2 = []
p1 = Player(screen, x=200, y=500, w=5, h=5, dx=5, dy=0, tron_path=tron_path_1, color=p1_color) #player 1
p2 = Player(screen, x=1000, y=500, w=5, h=5, dx=-5, dy=0, tron_path=tron_path_2, color=p2_color) #player 2
players.append(p1)
players.append(p2)
# Initialize
while True:
clockobject = pygame.time.Clock()
clockobject.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
# Player 1 controls
if event.key == pygame.K_w:
p1.dx = 0
p1.dy = -5
elif event.key == pygame.K_s:
p1.dx = 0
p1.dy = 5
elif event.key == pygame.K_d:
p1.dx = 5
p1.dy = 0
elif event.key == pygame.K_a:
p1.dx = -5
p1.dy = 0
# Player 2 controls
if event.key == pygame.K_UP:
p2.dx = 0
p2.dy = -5
elif event.key == pygame.K_DOWN:
p2.dx = 0
p2.dy = 5
elif event.key == pygame.K_RIGHT:
p2.dx = 5
p2.dy = 0
elif event.key == pygame.K_LEFT:
p2.dx = -5
p2.dy = 0
p1.update_position()
p2.update_position()
p1.draw_player()
p2.draw_player()
# Trying to detect collision with one player and another player's path
for rect in tron_path_1:
if p2.player_rect.colliderect(rect):
print("collision")
for rect in tron_path_2:
if p1.player_rect.colliderect(rect):
print("collision")
pygame.display.flip()
当您执行 tron_path_1.append(p1.player_rect)
时,您不会创建 p1.player_rect
的副本。 p1.player_rect
是一个引用 pygame.Rect
对象的变量。
在tron_path_1.append(p1.player_rect)
之后,变量p1.player_rect
和列表元素tron_path_1[0]
引用同一个对象。
因此,当您更改 p1.player_rect
时,列表的元素似乎也会更改,因为只有 1 个 pygame.Rect
对象。
使用.copy()
创建矩形的副本:
class Player():
# [...]
def update_position(self):
self.player_rect[0] += self.dx #changes rect's x-coordinate
self.player_rect[1] += self.dy #changes rect's y-coordinate
# self.tron_path.append(self.player_rect) <--- CHANGE TO
self.tron_path.append(self.player_rect.copy())
我不熟悉 Python 和一般的编程,所以我决定制作一个有 2 个玩家的 Tron 的基本克隆。澄清一下,Tron 是一款玩家骑自行车的游戏,在他们身后形成 path/trail。如果一个玩家撞到另一个玩家的path/trail,他们就输了。我试图通过使用 pygame 中的矩形来检测我的代码中的这种类型的碰撞。
我对如何实现这个想法有一个大致的想法:每次玩家移动时,他们都会在他们身后制作连续的矩形,这些矩形会附加到名为 tron_path_1 或 [=19= 的列表中].因此,如果玩家 1 的矩形与对方玩家 (tron_path_2) 列表中的矩形发生碰撞,我想检测该碰撞。但是在我的代码中,如果每个玩家的两个头相互碰撞,我只能检测到碰撞。所以我的问题是:如何检测玩家的矩形与对方玩家之前的矩形的碰撞?
import pygame
import sys
class Player():
def __init__(self, screen, x, y, w, h, dx, dy, tron_path, color):
"""Create player's tron bike."""
self.screen = screen
self.screen_rect = screen.get_rect()
self.x = x
self.y = y
self.w = w #width
self.h = h #height
self.dx = dx
self.dy = dy
self.tron_path = tron_path
self.color = color
self.player_rect = pygame.Rect(self.x, self.y, self.w, self.h)
def update_position(self):
self.player_rect[0] += self.dx #changes rect's x-coordinate
self.player_rect[1] += self.dy #changes rect's y-coordinate
self.tron_path.append(self.player_rect)
def draw_player(self):
pygame.draw.rect(self.screen, self.color, self.player_rect)
# Initialize pygame settings.
pygame.init()
screen = pygame.display.set_mode((1200,700))
pygame.display.set_caption("Tron")
# Player settings
p1_color = ((219,62,177)) #pink
p2_color = ((255,255,255)) #white
players = []
tron_path_1 = [] # List to keep track of rectangles for each player
tron_path_2 = []
p1 = Player(screen, x=200, y=500, w=5, h=5, dx=5, dy=0, tron_path=tron_path_1, color=p1_color) #player 1
p2 = Player(screen, x=1000, y=500, w=5, h=5, dx=-5, dy=0, tron_path=tron_path_2, color=p2_color) #player 2
players.append(p1)
players.append(p2)
# Initialize
while True:
clockobject = pygame.time.Clock()
clockobject.tick(30)
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
# Player 1 controls
if event.key == pygame.K_w:
p1.dx = 0
p1.dy = -5
elif event.key == pygame.K_s:
p1.dx = 0
p1.dy = 5
elif event.key == pygame.K_d:
p1.dx = 5
p1.dy = 0
elif event.key == pygame.K_a:
p1.dx = -5
p1.dy = 0
# Player 2 controls
if event.key == pygame.K_UP:
p2.dx = 0
p2.dy = -5
elif event.key == pygame.K_DOWN:
p2.dx = 0
p2.dy = 5
elif event.key == pygame.K_RIGHT:
p2.dx = 5
p2.dy = 0
elif event.key == pygame.K_LEFT:
p2.dx = -5
p2.dy = 0
p1.update_position()
p2.update_position()
p1.draw_player()
p2.draw_player()
# Trying to detect collision with one player and another player's path
for rect in tron_path_1:
if p2.player_rect.colliderect(rect):
print("collision")
for rect in tron_path_2:
if p1.player_rect.colliderect(rect):
print("collision")
pygame.display.flip()
当您执行 tron_path_1.append(p1.player_rect)
时,您不会创建 p1.player_rect
的副本。 p1.player_rect
是一个引用 pygame.Rect
对象的变量。
在tron_path_1.append(p1.player_rect)
之后,变量p1.player_rect
和列表元素tron_path_1[0]
引用同一个对象。
因此,当您更改 p1.player_rect
时,列表的元素似乎也会更改,因为只有 1 个 pygame.Rect
对象。
使用.copy()
创建矩形的副本:
class Player():
# [...]
def update_position(self):
self.player_rect[0] += self.dx #changes rect's x-coordinate
self.player_rect[1] += self.dy #changes rect's y-coordinate
# self.tron_path.append(self.player_rect) <--- CHANGE TO
self.tron_path.append(self.player_rect.copy())