如何在 pygame 中让正方形和圆形发生碰撞以触发游戏结束?

How do I make collisions between square and circle to trigger a game over in pygame?

我正在制作一个游戏,其中有一堆掉落的圆圈,玩家(正方形)需要避开它们。问题是我找不到让圆圈和玩家碰撞以触发游戏结束的方法。有没有办法让方块和圆圈相撞触发游戏结束或者游戏在pygame退出?

import pygame
from pygame.locals import *
import os
import random
import math
import sys
import time

white = (255,255,255)
blue = (0,0,255)
gravity = 10
size =10
height = 500
width =600
varHeigth = height
ballNum = 5
eBall = []
apGame = pygame.display.set_mode((width, height))
pygame.display.set_caption("AP Project")

clock = pygame.time.Clock()

class Player(object):

  def __init__(self):
    red = (255, 0, 0)
    move_x = 300
    move_y = 400
    self.rect = pygame.draw.rect(apGame,red, (move_x, move_y, 10, 10))
    self.dist = 10

  def handle_keys(self):
    for e in pygame.event.get():
      if e.type == pygame.QUIT:
        pygame.quit();
        exit()
    key = pygame.key.get_pressed()
    if key[pygame.K_LEFT]:
      self.draw_rect(-1, 0)
    elif key[pygame.K_RIGHT]:
      self.draw_rect(1, 0)
    elif key[pygame.K_ESCAPE]:
      pygame.quit();
      exit()
    else:
      self.draw_rect(0, 0)

  def draw_rect(self, x, y):
    red = (255, 0, 0)
    black = (0, 0, 0)
    '''apGame.fill(black)'''
    self.rect = self.rect.move(x * self.dist, y * self.dist);
    pygame.draw.rect(apGame, red , self.rect)
    pygame.display.update()


  def draw(self,surface):
    red = (255, 0, 0)
    move_x = 300
    move_y = 400
    pygame.draw.rect(apGame, red, (move_x, move_y, 10, 10))


move_x = 300
move_y = 400
red = (255, 0, 0)
black = (0, 0, 0)
player = Player()
clock = pygame.time.Clock()
'''apGame.fill(black)'''
player.draw(apGame)
pygame.display.update()

for q in range(ballNum):
  x = random.randrange(0, width)
  y = random.randrange(0, varHeigth)
  eBall.append([x, y])

while True:

  apGame.fill(black)


  for i in range(len(eBall)):

    pygame.draw.circle(apGame, blue, eBall[i], size)

    eBall[i][1] += 5

    if eBall[i][1] > height:

        y = random.randrange(-50, -10)
        eBall[i][1] = y

        x = random.randrange(0, width)
        eBall[i][0] = x

  player.handle_keys()
  pygame.display.flip()
  clock.tick(30)

使用球的边界矩形进行碰撞测试就足够了。界pygame.Rect is returned by pygame.draw.circle(). If 2 rectangles are intersecting can be evaluated by colliderect()

例如:

while True:
  # [...]

  for i in range(len(eBall)):

    ball_rect = pygame.draw.circle(apGame, blue, eBall[i], size)

    if player.rect.colliderect(ball_rect):
        print("hit")

    # [...]

如果你想在一个单独的循环中做碰撞测试,那么你必须手动构造球的边界矩形:

while True:
  # [...]

  for ball in eBall:
      ball_rect = pygame.Rect(ball[0]-size, ball[1]-size, size*2, size*2)
      if player.rect.colliderect(ball_rect):
          print("hit")

有 pygame 矩形的碰撞检查,可以检测矩形之间或矩形与点之间的碰撞。还有用于精灵的碰撞例程,将进行基于圆的碰撞检查(参见 here)。但是我不知道有任何内置例程可以进行圆到矩形碰撞检查。

正如@rabbid76 在他的回答中所说,通常人们只是通过使用 rect 作为圆来近似它。

如果将用于碰撞检测的圆矩形缩小到比圆的矩形边界框略小,这样角就会露出更少(但它实际上在顶部、底部、圆圈的左侧和右侧)通常不会注意到您实际上并没有使用圆圈。虽然它并不完美。

您还可以使用遮罩并对其进行碰撞检查,see here。它的计算成本更高,所以如果你这样做,你需要记住这一点。