[英]Pygame: Collision by Sides of Sprite
pygame 中有没有办法在 pygame 中寻找精灵的特定侧面和另一个精灵的特定侧面之间的碰撞? 例如,如果精灵 A 的顶部与精灵 B 的底部碰撞,则返回 True。
我确信有一种方法可以做到这一点,但我在文档中找不到任何特定的方法。
谢谢!
PyGame 中没有获得侧面碰撞的功能。
但是你可以尝试使用pygame.Rect.collidepoint来测试A.rect.midleft
, A.rect.midright
, A.rect.midtop
, A.rect.midbottom
, A.rect.topleft
, A.rect.bottomleft
, A.rect.topright
, A.rect.bottomright
在B.rect
( pygame.Rect ) 内。
编辑:
示例代码。 使用箭头移动玩家并接触敌人。
(可能不是最佳解决方案)
import pygame
WHITE = (255,255,255)
BLACK = (0 ,0 ,0 )
RED = (255,0 ,0 )
GREEN = (0 ,255,0 )
BLUE = (0 ,0 ,255)
class Player():
def __init__(self, x=0, y=0, width=150, height=150):
self.rect = pygame.Rect(x, y, width, height)
self.speed_x = 5
self.speed_y = 5
self.move_x = 0
self.move_y = 0
self.collision = [False] * 9
self.font = pygame.font.SysFont("", 32)
self.text = "";
def set_center(self, screen):
self.rect.center = screen.get_rect().center
def event_handler(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self.move_x -= self.speed_x
elif event.key == pygame.K_RIGHT:
self.move_x += self.speed_x
elif event.key == pygame.K_UP:
self.move_y -= self.speed_y
elif event.key == pygame.K_DOWN:
self.move_y += self.speed_y
elif event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
self.move_x += self.speed_x
elif event.key == pygame.K_RIGHT:
self.move_x -= self.speed_x
elif event.key == pygame.K_UP:
self.move_y += self.speed_y
elif event.key == pygame.K_DOWN:
self.move_y -= self.speed_y
def update(self):
self.rect.x += self.move_x
self.rect.y += self.move_y
def draw(self, screen):
pygame.draw.rect(screen, WHITE, self.rect, 2)
self.draw_point(screen, self.rect.topleft, self.collision[0])
self.draw_point(screen, self.rect.topright, self.collision[1])
self.draw_point(screen, self.rect.bottomleft, self.collision[2])
self.draw_point(screen, self.rect.bottomright, self.collision[3])
self.draw_point(screen, self.rect.midleft, self.collision[4])
self.draw_point(screen, self.rect.midright, self.collision[5])
self.draw_point(screen, self.rect.midtop, self.collision[6])
self.draw_point(screen, self.rect.midbottom, self.collision[7])
self.draw_point(screen, self.rect.center, self.collision[8])
def draw_point(self, screen, pos, collision):
if not collision:
pygame.draw.circle(screen, GREEN, pos, 5)
else:
pygame.draw.circle(screen, RED, pos, 5)
def check_collision(self, rect):
self.collision[0] = rect.collidepoint(self.rect.topleft)
self.collision[1] = rect.collidepoint(self.rect.topright)
self.collision[2] = rect.collidepoint(self.rect.bottomleft)
self.collision[3] = rect.collidepoint(self.rect.bottomright)
self.collision[4] = rect.collidepoint(self.rect.midleft)
self.collision[5] = rect.collidepoint(self.rect.midright)
self.collision[6] = rect.collidepoint(self.rect.midtop)
self.collision[7] = rect.collidepoint(self.rect.midbottom)
self.collision[8] = rect.collidepoint(self.rect.center)
def render_collision_info(self):
text = "collision: "
print "collision:",
if self.collision[0] or self.collision[2] or self.collision[4]:
text += "left "
print "left",
if self.collision[1] or self.collision[3] or self.collision[5]:
text += "right "
print "right",
if self.collision[0] or self.collision[1] or self.collision[6]:
text += "top "
print "top",
if self.collision[2] or self.collision[3] or self.collision[7]:
text += "bottom "
print "bottom",
if self.collision[8]:
text += "center "
print "center",
print
self.text = self.font.render(text, 1, WHITE)
def draw_collision_info(self, screen, pos):
screen.blit(self.text, pos)
#----------------------------------------------------------------------
class Game():
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode( (800,600) )
pygame.display.set_caption("Side Collision")
self.player = Player()
self.enemy = Player()
self.enemy.set_center(self.screen)
def run(self):
clock = pygame.time.Clock()
RUNNING = True
while RUNNING:
# --- events ----
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
RUNNING = False
self.player.event_handler(event)
# --- updates ---
self.player.update()
self.enemy.update()
self.player.check_collision(self.enemy.rect)
self.enemy.check_collision(self.player.rect)
self.player.render_collision_info()
self.enemy.render_collision_info()
# --- draws ----
self.screen.fill(BLACK)
self.player.draw(self.screen)
self.enemy.draw(self.screen)
self.player.draw_collision_info(self.screen, (0,0))
self.enemy.draw_collision_info(self.screen, (0,32))
pygame.display.update()
# --- FPS ---
clock.tick(30)
pygame.quit()
#----------------------------------------------------------------------
Game().run()
编辑(08.2016):带有碰撞rect
、 rect_ratio
、 circle
就像 Furas 所说的那样,不,没有办法在 Pygame 中通过他设置的点系统来获得侧面碰撞。 甚至那个也不会给你你想要的东西,因为在处理矩形的行、列或角时,你永远无法确定碰撞发生在哪个方向。
这就是为什么大多数教程建议保存您的精灵初始方向。 然后在发生碰撞时向相反的方向移动。
我通过创建多个碰撞盒解决了这个问题。 这应该可以帮助很多人。
代码:
if tanner.axe.colliderect(oak.red) and.
tanner.playerHitBox.colliderect(oak.leftHit) and.
keys_pressed[pygame.K_SPACE]:
Number_of_Hits_Left += 1
print(Number_of_Hits_Left)
if tanner.axe.colliderect(oak.red) and.
tanner.playerHitBox.colliderect(oak.rightHit) and.
keys_pressed[pygame.K_SPACE]:
Number_of_Hits_Right += 1
print(Number_of_Hits_Right)
所以我总共有 5 个命中盒来完成上述任务。 实际上,您所要做的就是创建主命中框,然后在主命中框的左侧和右侧创建 2 个侧框,以便它们几乎不重叠。 因此,假设您发射子弹,您的代码将类似于上面的内容。 “当子弹与侧框碰撞以及子弹与主框碰撞时,做点什么。”
碰撞背后的逻辑是这样的:
#Assume two surfaces
objectA
objectB
if objectA.right > objectB.left and objectA.left < objectB.right and objectA.top < objectB.bottom and objectA.bottom > objectB.top
#Collision happens
如果您想检测侧面碰撞(就像 objectA 在侧面击中 objectB),您可以执行以下操作:
#Here is the code where objectA moves
objectA.X += 10
#Here check Collision, if collision happens objectA hitted objectB from the side
objectA.Y += 10
#Here check Collision again, if collision is true then objectA hitted object B from top/bottom
对于 objectA 给对象这个方法:
def is_collided_with(self, sprite): return self.rect.colliderect(sprite.rect)
此 return 语句返回 True 或 False
然后在碰撞的主循环中只做: if objectA.is_collided_with(ObjectB): Collision happened!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.