views:

722

answers:

3

I have coded an animation (in python) for a beach ball to bounce around a screen. I now wish to add a second ball to the window, and when the two collide for them to bounce off each other.

So far, my attempts at this have been unsuccessful. Any ideas how to do this? The code I have so far is below.

import pygame

import sys

if __name__ =='__main__':

    ball_image = 'Beachball.jpg'
    bounce_sound = 'Thump.wav'
    width = 800
    height = 600
    background_colour = 0,0,0
    caption= 'Bouncing Ball animation'
    velocity = [1,1]
    pygame.init ()
    frame = pygame.display.set_mode ((width, height))
    pygame.display.set_caption (caption)
    ball= pygame.image.load (ball_image). convert()
    ball_boundary = ball.get_rect (center=(300,300))
    sound = pygame.mixer.Sound (bounce_sound)
    while True:
        for event in pygame.event.get():
            print event 
            if event.type == pygame.QUIT: sys.exit(0)
        if ball_boundary.left < 0 or ball_boundary.right > width:
            sound.play()
            velocity[0] = -1 * velocity[0]
        if ball_boundary.top < 0 or ball_boundary.bottom > height:
            sound.play()
            velocity[1] = -1 * velocity[1]

        ball_boundary = ball_boundary.move (velocity)
        frame.fill (background_colour)
        frame.blit (ball, ball_boundary)
        pygame.display.flip()
+3  A: 

You should probably create a class to represent your beachball. Then you'd instance as many as you like, and put the instances in a Python list.

You'd then go through that list on each frame, updating and rendering each.

You would need to include a method to test for collision against another ball (this is simple for circles). If a collision is detected, the balls involved should simulate a bounce away from each other.

unwind
+6  A: 

Here's a very basic restructure of your code. It could still be tidied up a lot, but it should show you how you can use instances of the class.

import pygame
import random
import sys

class Ball:
    def __init__(self,X,Y):
     self.velocity = [1,1]
     self.ball_image = pygame.image.load ('Beachball.jpg'). convert()
     self.ball_boundary = self.ball_image.get_rect (center=(X,Y))
     self.sound = pygame.mixer.Sound ('Thump.wav')

if __name__ =='__main__':
    width = 800
    height = 600
    background_colour = 0,0,0
    pygame.init()
    frame = pygame.display.set_mode((width, height))
    pygame.display.set_caption("Bouncing Ball animation")
    num_balls = 1000
    ball_list = []
    for i in range(num_balls):
     ball_list.append( Ball(random.randint(0, width),random.randint(0, height)) )
    while True:
     for event in pygame.event.get():
      print event 
      if event.type == pygame.QUIT:
       sys.exit(0)
     frame.fill (background_colour)
     for ball in ball_list:
      if ball.ball_boundary.left < 0 or ball.ball_boundary.right > width:
       ball.sound.play()
       ball.velocity[0] = -1 * ball.velocity[0]
      if ball.ball_boundary.top < 0 or ball.ball_boundary.bottom > height:
       ball.sound.play()
       ball.velocity[1] = -1 * ball.velocity[1]

      ball.ball_boundary = ball.ball_boundary.move (ball.velocity)
      frame.blit (ball.ball_image, ball.ball_boundary)
     pygame.display.flip()
Nathan Ross Powell
You just refactored the pygame introduction. http://www.pygame.org/docs/tut/intro/intro.html
David Locke
Do you really need to pass pygame to the __init__ function?
tgray
@tgray: I did it that way to use the same code as the the example as much as possible. In the thinking that it could make it easier for the OP to understand
Nathan Ross Powell
@Nathan Ross Powell: I understand your reasoning, but bad coding practices shouldn't be propagated. Ever. I would suggest that you either improve the code, so they can see how it should be done, or at least call out the fact that it's a poorly written example.
tgray
relevant article: http://typicalprogrammer.com/?p=4
tgray
Can you give the reason for why passing objects to the __init__ function is such a bad coding practice?
Nathan Ross Powell
Passing objects is fine, but redefining the name 'pygame' from an outer scope is bad coding practice. Also the fact that the code will break if you pass anything besides the pygame module.Check out the pylint project for help with code checking, http://www.logilab.org/project/pylint
tgray
Thanks for the information. I read the code as 'pygame' being an object, not a module. Mistake by me. Youre original comment makes perfect sence to me now! (its been a long day :) )
Nathan Ross Powell
Glad I could help :)
tgray
A: 

Anyone had a good way to add collisions?