I'm tired, and I've tried to run this all day. IT's a game of pong where the ball bounces off the wall and comes into contact with the user's "Slab" or paddle. I've treid to debug for a while, and turns out my iCollide and the iGet_Velocity parts have been causing a lot of issues.
from livewires import games, color
games.init (screen_width = 640, screen_height = 480, fps = 50)
class Ball (games.Sprite):
def update (self):
if self.right>544:
self.dx = -self.dx
if self.top > 11 or self.bottom > 470:
self.dy = -self.dy
if self.left < 0:
self.iLost()
def iLost (self):
games.Message (screen = self.screen,
x = 340,
y = 240,
text = "Game Over",
size = 90,
color = color.red,
lifetime = 250,
after_death = self.screen.quit)
def ihandle_collision (self):
new_dx, new_dy = Slab.iVelocity()
self.dx += self.dx + new_dx #For handling collision, must take velocity of the mouse object and put add it to the velocity of the ball.
self.dy += self.dy + new_dy
class Slab (games.Sprite):
def update (self):
self.x = games.mouse.x
self.y = games.mouse.y
self.iCollide()
def iCollide (self):
for Ball in self.overlapping_sprites:
Ball.ihandle_collision()
def iVelocity (self):
self.get_velocity()
def main():
#Backgrounds
pingpongbackground = games.load_image ("pingpongbackground.jpg", transparent = False)
games.screen.background = pingpongbackground
#Ball: Initializing object and setting speed.
ballimage = games.load_image ("pingpongball.jpg", transparent = True)
theball = Ball (image = ballimage,
x = 320,
y = 240,
dx = 2,
dy = 2)
games.screen.add(theball)
#Paddle: Initializing ping pong object and setting initial poisition to the initial mouse position
slabimage = games.load_image ("pingpongpaddle.jpg", transparent = True)
theslab = Slab (image = slabimage,
x = games.mouse.x,
y = games.mouse.y)
games.screen.add(theslab)
games.mouse.is_visible = False
games.screen.event_grab = True
games.screen.mainloop()
main ()
Well, without having some more data, I can't say for certain what is wrong. But it looks like your collision response code is a bit screwy. For example, in the first section you should do this to handle your boundary conditions properly:
def update (self):
if self.right>544 and self.dx > 0:
self.dx = -self.dx
if (self.top > 11 and self.dy < 0) or (self.bottom > 470 and self.dy > 0):
self.dy = -self.dy
if self.left < 0:
self.iLost()
Also your collision response code is a bit wonky. This is untested, but it does approximately the right thing: (EDIT: Rewrote this with more comments so that it would be more clear)
def iCollide (self):
for Ball in self.overlapping_sprites:
#Extract the components of the slab's velocity
slab_vx, slab_vy = self.iVelocity()
#Compute relative components of slab velocity
rel_vx, rel_vy = Ball.dx - slab_vx, Ball.dy - slab_vy
#Determine the time of intersection and the normal direction
#This is done to compute which face the ball hits
#Initially suppose that the objects intersect at t=infinity
t, nx, ny = 100000, 0, 0
#Check left/right faces
if rel_vx != 0:
#Check if ball hits left face
toi = (self.left - Ball.right) / rel_vx
if toi < t:
t, nx, ny = toi, -1, 0
#Check if ball hits right face
toi = (self.right - Ball.left) / rel_vx
if toi < t:
t, nx, ny = toi, 1, 0
#Check top/bottom faces:
if rel_vy != 0:
#Check if ball hits top face
toi = (self.top - Ball.bottom) / rel_vx
if toi < t:
t, nx, ny = toi, 0, -1
#Check if ball hits right face
toi = (self.bottom - Ball.top) / rel_vx
if toi < t:
t, nx, ny = toi, 0, 1
#Check if impact force properly corrects velocity
if Ball.dx * nx + Ball.dy * ny < 0:
#Reflect the ball's position
Ball.dx += Ball.dx * nx * 2.0
Ball.dy += Ball.dy * ny * 2.0
#Check if cursor movement is not pushing ball into paddle:
if slab_vx * nx + slab_vy * ny < 0:
Ball.dx += slab_vx
Ball.dy += slab.vy
What you should try to do is find which face of the slab the ball intersects, then reflect the balls velocity according to that direction. Now this code is by no means tested, since I couldn't get your example to run. However it should give you an idea of what the correct solution ought to do.