如何检测碰撞? pygame

How to detect collision? pygame

我正在创建平台游戏并且有红色方块(他们应该杀了我)和白色方块(平台) 当我死了,我应该在当前水平的开始复活。 我做了碰撞检测,但它只有在我移动时才有效(当我跳到红色方块并且我没有按下任何东西时,它不起作用)

所以我真的很想知道如何更好地处理碰撞。

谢谢 代码:

from pygame import *

WIN_WIDTH = 1923
WIN_HEIGHT = 1000

DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
DEPTH = 32
FLAGS = 0
CAMERA_SLACK = 30

pygame.init()

green = (0, 255, 0)


screen = pygame.display.set_mode(DISPLAY, FLAGS, DEPTH)

font = pygame.font.SysFont('Consolas', 30)
text = font.render('Your Score: ', True, (0, 255, 0))
textRect = text.get_rect()
textRect.center = (40, 55)

level = [
"PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
"P                                                          P",
"P                                                          P",
"P                        PP                                P",
"P                                                          P",
"P                                 PP                       P",
"P                                                          P",
"P                                                          P",
"P             PP                                           P",
"P                                                          P",
"P                                                          P",
"P                                                          P",
"P                                                          P",
"P                     PP                                   P",
"P                                                          P",
"P                                                          P",
"P                                                          P",
"P                                                   P      P",
"P                            PP                     P      P",
"P                                                   P      P",
"P                                                   P      P",
"P                                                   P      P",
"P                    PP                             P      P",
"P                                                   P      P",
"P                                                   P      P",
"P           PP                                      P      P",
"P                                                   P      P",
"P                      PPP                          P     PP",
"P                                                   P      P",
"P                                                   P     LP",
    "PSSSSSSSSSSSSSSSSSSSSSSPPPSSSSSSSSSSSSSSSSSSSSSSSSSSPSSPPPPPPP",
"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE",
]



def main():
    pygame.display.set_caption("Use W,A,S,D and Space to move!")
    timer = pygame.time.Clock()

    up = down = left = right = running = left_dash = right_dash = dashing = False
    bg = Surface((3200,32))
    bg.convert()
    bg.fill(Color("#000000"))
    entities = pygame.sprite.Group()
    platforms = []
    killing_entities = []
    another_level = []
    blockade = []
    player = Player(767, 900)


    x = y = 0


    global level
    for row in level:
        for col in row:
            if col == "P":
                p = Platform(x, y)
                platforms.append(p)
                entities.add(p)
            if col == "E":
                e = Block(x, y)
                platforms.append(e)
                entities.add(e)
            if col == "S":
                s = Spike(x, y)
                killing_entities.append(s)
                entities.add(s)
            if col == "L":
                l = Another_Level(x, y)
                another_level.append(l)
                entities.add(l)

            x += 32
        y += 32
        x = 0

    entities.add(player)
    running = True
    while running:
        screen.blit(text, textRect)

        timer.tick(65)

        for e in pygame.event.get():
            if e.type == KEYDOWN and e.key == K_SPACE:
                up = True
            if e.type == KEYDOWN and e.key == K_s:
                down = True
            if e.type == KEYDOWN and e.key == K_a:
                left = True
            if e.type == KEYDOWN and e.key == K_d:
                right = True
            if e.type == KEYDOWN and e.key == K_q:
                running = True
            if e.type == KEYDOWN and e.key == K_LEFT:
                left_dash = True
            if e.type == KEYDOWN and e.key == K_RIGHT:
                right_dash = True                

            if e.type == KEYUP and e.key == K_SPACE:
                up = False
            if e.type == KEYUP and e.key == K_s:
                down = False
            if e.type == KEYUP and e.key == K_d:
                right = False
            if e.type == KEYUP and e.key == K_a:
                left = False
            if e.type == KEYUP and e.key == K_d:
                right = False

            if pygame.sprite.spritecollideany(player, killing_entities):
                main()

            if pygame.sprite.spritecollideany(player, another_level):
                level = [
    "PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "PPS                                                        P",
    "PEE                                                        P",
    "PSS                                                        P",
    "P                                                          P",
    "P                                                          P",
    "PP                                                         P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P                                                          P",
    "P         P                                                P",
        "PSSSSSSSSSSSSSSSSSSSSSSPPPSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSPPPP",
    "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE",
]
                main()

        for y in range(32):
            for x in range(32):
                screen.blit(bg, (x * 32, y * 32))

        player.update(up, down, left, right, left_dash, right_dash, running, dashing, platforms)
        entities.draw(screen)
        
        pygame.display.flip()
        pygame.display.update()

