首页 文章

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

提问于
浏览
1

在我的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 回答

  • 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 更容易 .


    EDIT:

    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

相关问题