简体   繁体   中英

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. 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. 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.

  • You use the same variable running as condition for your main loop and to change the player's xvel .

  • There's also no need to update the display twice (just use pygame.display.flip() ).

  • You're blitting a huge (3200x32px) Surface 1024 times per frame to the screen. If you want to fill the screen with the color black, just call screen.fill('black') once per frame.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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