class Entity(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

class Player(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.xvel = 0
        self.yvel = 0
        self.onGround = False
        self.image = Surface((32,32))
        self.image.fill(Color("#0000FF"))
        self.image.convert()
        self.rect = Rect(x, y, 32, 32)

    def update(self, up, down, left, right, left_dash, right_dash, running, dashing, platforms):
        if up:
            if self.onGround: self.yvel -= 9
        if down:
            pass
        if running:
            self.xvel = 12

        if left_dash:
            self.rect.move_ip(-20, -2)
            left_dash = False
        
        if right_dash:
            self.rect.move_ip(20, -2)
            right_dash = False

        if left:
            self.xvel = -8
        if right:
            self.xvel = 8
        if not self.onGround:
            self.yvel += 0.25
            if self.yvel > 100: self.yvel = 100
        if not(left or right):
            self.xvel = 0        
        self.rect.left += self.xvel
        self.collide(self.xvel, 0, platforms)
        self.rect.top += self.yvel
        self.onGround = False
        self.collide(0, self.yvel, platforms)

    def collide(self, xvel, yvel, platforms):
        for p in platforms:
            if pygame.sprite.collide_rect(self, p):
                if isinstance(p, Block):
                    pygame.event.post(pygame.event.Event(QUIT))
                if xvel > 0:
                    self.rect.right = p.rect.left
                if xvel < 0:
                    self.rect.left = p.rect.right
                if yvel > 0:
                    self.rect.bottom = p.rect.top
                    self.onGround = True
                    self.yvel = 0
                if yvel < 0:
                    self.rect.top = p.rect.bottom
                    self.onGround = False
    

class Platform(Entity):
    def __init__(self, x, y):
        Entity.__init__(self)
        self.image = Surface((32, 32))
        self.image.convert()
        self.image.fill(Color("#DDDDDF"))
        self.rect = Rect(x, y, 32, 32)

    def update(self):
        pass

class Block(Platform):
    def __init__(self, x, y):
        Platform.__init__(self, x, y)
        self.image.fill(Color("#000000"))

class Spike(pygame.sprite.Sprite):
    def __init__(self, x, y):
        Platform.__init__(self, x, y)
        self.image = Surface((33, 33))
        self.image.convert()
        self.image.fill(Color("#E70018"))
        self.rect = Rect(x, y, 33, 33)

class Another_Level(pygame.sprite.Sprite):
    def __init__(self, x, y):
        Platform.__init__(self, x, y)
        self.image = Surface((33, 33))
        self.image.convert()
        self.image.fill(Color("#8C563E"))
        self.rect = Rect(x, y, 33, 33)
        
        
if __name__ == "__main__":
    main()```

您检查每个帧中每个事件与 killing_entities 列表的冲突。因此,如果事件队列中当前没有事件,则行:

if pygame.sprite.spritecollideany(player, killing_entities):
    main()

永远不会执行。我猜你只想在主循环中使用该代码,而不是在事件处理循环中。

您的代码中还有一些奇怪的地方,例如

  • 您没有操作QUIT event所以您无法关闭游戏window.

  • 您使用相同的变量 running 作为主循环的条件并更改播放器的 xvel.

  • 也无需更新显示两次(只需使用 pygame.display.flip())。

  • 您正在将一个巨大的 (3200x32px) 表面每帧传输到屏幕 1024 次。如果你想用黑色填充屏幕,只需每帧调用一次screen.fill('black')