I everyone! I'm having a little math trouble with a simple physics program I'm writing in python w/ pygame. If you notice in the code where it says: "((-ballSpeed[1]/4*3))", my ball on the screen just sits there and does nothing!! Whats wrong with my program?

import sys
import pygame


SCREEN_WIDTH  = 640
SCREEN_HEIGHT = 480
BLACK = (0, 0, 0)

ballSpeed = [0,4]

pygame.init()

screen = pygame.display.set_mode( (SCREEN_WIDTH,SCREEN_HEIGHT) )

ballImage = pygame.image.load( "box.bmp" )

ballRect = ballImage.get_rect()
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT: sys.exit()

    pygame.display.set_caption("Testing! "+str(ballSpeed[0])+str(ballSpeed[1]))

    ballRect = ballRect.move( ballSpeed )

    if ballRect.left < 0 or ballRect.right > SCREEN_WIDTH:
        ballSpeed[0] = -ballSpeed[0]



    if ballRect.top < 0 or ballRect.bottom > SCREEN_HEIGHT:
        ballSpeed[1] = ((-ballSpeed[1]/4*3))
        


    screen.fill( BLACK )
    screen.blit( ballImage, ballRect )
    pygame.display.flip()

I don't have the pygame module, but can you put a print statement saying anything (just something to check for) into the if statement with the line ballSpeed[1] = ((-ballSpeed[1]/4*3)) to make sure that the if statement is actually being executed? And why is that segment encapsulated within two pairs of brackets? Wouldn't it be fine as just ballSpeed[1] = -ballSpeed[1]/4*3 ?

Ok so I changed the code (I forgot to remove to second pair of parenthesis. I don't think there is a difference between one or two pair of parenthesis):

ballSpeed[1] = (-ballSpeed[1]/4*3)
        print ballSpeed[1]

So this code lets me view the value of ballSpeed[1].

pygame.display.set_caption("Testing! "+str(ballSpeed[0])+str(ballSpeed[1]))

This code let's me see the value of ballSpeed[0] and ballSpeed[1] in the caption bar (a.k.a the window bar)

Although, I when using the "print ballSpeed[1]" code, I stopped the command line scroll bar to slowly let me see the outcome of "ballSpeed[1]". I noticed the very first number that was recorded (the first time the ball hit the floor) was -3!! That's the number I wanted...but then it just goes back to 0's. I have an image right here (http://i510.photobucket.com/albums/s342/besktrap/-3.jpg)

Yeah, I don't know what's wrong with this. I tried print float(3/4*3) and only recieved 0.0 ... So now we know that it's not a problem of your code per se, but just the way the math is being done.

Wow, why is Python so specific about the 3 being a float in order for it not to round the answer? Thanks though Gribouillis, as I now learned something new today :)

Also
ballSpeed = [0,4]
means move the ball 0 pixels along the x axis and 4 pixels along the y axis. Pixels have to be integers. When you set it to [0,0] it stops of course.

Wow, why is Python so specific about the 3 being a float in order for it not to round the answer? Thanks though Gribouillis, as I now learned something new today :)

Most computer languages consider integer/integer an integer division and for instance 1/2 will give you 0. Conversely float/integer or integer/float will be considered a floating point division, such that 1.0/2 will give 0.5

The new version 3.0 of Python will depart from this traditional concept and make / a floating point division and // an integer division.

I changed my code from "ballSpeed = [0,4]" to "ballSpeed[0.0,4.0]". It works for the first millisecond (changing 4 to -3), but then turns into 2.25, -1.6875, ect. Link to image.

The ball goes up, but then all of the other numbers take over to control the ball! Ahhhh!!

I think you should modify your test like this

if (ballRect.left < 0 and ballSpeed[0] < 0) or (ballRect.right > SCREEN_WIDTH and ballSpeed[0]>0):
        ballSpeed[0] = -ballSpeed[0]



    if (ballRect.top < 0 and ballSpeed[1] < 0) or (ballRect.bottom > SCREEN_HEIGHT and ballSpeed[1]>0):
        ballSpeed[1] = ((-ballSpeed[1]/4*3))

