Python Forum

Full Version: Problems with jump code in pygame
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello!
I' ve started learning pygame after I learned some python. But than I got to the problem with jumping code. When I press space it goes up and doesn' t go down.
There is also another problem; when I have the same value in if and while loop it doesn't jump at all. Here is the code:
import pygame
pygame.init()
import math
x = 600
y = 600
h = 3
W = 9
v = 3
t = 2 * v
a = 0
run = True 
skok = False
screen= pygame.display.set_mode((800, 700))
screen.fill((255, 0, 0))
pygame.display.set_caption("Grafika 101")
while run:
 for event in pygame.event.get():
  if event.type == pygame.QUIT:
   run = False
 pygame.display.flip()
 screen.fill((255, 0, 0))
 pygame.draw.circle(screen, (0, 0, 0), (x, y), 30)
 if event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT and x > h:
  x -= h
 if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT and x < 800 - 30 - h:
  x += h
 if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
  skok = True
  while skok:
   y -= v
   //This is  while loop I was talking about
   while a < 601:
    a = a+1 
	// And this is if loop
   if a == 600:
    while y < 600:
     y += v
     a = 0
   skok = False
pygame.quit()
I hope someone helps me
Thanks for replying
joningstone
First, I notice that you have the if event.type ==... outside of the for loop. The for loop creates the variable event for use inside of the for loop. The variable cannot be used outside of that for loop. So the if statements need to be moved inside the for loop. I also notice that you must have come from a another language that uses slashes as comments. Python uses "#" to make a comment. Now, in the beginning you made a lot of variables for use in the loop. It would probably be more efficient to just make one dictionary and carry all the values in that dictionary. Also, for making pygames, there are lots of ways to mess up towards spaghetti code. I would recommend checking out the tutorials of pygame on this forum for tips on minimizing code and maximizing its efficiency - https://python-forum.io/Forum-Game-Tutorials. If you still have problems after fixing up your code, just post your new code and the problem you're having on this same thread.
OK thanks. But I'm courious as to why left and right do work? Anyway I will ceartanly remember what you told me.
hey man are you bulgarian? cuz i see the words you use like skok or grafika so i wonder if you can teach me something about the codng cuz im new too and i relly wannet to learn faster (im not patient)
Your game has a loop that processes events (while run:). This should be the only loop in your program.

It looks like you are trying to jump here:
 if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
  skok = True
  while skok:
   y -= v
   //This is  while loop I was talking about
   while a < 601:
    a = a+1 
    // And this is if loop
   if a == 600:
    while y < 600:
     y += v
     a = 0
   skok = False
The while loops prevents the main loop from running, and since the main loop is not running the circle is not redrawn to reflect the changing y location. Instead of trying to do the entire jump in one cycle of the main loop, you need to spread it out over several iterations. This code does a "flappy bird" style jump where each time you jump you shoot upward, even if you aren't standing on the ground.
    if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
        v = JUMP

    if y > 0 or v > 0:  # In the air gravity pulls you down
        v -= GRAVITY
        y += v   # Integrate velocity to get position
    else:  # On the ground
        v = 0
        y = 0
Jumping is physics. Displacement is the integral of velocity over time. Velocity is the integral of acceleration over time. Acceleration is caused by force, in this case gravity pulling down on your mass (ball).

Velocity and acceleration introduce another complication. Displacement is the integral of velocity over TIME. Velocity is the integral of acceleration over TIME. Time is important. I don't have Pygame installed, so I have no idea what the above code will act like when it runs (or even if it will run). My guess is the ball will shoot off the screen because the loop runs very quickly and the ball speeds are probably set too high. To give realistic results the program needs to keep track of time.

In this example I use the time module to get the current time. Each time through the main loop I measure how much time passed since the last interval and use that to scale how much velocity changes and how far the ball moves. Since we are measuring time I decided to modify horizontal movement so the ball keeps moving left/right while the key is pressed.
import math
import time
import pygame

