碰撞检测不适用于pygame

时间:2015-11-25 17:13:05

标签: python 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()

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

它没有切换到下一级别的原因是你在与平台发生碰撞时改变了矩形的位置,因此player.rect被移出blocks.rect因此,当您使用spritecollide群组致电endPlatform时,又无法再次发生碰撞。

快速而肮脏的修复方法是检查for blocks in platforms_hit:循环,如果该块位于endPlatform组中,然后返回True

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