Question

I am making a 8bit style platformer. The player falls and gains speed because of the pseudo gravity but he will fall a few pixels into the ground level. Without gravity he will land on the ground and not fall though but it is a constant fall speed.When in the ground you can go up but he will fall when you let up. He will not got down so that is not an issue for now. Any help would be appreciated.

The player class/file.

import pygame,sys
from pygame.locals import *
class Player:
    x=0
    y=0
    offset = 5
    L=False
    R=False
    U=False
    D=False
    image = None
    gravity = .25
    velocity = offset
    objectDict = None #this si the list of the current objects so that collision can be check with every
    #object.. get updated every loop to keep a accurate check of locations
    rect = None
    grav = True    #TODO use this to check if we are paying attention to the gravity
    def __init__(self,x,y):
        self.x = x
        self.y = y
        self.image = pygame.image.load('Resources/Pics/player.png')



    def draw(self,DISPLAY):
        #print('draw will go here')
        imgRect = self.image.get_rect()
        imgRect.midleft = (self.x,self.y)
        self.rect = imgRect
        DISPLAY.blit(self.image, imgRect)
        #and now im here

    def checkCollide(self,otherRect):
        return self.rect.colliderect(otherRect)

    def checkCollideAll(self):
        if(self.objectDict != None):
            # print(len(self.objectDict))
        #     for x in range(1,len(self.objectDict)):
        #         newb = self.checkCollide(self.objectDict[x].getRect())
        #         print(self.objectDict[x].getRect())
        #     if(newb):
        #         return True
        # return False
            collideNum = self.rect.collidelist(self.objectDict)
            if(collideNum == -1):
                return False
            else:
                return True

    def willCollideBelow(self):
        if(self.objectDict):
            checkRect = (self.x,(self.y),self.image.get_size())
            collideNum = self.rect.collidelist(self.objectDict)
            if collideNum == -1:
                return False
            else:
                return True


    def objUpdate(self,dict):
        self.objectDict = dict

    def getRect(self):
        return self.rect

    def update(self):
        # while(self.checkCollideAll()):
        #     print('while happened')
        #     self.y -= self.offset
        #     imgRect = self.image.get_rect()
        #     imgRect.midleft = (self.x,self.y)
        #     self.rect = imgRect
        # print(self.willCollideBelow())
        if not self.willCollideBelow():
            self.D = True
            # print('will fall')
        else:
            self.D = False

        if self.U == True:
            self.y -= self.offset

        if self.D == True:
                self.y += self.velocity
                if not self.velocity >= 9.8:
                    self.velocity += self.gravity
        else:
            self.velocity = self.offset
        if self.L == True:
                self.x -= self.offset

        if self.R == True:
                self.x += self.offset
Was it helpful?

Solution

You didn't provide a running example and your code is hard to read (pascal case, a lot of unnecessary parenthesis), but here's my guess:

In your willCollideBelow function, you check if you hit an object beneath the player:

def willCollideBelow(self):
        if(self.objectDict):
            checkRect = (self.x,(self.y),self.image.get_size())
            collideNum = self.rect.collidelist(self.objectDict)
            if collideNum == -1:
                return False
            else:
                return True

instead of just returning True or False, return the object (or the index of the object) you actually collide with:

def will_collide_below(self):
        if(self.objectDict):
            # using 'collidelistall' would be better, but that's another topic
            return self.rect.collidelist(self.objectDict)

Now that you know which object the player collides with, you can adjust the vertical position of the player:

ground_i = self.will_collide_below()
if ground_i:
    ground = self.objectDict[ground_i]
    self.velocity = 0
    self.rect.bottom = ground.top # or self.y = ground.top

You'll get the idea.


Some more notes:

You use different variables to store the position of the player (I see x, y, rect and imgRect). It would make you code a lot simpler if you would just use a single Rect to store the position:

class Player:
    ...
    def __init__(self,x,y):
        self.image = pygame.image.load('Resources/Pics/player.png')
        self.rect = self.image.get_rect(midleft=(x,y))

    def draw(self, display):
        display.blit(self.image, self.rect)

    def update(self):
        ...
        if self.L: # no need to check == True
            self.rect.move_ip(-self.offset)

        if self.R: # simply use move_ip to alter the position
            self.rect.move_ip(self.offset)

You also use a bunch of class variables where you really should use instance variables, like rect, L, R, U and D.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top