# Scale field so 1 pixel = 1' or 1/3m
WIDTH = 800
HEIGHT = 700
RADIUS = 30
PIXEL_SCALING  = 10 # 10 pixels = 1 meter
SPEED = 3 * PIXEL_SCALING   # Horizontal movement at 3 m/s or 10 km/h
JUMP = 5 * PIXEL_SCALING     # Vertical jump of 1.27m!
GRAVITY = 9.8 * PIXEL_SCALING   # 1 G
GROUND = RADIUS
BACKGROUND = (255, 0, 0)
BALL_COLOR = (0, 255, 255)

x = WIDTH/2
y = GROUND
v = 0  # Vertical speed
h = 0  # Horizontal speed
t = time.time() # Current time

pygame.init()
screen= pygame.display.set_mode((WIDTH, HEIGHT))
screen.fill(BACKGROUND)
pygame.display.set_caption("Grafika 101")

while True:
    # Process events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            break
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                h = -SPEED  # Start moving left
            elif event.key == pygame.K_RIGHT:
                h = SPEED   # Start moving right
            elif event.key == pygame.K_SPACE:
                v = JUMP
        elif event.type == pygame.KEYUP:
            h = 0   # Stop moving left/right

    # Measure how much time passed since last loop
    last_time, t = t, time.time()
    delta_time = t - last_time

    # Handle horizontal move.  Clip so ball stays in window
    x = max(RADIUS, min(WIDTH-RADIUS, x + h * delta_time))

    # Handle jumps.  Clip so ball stays in window and doesn't sink below ground
    if y > GROUND or v > 0:  # You are jumping or in the air
        v += GRAVITY * delta_time
        y = max(RADIUS, min(HEIGHT-RADIUS, y + v * delta_time))
    else:  # On the ground
        v = 0
        y = GROUND

    screen.fill(BACKGROUND)
    pygame.draw.circle(screen, BALL_COLOR, (int(x), int(HEIGHT-y)), RADIUS)
    pygame.display.flip()

pygame.quit()
I can use anything for JUMP and SPEED and GRAVITY. To help me decide what values to start with I decided to scale the playing field to some standardized unit and use earth gravity and everyday speeds for a starting point. 10 pixels = 1 meter gives a virtual playing field that is 80 meters wide and 70 meters high. If the ball moves horizontally at 10m/second it takes only 8 seconds to move from one side of the board to the other. Quick enough to be interesting and slow enough to be controllable.

For JUMP, I decided to make my ball jump around 1 meter for each key press. I need to convert this to an initial velocity for my jump.

After I jump, gravity makes me decelerate at 9.8 m/s^2. If my jump velocity is 9.8m/s I will reach the apex (zero velocity) 1 second later (9.8m/s / 9.8m/s^2 = 1 s). My average velocity over the jump is one half the starting jump velocity, or 4.9m/s (Vavg = (Vstart + Vend) / 2). So if I jump at 9.8m/s I travel at an average speed of 4.9m/s for 1 second, for a vertical leap of 4.9m. That is a bit high, but it gives me an equation I can use to calculate JUMP.

Height = JUMP/2 * JUMP/GRAVITY = JUMP^2/(2 * GRAVITY)
JUMP= sqrt(Height * 2 * GRAVITY)
4.42m/s = sqrt(1m * 2 * 9.8 m/s^2)

I bump this up to 5m/s or a jump height of 1.27m

Since I am using real time and realistic accelerations an velocity, I need to use float numbers instead of integers. I think I also remember something about pygame being upside down; the (0, 0) pixel is in the upper left of the screen. I need to convert my (x, y) from floats to ints, and I need to flip the y so zero is at the bottom of the screen and 700 at the top. That is done here:
pygame.draw.circle(screen, BALL_COLOR, (int(x), int(HEIGHT-y)), RADIUS)
EDIT: I just noticed the OP is really old (over 20 months). I doubt joninstone is still monitoring this thread.