碰撞检测不适用于pygame

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了碰撞检测不适用于pygame相关的知识,希望对你有一定的参考价值。

我正在制作游戏,我遇到了碰撞检测问题。我正在结束等级块,但它无法检测到玩家是否站在它上面以更改为等级2.该块的碰撞检测在player.updater()中找到。除此之外,该块是一个类,并且在一个名为endPlatform的组中,以允许冲突检测工作。游戏运行完全正常,但它无法检测播放器何时触及Endplatform。我没有出现任何错误。

EndPlatform:

class EndPlatform(pygame.sprite.Sprite):
    def __init__(self, display):
        super().__init__()
        self.image = pygame.image.load("endPlatform.png")
        self.rect = self.image.get_rect()
        display.blit(self.image, self.rect)

玩家:

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        # Is it touching the floor?
        self.standing = True
        # Rendering image and creating some variables
        self.image = pygame.image.load("Slime.png")
        self.sprite_x_change = 0
        self.sprite_y_change = 0
        self.rect = self.image.get_rect()
        self.rect.y = 460
        self.rect.x = 120
    # Mobility: Left, right, up and stop
    def move_right(self):
        self.sprite_x_change = 8

    def move_left(self):
        self.sprite_x_change = -8

    def move_up(self, platform):
        if self.standing ==  True:
            self.sprite_y_change = -25
            self.standing = False
    def stop(self):
        self.sprite_x_change = 0

    def sprint(self):
        self.sprite_x_change += 10

    def updater(self, platforms, powerups, score, endPlatform):
        self.gravity()
        self.rect.x += self.sprite_x_change
        self.standing = False
        platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
        for blocks in platforms_hit:
            if self.sprite_x_change > 0:
                self.rect.right = blocks.rect.left

            elif self.sprite_x_change < 0:
                self.rect.left = blocks.rect.right

        self.rect.y += self.sprite_y_change

        platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
        for blocks in platforms_hit:
            # Going down
            if self.sprite_y_change > 0:
                self.rect.bottom = blocks.rect.top - 1
                self.standing = True
            # Going up
            elif self.sprite_y_change < 0:
                self.rect.top = blocks.rect.bottom
                self.standing = False

            self.sprite_y_change = 0

        coins_hit = pygame.sprite.spritecollide(self, powerups, True)
        if len(coins_hit) > 0:
            score.add()
        endLevel = pygame.sprite.spritecollide(self, endPlatform, True)
        if len(endLevel) > 0:
            score.add()

所有代码:

import pygame
import random

pygame.font.init()
# Colours + Global constants
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0,  0, 255)
BLACK = (0, 0, 0)
RANDOM = (12, 211, 123)
WIDTH = 800
HEIGHT = 600
SIZE = (WIDTH, HEIGHT)
AGENT = pygame.font.SysFont("Agent Orange", 30)


# CLASSES
# Block is the common platform
class EndPlatform(pygame.sprite.Sprite):
    def __init__(self, display):
        super().__init__()
        self.image = pygame.image.load("endPlatform.png")
        self.rect = self.image.get_rect()
        display.blit(self.image, self.rect)




class Coins(pygame.sprite.Sprite):
    def __init__(self, display):
        super().__init__()
        self.image = pygame.image.load("hud_coins.png")
        self.rect = self.image.get_rect()
        display.blit(self.image, self.rect)



class Score:
    def __init__(self):
        self.score = 0

    def msgs(self, msg, colour, display):
        screen_text = AGENT.render(msg, True, colour)
        display.blit(screen_text, [0, 0])

    def add(self):
        self.score += 1


class Monster(pygame.sprite.Sprite):
    def __init__(self, length, height, colour):
        super().__init__()
        self.image = pygame.Surface([length, height])
        self.image.fill(colour)
        self.rect = self.image.get_rect()
        # Setting Y coordinates
        self.rect.y = HEIGHT - 80

    def jump(self):
        self.rect.y = -10


class Block(pygame.sprite.Sprite):
    def __init__(self, length, height, colour):
        super().__init__()
        # Making image
        self.image = pygame.Surface([length, height])
        self.image.fill(colour)
        self.rect = self.image.get_rect()
        # Setting Y coordinates
        self.rect.y = 468


class Platform(pygame.sprite.Sprite):
    def __init__(self, display, x_screen, y_screen, x_sheet, y_sheet, height, length):
        super().__init__()

        self.tiles = pygame.image.load("tiles_spritesheet.png")

        self.image = self.tiles.subsurface(pygame.Rect(x_sheet, y_sheet, height, length))
        self.rect = self.image.get_rect(x=x_screen, y=y_screen)



class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        # Is it touching the floor?
        self.standing = True
        # Rendering image and creating some variables
        self.image = pygame.image.load("Slime.png")
        self.sprite_x_change = 0
        self.sprite_y_change = 0
        self.rect = self.image.get_rect()
        self.rect.y = 460
        self.rect.x = 120
    # Mobility: Left, right, up and stop
    def move_right(self):
        self.sprite_x_change = 8

    def move_left(self):
        self.sprite_x_change = -8

    def move_up(self, platform):
        if self.standing ==  True:
            self.sprite_y_change = -25
            self.standing = False
    def stop(self):
        self.sprite_x_change = 0

    def sprint(self):
        self.sprite_x_change += 10

    def updater(self, platforms, powerups, score, endPlatform):
        self.gravity()
        self.rect.x += self.sprite_x_change
        self.standing = False
        platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
        for blocks in platforms_hit:
            if self.sprite_x_change > 0:
                self.rect.right = blocks.rect.left

            elif self.sprite_x_change < 0:
                self.rect.left = blocks.rect.right

        self.rect.y += self.sprite_y_change

        platforms_hit = pygame.sprite.spritecollide(self, platforms, False)
        for blocks in platforms_hit:
            # Going down
            if self.sprite_y_change > 0:
                self.rect.bottom = blocks.rect.top - 1
                self.standing = True
            # Going up
            elif self.sprite_y_change < 0:
                self.rect.top = blocks.rect.bottom
                self.standing = False

            self.sprite_y_change = 0

        coins_hit = pygame.sprite.spritecollide(self, powerups, True)
        if len(coins_hit) > 0:
            score.add()
        endLevel = pygame.sprite.spritecollide(self, endPlatform, True)
        if len(endLevel) > 0:
            score.add()

    def gravity(self):
        self.sprite_y_change += 3


class Level:
    def __init__(self):
        # Creating groups
        self.endPlatform = pygame.sprite.Group()
        self.powerups = pygame.sprite.Group()
        self.sprites = pygame.sprite.Group()
        self.all_things = pygame.sprite.Group()
        self.platforms = pygame.sprite.Group()
        self.entities = pygame.sprite.Group()
        self.shift_x = 0
        self.shift_y = 0

    def updater(self, display, score):
        self.all_things.draw(display)
        score.msgs("Score: " + str(score.score), RED, display)


    def scroll_x(self, shift_x_change):
        self.shift_x += shift_x_change
        for platform in self.entities:
            platform.rect.x += shift_x_change

    def scroll_y(self, shift_y_change):
        self.shift_y += shift_y_change
        for platform in self.entities:
            platform.rect.y += shift_y_change



class Level01(Level):
    def __init__(self, player1, monster, display):
        # Initialise level1
        super().__init__()
        # Level01 things
        block = Block(245, 3, BLACK)
        Level.all_things = self.all_things
        self.sprites.add(player1, monster)
        self.platforms.add(block)
        self.all_things.add(player1, block, monster)
        self.entities.add(block)

        theLevel = []

        level = [[600, 400, 648, 0, 70, 70],
                 [740, 320, 648, 0, 70, 70],
                 [380, 400, 648, 0, 70, 70],
                 [900, 280, 648, 0, 70, 70],
                 [1200, 530, 648, 0, 70, 70],
                 [1350, 450, 648, 0, 70, 70],
                 [1500, 550, 648, 0, 70, 70],
                 [1680, 500, 648, 0, 70, 70],
                 ]

        for platform in theLevel:
            block = Block(platform[0], platform[1], RED)
            block.rect.x = platform[2]
            block.rect.y = platform[3]
            self.platforms.add(block)
            self.all_things.add(block)
            self.entities.add(block)
        for goodPlatform in level:
            platform = Platform(display, goodPlatform[0], goodPlatform[1], goodPlatform[2], goodPlatform[3], goodPlatform[4], goodPlatform[5])
            self.platforms.add(platform)
            self.all_things.add(platform)
            self.entities.add(platform)
        for n in range(1):
            coin = Coins(display)
            coin.rect.x = random.randint(0, WIDTH*3)
            coin.rect.y = 400
            self.all_things.add(coin)
            self.entities.add(coin)
            self.powerups.add(coin)
            platforms_hit = pygame.sprite.spritecollide(coin, self.entities, False)
            for hit in platforms_hit:
                coin.rect.x = random.randrange(0, WIDTH*3)
        finalPlatform = EndPlatform(display)
        finalPlatform.rect.x = 1900
        finalPlatform.rect.y = 420
        self.all_things.add(finalPlatform)
        self.entities.add(finalPlatform)
        self.platforms.add(finalPlatform)
        self.endPlatform.add(finalPlatform)


