简体   繁体   中英

Issue with Collision Detection in Pygame for simple 2D Platformer

This is my first post so please let me know if I should alter anything.

I am attempting to create a simple test 2D platformer, this is the first pygame project I've undertaken without a tutorial. The issue I am encountering is due to this can_jump variable. I am using this variable to stop the player from being able to jump when not on a platform or the bottom of the screen. I had attempted other methods but this is where I have ended up. I feel I've gotten so close.

The issue at the moment appears to be that the variable self.can_jump1 continuously swaps between True and False in the platform loop (at exactly 3 False s for every True I have noticed) when standing on a platform, I have isolated it to the commented section in collision_check() . I don't know why this happens, and as far as I can tell the rest of the code works as I want it.

I would be happy to provide any extra information/clarification if need be.

Here's my code:

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)

When the player is standing on the platform, the player does not collide with the platform and self.can_jump1 is set False . Test if the player is on the platform when the player does not collide with the platform:

self.can_jump1 = False

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

Method 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 needs to check if the plyer collides with any platform:

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

This can be simplified with the 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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