0

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 
0

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

17 Comments

So if I now do if player_one.rect.y (player one is the object) == wood_platform.rect.y would that work because thats what I feel most comfy doing
you can do it - but it may not works if you move player more than one pixel in every move. In one moment player_one.rect.y can be smaller than wood_platform.rect.y (so it doesn't collide) and in next moment it can be bigger than wood_platform.rect.y (so it collides) and == will not catch it. Better use self.rect.colliderect(other.rect). It can also recognize collision on left/right side or when you jump and player's head touch platform at bottom - so it should stop moving up and start moving down.
Ok, I have added the code block above but this appears to still not happen
do you use self.rect.x , self.rect.y in Player and in Platform ?
Yes I can confirm that I do
|
0

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 

Comments