class Level02(Level):
    def __init__(self, player1, monster):
        super().__init__()
        # Level01 things
        block = Block(245, 3, BLACK)
        Level.all_things = self.all_things
        self.sprites.add(player1, monster)
        self.platforms.add(block)
        self.all_things.add(player1, block, monster)
def main():
    # Init pygame
    pygame.init()
    # Set screen
    backgrounds = ["background2.jpg", "background.jpg"]
    background = pygame.image.load(backgrounds[0])
    backgroundRect = background.get_rect()
    display = pygame.display.set_mode(background.get_size())
    # Creating FPS thingy
    clock = pygame.time.Clock()
    # Making levels  + Player
    score = Score()
    monster = Monster(30, 30, RANDOM)
    player = Player()
    level_1 = Level01(player, monster, display)
    level_2 = Level02(player, monster)
    # Choosing level
    levelList = []
    levelList.append(level_1)
    levelList.append(level_2)
    currentLevelNumber = 0
    # Game loop
    loop = True
    while loop == True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RIGHT:
                        player.move_right()
                    if event.key == pygame.K_LEFT:
                        player.move_left()
                    if event.key == pygame.K_UP:
                        player.move_up(currentLevel.platforms)
                    if event.key == pygame.KMOD_LSHIFT and event.key == pygame.K_RIGHT:
                        player.sprint()
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT and player.sprite_x_change < 0:
                    player.stop()
                if event.key == pygame.K_RIGHT and player.sprite_x_change > 0:
                    player.stop()
                if event.key == pygame.KMOD_LSHIFT:
                    player.sprite_x_change -= 10
        # Update things
        #monster.jump()
        if player.rect.x > 400:
            player.rect.x = 400
            currentLevel.scroll_x(-10)

        if player.rect.x >= WIDTH:
            player.rect.x = WIDTH
            currentLevel.scroll(0)

        if player.rect.y >= HEIGHT:
            main()

        if player.sprite_x_change < 0 and player.rect.x >= 120:
            currentLevel.scroll_x(0)


        if player.rect.left <= 120 and player.sprite_x_change < 0:
            player.rect.x = 120
            player.rect.left = 120
            currentLevel.scroll_x(10)
        '''
        if player.rect.y <= 300:
            if player.standing == False and player.sprite_y_change < 0:
                currentLevel.scroll_y(10)

        if currentLevel.shift_y > 0:
            y_speed = -4
            if player.standing == True and player.rect.y < 300:
                y_speed = 4
            print(currentLevel.shift_y)
            currentLevel.scroll_y(y_speed)
        '''
        currentLevel = levelList[currentLevelNumber]

        if currentLevel.shift_x > 0:
            currentLevel.scroll_x(currentLevel.shift_x * -1)

        display.blit(background, backgroundRect)
        player.updater(currentLevel.platforms, currentLevel.powerups, score, currentLevel.endPlatform)
        currentLevel.updater(display, score)
        # Refresh screen
        clock.tick(30)
        pygame.display.update()
    pygame.quit()
    loop = False

if __name__ == "__main__":
    main()
答案

我似乎发现了这个问题,因为一些愚蠢的原因你不能在同一个对象上使用两次碰撞检测。我曾经使用过一次,所以玩家可以站在街区和另一个时间,这样你就可以进入下一个级别了!

另一答案

它没有切换到下一个级别的原因是当你与平台碰撞时你改变了矩形的位置,所以player.rect被移出blocks.rect,因此当你用spritecollide调用endPlatform时它不能再碰撞for blocks in platforms_hit:集团。

一个快速而肮脏的修复方法是检查True循环,如果该块在endPlatform组中,然后返回for blocks in platforms_hit: if blocks in endPlatform: score.add() return True

currentLevelNumber

如果返回main,则增加True函数中的change_level = player.updater(currentLevel.platforms, currentLevel.powerups, score, currentLevel.endPlatform) if change_level: currentLevelNumber += 1

qazxswpoi

以上是关于碰撞检测不适用于pygame的主要内容,如果未能解决你的问题,请参考以下文章

pygame游戏检测矩形是否碰撞指定颜色的自定义函数(仅5行代码)

pygame游戏检测矩形是否碰撞指定颜色的自定义函数(仅5行代码)

Pygame碰撞检测

如何在pygame中检测两个矩形对象或图像之间的碰撞

Pygame中图像和矩形之间的碰撞检测?

pygame碰撞检测函数python3中的语法错误[重复]