gpt4 book ai didi

python - 在 Pygame 中检测多边形和矩形之间的碰撞

转载 作者:行者123 更新时间:2023-12-04 08:51:12 25 4
gpt4 key购买 nike

所以我试图用 pygame 制作一个我们中间的类型游戏。我刚开始,所以我没有太多东西,现在正在制作 map 。但是,我正在努力解决的一件事是碰撞逻辑。 map 现在有一个细长的八边形形状,但我认为无论形状如何,我都会使用类似 pygame 多边形的东西。当我运行我现在拥有的代码时,它会检查我的玩家(pygame 矩形)和墙壁(pygame 多边形)之间的碰撞,它说:TypeError: Argument must be rect style object我发现这是因为 pygame 多边形返回一个矩形,但在碰撞检查器中没有以这种方式分类。我尝试了一个名为 collision 的库,并归功于碰撞检测付出了巨大的努力,但玩家仍然能够穿过墙壁。旁注:我保存了我使用这个库的代码,如果有人想看到它,也许可以改进我的缺点。
无论如何,把这一切归结起来:
我需要一种方法来检测多边形和矩形之间的碰撞(真的,最好在 pygame 中)
感谢您提供的任何帮助,如果您有问题/要求,请发表评论。
这是我的代码:

import pygame
pygame.init()
W, H=500, 500
screen = pygame.display.set_mode([500, 500])
running = True

bcg=(200, 200, 200)
red=(255, 0 ,0)
purp=(255, 0, 255)
wall=(100, 100, 100)

class player:
def bg(self):
screen.fill(bcg)
x,y=self.x,self.y

self.outer=(
(x,y),
(x+800, y),
(x+1200, y+200),
(x+1200, y+600),
(x+800, y+800),
(x, y+800),
(x-400, y+600),
(x-400, y+200),

(x,y),

(x, y+50),
(x-350, y+225),
(x-350, y+575),
(x, y+750),
(x+800, y+750),
(x+1150, y+575),
(x+1150, y+225),
(x+800, y+50),
(x, y+50)
)

pygame.draw.polygon(screen, wall, self.outer)


def __init__(self, color, size=20, speed=0.25):
self.x=0
self.y=0
self.col=color
self.size=size
self.speed=speed


def draw(self):
s=self.size
self.rect=pygame.Rect(W/2-s/2, H/2-s/2, self.size, self.size)
pygame.draw.rect(screen, self.col, self.rect)

def move(self, x, y):
x*=self.speed
y*=self.speed
if not self.rect.colliderect(self.outer):
self.x+=x
self.y+=y




p=player(red)

while running:
for event in pygame.event.get():

if event.type == pygame.QUIT:
running = False

p.bg()

keys=pygame.key.get_pressed()

if keys[pygame.K_a]: p.move(1, 0)
if keys[pygame.K_d]: p.move(-1, 0)
if keys[pygame.K_w]: p.move(0, 1)
if keys[pygame.K_s]: p.move(0, -1)

p.draw()

pygame.display.update()

pygame.quit()

最佳答案

写一个函数 collideLineLine测试线段是否相交。这个函数的算法在问题pygame, detecting collision of a rotating rectangle的回答中有详细解释。 :

def collideLineLine(l1_p1, l1_p2, l2_p1, l2_p2):

# normalized direction of the lines and start of the lines
P = pygame.math.Vector2(*l1_p1)
line1_vec = pygame.math.Vector2(*l1_p2) - P
R = line1_vec.normalize()
Q = pygame.math.Vector2(*l2_p1)
line2_vec = pygame.math.Vector2(*l2_p2) - Q
S = line2_vec.normalize()

# normal vectors to the lines
RNV = pygame.math.Vector2(R[1], -R[0])
SNV = pygame.math.Vector2(S[1], -S[0])
RdotSVN = R.dot(SNV)
if RdotSVN == 0:
return False

# distance to the intersection point
QP = Q - P
t = QP.dot(SNV) / RdotSVN
u = QP.dot(RNV) / RdotSVN

return t > 0 and u > 0 and t*t < line1_vec.magnitude_squared() and u*u < line2_vec.magnitude_squared()
编写函数 colideRectLine测试矩形和线段是否相交。要测试线段是否与矩形相交,您必须测试它是否与矩形的 4 条边中的任何一条相交:
def colideRectLine(rect, p1, p2):
return (collideLineLine(p1, p2, rect.topleft, rect.bottomleft) or
collideLineLine(p1, p2, rect.bottomleft, rect.bottomright) or
collideLineLine(p1, p2, rect.bottomright, rect.topright) or
collideLineLine(p1, p2, rect.topright, rect.topleft))
下一个函数 collideRectPolygon测试多边形和矩形是否相交。这可以通过在循环中针对矩形测试多边形上的每个线段来实现:
def collideRectPolygon(rect, polygon):
for i in range(len(polygon)-1):
if colideRectLine(rect, polygon[i], polygon[i+1]):
return True
return False
最后你可以使用 collideRectPolygon用于碰撞测试。但是请注意,对于测试,您需要像玩家在移动一样使用多边形:
class player:
def bg(self):
screen.fill(bcg)
self.outer = self.createPolygon(self.x, self.y)
pygame.draw.polygon(screen, wall, self.outer)

