For the first time ever, I tried my hand at creating a pretty simple game, pong. I did this using turtle and figured it out by using a mixture of searching online, previous knowledge, and some stack overflow questions, and for the most part, it's working perfectly. However, when running the game, I seem to encounter the occasional lag spike where the game will slow down by nearly 50%, and then all of a sudden go to 150%. I have a decent laptop, but even so, for a game this size, this shouldn't be happening, any idea why? The audio also seems to be delayed slightly too.
If you want to try it with the font + audio files: https://github.com/JamesJ42/PythonPong
# My attempt at pong (atari game)
import turtle
import winsound
wn = turtle.Screen()
wn.title("Pong")
wn.bgcolor("black")
wn.setup(width = 800, height = 600)
wn.tracer(0)
# Score
player_1_score = 0
player_2_score = 0
# Paddle A
paddle_a = turtle.Turtle()
paddle_a.speed(0)
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid = 5, stretch_len = 1)
paddle_a.penup()
paddle_a.goto(-350, 0)
# Paddle B
paddle_b = turtle.Turtle()
paddle_b.speed(0)
paddle_b.shape("square")
paddle_b.color("white")
paddle_b.shapesize(stretch_wid = 5, stretch_len = 1)
paddle_b.penup()
paddle_b.goto(350, 0)
# Ball
ball = turtle.Turtle()
ball.speed(0)
ball.shape("square")
ball.color("white")
ball.penup()
ball.goto(0, 0)
ball.dx = 0.1
ball.dy = 0.1
# Pen
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("PLAYER 1: 0 PLAYER 2: 0", align = "center", font = ("EightBit Atari", 24, "normal"))
# Finish game
finish = turtle.Turtle()
finish.speed(0)
finish.color("white")
finish.penup()
finish.hideturtle()
finish.goto(0, 240)
finish.write("FINISH GAME: SHIFT + Q", align = "center", font = ("EightBit Atari", 10, "normal"))
# Functions
def paddle_a_up():
y = paddle_a.ycor()
y += 20
paddle_a.sety(y)
def paddle_a_down():
y = paddle_a.ycor()
y -= 20
paddle_a.sety(y)
def paddle_b_up():
y = paddle_b.ycor()
y += 20
paddle_b.sety(y)
def paddle_b_down():
y = paddle_b.ycor()
y -= 20
paddle_b.sety(y)
def exit_game():
turtle.bye()
# Keyboard binding
wn.listen()
wn.onkeypress(paddle_a_up, "w")
wn.onkeypress(paddle_a_down, "s")
wn.onkeypress(paddle_b_up, "Up")
wn.onkeypress(paddle_b_down, "Down")
wn.onkeypress(exit_game, "Q")
# Main game loop
while True:
wn.update()
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border checking
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
winsound.PlaySound("wall.wav", winsound.SND_ASYNC)
if ball.ycor() < -290:
ball.sety(- 290)
ball.dy *= -1
winsound.PlaySound("wall.wav", winsound.SND_ASYNC)
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx *= -1
player_1_score += 1
pen.clear()
pen.write(f"PLAYER 1: {player_1_score} PLAYER 2: {player_2_score}", align = "center", font = ("EightBit Atari", 24, "normal"))
winsound.PlaySound("score.wav", winsound.SND_ASYNC)
if ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1
player_2_score += 1
pen.clear()
pen.write(f"PLAYER 1: {player_1_score} PLAYER 2: {player_2_score}", align = "center", font = ("EightBit Atari", 24, "normal"))
winsound.PlaySound("score.wav", winsound.SND_ASYNC)
# Paddle and ball collisions
if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < paddle_b.ycor() + 40 and ball.ycor() > paddle_b.ycor() - 40):
ball.setx(340)
ball.dx *= -1
winsound.PlaySound("paddle.wav", winsound.SND_ASYNC)
if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < paddle_a.ycor() + 40 and ball.ycor() > paddle_a.ycor() - 40):
ball.setx(-340)
ball.dx *= -1
winsound.PlaySound("paddle.wav", winsound.SND_ASYNC)
I found some Pygame documentation on my computer. It had some advice from David Clark, where he suggested you add .convert_alpha() at the end of all Pygame image loads. This increased my framerate from 9 to 32
or even try using Pyglet
I wasn't able to reproduce the lag spike problem on my slow laptop, but I'm guessing it's due to the while True: busy loop and the tiny step size here:
ball.dx = 0.1
ball.dy = 0.1
What seems to be happening is the render loop is running (or trying to run) as fast as possible, moving the ball a very small amount on each step. On a fast machine, this achieves the correct feel for the game speed, but on slower machines (like mine), the game runs at a snail's pace (it takes 10 seconds or so to get the ball across the screen once).
Although it's not likely to be perfectly consistent for all machines, if you use ontimer and a faster movement speed for the ball, you can take control of the framerate and ensure the process isn't just maxing out all of its CPU time trying to render as many frames as possible. Hopefully, this will reduce lag spikes that might be caused by periodic scheduling anomalies and interruptions.
# ...
ball.dx = 7 # bigger step per frame
ball.dy = 7
# ...
# Main game loop
def tick():
# not the greatest practice; TODO convert to a function
global player_1_score
global player_2_score
# Move the ball
# ...
wn.update()
wn.ontimer(tick, frame_delay_ms)
frame_delay_ms = 1000 // 30
tick()
turtle.mainloop()
If this runs abnormally fast or slow on your machine, I'd be curious to hear. It can be improved to render frames at a fixed rate by checking the delta time between frames, but I'll assume it's good enough until I hear otherwise.
Related
I've been looking at this for hours and can't figure out why it won't run properly. Any ideas? I've tried messing with different x and y coords to see if that was the problem but nothing works.
The program just runs twitches and ends, when it should be playing through a game of pong until the user exits out.
code: you can ignore the comments
import turtle
# screen
screen = turtle.Screen()
screen.title('Pong')
screen.bgcolor('black')
screen.setup(width=1000, height=500)
# ball
ball = turtle.Turtle()
ball.shape('circle')
ball.color('white')
ball.speed(0)
ball.penup() #solves line issue
ball.goto(0, 0)
ball.dx = 5
ball.dy = -5
# right paddle____add speed___
r_pad = turtle.Turtle()
r_pad.speed(0.5)
r_pad.shape('square')
r_pad.color('white')
r_pad.shapesize(stretch_wid=5, stretch_len=2)
r_pad.penup()
r_pad.goto(450, 0)
# left paddle
l_pad = turtle.Turtle()
l_pad.speed(0.5)
l_pad.shape('square')
l_pad.color('white')
l_pad.shapesize(stretch_wid=5, stretch_len=2)
l_pad.penup()
l_pad.goto(-450, 0)
# Score
score = turtle.Turtle()
score.speed(0)
score.color('white')
score.penup()
score.hideturtle()
score.goto(0, 200)
score.write("Left_player : 0 Right_player: 0",
align="center", font=("arial", 24, "normal"))
#solving that score error
left_player = 0
right_player = 0
# movement
def paddler_up():
y = r_pad.ycor()
y += 20
r_pad.sety(y)
def paddler_down():
y = r_pad.ycor()
y -= 20
r_pad.sety(y)
def paddlel_up():
y = l_pad.ycor()
y += 20
l_pad.sety(y)
def paddlel_down():
y = l_pad.ycor()
y -= 20
l_pad.sety(y)
#main game
screen.listen()
screen.onkeypress(paddler_up, "w")
screen.onkeypress(paddler_down, "s")
screen.onkeypress(paddlel_up, "up")
screen.onkeypress(paddlel_down, "down")
while True:
screen.update()
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Checking borders
if ball.ycor() > 230:
ball.sety(230)
ball.dy *= -1
if ball.ycor() < -230:
ball.sety(-230)
ball.dy *= -1
if ball.xcor() > 600:
ball.goto(0, 0)
ball.dy *= -1
left_player += 1
score.clear()
score.write("Left_player : {} Right_player: {}".format(
left_player, right_player), align="center",
font=("Courier", 24, "normal"))
if ball.xcor() < -600:
ball.goto(0, 0)
ball.dy *= -1
right_player += 1
score.clear()
score.write("Left_player : {} Right_player: {}".format(
left_player, right_player), align="center",
font=("Courier", 24, "normal"))
# Paddle ball collision
if (ball.xcor() > 360 and ball.xcor() < 370) \
and (ball.ycor() < r_pad.ycor() + 40 and ball.ycor() > r_pad.ycor() - 40):
ball.setx(360)
ball.dx *= -1
if (ball.xcor() < -360 and ball.xcor() > -370) \
and (ball.ycor() < l_pad.ycor() + 40 and ball.ycor() > l_pad.ycor() - 40):
ball.setx(-360)
ball.dx *= -1
Your onkeypress calls for up and down keys should be capitalized (Up and Down instead of up and down) for it to work
screen.onkeypress(paddlel_up, "Up")
screen.onkeypress(paddlel_down, "Down")
I made a basic pong by going through a tutorial and tweaking a few things, currently I'd like the left paddle which is the variable paddle_a to be moved based on where the cursor is while still maintaining its x value. Or, in other words, moving up and down based on the y value of the mouse. I've looked around the internet and couldn't find anything that would help me in this case so help would be appreciated.
import turtle
wn = turtle.Screen()
wn.title("Pong")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)
# Paddle A
paddle_a = turtle.Turtle()
paddle_a.speed(0)
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid=5, stretch_len=0.5)
paddle_a.penup()
paddle_a.goto(-380, 0)
# Ball
ball = turtle.Turtle()
ball.speed(0)
ball.shape("square")
ball.color("white")
ball.shapesize(stretch_len=0.75, stretch_wid=0.75)
ball.penup()
ball.goto(0, 0)
ball.dx = 0.3
ball.dy = 0.3
# Functions
def paddle_a_up():
y = paddle_a.ycor()
y += 10
paddle_a.sety(y)
def paddle_a_down():
y = paddle_a.ycor()
y -= 10
paddle_a.sety(y)
# Keybinding
wn.listen()
wn.onkeypress(paddle_a_up, "w")
wn.onkeypress(paddle_a_down, "s")
# Main game loop
while True:
wn.update()
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border checking
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
if ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx *= -1
if ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1
Here's a simple approach using the mouse ondrag() event on the paddle instead of key events. Click and hold on the paddle while you move it up and down. The ball will continue to move independently:
from turtle import Screen, Turtle
# Functions
def paddle_move(x, y):
paddle_a.sety(y)
screen = Screen()
screen.title("Pong")
screen.bgcolor("black")
screen.setup(width=800, height=600)
screen.tracer(0)
# Paddle A
paddle_a = Turtle()
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid=5, stretch_len=0.5)
paddle_a.penup()
paddle_a.setx(-380)
# Ball
ball = Turtle()
ball.shape("square")
ball.color("white")
ball.shapesize(stretch_len=0.75, stretch_wid=0.75)
ball.penup()
ball.dx = 1.3 # user defined properties
ball.dy = 1.3
# Keybinding
paddle_a.ondrag(paddle_move)
# Main game loop
def play():
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border checking
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
elif ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if not -390 <= ball.xcor() <= 390:
ball.goto(0, 0)
ball.dx *= -1
screen.update()
screen.ontimer(play)
play()
screen.mainloop()
Here's the full code
import os
wn = turtle.Screen()
wn.title("Pong")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)
# Score
score_a = 0
score_b = 0
# Paddle A
paddle_a = turtle.Turtle()
paddle_a.speed(0)
paddle_a.shape("square")
paddle_a.color("white")
paddle_a.shapesize(stretch_wid=5,stretch_len=1)
paddle_a.penup()
paddle_a.goto(-350, 0)
# Paddle B
paddle_b = turtle.Turtle()
paddle_b.speed(0)
paddle_b.shape("square")
paddle_b.color("white")
paddle_b.shapesize(stretch_wid=5,stretch_len=1)
paddle_b.penup()
paddle_b.goto(350, 0)
# Ball
ball = turtle.Turtle()
ball.speed(0)
ball.shape("square")
ball.color("white")
ball.penup()
ball.goto(0, 0)
ball.dx = 0.5
ball.dy = 0.5
# Pen
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Player 1: 0 Player 2: 0", align="center", font=("Impact", 24, "normal"))
# Functions
def paddle_a_up():
y = paddle_a.ycor()
y += 20
paddle_a.sety(y)
def paddle_a_down():
y = paddle_a.ycor()
y -= 20
paddle_a.sety(y)
def paddle_b_up():
y = paddle_b.ycor()
y += 20
paddle_b.sety(y)
def paddle_b_down():
y = paddle_b.ycor()
y -= 20
paddle_b.sety(y)
# Keyboard bindings
wn.listen()
wn.onkeypress(paddle_a_up, "w")
wn.onkeypress(paddle_a_down, "s")
# Main game loop
while True:
wn.update()
# Computer player
if ball.xcor() > 250:
paddle_b.goto (ball.ycor())
# Move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# Border checking
# Top and bottom
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
os.system("afplay bounce.wav&")
elif ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
os.system("afplay bounce.wav&")
# Left and right
if ball.xcor() > 350:
score_a += 1
pen.clear()
pen.write("Player 1: {} Player 2: {}".format(score_a, score_b), align="center", font=("Impact", 24, "normal"))
ball.goto(0, 0)
ball.dx *= -1
elif ball.xcor() < -350:
score_b += 1
pen.clear()
pen.write("Player 1: {} Player 2: {}".format(score_a, score_b), align="center", font=("Impact", 24, "normal"))
ball.goto(0, 0)
ball.dx *= -1
# Paddle and ball collisions
if ball.xcor() < -340 and ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() - 50:
ball.dx *= -1
os.system("afplay bounce.wav&")
elif ball.xcor() > 340 and ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() - 50:
ball.dx *= -1
os.system("afplay bounce.wav&")
I'm trying to make a computer player with # Computer player
if ball.xcor() > 250:
paddle_b.goto (ball.ycor())
Each time the ball's xcor gets passed 250, the program crashes. Any fixes?
It wont let me post till I have more text ignore this please
It wont let me post till I have more text ignore this please
It wont let me post till I have more text ignore this please
I always feel like
Somebodys watching meee
And I got no privacy
Oh Oh Oh
So, your main problem is that paddle_b.goto uses an x/y point, not just the y-coordinate which you're inputting from the ball.
This should be giving you the error:
Traceback (most recent call last):
File "<Path>", line 85, in <module>
paddle_b.goto(ball.ycor())
File "<Path>\turtle.py", line 1774, in goto
self._goto(Vec2D(*x))
TypeError: type object argument after * must be an iterable, not float
From the documentation of goto ( https://docs.python.org/3.3/library/turtle.html?highlight=turtle#turtle.goto ):
If y is None, x must be a pair of coordinates or a Vec2D (e.g. as returned by pos()).
You should be able to do: paddle_b.sety(ball.ycor()) instead, which only needs the y-coordinate and you use already. Alternatively, another way to solve this is to keep the X-coordinate of the paddle the same through: paddle_b.goto(paddle_b.xcor(), ball.ycor()).
I can't seem to get my AI pong paddle to work in Python 3.7.1. I'll admit that I'm new to this so the fix may be easier than I'm making it.
I've tried various forms of adjusting the loops but i think i'm missing something small that plays a big role in the code's processing.
import turtle
# build window
win = turtle.Screen()
# window title/color/size
win.title("csc2280 Project")
win.bgcolor("black")
win.setup(width=800, height=800)
win.tracer(0)
# user paddle
user_paddle = turtle.Turtle()
# user paddle build
user_paddle.shape('square')
user_paddle.shapesize(stretch_wid=5, stretch_len=1)
user_paddle.speed('fastest')
user_paddle.color("white")
# user paddle position
user_paddle.penup()
user_paddle.goto(-350, 0)
# ai paddle
AI_paddle = turtle.Turtle()
# ai paddle build
AI_paddle.shape('square')
AI_paddle.shapesize(stretch_wid=5, stretch_len=1)
AI_paddle.speed('fastest')
AI_paddle.color('white')
#ai paddle position
AI_paddle.penup()
AI_paddle.goto(350, 0)
AI_paddle.speed = 15
# ball
ball = turtle.Turtle()
ball.speed(0)
# ball shape
ball.shape('circle')
ball.color('white')
# ball position
ball.penup()
ball.goto(0, 0)
# ball movement
ball.dx = 2
ball.dy = 2
# Pen
pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Player A: 0 Player B: 0", align = "center", font = ("Calibri", 24, "normal"))
# Keeping Score
score_p1 = 0
score_p2 = 0
# move user paddle up and down
# user paddle up
def user_paddle_up():
y = user_paddle.ycor()
y += 20
user_paddle.sety(y)
# user paddle down
def user_paddle_down():
y = user_paddle.ycor()
y -= 20
user_paddle.sety(y)
# actually moving the paddle
win.listen()
win.onkeypress(user_paddle_up, "Up")
win.onkeypress(user_paddle_down, "Down")
AI_paddle.forward(AI_paddle.speed)
y = AI_paddle.ycor()
if y < -300 or y > 300:
AI_paddle.speed *= -1
I think the issue is right in here somewhere.
# game loop
while True:
win.update()
# moving the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# create border
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
if ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
ball.goto(0,0)
ball.dx *= -1
# updating score
score_p1 += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_p1, score_p2), align = "center", font = ("Calibri", 24, "normal"))
if ball.xcor() < -400:
ball.goto(0,0)
ball.dx *= -1
# updating score
score_p2 += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_p1, score_p2), align = "center", font = ("Calibri", 24, "normal"))
# paddle/ball interaction
if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < AI_paddle.ycor() + 40 and ball.ycor() > AI_paddle.ycor() -40):
ball.setx(340)
ball.dx *= -1
if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < user_paddle.ycor() + 40 and ball.ycor() > user_paddle.ycor() -40):
ball.setx(-340)
ball.dx *= -1
Any help would be super appreciated as this is my final project for the semester and this is literally the only thing holding me up.
The problem I found with your AI player is that this code is in the wrong place:
AI_paddle.forward(AI_paddle.speed)
y = AI_paddle.ycor()
if y < -300 or y > 300:
AI_paddle.speed *= -1
It's just before the main loop so it only gets executed once. It should be inside the main loop, e.g. as the last item.
I found your game difficult to play so I've tweaked some things below to make it more playable and I've made the fix I described above:
from turtle import Screen, Turtle
FONT = ("Calibri", 24, "normal")
# move user paddle up and down
# user paddle up
def user_paddle_up():
y = user_paddle.ycor() + 20
user_paddle.sety(y)
# user paddle down
def user_paddle_down():
y = user_paddle.ycor() - 20
user_paddle.sety(y)
# build window
win = Screen()
# window title/color/size
win.title("csc2280 Project")
win.bgcolor("black")
win.setup(width=800, height=800)
win.tracer(0)
# user paddle
user_paddle = Turtle('square')
# user paddle build
user_paddle.shapesize(stretch_wid=5, stretch_len=1)
user_paddle.color("white")
# user paddle position
user_paddle.penup()
user_paddle.setx(-350)
# AI paddle
AI_paddle = Turtle('square')
# AI paddle build
AI_paddle.shapesize(stretch_wid=5, stretch_len=1)
AI_paddle.color('white')
# AI paddle position
AI_paddle.penup()
AI_paddle.setx(350)
AI_paddle.speed = 10
# ball
ball = Turtle('circle')
# ball shape
ball.color('white')
# ball position
ball.penup()
# ball movement
ball.dx = 2
ball.dy = 2
# Court
court = Turtle(visible=False)
court.color("white")
court.penup()
court.goto(-400, -300)
court.pendown()
court.forward(800)
court.penup()
court.goto(-400, 300)
court.pendown()
court.forward(800)
court.penup()
# Pen
pen = Turtle(visible=False)
pen.color("white")
pen.penup()
pen.sety(325)
pen.write("Player A: 0 Player B: 0", align="center", font=("Calibri", 24, "normal"))
# Keeping Score
score_p1 = 0
score_p2 = 0
# actually moving the paddle
win.onkeypress(user_paddle_up, "Up")
win.onkeypress(user_paddle_down, "Down")
win.listen()
# game loop
while True:
win.update()
# moving the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# enforce boundaries
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
elif ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx *= -1
# updating score
score_p1 += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_p1, score_p2), align="center", font=FONT)
elif ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1
# updating score
score_p2 += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_p1, score_p2), align="center", font=FONT)
# paddle/ball interaction
if (330 < ball.xcor() < 370) and (AI_paddle.ycor() - 60 < ball.ycor() < AI_paddle.ycor() + 60):
ball.setx(330)
ball.dx = - abs(ball.dx)
if (-370 < ball.xcor() < -330) and (user_paddle.ycor() - 60 < ball.ycor() < user_paddle.ycor() + 60):
ball.setx(-330)
ball.dx = abs(ball.dx)
y = AI_paddle.ycor() + AI_paddle.speed
if y < -240 or y > 240:
AI_paddle.speed *= -1
AI_paddle.sety(y)
Good luck with making your AI player smarter!
I'm new here and I'm the beginner. I've been learning programming since 5 months and as the main language I've decided to stick to python. I wrote my first simple game which is ping-pong (based on yt tutorials) and I want to improve it a bit by speeding up the ball after each paddle hit and comes back to normal speed when scored. I know that I put ball.dx +=1 in wrong place. It speeds up tho, but only when ball goes up. When it goes down, it comes back to normal speed and of course the speed is looped and even if scored, it still speeds up. Appreciate for any help.
import turtle
wn = turtle.Screen()
wn.title("gra by mati")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)
# Paddle A
paddle_a = turtle.Turtle()
paddle_a.shape("square")
paddle_a.shapesize(stretch_wid=5, stretch_len=1)
paddle_a.speed(0)
paddle_a.color("white")
paddle_a.penup()
paddle_a.goto(-350, 0)
# Paddle B
paddle_b = turtle.Turtle()
paddle_b.shape("square")
paddle_b.shapesize(stretch_wid=5, stretch_len=1)
paddle_b.speed(0)
paddle_b.color("white")
paddle_b.penup()
paddle_b.goto(350, 0)
# ball
ball = turtle.Turtle()
ball.shape("square")
ball.speed(0)
ball.color("white")
ball.penup()
ball.goto(0, 0)
ball.dx = 1/5
ball.dy = 1/5
# Pen
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Player A: 0 Player B: 0", align="center", font=("Courier", 24, "normal"))
# Score
score_a = 0
score_b = 0
# Function
def paddle_a_up():
y = paddle_a.ycor()
y += 20
paddle_a.sety(y)
def paddle_a_down():
y = paddle_a.ycor()
y -= 20
paddle_a.sety(y)
def paddle_b_up():
y = paddle_b.ycor()
y += 20
paddle_b.sety(y)
def paddle_b_down():
y = paddle_b.ycor()
y -= 20
paddle_b.sety(y)
#keyboard biding
wn.listen()
wn.onkeypress(paddle_a_up, "w")
wn.onkeypress(paddle_a_down, "s")
wn.onkeypress(paddle_b_up, "Up")
wn.onkeypress(paddle_b_down, "Down")
# Main game loop
while True:
wn.update()
# move the ball
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# border checking
if ball.ycor() > 290:
ball.sety(290)
ball.dy *= -1
if ball.ycor() < -290:
ball.sety(-290)
ball.dy *= -1
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx *= -1
score_a += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_a, score_b), align="center", font=("Courier", 24, "normal"))
if ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1
score_b += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_a, score_b), align="center", font=("Courier", 24, "normal"))
# paddle and ball collision
if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() -40):
ball.setx(340)
ball.dx +=1
ball.dx *= -1
if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() -40):
ball.setx(-340)
ball.dx +=1
ball.dx *= -1
So after reviewing your game a bit I found an error that the ball would "stick" to the paddle on the left side, and like you said the speed did not reset each score. I've adjusted it in a few places and it seems much improved.
Firstly I reset the speed every time there was a score:
if ball.xcor() > 390:
ball.goto(0, 0)
ball.dx = 1 / 5 # reset to initial speed
score_a += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_a, score_b), align="center", font=("Courier", 24, "normal"))
if ball.xcor() < -390:
ball.goto(0, 0)
ball.dx = 1 / 5 # reset to initial speed
ball.dx *= -1
score_b += 1
pen.clear()
pen.write("Player A: {} Player B: {}".format(score_a, score_b), align="center", font=("Courier", 24, "normal"))
I think this could be improved by having a variable at the top like initial_speed = 1/5 and then you can put ball.dx = initial_speed everywhere it resets. This allows you to only change one number at the top of your program and it will adjust the speed everywhere, preventing you to have to hunt down everywhere you reset it every time!
Secondly I fixed the paddle collision a little bit
if (ball.xcor() > 340 and ball.xcor() < 350) and (ball.ycor() < paddle_b.ycor() + 50 and ball.ycor() > paddle_b.ycor() -40):
ball.setx(340)
ball.dx *= -1 # flip direction first
ball.dx -=1 # speed it up
if (ball.xcor() < -340 and ball.xcor() > -350) and (ball.ycor() < paddle_a.ycor() + 50 and ball.ycor() > paddle_a.ycor() -40):
ball.setx(-340)
ball.dx *= -1
ball.dx +=1
Again this could be improved by making a variable speed_up_by = 1 and then using ball.dx += speed_up_by to easily adjust it. I think that 1 is far too large of a number and you won't be able to get more than 5 hits in (if you're lucky). To answer your comment about why one is ball.dx +=1 and the other is ball.dx -=1 I urge you to think about it in numbers. The initial speed is .2 (or 1/5), and then after it hits on the right side you should reverse it (to -.2 and now it is traveling left) and then increase its speed (by minusing 1 -> -1.2). Now when it gets to the other side you reverse it again (to 1.2) and then increase its speed (by adding 1 -> 2.2). You can see that even though we are subtracting from the speed it actually increases the magnitude of the speed!! I think this also shows you that increasing the speed by 1 each hit is insanely large. After the first hit the ball is going 6 times as fast as the initial speed!!! After 2 hits it is going 11 times the initial speed!!! You probably want to increase the magnitude of speed by .1 each time. That makes it so after 1 hit the speed is only 1.5 times initial speed. After 2 hits, the speed is twice the initial speed...and so on.