0
votes

I am trying to add a platform to my game so that once you hit it the player stays on the platform until it fall off in which case it would hit the ground. The jump does work but the collision does not

I have tried adding some of the typical types of collision detectors below but they all have down sides

class Platform:
    def __init__(self, x, y, background):
        self.xpos = x
        self.ypos = y
        self.picture = background
        self.picture = pygame.transform.scale(self.picture, (500, 100))
        self.rect = self.picture.get_rect()

    def draw(self):
        screen.blit(self.picture, (self.xpos, self.ypos))

class Player:
    def __init__(self, x, y, pic_one, pic_two, pic_three, pic_four):
        self.xpos = x
        self.ypos = y
        self.speed_y = 0
        self.speed_x = 0
        self.picture = pic_one
        self.picture_one = pic_one
        self.picture_two = pic_two
        self.picture_three = pic_three
        self.picture_four = pic_four
        self.on_ground = True
        self.picture = pygame.transform.scale(self.picture, (100, 100))
        self.rect = self.picture.get_rect()

    def update(self):
        self.xpos += self.speed_x
        self.ypos += self.speed_y

        GRAVITY = 0.9

        self.speed_y += GRAVITY  # Accelerate downwards.
        self.xpos += self.speed_x 
        self.ypos += self.speed_y


        if self.ypos >= 620:
            self.ypos = 620
            self.speed_y = 0
            self.on_ground = True


        if self.on_ground == True:
            self.speed_y = 0


    def jump(self):
        if self.on_ground:
            self.on_ground = False
            self.speed_y = -20#Makes you move upwards

    def draw(self):
        screen.blit(self.picture, (self.xpos, self.ypos))

    def is_collided_with(self, sprite):
        return self.rect.colliderect(sprite.rect)

player_one = Player(30, 600, player_one_first_pic)
wood_platform = Platform(400, 400, platform_pic)
while True:
    [...]

this is the typical type of collision I would try and have used but the if statement appears to never happen

if player_one.rect.bottom == wood_platform.rect.top:
    player_one.on_ground = True

another on which I have tried which is detecting if the rectangles collide and the if statement is True even when the rectangles are not colliding

if player_one.is_collided_with(wood_platform):
     player_one.on_ground = True 

this method I am not comfortable with doing because its insufficient

if player_one.ypos == 600:
    player_one.on_ground = True

The actual results for the method that I used were that the player did not collide with the wooden platform at all

(Here is a diagram if you do need a little bit more of an understanding:) player_platform Checks for collision but does not appear to work

if player_one.rect.y == wood_platform.rect.y:
        print(True)
        player_one.on_ground = True
        on_platform = True

    else:
        on_platform = False

changes after each update

self.rect.x = self.xpos
self.rect.y = self.ypos
2

2 Answers

1
votes

As for me problem is that you use self.xpos, self.ypos to move object and you don't change values in self.rect (self.rect.x, self.rect.y) but you use self.rect to check collision.

You have to set

self.rect.x = self.xpos
self.rect.y = self.ypos 

before you check collision.

And you have to do this for all moving objects. Maybe it is better to do this after every move.


You could use only self.rect.x, self.rect.y (instead of self.xpos, self.ypos) but it can keeps only integer values. You use float value in gravity and self.rect.x, self.rect.y would round down position and gives not so smooth animation.

But objects which don't use float gravity or float speed could use only self.rect to keep position.

0
votes

I often have the same problem in my job. Checking if numbers are equal might fail when using floats. You could try to change this

if player_one.rect.bottom == wood_platform.rect.top:
    player_one.on_ground = True

to this:

margin = 0.001 # Whatever amount you feel comfy with.
if wood_platform.rect.top*(1-margin) <= player_one.rect.bottom <= wood_platform.rect.top*(1+margin):
    player_one.on_ground = True