python - 如何检测碰撞? pygame

标签 python collections pygame collision-detection

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

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

谢谢 代码:

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所以你无法关闭游戏窗口。

  • 您使用相同的变量running作为主循环的条件并更改玩家的xvel

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

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

关于python - 如何检测碰撞? pygame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66778231/

相关文章:

python - 使用python脚本在 Notepad++ 中进行多词搜索和替换

Python 元组 : compare and merge without for loops

python - 装饰一个函数并添加功能,保留参数的数量

javascript - CollectionFS Meteor、所见即所得、Summernote、图片上传

python - 如何将关卡布局保存在变量中

python - 类型错误 : 'pygame.Surface' object is not callable [Pygame module]

python - 如何将系列和 pandas 的数据框合并为一个数据框?

Java Immutable Collection,也修复引用

即使我导入了集合,也没有定义 python 全局名称 'collections'

python - 自动完成并不总是适用于 Pycharm