繁体   English   中英

简单 2D Platformer 的 Pygame 中的碰撞检测问题

[英]Issue with Collision Detection in Pygame for simple 2D Platformer

这是我的第一篇文章,所以请告诉我是否应该更改任何内容。

我正在尝试创建一个简单的测试 2D 平台游戏,这是我在没有教程的情况下进行的第一个 pygame 项目。 我遇到的问题是由于这个can_jump变量。 我正在使用这个变量来阻止玩家在不在平台或屏幕底部时能够跳跃。 我曾尝试过其他方法,但这就是我最终的结果。 我觉得我已经很接近了。

目前的问题似乎是变量self.can_jump1在平台循环中不断在TrueFalse之间交换(我注意到的每个True正好是 3 个False s),当我站在平台上时,我已经将它隔离到评论中collision_check()中的部分。 我不知道为什么会发生这种情况,据我所知,代码的 rest 可以按我的意愿工作。

如果需要,我很乐意提供任何额外的信息/说明。

这是我的代码:

import pygame, sys, random

#---Classes----------------------------------------#
class Block(pygame.sprite.Sprite): #inherited by rest of classes
    def __init__(self,path,x_pos,y_pos,size_x,size_y):
        super().__init__()
        self.image = pygame.transform.scale(pygame.image.load(path).convert_alpha(),(size_x,size_y))
        self.rect = self.image.get_rect(center = (x_pos,y_pos))

class PlatformRect(pygame.sprite.Sprite):
    def __init__(self,x_pos,y_pos,size_x,size_y,colour,players):
        super().__init__()
        self.center_x = x_pos
        self.center_y = y_pos
        self.size_x = size_x
        self.size_y = size_y
        self.colour = colour
        self.players = players
        self.can_jump1 = None

        self.image = pygame.Surface((self.size_x,self.size_y))
        self.image.fill(self.colour)
        self.rect = self.image.get_rect(center = (self.center_x,self.center_y))

    def collision_check(self):
        if pygame.sprite.spritecollide(self,self.players,False):
            collision_paddle = pygame.sprite.spritecollide(self,self.players,False)[0].rect
            if abs(self.rect.top - collision_paddle.bottom) < 10:
                collision_paddle.bottom = self.rect.top
                player.movement_y = 0
                self.can_jump1 = True
        else: #error isolated to here,consistently fluctuates between True and False, not sure why
            self.can_jump1 = False
        print(self.can_jump1) #if standing on platform should only produce True, everywhere else produce False

    def can_jump_check(self):
        return self.can_jump1

    def update(self):
        self.collision_check()


class Player(Block):
    def __init__(self,path,x_pos,y_pos,size_x,size_y,speed_x,acceleration_y):
        super().__init__(path,x_pos,y_pos,size_x,size_y)
        self.size_x = size_x
        self.size_y = size_y
        self.speed_x = speed_x
        self.acceleration_y = acceleration_y
        self.movement_x = 0
        self.movement_y = 0

    def screen_constrain(self):
        if self.rect.bottom >= sresy:
            self.rect.bottom = sresy
        if self.rect.left <= 0:
            self.rect.left = 0
        if self.rect.right >= sresx:
            self.rect.right = sresx

    def update(self):
        if abs(self.movement_y) <= 9:
            self.movement_y += GRAVITY
        self.rect.centery += self.movement_y
        self.rect.centerx += self.movement_x
        self.screen_constrain()

class GameManager:
    def __init__(self,player_group,platform_group):
        self.player_group = player_group
        self.platform_group = platform_group
        self.can_jump = True

    def run_game(self):
        #---drawing---#
        self.player_group.draw(screen)
        self.platform_group.draw(screen)

        #---updating---#
        self.player_group.update()
        self.platform_group.update()

    def game_checking(self):
        #---checking---#
        for sprite_platform in self.platform_group.sprites():
            if not sprite_platform.can_jump_check() == True:
                self.can_jump = False
            else:
                self.can_jump = True
            return self.can_jump




#---Setup------------------------------------------#
#---constants-----#
global GRAVITY
GRAVITY = 0.25

#---Gamevariables-----#
can_jump = True

#---colour---#
bg_colour = (50,50,50)
white_colour = (255,255,255)
black_colour = (0,0,0)

#---res---#
resx = 900
resy = 675
sresx = resx - 50
sresy = resy - 50


#---start window-----#
clock = pygame.time.Clock()

screendisplay = pygame.display.set_mode((resx,resy))
screendisplay.fill(bg_colour)
pygame.display.set_caption("PlatformerGame1 started 09/02/2021")

screen = pygame.Surface((sresx,sresy))
screen.fill(white_colour)

#---startgame-----#
player = Player("assets\\pics\\TestPlayerFigure1_256512.png",100,100,32,64,10,30)
player_group = pygame.sprite.GroupSingle()
player_group.add(player)

platform1 = PlatformRect(100,550,100,10,black_colour,player_group)
platform_group = pygame.sprite.Group()
platform_group.add(platform1)

game_manager = GameManager(player_group,platform_group)

#---Loop--------------------------------------------#
while True:
    #---events-----#
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                sys.exit()

            if event.key == pygame.K_SPACE:
                if can_jump == True:
                    player.movement_y = 0
                    player.movement_y -= player.acceleration_y * GRAVITY
            if event.key == pygame.K_a:
                player.movement_x -= player.speed_x
            if event.key == pygame.K_d:
                player.movement_x += player.speed_x

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_SPACE:
                if player.movement_y < 0:
                    player.movement_y = 0
            if event.key == pygame.K_a:
                player.movement_x += player.speed_x
            if event.key == pygame.K_d:
                player.movement_x -= player.speed_x

    #---background---#
    screendisplay.blit(screen,(25,25))
    screen.fill(white_colour)

    #---running---#
    game_manager.run_game()
    if not game_manager.game_checking() == True and player.rect.bottom < sresy:
        can_jump = False
    else:
        can_jump = True
    #print(can_jump)

    #---updating-----#
    pygame.display.update()
    clock.tick(60)

当玩家站在平台上时,玩家不会与平台发生碰撞,并且self.can_jump1设置为False 当玩家不与平台发生碰撞时,测试玩家是否平台上:

self.can_jump1 = False

self.can_jump1 = self.rect.top == self.players.sprites()[0].rect.bottom

方法collision_check

class PlatformRect(pygame.sprite.Sprite):
    # [...]

    def collision_check(self):
        collide_list = pygame.sprite.spritecollide(self,self.players,False)
        if collide_list: 
            collision_paddle = collide_list[0].rect
            if abs(self.rect.top - collision_paddle.bottom) < 10:
                collision_paddle.bottom = self.rect.top
                player.movement_y = 0
                self.can_jump1 = True
        else:
            self.can_jump1 = self.rect.top == self.players.sprites()[0].rect.bottom

GameManager.game_checking需要检查 plyer 是否与任何平台发生碰撞:

class GameManager:
    # [...]

    def game_checking(self):
        #---checking---#
        self.can_jump = False
        for sprite_platform in self.platform_group.sprites():
            if sprite_platform.can_jump_check() == True:
                self.can_jump = True
        return self.can_jump

这可以使用any function 来简化:

class PlatformRect(pygame.sprite.Sprite):
    # [...]

    def game_checking(self):
        #---checking---#
        self.can_jump = any(p.can_jump_check() for p in self.platform_group)
        return self.can_jump

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM