python - 碰撞检测在 pygame 中不起作用

标签 python pygame

我现在正在制作游戏,但遇到了碰撞检测问题。我正在制作一个关卡结束 block ,但它无法检测玩家是否站在其上以更改为第 2 级。该 block 的碰撞检测可在player.updater() 中找到。除此之外,该 block 是一个类,位于一个名为 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()

最佳答案

看来我发现了问题,由于某些愚蠢的原因,你不能在同一个对象上使用两次碰撞检测。我使用它一次是为了让玩家能够站在方 block 上,另一次则是为了让你可以进入下一个关卡!

关于python - 碰撞检测在 pygame 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33922546/

相关文章:

python - 如何修复碰撞,以便我可以站在盒子上而不会从盒子上掉下来

python - gTTS 无法保存文件两次

python-3.x - 用于 2D Python 游戏编程的工具包选项

python - 在 Django 中使用通用 create_object View 设置对象所有者

python - 在 python 中解析 METAR 网页

python:当类属性、实例属性和方法都同名时会发生什么?

python:二进制文件的正则表达式搜索模式(半字节)

python - Trac SvnAuthzAdminPlugin 不显示用户

python - Pygame alpha 仅在多边形中

python - Pygame - 创建 "Enemy"类,然后将其导入游戏