The ball is moving but on a sudden the velocity increases, watch at 0:01.
link for the video:
Additionally, at the edge of the paddle the ball transgress inside , doesn't collide and bounce back. Also, when the ball collide at the top of the paddle ball moves speedy at horizontally
#main.py
from turtle import Screen
from pong_setup import Paddle
from ball import Ball
import time
screen = Screen()
ball = Ball()
screen.bgcolor("black")
screen.setup(width=800, height=600)
screen.title("Pong")
screen.tracer(0)
screen.listen()
computer = Paddle(x=350, y=0)
user = Paddle(x=-350, y=0)
screen.onkey(fun=computer.mv_fd,key="w")
screen.onkey(fun=computer.mv_bk,key="s")
while True:
screen.update()
ball.move()
# collisions
if ball.ycor() >= 290 or ball.ycor() < -290:
ball.bounce_y()
if (ball.distance(computer) < 20 and ball.xcor() > 340):
ball.bounce_x()
screen.exitonclick()
#ball.py
import time
from turtle import Turtle
class Ball(Turtle):
def __init__(self):
super().__init__()
self.shape("circle")
self.color("white")
self.penup()
self.x_move = 0.05
self.y_move = 0.05
def move(self):
new_x = self.xcor() + self.x_move
new_y = self.ycor() + self.y_move
self.goto(new_x, new_y)
def bounce_y(self):
self.y_move *= -1
def bounce_x(self):
self.x_move *= -1
#paddle.py
from turtle import Turtle
class Paddle(Turtle):
def __init__(self,x,y):
super().__init__()
# self.speed(0)
self.shape("square")
self.penup()
self.color("white")
self.turtlesize(5,1)
self.goto(x,y)
def mv_fd(self):
self.goto(350,self.ycor()+30)
def mv_bk(self):
self.goto(350,self.ycor()-30)
If the ball collides at the middle of the paddle then it bounce off(works fine). I tried to change the speed of ball. The result was still buggy for the cases mentioned above
As everyone has mentioned, a while loop runs at varaible speed, this is because it goes as fast as possible, but depending on what's occuring on your computer at any moment this will vary.
To fix this we need to measure the amount of real time that has occurred, if lots of time has passed since the last update, we need to move the ball a lot, if not, then we don't move it a lot. This is what measuring a delta time between updates and then multiplying by it does.
Here is some python code which does this using the library pygame
which you will have to install to run this demo. Feel free to re-implement this using turtle and built in time libraries in python.
import pygame
import sys
pygame.init()
screen_width = 800
screen_height = 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("moving ball with controllable paddle")
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
ball_radius = 20
ball_x = screen_width // 2
ball_y = screen_height // 2
ball_speed_x = 300 # Pixels per second
ball_speed_y = 300 # Pixels per second
paddle_width = 100
paddle_height = 20
paddle_x = (screen_width - paddle_width) // 2
paddle_y = screen_height - 50
paddle_speed = 500
prev_time = pygame.time.get_ticks()
while True:
# Calculate delta time
current_time = pygame.time.get_ticks()
dt = (current_time - prev_time) / 1000.0 # Convert to seconds
prev_time = current_time
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
paddle_x -= paddle_speed * dt
if keys[pygame.K_RIGHT]:
paddle_x += paddle_speed * dt
if paddle_x < 0:
paddle_x = 0
elif paddle_x > screen_width - paddle_width:
paddle_x = screen_width - paddle_width
ball_x += ball_speed_x * dt
ball_y += ball_speed_y * dt
if ball_x + ball_radius >= screen_width or ball_x - ball_radius <= 0:
ball_speed_x *= -1
if ball_y + ball_radius >= screen_height or ball_y - ball_radius <= 0:
ball_speed_y *= -1
if ball_y + ball_radius >= paddle_y and ball_x >= paddle_x and ball_x <= paddle_x + paddle_width:
ball_speed_y *= -1
screen.fill(BLACK)
pygame.draw.circle(screen, WHITE, (int(ball_x), int(ball_y)), ball_radius)
pygame.draw.rect(screen, WHITE, (paddle_x, paddle_y, paddle_width, paddle_height))
pygame.display.flip()
pygame.time.Clock().tick(60)
See if you can then remake your example and add a secondary paddle using this as an example.