title: Problems with Jumping in my pygame platormer
body: <p>In my pygame platformer, the jump height is inconsistent which means that the player sometimes jumps lower and sometimes higher than the height i want it to jump at. I also want to make the height that the player jumps at dependent on how long the space bar is held down. Is there a way that I can fix the jumping problem and make the jump height depend on how long the space bar is held? The code of the game's 3 files can be found below. Please tell me why the player isn't jumping at a fixed height and how I can make jump height based on the duration of the key press.</p>
  
  <p>Main.py</p>
  
  <pre><code>import pygame
  import random
  from settings import *
  from obj import *
  
  pygame.init()
  pygame.mixer.init()
  pygame.font.init()
  
  pygame.display.set_caption(TITLE)
  screen = pygame.display.set_mode([WIDTH,HEIGHT])
  
  clock = pygame.time.Clock()
  
  me = Player()
  all_sprites.add(me)
  
  platforms = []
  
  pf = Wall(100,40,500,400, 0)
  pf2 = Wall(WIDTH,40, 400,500, 0)
  platforms.append(pf)
  platforms.append(pf2)
  
  for i in platforms:
      wall_sprites.add(i)
  
  running = True
  
  while running:
      clock.tick(FPS)
  
      all_sprites.update()
      wall_sprites.update()
  
      for event in pygame.event.get():
          if event.type == pygame.QUIT:
              running = False
          if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
              me.jump()
  
      screen.fill(GREY)
      all_sprites.draw(screen)
      wall_sprites.draw(screen)
      pygame.display.update()
  
  pygame.quit()
  </code></pre>
  
  <p>obj.py</p>
  
  <pre><code>import pygame
  import math
  from settings import *
  
  class Player(pygame.sprite.Sprite):
      def __init__(self):
          pygame.sprite.Sprite.__init__(self)
          self.image = pygame.Surface((40,40))
          self.image.fill(BLACK)
          self.rect = self.image.get_rect()
          self.rect.x = WIDTH / 2
          self.rect.y = 20
          self.vx = 0
          self.vy = 0
          self.SW = False  # Can you screen wrap?
          self.player_states = ["Standing","Falling"]
          self.state = self.player_states[1]
  
      def jump(self):
          if self.state == self.player_states[0]:
              self.vy -= JUMP_SPEED
              self.state = self.player_states[1]        
  
      def update(self):
          self.vx = 0  # X speed set to 0 if no input is received
          self.vy += GRAVITY  # Gravity 
  
          keys = pygame.key.get_pressed()
          if keys[pygame.K_LEFT]:
              self.vx = -SPEED
          if keys[pygame.K_RIGHT]:
              self.vx = SPEED
  
          self.rect.left += self.vx  # X and Y positions are updated
          self.collide(self.vx, 0, wall_sprites)  # Collision is checked. Second param is 0 b/c we aren't checking for vertical collision here
          self.rect.top += self.vy
          self.collide(0, self.vy, wall_sprites)
  
  
          if self.SW:
              if self.rect.left &gt; WIDTH:
                  self.rect.right = 0
              if self.rect.right &lt; 0:
                  self.rect.left = WIDTH
  
              if self.rect.top &gt; HEIGHT:
                  self.rect.bottom = 0
              if self.rect.bottom &lt; 0:
                  self.rect.top = HEIGHT
  
      def collide(self, xDif, yDif, platform_list):
          for i in platform_list:                      # Shuffle through list of platforms
              if pygame.sprite.collide_rect(self, i):  # If there is a collision between the player and a platform...
                  if xDif &gt; 0:                         # And our x (horizontal) speed is greater than 0...
                      self.rect.right = i.rect.left    # That means that we are moving right, 
                  if xDif &lt; 0:                         # So our right bounding box becomes equal to the left bounding box of all platforms and we don't collide    
                      self.rect.left = i.rect.right
                  if yDif &gt; 0:
                      self.rect.bottom = i.rect.top
                      self.state = self.player_states[0]
                      self.vy = 0
                  if yDif &lt; 0:
                      self.rect.top = i.rect.bottom
                      self.vy = 0
  
  
  class Wall(pygame.sprite.Sprite):  # Collision is added for platforms just in case that they are moving. If they move to you, they push you
      def __init__(self, width, height, xpos, ypos, speed):
          pygame.sprite.Sprite.__init__(self)
          self.image = pygame.Surface((width,height))
          self.image.fill(BLUE)
          self.rect = self.image.get_rect()
          self.rect.centerx = xpos
          self.rect.centery = ypos
          self.speed = speed
  
      def update(self):
          self.rect.left += self.speed
          self.collide(self.speed, all_sprites)  # Collision only for platforms moving left and right. Not up and down yet
  
      def collide(self, xDif, player_list): 
          for i in player_list:                      
              if pygame.sprite.collide_rect(self, i):
  
                  if xDif &gt; 0:                         # If the platform is moving right... (has positive speed)
                      i.rect.left += self.speed        # Platform pushes player
                      self.rect.right = i.rect.left    # Player sticks to the wall and is pushed
  
                  if xDif &lt; 0:
                      i.rect.right -= self.speed
                      self.rect.left = i.rect.right
  </code></pre>
  
  <p>settings.py</p>
  
  <pre><code>import pygame
  
  FPS = 60
  WIDTH = 800
  HEIGHT = 600
  TITLE = "Perfect collision"
  
  GREY = (150,150,150)
  BLACK = (0,0,0)
  BLUE = (0,0,255)
  
  SPEED = 5
  JUMP_SPEED = 9
  GRAVITY = 0.3
  
  all_sprites = pygame.sprite.Group()
  wall_sprites = pygame.sprite.Group()
  </code></pre>