简体   繁体   English

如何检测碰撞? pygame

[英]How to detect collision? pygame

I am creating platfrormer game and there are red squares (they should kill me) and white squares (platforms) when I die, I should revive on the start of current level.我正在创建 platfrormer 游戏,当我死时有红色方块(他们应该杀了我)和白色方块(平台),我应该在当前关卡开始时复活。 I did collision detection, but it works only if I´m moving (when I jump to red squares and i´m not pressing anything, it doesn´t work)我做了碰撞检测,但它只有在我移动时才有效(当我跳到红色方块并且我没有按下任何东西时,它不起作用)

so I really want to know how to do collisions better.所以我真的很想知道如何更好地进行碰撞。

thanks code:感谢代码:

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()```

You check for collisions with the killing_entities list for each event in each frame.您检查每帧中每个事件与killing_entities列表的冲突。 So if there's currently not event in the event queue, the lines:因此,如果事件队列中当前没有事件,则以下行:

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

are never executed.永远不会被执行。 I guess you want that code in your main loop only, not in the event handling loop.我猜您只希望在主循环中使用该代码,而不是在事件处理循环中。

There are some more oddities in your code, eg您的代码中还有一些奇怪的地方,例如

  • You don't handle the QUIT event so you can't close the game's window.您不处理QUIT事件,因此您无法关闭游戏的 window。

  • You use the same variable running as condition for your main loop and to change the player's xvel .您使用相同的变量running作为主循环的条件并更改播放器的xvel

  • There's also no need to update the display twice (just use pygame.display.flip() ).也不需要更新显示两次(只需使用pygame.display.flip() )。

  • You're blitting a huge (3200x32px) Surface 1024 times per frame to the screen.你每帧将一个巨大的(3200x32px)Surface 传送到屏幕上 1024 次。 If you want to fill the screen with the color black, just call screen.fill('black') once per frame.如果你想用黑色填充屏幕,只需每帧调用screen.fill('black')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM