Jason Palmira
Jason Palmira

Reputation: 1

Making a Ball Bounce on the Screen

I'm in the process of trying to make a very simple ball and paddle game in Python and have the ball moving on the screen with a paddle that moves from left to right. But, the ball moves and hits the bottom of the screen and doesn't change direction, it just stops and slides against the wall.

Any help or suggestions would be appreciated. Here is the code:

from tkinter import Canvas, Tk
import random

canvas_width = 800
canvas_height = 400

root = Tk()
root.title("Ball and Paddle")
c = Canvas(root,width=canvas_width,height=canvas_height,background='orange')
c.pack()

paddle_color = 'blue'
paddle_width = 60
paddle_height = 10
paddle_start_x = canvas_width/2 - paddle_width/2
paddle_start_y = canvas_height - paddle_height - 20
paddle_start_x2 = canvas_width/2 + paddle_width/2
paddle_start_y2 = canvas_height - 20

paddle = c.create_rectangle(paddle_start_x,paddle_start_y,\
                        paddle_start_x2,paddle_start_y2,\
                        fill='blue', width=0)

ball_color = 'green'
ball_width = 20
ball_height = 20
ball_start_x1 = canvas_width/2 - ball_width/2
ball_start_y1 = canvas_height/2 - ball_height/2
ball_start_x2 = canvas_width/2 + ball_width/2
ball_start_y2 = canvas_height/2 + ball_height/2
ball_speed = 5

ball = c.create_oval(ball_start_x1, ball_start_y1, \
                 ball_start_x2, ball_start_y2, \
                 fill = ball_color, width = 0)
dx = 1
dy = 1

def ball_move():
    global dx, dy
    (bx1,by1,bx2,by2) = c.coords(ball)
    c.move(ball, dx, dy)
    if bx1 <= 0:
    dx = -dx
    if bx2 >= canvas_width:
        dx = -dx
    if by1 <= 0:
        dy = -dy
    if by2 >= canvas_height:
        dy = -dy
    root.after(ball_speed, ball_move)

def move_left(event):
    (x1,y1,x2,y2) = c.coords(paddle)
    if x1>0:
        c.move(paddle,-20,0)

def move_right(event):
    (x1,y1,x2,y2) = c.coords(paddle)
    if x2 < canvas_width:
        c.move(paddle, 20, 0)

c.bind('<Left>',move_left)
c.bind('<Right>',move_right)
c.focus_set()

root.after(ball_speed, ball_move)

root.mainloop()

Upvotes: 0

Views: 1642

Answers (2)

Kevin
Kevin

Reputation: 76234

(I'm assuming that the if bx1 <= 0: indentation problem isn't actually present in your real code, and was just a transcription error when writing this post)

This occurs because the ball is getting "lodged" into the border of the screen, when by2 has a value of 401. You reverse dy, which makes it move up to 400 at the next frame. But then you reverse dy again, so it moves back down to 401.

This happens because you're creating the b* variables, then moving the ball, then doing boundary checking on the b* variables. You're effectively inspecting the position of the ball from the previous frame.

Try moving the move call to after the boundary check.

def ball_move():
    global dx, dy
    (bx1,by1,bx2,by2) = c.coords(ball)
    if bx1 <= 0:
        dx = -dx
    if bx2 >= canvas_width:
        dx = -dx
    if by1 <= 0:
        dy = -dy
    if by2 >= canvas_height:
        dy = -dy
    c.move(ball, dx, dy)
    root.after(ball_speed, ball_move)

Now your ball should bounce.

enter image description here

Upvotes: 2

ZF007
ZF007

Reputation: 3731

Indentation issue:

def ball_move():
    global dx, dy
    (bx1,by1,bx2,by2) = c.coords(ball)
    c.move(ball, dx, dy)
    if bx1 <= 0:
    dx = -dx
    if bx2 >= canvas_width:
    ..snippet..

should be:

def ball_move():
    global dx, dy
    (bx1,by1,bx2,by2) = c.coords(ball)
    c.move(ball, dx, dy)
    if bx1 <= 0:
        dx = -dx              # indent corrected here!
    if bx2 >= canvas_width:
    ..snippet..

Upvotes: 0

Related Questions