python - pygame中自制的2D碰撞检测不起作用
问题描述
我正在制作一个类似 tron 的游戏,两个玩家用按键 w、a、s、d 控制他们的角色,玩家 1 和 player2 用上、下、左、右控制他们的角色。在玩家移动时,用户进行追踪,如果对方玩家接触到玩家的踪迹,则他们“出局”。
游戏代码:
from steel2D import *
window = Window(600, 450, "Steel 2D Tutorial")
running = True
char1 = Rect(window, 0, 0, 5, 5, (255, 0, 0))
char2 = Rect(window, 595, 445, 5, 5, (0, 0, 255))
trail1 = []
trail2 = []
red = 0
blue = 0
while running:
sleep(2)
keys = OnKeyInput()
if keys[pygame.K_w]:
char1.y -= 2.2
trail1.append(char1)
if keys[pygame.K_a]:
char1.x -= 2.2
trail1.append(char1)
if keys[pygame.K_s]:
char1.y += 2.2
trail1.append(char1)
if keys[pygame.K_d]:
char1.x += 2.2
trail1.append(char1)
if keys[pygame.K_UP]:
char2.y -= 2.2
trail2.append(char2)
if keys[pygame.K_LEFT]:
char2.x -= 2.2
trail2.append(char2)
if keys[pygame.K_DOWN]:
char2.y += 2.2
trail2.append(char2)
if keys[pygame.K_RIGHT]:
char2.x += 2.2
trail2.append(char2)
if char1.x >= 595:
char1.x = 595
if char1.x <= 0:
char1.x = 0
if char1.y >= 445:
char1.y = 445
if char1.y <= 0:
char1.y = 0
if char2.x >= 595:
char2.x = 595
if char2.x <= 0:
char2.x = 0
if char2.y >= 445:
char2.y = 445
if char2.y <= 0:
char2.y = 0
char1.draw()
char2.draw()
Update()
for t1, t2 in zip(trail1, trail2):
if OnRectCollison(t1, t2):
exit()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pygame.quit()
在每次按键时,用户轨迹都会被附加到一个列表中,然后它会循环通过以检查是否存在冲突。现在它似乎只在玩家的第一条轨迹接触时才开始碰撞,没有别的。
steel2D 代码(我的游戏引擎):
import pygame
from threading import Thread
pygame.init()
def sleep(ms):
pygame.time.delay(ms)
def Window(w, h, title="steel2D"):
window = pygame.display.set_mode((w, h))
pygame.display.set_caption(title)
return window
def Update():
pygame.display.update()
def OnKeyInput():
return pygame.key.get_pressed()
class Rect:
def __init__(self, window, x, y, w, h, color=(0, 0, 0)):
self.window = window
self.x = x
self.y = y
self.w = w
self.h = h
self.color = color
def draw(self):
pygame.draw.rect(self.window, self.color, (self.x, self.y, self.w, self.h))
class Circle:
def __init__(self, window, x, y, r, color=(0, 0, 0)):
self.window = window
self.x = x
self.y = y
self.r = r
self.color = color
def draw(self):
pygame.draw.circle(self.window, self.color, (self.x, self.y), self.r, self.r)
def Line(window, color, sx, sy, ex, ey, width=2):
pygame.draw.line(window, color, (sx, sy), (ex, ey), width)
def OnRectCollison(rect1, rect2):
if rect1.x < rect2.x + rect2.w and rect1.x + rect1.w > rect2.x and rect1.y < rect2.y + rect2.h and rect1.y + rect1.h > rect2.y:
return True
else:
return False
任何帮助,将不胜感激。
解决方案
有几个问题:
zip
如果您想将头部矩形与 和 中的每个矩形进行比较,则该函数是错误trail1
的trail2
。您只会在相同的索引处获得成对的矩形,并且还会删除较长列表的元素。看看这个例子:>>> trail1 = [1, 2, 3] >>> trail2 = ['a', 'b', 'c', 'd', 'e'] >>> list(zip(trail1, trail2)) [(1, 'a'), (2, 'b'), (3, 'c')]
只需遍历跟踪列表中的矩形并检查是否
char1
或char2
与它们碰撞。# I skip the last few rects by slicing the list, otherwise they would collide immediately. for trail in trail1[:-5]: if OnRectCollison(char1, trail): print('collision') for trail in trail2: if OnRectCollison(char1, trail): print('collision')
Rect
您在移动时将相同的对象 (char1
, )附加char2
到轨迹列表中,因此列表仅包含对头部矩形的引用,因此只有轨迹的头部能够碰撞。trail1.append(char1)
改为附加(浅)副本:
trail1.append(copy.copy(char1))
旁注:碰撞拼写错误。
推荐阅读
- linux - 使用 g++ -std=c++11 使用模板创建静态库
- c# - 我的应用程序不使用 SQL Server Express,但它正在 App_Data 中寻找数据库——为什么?
- matlab - 液位控制系统 - Simulink
- laravel - 如果您在使用 Laravel 的测试环境中,是否有默认模拟 API 请求的方法?
- python - 是否可以使用 Tweepy on_data 函数流式传输完整的推文
- r - 在R中按行编号非零元素
- c - 如何使用 char** ?(指向字符数组的指针)
- spring-boot - 无效的 JWToken:kid 是必需的 JOSE 标头
- rest - 如何根据 HATEOAS 约束使用 PUT 对资源创建进行建模?
- android - 如何修复未解决的参考:DialogFragment 中的 packageManager