如何检查任何矩形是否包含圆圈? (在pygame中)

时间:2017-01-22 15:18:47

标签: python pygame

在我的pygame中,我有一个带有for循环的几个矩形。我有一个由圆形物体代表的玩家。它看起来像这样:

enter image description here

因此玩家可以使用箭头键移动,这会使每个键移动一个点。最终玩家不应该移动到这些矩形之外。所以每次他们搬家我想检查: 如果(任何绘制的矩形包含一个玩家):返回True否则返回False。

有没有简单的方法可以做到这一点?或者我应该彻底改变我的做法?

它不应该像这样在矩形外的点上移动: enter image description here

但仅限于这样的矩形: enter image description here

这是我现在拥有的这个例子的代码:

import pygame

pygame.init()

#grid
w = 25
h = 25
m = 2

size = (550, 700)
screen = pygame.display.set_mode(size)
screen.fill((255, 255, 255))


class Player:
    def __init__(self):
        self.x = 149
        self.y = 14
        self.r = 10

    def draw(self):
        pygame.draw.circle(screen, (255, 0, 0), (self.x, self.y), self.r)

    def update(self,event):
            if event.key == pygame.K_LEFT:
                screen.fill((250, 250, 250))
                self.x -= 27
                self.draw()
            elif event.key == pygame.K_RIGHT:
                screen.fill((250, 250, 250))
                self.x += 27
                self.draw()
            elif event.key == pygame.K_UP:
                screen.fill((250, 250, 250))
                self.y -= 27
                self.draw()
            elif event.key == pygame.K_DOWN:
                screen.fill((250, 250, 250))
                self.y += 27
                self.draw()

player1 = Player()
player1.draw()

done = False

while not done:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

        elif event.type == pygame.KEYDOWN:
            player1.update(event)

        for row in range(5):
            for col in range(5):
                if row == 0 or row == 4 or col == 0 or col == 4:
                    pygame.draw.rect(screen, (0,0,0), ((w + m) * col + m, ((h + m) * row + m), w, h), 1)

    pygame.display.flip()

有一个 Rect.contains(Rect)函数,但如果一个矩形包含另一个矩形,则会检查它。是否可能有这样的函数基本上说:选择所有现有的矩形并检查它们是否包含(选择矩形)?

任何提示或帮助都绝对赞赏。如果这是完全错误的做法,请告诉我。

问候。

1 个答案:

答案 0 :(得分:1)

您可以将circle视为rectangle。如果将所有对象视为矩形,则需要较少的计算(CPU功率)来检查冲突。

您必须创建包含所有矩形的列表,以便您可以使用此列表检查圈子位置 - 然后您可以使用circle_rect.colliderect(some_rect)

import pygame

# --- constants ---

#grid
W = 25
H = 25
M = 2

SIZE = (550, 700)

BLACK = (  0,   0,   0)
WHITE = (255, 255, 255)
RED   = (255,   0,   0)

FPS = 25
# --- classes ---

class Player:

    def __init__(self):
        # to keep position and size
        self.rect = pygame.Rect(0, 0, 20, 20)

        # set start position
        self.rect.center = 149, 14

        self.r = 10

    def draw(self):
        pygame.draw.circle(screen, RED, self.rect.center, self.r)

    def update(self, event):
        # create copy of position
        newrect = self.rect.copy()

        # move "copy" to new position
        if event.key == pygame.K_LEFT:
            newrect.x -= 27
        elif event.key == pygame.K_RIGHT:
            newrect.x += 27
        elif event.key == pygame.K_UP:
            newrect.y -= 27
        elif event.key == pygame.K_DOWN:
            newrect.y += 27

        # check if "copy" is still in rectangles
        for rectangle in all_rectangles:
            if newrect.colliderect(rectangle):
                # now you can set new position
                self.rect = newrect
                # don't check other rectangles
                break

# --- main ---

# - init -

pygame.init()

screen = pygame.display.set_mode(SIZE)
screen_rect = screen.get_rect()

# - objects -

player1 = Player()

# create list with rectangles (but not draw them)

all_rectangles = []

for row in range(5):
    for col in range(5):
        if row == 0 or row == 4 or col == 0 or col == 4:
            all_rectangles.append( pygame.Rect((W + M) * col + M, ((H + M) * row + M), W, H) )

# - mainloop -

clock = pygame.time.Clock()    
done = False

while not done:

    # - events (without draws) -
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            done = True

        elif event.type == pygame.KEYDOWN:
            player1.update(event)


    # - draw everything in one place -

    screen.fill(WHITE)

    for rectangle in all_rectangles:
        pygame.draw.rect(screen, BLACK, rectangle, 1)

    player1.draw()

    pygame.display.flip()

    # - FPS - keep the same speed on all computers -

    clock.tick(FPS)

# - end -
pygame.quit()

BTW:您可以使用rowcol代替xy来保留矩形位置和圆位(并检查碰撞) )并且在绘制时仅将row/col转换为x/y。您还可以使用矩形创建列表,如

all_rectangles = [
   "######",
   "#    #",
   "#    #",
   "#    #",
   "######",
]

然后创建地图会更容易。

修改

map = [
   "########  #######",
   "#      ####     #",
   "#      #  #     #",
   "#    ########   #",
   "######      #   #",
   "   #        #####",
   "   #          #  ",
   "   ############  ",
]

all_rectangles = []

for r, row in enumerate(map):
    for c, item in enumerate(row):
        if item == '#':
            all_rectangles.append(pygame.Rect((W + M) * c + M, ((H + M) * r + M), W, H))

enter image description here