def createPolygon(self, x, y):
return [
(x,y), (x+800, y), (x+1200, y+200), (x+1200, y+600),
(x+800, y+800), (x, y+800), (x-400, y+600), (x-400, y+200),
(x,y), (x, y+50), (x-350, y+225), (x-350, y+575),
(x, y+750), (x+800, y+750), (x+1150, y+575), (x+1150, y+225),
(x+800, y+50),(x, y+50)]

# [...]

def move(self, x, y):

x *= self.speed
y *= self.speed
polygon = self.createPolygon(self.x + x, self.y + y)
if not collideRectPolygon(self.rect, polygon):
self.x += x
self.y += y
另见 Collision and Intersection - Rectangle and polygon

最小的例子:
repl.it/@Rabbid76/PyGame-CollisionPolygonRectangle


完整示例:

import pygame
pygame.init()
W, H=500, 500
screen = pygame.display.set_mode([500, 500])
running = True

bcg=(200, 200, 200)
red=(255, 0 ,0)
purp=(255, 0, 255)
wall=(100, 100, 100)

def collideLineLine(l1_p1, l1_p2, l2_p1, l2_p2):

# normalized direction of the lines and start of the lines
P = pygame.math.Vector2(*l1_p1)
line1_vec = pygame.math.Vector2(*l1_p2) - P
R = line1_vec.normalize()
Q = pygame.math.Vector2(*l2_p1)
line2_vec = pygame.math.Vector2(*l2_p2) - Q
S = line2_vec.normalize()

# normal vectors to the lines
RNV = pygame.math.Vector2(R[1], -R[0])
SNV = pygame.math.Vector2(S[1], -S[0])
RdotSVN = R.dot(SNV)
if RdotSVN == 0:
return False

# distance to the intersection point
QP = Q - P
t = QP.dot(SNV) / RdotSVN
u = QP.dot(RNV) / RdotSVN

return t > 0 and u > 0 and t*t < line1_vec.magnitude_squared() and u*u < line2_vec.magnitude_squared()

def colideRectLine(rect, p1, p2):
return (collideLineLine(p1, p2, rect.topleft, rect.bottomleft) or
collideLineLine(p1, p2, rect.bottomleft, rect.bottomright) or
collideLineLine(p1, p2, rect.bottomright, rect.topright) or
collideLineLine(p1, p2, rect.topright, rect.topleft))

def collideRectPolygon(rect, polygon):
for i in range(len(polygon)-1):
if colideRectLine(rect, polygon[i], polygon[i+1]):
return True
return False

class player:
def bg(self):
screen.fill(bcg)
self.outer = self.createPolygon(self.x, self.y)
pygame.draw.polygon(screen, wall, self.outer)

def createPolygon(self, x, y):
return [
(x,y), (x+800, y), (x+1200, y+200), (x+1200, y+600),
(x+800, y+800), (x, y+800), (x-400, y+600), (x-400, y+200),
(x,y), (x, y+50), (x-350, y+225), (x-350, y+575),
(x, y+750), (x+800, y+750), (x+1150, y+575), (x+1150, y+225),
(x+800, y+50),(x, y+50)]

def __init__(self, color, size=20, speed=0.25):
self.x=0
self.y=0
self.col=color
self.size=size
self.speed=speed

def draw(self):
s=self.size
self.rect=pygame.Rect(W/2-s/2, H/2-s/2, self.size, self.size)
pygame.draw.rect(screen, self.col, self.rect)

def move(self, x, y):

x *= self.speed
y *= self.speed
polygon = self.createPolygon(self.x + x, self.y + y)
if not collideRectPolygon(self.rect, polygon):
self.x += x
self.y += y

p=player(red)
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

p.bg()

keys=pygame.key.get_pressed()

if keys[pygame.K_a]: p.move(1, 0)
if keys[pygame.K_d]: p.move(-1, 0)
if keys[pygame.K_w]: p.move(0, 1)
if keys[pygame.K_s]: p.move(0, -1)

p.draw()
pygame.display.update()

pygame.quit()

关于python - 在 Pygame 中检测多边形和矩形之间的碰撞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64095396/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com