如何在Pygame中检查矩形与矩形的先前位置的碰撞?

时间:2019-02-28 22:04:32

标签: python pygame

我正在制作Tron游戏(https://www.classicgamesarcade.com/game/21670/tron-game.html),需要检查所有赛车手是否相互碰撞。

import pygame
pygame.init()

screenWidth = 500
screenHeight = 500
clock = pygame.time.Clock()
win = pygame.display.set_mode((screenWidth,screenHeight))
#both width and height of the characters
radius = 5
#amount of change in the x or y of the characters every frame
vel = 5

pygame.display.set_caption("Tron")


class character(object):
    #'direction' is the direction the character will move
    #'keyBinds' are the keys that can change the direction
    def __init__(self, x, y, color, direction, keyBinds):
        self.x = x
        self.y = y
        self.color = color
        self.direction = direction
        self.keyBinds = keyBinds

    #changes the direction the character moves
    def changeDirection(self, keys):
        #only changes when the right key was pressed and the character isn't already moving the opposite direction
        if keys[self.keyBinds[0]] and self.direction != 'r': 
            self.direction = 'l'
        elif keys[self.keyBinds[1]] and self.direction != 'l':
            self.direction = 'r'
        elif keys[self.keyBinds[2]] and self.direction != 'd':
            self.direction = 'u'
        elif keys[self.keyBinds[3]] and self.direction != 'u':
            self.direction = 'd'

    def move(self, vel):
        if self.direction == 'l':
            self.x -= vel
        elif self.direction == 'r':
            self.x += vel
        elif self.direction == 'u':
            self.y -= vel
        elif self.direction == 'd':
            self.y += vel

    #returns True if the character should be dead
    def checkDead(self, radius, screenWidth, screenHeight):
        #check if the character is out of bounds
        if (self.x < 0) or (self.x + radius > screenWidth) or (self.y < 0) or (self.y + radius > screenWidth):
            return True
        #check if the character has collided WIP


#makes a list with characters
chars = [
    character(480, 250, (255,0,0), 'l', (pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN)),
    character(20, 250, (0,255,0), 'r', (pygame.K_a, pygame.K_d, pygame.K_w, pygame.K_s))
    ]
run = True

#main loop
while run:
    #makes the loop run 30 times a second
    clock.tick(30)

    #closes the window, if 'X' is pressed
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    #logs all keys being pressed in a list I think xd
    keys = pygame.key.get_pressed()

    #closes the window, if there are no characters left in 'chars'
    if len(chars) > 0:
        #runs all object functions of every character in 'chars'
        for char in chars:
            char.changeDirection(keys)
            char.move(vel)
            #draws a rectangle representing the charater
            pygame.draw.rect(win, char.color, (char.x, char.y, radius, radius))
            #removes the character from 'chars' if checkDead returns True
            if char.checkDead(radius, screenWidth, screenHeight):
                chars.pop(chars.index(char))
    else:
        run = False

    pygame.display.update()

pygame.quit()

只有2个赛车手(在我的代码中称为字符),我可以仅使用一堆if语句来检查其命中框的位置是否匹配,但是我计划稍后再增加8个赛车手。我认为这不是一个好选择。

现在,问题来了。 与经典《特隆》中的赛车一样,我也需要让赛车手的先前位置也算在内。

此外,我总是感谢我如何改善代码的提示,因此,如果您发现任何不同的处理方法,请告诉我!

谢谢!

编辑1:将标题更改为:如何在Pygame中检查多个对象的矩形碰撞?到:如何在Pygame中检查矩形与矩形的先前位置之间的碰撞?,因为主要问题已经在其他文章中得到解答,但仍有其他问题需要解答。 另外,在我的代码结构中,冲突检查将在checkDead()

中进行

1 个答案:

答案 0 :(得分:1)

最后,Tron是一款基于格网的游戏,所以一个简单的解决方案是仅保留“已获得”欠款的点/平铺列表,然后检查玩家是否试图移至已获得的图块。

...
painted = set()
...
class character(object):
    ...
    #returns True if the character should be dead
    def checkDead(self, radius, screenWidth, screenHeight, painted):
        #check if the character is out of bounds
        if (self.x < 0) or (self.x + radius > screenWidth) or (self.y < 0) or (self.y + radius > screenWidth):
            return True

        #check if the character has collided WIP
        return (char.x / radius, char.y / radius) in painted

...
while run:
    ...
    #closes the window, if there are no characters left in 'chars'
    if len(chars) > 0:
        #runs all object functions of every character in 'chars'
        for char in chars:
            char.changeDirection(keys)
            char.move(vel)
            #removes the character from 'chars' if checkDead returns True
            if char.checkDead(radius, screenWidth, screenHeight, painted):
                chars.pop(chars.index(char))

        for char in chars:
            painted.add((char.x / radius, char.y / radius))

        for char in chars:
            #draws a rectangle representing the charater
            pygame.draw.rect(win, char.color, (char.x, char.y, radius, radius))

请注意,这是因为每帧移动一个图块。如果您决定让玩家每帧移动一个以上的图块,那么您也必须将这些额外的图块添加到painted集中。

当然,有许多不同的方法可以做到这一点。例如,您可以检查要绘制矩形的屏幕部分是否有非黑色像素。或者,您可以将绘制到屏幕上的所有矩形存储在列表中,并使用Rect.colliderect检查是否存在碰撞(可能很慢)。因此,让我们保持简单。