so, that if the ball is above the top of the window, you change the sign of the velocity only if the ball is going upwards, and if it's below the bottom of the window, you reverse velocity only if it's going downwards, etc. Tell us if it works.

The first part of the code looks fine, but the math still doesn't work right. Link.

I though of just doing the math without multiplication; and I'm trying to also add a bounce effect:

# Gravity Part of the code
    if ballRect.bottom == 50:
        a = 0
        ballSpeed[1] = (ballSpeed[1] + 1)

    if ballRect.bottom == 180:
        a = 0
        ballSpeed[1] = (ballSpeed[1] + 1)

    if ballRect.bottom == 260:
        a = 0 
        ballSpeed[1] = (ballSpeed[1] + 1)

    if ballRect.bottom == 340:
        a = 0
        ballSpeed[1] = (ballSpeed[1] + 1)

    if ballRect.bottom == 380:
        a = 0
        ballSpeed[1] = (ballSpeed[1] + 1)

    if ballRect.bottom == 440:
        a = 0
        ballSpeed[1] = (ballSpeed[1] + 1)

A = 0 could be used to identify if the ball is going down, or if it is bouncing.

I think you shoudn't add new features before the first effect work. I don't understand why your speed is multiplied by 3/4 at each loop (at least if you implemented the tests as I said before).
I don't have pygame here, so I cant test your code :)

I'm trying to make it multiply by 3/4 every time the ball hits the bottom of the screen, but it just loops on that if statment.

I just tested the code from the first page and after creating my own "box.bmp" in MSPaint I was able to observe the box "bounce" from the top of the screen to the bottom and back again before finally coming to a stop at the bottom of the window.

Looks like the "speed" value doesn't like anything below 1.0?

try this version

import sys
import pygame


SCREEN_WIDTH  = 640
SCREEN_HEIGHT = 480
BLACK = (0, 0, 0)

def debug(msg):
    print "debug:", msg

ballSpeed = [0,4]

pygame.init()

screen = pygame.display.set_mode( (SCREEN_WIDTH,SCREEN_HEIGHT) )

ballImage = pygame.image.load( "box.bmp" )

ballRect = ballImage.get_rect()
cnt = 0
MAXCNT = 20
while cnt < MAXCNT:
    for event in pygame.event.get():
        if event.type == pygame.QUIT: sys.exit()

    pygame.display.set_caption("Testing! "+str(ballSpeed[0])+str(ballSpeed[1]))

    ballRect = ballRect.move( ballSpeed )

    cnt += 1
    debug("loop % d" % cnt)

    if ballRect.left < 0 and ballSpedd[0] < 0:
        debug("too far left %s %s" % (ballRect.left, ballSpeed[0]))
        ballSpeed[0] = -ballSpeed[0]
    elif ballRect.right > SCREEN_WIDTH and ballSpeed[0] > 0:
        debug("too far right %s %s" % (ballRect.right, ballSpeed[0]))
        ballSpeed[0] = -ballSpeed[0]


    if ballRect.bottom < 0 and ballSpeed[1] < 0:
        debug("too far down  %s %s" % (ballRect.bottom, ballSpeed[1])
        ballSpeed[1] = ((-ballSpeed[1]*0.75))
    elif ballRect.top > SCREEN_HEIGHT and ballSpeed[1] > 0:
        debug("too far up  %s %s" % (ballRect.top, ballSpeed[1])
        ballSpeed[1] = ((-ballSpeed[1]*0.75))


    screen.fill( BLACK )
    screen.blit( ballImage, ballRect )
    pygame.display.flip()

try this version

After removing the two syntax errors the object simply rests at about 3/4 of the way up the screen.

I found a version online that produces accurate physics with much simpler syntax; however I am hesitant to post the code as you may not take the time to learn why it works as well as it does (The secret is in the phyics calculations).

If you ask, I will post the working version.

Sure; I promise to understand it. If I don't, I'll look online or the Pygame documentations for help.

I hate it when I make something, but I don't know how it works.

There is a missing parenthesis on the previous line. I can't test the code, I don't have pygame. Aso, you may have to modify the value of MAXCNT (I put this variable so that the animation stops after a certain number of steps)

This article has been dead for over six months. Start a new discussion instead.