2017-01-22 114 views
1

在我的pygame中,我绘制了一个带for循环的几个矩形。我有一个由一个圆圈物体代表的球员。它看起来像这样:如何检查任何矩形是否包含圆? (在pygame中)

enter image description here

所以玩家可以用方向键移动,这将移动它们每一个关键点。最终,玩家不应该移动到这些矩形之外。所以他们每次移动我想检查: 如果(任何绘制的矩形包含一个球员):return True else return 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(矩形)功能,但此检查,如果一个矩形包含另一个矩形。是否有这样的功能,基本上说:选择所有现有的矩形,并检查它们是否包含(选择矩形)?

任何提示或帮助绝对赞赏。同时让我知道这是否是完全错误的方法来做这件事。

问候。

+0

'pygame.draw.circle'返回'python.Rect'对象,所以你可以把'circle'为'rectangle'。此外,你可以使用'row','col'而不是'x','y'来检查'collision'。 – furas

+1

但是在你所有的代码中都有一个小错误 - 你不能保留列表上所有矩形的位置,所以你不能检查它们在圆位置的位置。 – furas

+0

BTW:为了使代码更具可读性,你可以在pygame.init()之前保留所有类和函数 - 参见[简单模板](https://github.com/furas/python-examples/blob/master/pygame/ __templates __/1__simple__.py) – furas

回答

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:你可以使用,而不是rowcolx,y保持矩形位置和圆圈位置(和检查碰撞),并且只绘制时将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

+0

彻底彻底地完成之后,我创建了一个包含所有位置的列表,并且像移动播放器之前那样比较移动,我的pygame正在按照我现在想要的方式工作!谢谢你,我永远感激! – Noob17

+1

@ Noob17查看[其他修改](https://github.com/furas/python-examples/tree/master/pygame/example-maze) – furas