碰撞检测在pygam中不起作用

2024-04-20 13:45:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在做一个游戏,我遇到了碰撞检测的问题。我正在做一个关卡结束,但它不能检测到玩家是否站在它上面去改变到2级。块的碰撞检测在中找到播放器更新程序(). 此外,该块是一个类和一个名为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)

玩家:

^{pr2}$

所有代码:

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()

Tags: rectimageselfaddifinitdefdisplay
2条回答

它不切换到下一个级别的原因是,当rect与平台发生冲突时,您更改了rect的位置,因此player.rect将移出{},因此当您使用endPlatform组调用{}时,它就不会再发生碰撞。在

如果块在endPlatform组中,那么一个快速而棘手的修复方法是检查for blocks in platforms_hit:循环,然后返回True

for blocks in platforms_hit:
    if blocks in endPlatform:
        score.add()
        return True

如果返回True,则增加main函数中的currentLevelNumber

^{pr2}$

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

相关问题 更多 >