2017-01-22 6 views
1

В моем pygame я нарисовал пару прямоугольников с циклом for. У меня есть игрок, который представлен объектом круга. Это выглядит следующим образом:Как проверить, содержит ли круг какой-либо прямоугольник? (in 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 (Rect) функция, но это проверяет, если один прямоугольник содержит другой прямоугольник. Возможно, есть такая функция, которая в основном говорит: выберите все существующие прямоугольники и проверьте, содержат ли они (выбранный rect)?

Любые советы или помощь абсолютно оценены. Также дайте мне знать, если это совершенно неправильный подход к выполнению всего этого.

Приветствия.

+0

'' pygame.draw.circle' возвращает объект python.Rect' таким образом Вы можете обрабатывать 'circle' как' rectangle'. Кроме того, вы можете использовать 'row',' col' вместо 'x',' y' для проверки «столкновения». – furas

+1

НО есть одна небольшая ошибка во всем вашем коде - вы не сохраняете позиции всех прямоугольников в списке, чтобы вы не могли проверить их положение с положением круга. – furas

+0

BTW: чтобы сделать код более читаемым, вы можете сохранить все классы и функции до 'pygame.init()' - см. [Простой шаблон] (https://github.com/furas/python-examples/blob/master/pygame/ __templates __/1__simple__.py) – furas

ответ

1

Вы можете обрабатывать circle как rectangle. Для проверки коллизий, если вы рассматриваете все объекты как прямоугольники, требуется меньше вычислений (мощность процессора).

Вы должны создать список всех прямоугольников, чтобы вы могли проверить положение круга с этим списком - а затем вы можете использовать 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() 

КСТАТИ: вы могли бы использовать row, col вместо x, y, чтобы сохранить прямоугольники в позициях и положении круга (и проверить коллизии) и только конвертировать row/col в x/y, когда вы его нарисуете. Вы также можете создать список с прямоугольниками, например

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

, а затем его легче создать.


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

+0

После тщательного изучения я создал список со всей позицией со всеми позициями, как вы делали, чтобы сравнить движение сначала перед перемещением игрока, мой pygame работает именно так, как я хочу его сейчас !! Спасибо, я навсегда благодарен !! – Noob17

+1

@ Noob17 см. [Другие модификации] (https://github.com/furas/python-examples/tree/master/pygame/example-maze) – furas