0

I am currently trying to make my own platformer on pygame. I have coded the collisions for the top and bottom of the platform so that the player can only jump on top of the platform if they are falling onto it. However, if the player walks into the side of the platform, he snaps on top of it. How can I make it so the sides of a platform act as a border? This is my update section in the main game loop:

def update(self):
    self.all_sprites.update() 
    hits = p.sprite.spritecollide(self.player, self.platforms, False) 
    if self.player.vel.y > 0: 
        if hits: 
            self.player.rect.bottom = hits[0].rect.top + 1 
            self.player.pos = self.player.rect.midbottom 
            self.player.vel.y = 0 
    if self.player.vel.y < 0: 
        if hits: 
            self.player.rect.top = hits[0].rect.bottom 
            self.player.pos = self.player.rect.midbottom 
            self.player.vel.y = 0 

I have tried using this, but it didnt work:

if self.player.vel.x > 0:
    if hits:
        self.player.rect.right = hits[0].rect.left
        self.player.pos = self.player.rect.midleft
        self.player.vel.x = 0
if self.player.vel.x < 0:
    if hits:
        self.player.rect.left = hits[0].rect.right
        self.player.pos = self.player.rect.midright
        self.player.vel.x = 0

This is my player class:

vec = p.math.Vector2 

class Player(p.sprite.Sprite): 
    def __init__(self, game):
        p.sprite.Sprite.__init__(self) 
        self.game = game 
        self.image = p.Surface((p_width, p_height)) 
        self.image.fill(p_colour) 
        self.rect = self.image.get_rect() 
        self.rect.center = (0, height - 30) 
        self.pos = vec(0, height - 30) 
        self.vel = vec(0, 0) 
        self.acc = vec(0, 0)

    def jump(self): 
       
        self.rect.y += 1 
        hits = p.sprite.spritecollide(self, self.game.platforms, False) 
        self.rect.y -= 1 
        if hits: 
            self.vel.y = p_jump 
    def update(self): 
        self.acc = vec(0, p_grav) 

        keys = p.key.get_pressed() 

        if keys[p.K_LEFT]: 
            self.acc.x = -p_acc 
        if keys[p.K_RIGHT]: 
            self.acc.x = p_acc 

        self.acc.x += self.vel.x * p_friction 

        self.vel += self.acc 
        self.pos += self.vel + 0.5 * self.acc 

        if self.rect.right > width - 1: 
            self.rect.right = width - 1 
            self.pos = self.rect.midbottom 
        if self.rect.left < 1: 
            self.rect.left = 1 
            self.pos = self.rect.midbottom 
        self.rect.midbottom = self.pos 

Any help is appreciated. I tried keeping the code minimal

Rabbid76
  • 177,135
  • 25
  • 101
  • 146
Mr-Nightmare
  • 65
  • 1
  • 7
  • 1
    Make sure you are not evaluating the vertical hits if you have made a horizontal hit during the same cycle. Evaluate the x direction first, and if you hit, set a flag to prevent the vertical hit from begin checked. You should probably "back away" from the platform too, so you don't get a vertical hit the next iteration., – RufusVS Dec 31 '20 at 17:10
  • I’m not too sure what you mean could you elaborate please? – Mr-Nightmare Dec 31 '20 at 17:14
  • 1
    I think your collision logic will be evaluated for both a vertical and horizontal collision at the same time, so even if you try to use the x-collision logic, you will still evaluate the y-collision logic. – RufusVS Dec 31 '20 at 17:21
  • pygame doesn't give information on which side you colide (vertically or horizontally) so better split it in two steps. First move only vertically and check collision. If you collide then you know it is vertical collision (if you was moving down then you collide on bottom side, if you was moving up then you collide on top side). Next move only horizontally and check collision again. If you collide then you know that it horizontal collision (if you was moving left then you collide on left side, if you was moving rigth then you collide on right side). – furas Dec 31 '20 at 18:12
  • So would I create a function for collisions and call it every time I move the player? – Mr-Nightmare Jan 01 '21 at 11:07
  • @RufusVS Would you be able to let me know if my comment above is correct or not? Im still stuck and some example code would be appreciatedif its no trouble – Mr-Nightmare Jan 06 '21 at 12:00
  • As I envision it, you are checking the collision of what are ultimately two rectangles. When you get a collision, you should check where the relative corners are, to decide if the collision is a "from above" collision or "hit the side" collision. To me, it is a comparison of the bottom corners of the player and the top corners of the platform. – RufusVS Jan 07 '21 at 02:28
  • @RufusVS I see, so when there is a collision, instead of using the velocities, i should use the rectangle borders instead to determine if it is the sides, or top/bottom being hit – Mr-Nightmare Jan 08 '21 at 10:35
  • You will change your velocity in one direction depending on the hit, and you may need to "back off" the player away from the platform so you don't get a second hit on the next pass through your logic. – RufusVS Jan 08 '21 at 13:35

0 Answers0