Processing speed changes turtle animation speed - python

I was learning python turtle module.
And I was trying to make a simple pong game.
Here is the code:
import turtle
import win32api
wind = turtle.Screen()
wind.title("Pong game")
wind.bgcolor("black")
wind.setup(width=800, height=500)
wind.tracer(0) # stops window from updating automaticly
# racket1
racket1 = turtle.Turtle()
racket1.speed(0)
racket1.penup()
racket1.color("blue")
racket1.shape("square")
racket1.goto(-370, 0)
racket1.shapesize(stretch_wid=5, stretch_len=1)
# racket2
racket2 = turtle.Turtle()
racket2.speed(0)
racket2.penup()
racket2.color("red")
racket2.shape("square")
racket2.goto(370, 0)
racket2.shapesize(stretch_wid=5, stretch_len=1)
# ball
ball = turtle.Turtle()
ball.speed(0)
ball.penup()
ball.color("white")
ball.shape("circle")
ball.goto(0, 0)
ball.dx = 0.2
ball.dy = 0.2
# score writer
scw = turtle.Turtle()
scw.penup()
scw.speed(0)
scw.hideturtle()
scw.goto(0, 210)
scw.color("white")
scw.write("Blue: 0 Red: 0", font=("Arial", 24, "bold"), align="center")
# racket 1 functions
def racket1_up():
y = racket1.ycor()
if y < 200:
y += 0.3
racket1.sety(y)
def racket1_down():
y = racket1.ycor()
if y > -200:
y -= 0.3
racket1.sety(y)
# racket 2 functions
def racket2_up():
y = racket2.ycor()
if y < 200:
y += 0.3
racket2.sety(y)
def racket2_down():
y = racket2.ycor()
if y > -200:
y -= 0.3
racket2.sety(y)
# scores
p1 = 0
p2 = 0
while True:
wind.update()
# ball move
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
# border check
if ball.ycor() > 239: #240
ball.dy *= -1
if ball.ycor() < -239: #-240
ball.dy *= -1
if ball.xcor() > 389: #390
ball.goto(0, 0)
p1 += 1
ball.dx *= -1
scw.clear()
scw.write(f"Blue: {p1} Red: {p2}", font=("Arial", 24, "bold"), align="center")
if ball.xcor() < -389: #-390
ball.goto(0, 0)
p2 += 1
ball.dx *= -1
scw.clear()
scw.write(f"Blue: {p1} Red: {p2}", font=("Arial", 24, "bold"), align="center")
# ball and madareb collision
if ball.xcor() > 350 and ball.ycor() < racket2.ycor()+60 and ball.ycor() > racket2.ycor()-60:
ball.dx *= -1
if ball.xcor() < -350 and ball.ycor() < racket1.ycor()+60 and ball.ycor() > racket1.ycor()-60:
ball.dx *= -1
# racket 1 movement
w = win32api.GetKeyState(0x57)
s = win32api.GetKeyState(0x53)
if w < 0:
racket1_up()
if s < 0:
racket1_down()
# racket 2 movement
u = win32api.GetKeyState(0x26)
d = win32api.GetKeyState(0x28)
if u < 0:
racket2_up()
if d < 0:
racket2_down()
The game worked properly but the ball speed changes, I think that this is due to the change of the processing speed changes.
So is it possible to make the speed not change with the changing of the processing speed?

Related

The ball for a pong game is stuck outside of the screen

I made a code for a simple pong game, but the ball keeps glitching outside of the screen. The score increases but the ball are not visible. I was expecting to see the ball go to the center of the screen but instead it is stuck at the bottom. I followed a youtube tutorial for beginners as I haven't coded in a long time. This is the youtube video link:https://www.youtube.com/watch?v=gJnUTX00Z9k
This is the code:
import turtle as t
playerAscore=0
playerBscore=0
window=t.Screen()
window.title("Pong-Game")
window.bgcolor("black")
window.setup(width=800,height=600)
window.tracer(0)
leftpaddle=t.Turtle()
leftpaddle.speed(0)
leftpaddle.shape("square")
leftpaddle.color("green")
leftpaddle.shapesize(stretch_wid=5,stretch_len=1)
leftpaddle.penup()
leftpaddle.goto(-350,0)
rightpaddle=t.Turtle()
rightpaddle.speed(0)
rightpaddle.shape("square")
rightpaddle.color("green")
rightpaddle.shapesize(stretch_wid=5,stretch_len=1)
rightpaddle.penup()
rightpaddle.goto(350,0)
ball=t.Turtle()
ball.speed(0)
ball.shape("circle")
ball.color("white")
ball.penup()
ball.goto(0,0)
ballxdirection=0.2
ballydirection=0.2
pen=t.Turtle()
pen.speed(0)
pen.color("blue")
pen.penup()
pen.goto(0,260)
pen.write("score",align="center",font=("Arial",24,"normal"))
#Movement&Logik
def leftpaddleup():
y=leftpaddle.ycor()
y=y+90
leftpaddle.sety(y)
def leftpaddledown():
y=leftpaddle.ycor()
y=y-90
leftpaddle.sety(y)
def rightpaddleup():
y=rightpaddle.ycor()
y=y+90
rightpaddle.sety(y)
def rightpaddledown():
y=rightpaddle.ycor()
y=y-90
rightpaddle.sety(y)
window.listen()
window.onkeypress(leftpaddleup,"w")
window.onkeypress(leftpaddledown,"s")
window.onkeypress(rightpaddleup,"Up")
window.onkeypress(rightpaddledown,"Down")
while True:
window.update()
ball.setx(ball.xcor()+ballxdirection)
ball.sety(ball.ycor() +ballydirection)
if ball.ycor()>290:
ball.sety(290)
ballydirection=ballydirection*-1
if ball.ycor() > -290:
ball.sety(-290)
ballydirection = ballydirection * -1
if ball.xcor()>390:
ball.goto(0,0)
ballxdirection=ballxdirection*-1
playerAscore=playerAscore+1
pen.clear()
pen.write("Player A: {} Player B: {}".format(playerAscore,playerBscore),align='center',font=("Arial"))
if ball.xcor()<-390:
ball.goto(0,0)
ballxdirection=ballxdirection*-1
playerBscore+=1
pen.clear()
pen.write("Player A: {} Player B: {}".format(playerAscore,playerBscore),align='center',font=("Arial"))
if (ball.xcor() > 340) and (ball.xcor() < 350) and (ball.ycor() < rightpaddle.ycor() + 40) and (ball.ycor() > rightpaddle.ycor() - 40):
ball.sety(340)
ballydirection = ballydirection * -1
if (ball.xcor() > -340) and (ball.xcor() < -350) and (ball.ycor() < leftpaddle.ycor() + 40) and (ball.ycor() > leftpaddle.ycor() - 40):
ball.setx(-340)
ballxdirection = ballxdirection * -1
I tried out your code and kept seeing quick flashes of the ball at the bottom of the screen as you probably did. After reviewing various tests and positioning updates, I found lines where the test condition needed to be corrected from "greater than" to "less than", corrected some range testing, and corrected how some positioning values were derived. Following is a refactored version of your program where I added some comments noting the corrections made.
import turtle as t
playerAscore=0
playerBscore=0
window=t.Screen()
window.title("Pong-Game")
window.bgcolor("black")
window.setup(width=800,height=600)
window.tracer(0)
leftpaddle=t.Turtle()
leftpaddle.speed(0)
leftpaddle.shape("square")
leftpaddle.color("green")
leftpaddle.shapesize(stretch_wid=5,stretch_len=1)
leftpaddle.penup()
leftpaddle.goto(-350,0)
rightpaddle=t.Turtle()
rightpaddle.speed(0)
rightpaddle.shape("square")
rightpaddle.color("green")
rightpaddle.shapesize(stretch_wid=5,stretch_len=1)
rightpaddle.penup()
rightpaddle.goto(350,0)
ball=t.Turtle()
ball.speed(0)
ball.shape("circle")
ball.color("white")
ball.penup()
ball.goto(0,0)
ballxdirection=0.2
ballydirection=0.2
pen=t.Turtle()
pen.speed(0)
pen.color("blue")
pen.penup()
pen.goto(0,260)
pen.write("score",align="center",font=("Arial",24,"normal"))
#Movement&Logik
def leftpaddleup():
y=leftpaddle.ycor()
y=y+90
leftpaddle.sety(y)
def leftpaddledown():
y=leftpaddle.ycor()
y=y-90
leftpaddle.sety(y)
def rightpaddleup():
y=rightpaddle.ycor()
y=y+90
rightpaddle.sety(y)
def rightpaddledown():
y=rightpaddle.ycor()
y=y-90
rightpaddle.sety(y)
window.listen()
window.onkeypress(leftpaddleup,"w")
window.onkeypress(leftpaddledown,"s")
window.onkeypress(rightpaddleup,"Up")
window.onkeypress(rightpaddledown,"Down")
while True:
window.update()
ball.setx(ball.xcor() + ballxdirection)
ball.sety(ball.ycor() + ballydirection)
if ball.ycor()>290:
ball.sety(290)
ballydirection = ballydirection * -1
if ball.ycor() < -290: # Corrected the comparison operator here
ball.sety(-290)
ballydirection = ballydirection * -1
if ball.xcor()>390:
ball.goto(390,ball.ycor()) # Corrected the positioning of the ball
ballxdirection=ballxdirection*-1
playerAscore=playerAscore+1
pen.clear()
pen.write("Player A: {} Player B: {}".format(playerAscore,playerBscore),align='center',font=("Arial"))
if ball.xcor()<-390:
ball.goto(-390,ball.ycor()) # Corrected the positioning of the ball
ballxdirection=ballxdirection*-1
playerBscore+=1
pen.clear()
pen.write("Player A: {} Player B: {}".format(playerAscore,playerBscore),align='center',font=("Arial"))
if (ball.xcor() > 340) and (ball.xcor() < 350) and (ball.ycor() < rightpaddle.ycor() + 40) and (ball.ycor() > rightpaddle.ycor() - 40):
ball.setx(340) # Changed this to setx
ballydirection = ballydirection * -1
ballxdirection = ballxdirection * -1 # Added the missing x direction change
# Corrected the range testing on this
if (ball.xcor() > -350) and (ball.xcor() < -340) and (ball.ycor() < leftpaddle.ycor() + 40) and (ball.ycor() > leftpaddle.ycor() - 40):
ball.setx(-340)
ballydirection = ballydirection * -1 # Added the missing y direction change
ballxdirection = ballxdirection * -1
With those changes, the ball shows up on the screen and bounces about either off the walls or the paddles.
There might be some tweaking of the paddle range test for collision as the range and offset was a bit off, but I will leave that for further game refinement.
Try out these tweaks to see if it meets the spirit of your project.

What do I do when I exceed maximum recursion depth in __instancecheck__ in python pong?

I created pong with the help of a youtube tutorial https://www.youtube.com/watch?v=XGf2GcyHPhc&ab_channel=freeCodeCamp.org , and everything works, except the ball goes really fast, and then really slow and so on. The speed of the ball is inconsistent and this makes it hard to play. I did some research and found this, How to fix inconsistent frame rate (speed) in python turtle , I think I did what I had to do, but now the program runs for a couple of seconds, and then stops and gives this error: RecursionError: maximum recursion depth exceeded in instancecheck , what do I do?
This is my code right now:
import turtle
window = turtle.Screen()
window.title("Pong by #Ubevg")
window.bgcolor("black")
window.setup(width=800, height=600)
window.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.shapesize(stretch_wid=5, stretch_len=1)
paddle_A.color("white")
paddle_A.penup()
paddle_A.goto(-350, 0)
# paddle B
paddle_B = turtle.Turtle()
paddle_B.speed(0)
paddle_B.shape("square")
paddle_B.shapesize(stretch_wid=5, stretch_len=1)
paddle_B.color("white")
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.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
pen.write("Player A: " + str(score_A) + " " + "Player B: " + str(score_B), align="center", font=("Courier", 24, "normal"))
# 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)
# keybind
window.listen()
window.onkeypress(paddle_A_up, ("w"))
window.onkeypress(paddle_A_down, ("s"))
window.onkeypress(paddle_B_up, ("Up"))
window.onkeypress(paddle_B_down, ("Down"))
# main game loop
def move_balls():
global score_A, score_B
window.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
elif 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: " + str(score_A) + " " + "Player B: " + str(score_B), align="center",
font=("Courier", 24, "normal"))
elif ball.xcor() < -390:
ball.goto(0, 0)
ball.dx *= -1
score_B += 1
pen.clear()
pen.write("Player A: " + str(score_A) + " " + "Player B: " + str(score_B), align="center",
font=("Courier", 24, "normal"))
# 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
elif 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
window.ontimer(move_balls(), 100)
move_balls()
i got the same problem with tkinter when trying to implement the timer. i think u should remove the brackets from the function when passing it to window.ontimer , like so window.ontimer(move_balls,100) rather not window.ontimer(move_balls(),100)
move_balls has window.ontimer(move_balls(), 100) in it, which is the problem. You need to put the window.ontimer call outside of that function, to avoid infinite recursion. Otherwise the function is going to call itself every 100ms, and each call will then call itself again every 100ms, and that's going to multiply until the program crashes.

Collision detection for player

My code works like pong except I tried to make it 4 players. Collision between the ball and the player sort of works but it only goes towards one direction. I want to make it so that if the ball hits the top edge of the player the ball goes up and if it hit's the side of the player, the ball goes flying to that direction. Right now the ball only goes in a diagonal direction.
import turtle
import math
wn = turtle.Screen()
wn.title("PMH HANDBALL")
wn.bgcolor("Black")
wn.setup(width=800, height=600)
wn.tracer(0)
def isCollision(t1, t2):
distance = math.sqrt(math.pow(t1.xcor()-
t2.xcor(),2)+math.pow(t1.ycor()-t2.ycor(),2))
if distance < 50:
return True
else:
return False
#Handball court top right
court = turtle.Turtle()
court.speed(0)
court.color("white")
court.hideturtle()
court.goto(400, 0)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
#handball court top left
court.speed(0)
court.color("white")
court.hideturtle()
court.goto(-400, 0)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
#Handball court bottom left
court.speed(0)
court.color("white")
court.hideturtle()
court.goto(-400, -400)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
#handball court bottom right
court.speed(0)
court.color("white")
court.hideturtle()
court.goto(0, -400)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
court.left(90)
court.forward(400)
#handball
ball = turtle.Turtle()
ball.speed(0)
ball.shape("square")
ball.color("white")
ball.penup()
ball.goto(50, 50)
ball.dx = 2
ball.dy = -2
#player 1
player1 = turtle.Turtle()
player1.speed(0)
player1.shape("square")
player1.color("red")
player1.shapesize(stretch_wid=4, stretch_len=4)
player1.penup()
player1.goto(100, 200)
#player 2
player2 = turtle.Turtle()
player2.speed(0)
player2.shape("square")
player2.color("yellow")
player2.shapesize(stretch_wid=4, stretch_len=4)
player2.penup()
player2.goto(100, -200)
#player 3
player3 = turtle.Turtle()
player3.speed(0)
player3.shape("square")
player3.color("green")
player3.shapesize(stretch_wid=4, stretch_len=4)
player3.penup()
player3.goto(-100, 200)
#player 4
player4 = turtle.Turtle()
player4.speed(0)
player4.shape("square")
player4.color("blue")
player4.shapesize(stretch_wid=4, stretch_len=4)
player4.penup()
player4.goto(-100, -200)
#function
def player1_up():
y = player1.ycor()
y += 20
player1.sety(y)
x = player1.xcor()
x += 20
def player1_down():
y = player1.ycor()
y -= 20
player1.sety(y)
def player1_right():
x = player1.xcor()
x += 20
player1.setx(x)
def player1_left():
x = player1.xcor()
x -= 20
player1.setx(x)
def player2_up():
y = player2.ycor()
y += 20
player2.sety(y)
def player2_down():
y = player2.ycor()
y -= 20
player2.sety(y)
def player2_right():
x = player2.xcor()
x += 20
player2.setx(x)
def player2_left():
x = player2.xcor()
x += -20
player2.setx(x)
def player3_up():
y = player3.ycor()
y += 20
player3.sety(y)
x = player1.xcor()
x += 20
def player3_down():
y = player3.ycor()
y -= 20
player3.sety(y)
def player3_right():
x = player3.xcor()
x += 20
player3.setx(x)
def player3_left():
x = player3.xcor()
x -= 20
player3.setx(x)
def player4_up():
y = player4.ycor()
y += 20
player4.sety(y)
x = player4.xcor()
x += 20
def player4_down():
y = player4.ycor()
y -= 20
player4.sety(y)
def player4_right():
x = player4.xcor()
x += 20
player4.setx(x)
def player4_left():
x = player4.xcor()
x -= 20
player4.setx(x)
#keyboard bind
wn.listen()
wn.onkeypress(player1_up, "i")
wn.onkeypress(player1_down, "k")
wn.onkeypress(player1_right, "l")
wn.onkeypress(player1_left, "j")
wn.onkeypress(player2_up, "Up")
wn.onkeypress(player2_down, "Down")
wn.onkeypress(player2_right, "Right")
wn.onkeypress(player2_left, "Left")
wn.onkeypress(player3_up, "w")
wn.onkeypress(player3_down, "s")
wn.onkeypress(player3_right, "d")
wn.onkeypress(player3_left, "a")
wn.onkeypress(player4_up, "t")
wn.onkeypress(player4_down, "g")
wn.onkeypress(player4_right, "h")
wn.onkeypress(player4_left, "f")
#main loop that keeps window running
while True:
wn.update()
#boundary checking topright
if player1.xcor() > 360:
player1.goto(360, player1.ycor())
if player1.xcor() < 25:
player1.goto(40, player1.ycor())
if player1.ycor() > 360:
player1.goto(player1.xcor(), 360)
if player1.ycor() < 35:
player1.goto(player1.xcor(), 40)
#Boundary checking bottomright
if player2.xcor() > 360:
player2.goto(360, player2.ycor())
if player2.xcor() < 25:
player2.goto(40, player2.ycor())
if player2.ycor() > -40:
player2.goto(player2.xcor(), -40)
if player2.ycor() < -360:
player2.goto(player2.xcor(), -360)
#boundary checking topleft
if player3.xcor() > -40:
player3.goto(-40, player3.ycor())
if player3.xcor() < -360:
player3.goto(-360, player3.ycor())
if player3.ycor() > 360:
player3.goto(player3.xcor(), 360)
if player3.ycor() < 35:
player3.goto(player3.xcor(), 40)
#boundary checking bottomleft
if player4.xcor() > -40:
player4.goto(-40, player4.ycor())
if player4.xcor() < -360:
player4.goto(-360, player4.ycor())
if player4.ycor() > -40:
player4.goto(player4.xcor(), -40)
if player4.ycor() < -360:
player4.goto(player4.xcor(), -360)
#ball movement
ball.setx(ball.xcor() + ball.dx)
ball.sety(ball.ycor() + ball.dy)
#border checking for ball
if ball.ycor() > 420:
ball.goto(50,50)
ball.dy *= -1
if ball.ycor() < -420:
ball.goto(50,50)
ball.dy *= 1
if ball.xcor() > 420:
ball.goto(50, 50)
ball.dx *= -1
if ball.xcor() < -420:
ball.goto(50, 50)
ball.dx *= -1
#player and ball collisons
if isCollision(ball, player4):
ball.dy *= -1
ball.dx *= -1
if isCollision(ball, player3):
ball.dy *= -1
ball.dx *= -1
if isCollision(ball, player2):
ball.dy *= -1
ball.dx *= -1
if isCollision(ball, player1):
ball.dy *= -1
ball.dx *= -1
I've reworked the ball with player collision logic in your code to provide a simple, but playable bounce motion:
Far from perfect, this should give you a starting point from which to experiment. I've also rewritten your code to simplify extending it -- it's about half the size and paramerterized to the size of the screen and players:
from turtle import Screen, Turtle
from functools import partial
from random import choice
WIDTH, HEIGHT = 800, 600
CURSOR_SIZE = 20
PLAYER_SIZE = 80
def isCollision(t1, t2):
return t1.distance(t2) < (PLAYER_SIZE + CURSOR_SIZE) / 2
# Event handlers
def player_up(player):
player.sety(player.ycor() + 20)
def player_down(player):
player.sety(player.ycor() - 20)
def player_right(player):
player.setx(player.xcor() + 20)
def player_left(player):
player.setx(player.xcor() - 20)
screen = Screen()
screen.title("PMH HANDBALL")
screen.setup(WIDTH, HEIGHT)
screen.bgcolor('black')
screen.tracer(0)
# Handball court
court = Turtle()
court.hideturtle()
court.color('white')
court.width(4)
for x, y in ((0, -HEIGHT/2), (-WIDTH/2, -HEIGHT/2), (-WIDTH/2, 0), (0, 0)):
court.goto(x, y)
for _ in range(2):
court.forward(WIDTH/2)
court.left(90)
court.forward(HEIGHT/2)
court.left(90)
# Handball
ball = Turtle()
ball.shape('circle')
ball.color('white')
ball.penup()
ball.dx = 2
ball.dy = 2
ball.dx *= choice([-1, 1])
ball.dy *= choice([-1, 1])
# Player 1
player1 = Turtle()
player1.shape('square')
player1.color('red')
player1.shapesize(PLAYER_SIZE / CURSOR_SIZE)
player1.penup()
player1.goto(WIDTH/4, HEIGHT/4)
# Player 2
player2 = player1.clone()
player2.color('yellow')
player2.goto(WIDTH/4, -HEIGHT/4)
# Player 3
player3 = player1.clone()
player3.color('green')
player3.goto(-WIDTH/4, HEIGHT/4)
# Player 4
player4 = player1.clone()
player4.color('blue')
player4.goto(-WIDTH/4, -HEIGHT/4)
# Keyboard bindings
screen.onkeypress(partial(player_up, player1), 'i')
screen.onkeypress(partial(player_down, player1), 'k')
screen.onkeypress(partial(player_right, player1), 'l')
screen.onkeypress(partial(player_left, player1), 'j')
screen.onkeypress(partial(player_up, player2), 'Up')
screen.onkeypress(partial(player_down, player2), 'Down')
screen.onkeypress(partial(player_right, player2), 'Right')
screen.onkeypress(partial(player_left, player2), 'Left')
screen.onkeypress(partial(player_up, player3), 'w')
screen.onkeypress(partial(player_down, player3), 's')
screen.onkeypress(partial(player_right, player3), 'd')
screen.onkeypress(partial(player_left, player3), 'a')
screen.onkeypress(partial(player_up, player4), 't')
screen.onkeypress(partial(player_down, player4), 'g')
screen.onkeypress(partial(player_right, player4), 'h')
screen.onkeypress(partial(player_left, player4), 'f')
screen.listen()
# Main loop that keeps window running
while True:
# boundary checking top right
if player1.xcor() > WIDTH/2 - PLAYER_SIZE/2:
player1.setx(WIDTH/2 - PLAYER_SIZE/2)
elif player1.xcor() < PLAYER_SIZE/2:
player1.setx(PLAYER_SIZE/2)
if player1.ycor() > HEIGHT/2 - PLAYER_SIZE/2:
player1.sety(HEIGHT/2 - PLAYER_SIZE/2)
elif player1.ycor() < PLAYER_SIZE/2:
player1.sety(PLAYER_SIZE/2)
# boundary checking bottom right
if player2.xcor() > WIDTH/2 - PLAYER_SIZE/2:
player2.setx(WIDTH/2 - PLAYER_SIZE/2)
elif player2.xcor() < PLAYER_SIZE/2:
player2.setx(PLAYER_SIZE/2)
if player2.ycor() > -PLAYER_SIZE/2:
player2.sety(-PLAYER_SIZE/2)
elif player2.ycor() < PLAYER_SIZE/2 - HEIGHT/2:
player2.sety(PLAYER_SIZE/2 - HEIGHT/2)
# boundary checking top left
if player3.xcor() > -PLAYER_SIZE/2:
player3.setx(-PLAYER_SIZE/2)
elif player3.xcor() < PLAYER_SIZE/2 - WIDTH/2:
player3.setx(PLAYER_SIZE/2 - WIDTH/2)
if player3.ycor() > HEIGHT/2 - PLAYER_SIZE/2:
player3.sety(HEIGHT/2 - PLAYER_SIZE/2)
elif player3.ycor() < PLAYER_SIZE/2:
player3.sety(PLAYER_SIZE/2)
# boundary checking bottom left
if player4.xcor() > -PLAYER_SIZE/2:
player4.setx(-PLAYER_SIZE/2)
elif player4.xcor() < PLAYER_SIZE/2 - WIDTH/2:
player4.setx(PLAYER_SIZE/2 - WIDTH/2)
if player4.ycor() > -PLAYER_SIZE/2:
player4.sety(-PLAYER_SIZE/2)
elif player4.ycor() < PLAYER_SIZE/2 - HEIGHT/2:
player4.sety(PLAYER_SIZE/2 - HEIGHT/2)
# Ball movement
x, y = ball.position()
x += ball.dx
y += ball.dy
# Border checking for ball
if not - (WIDTH/2 + CURSOR_SIZE/2) < x < WIDTH/2 + CURSOR_SIZE/2:
ball.home()
ball.dx *= choice([-1, 1])
ball.dy *= choice([-1, 1])
continue
elif not - (HEIGHT/2 + CURSOR_SIZE/2) < y < HEIGHT/2 + CURSOR_SIZE/2:
ball.home()
ball.dx *= choice([-1, 1])
ball.dy *= choice([-1, 1])
continue
ball.setposition(x, y)
# Player and ball collisions
# Simplistic player and ball collision logic
for player in [player1, player2, player3, player4]:
if isCollision(ball, player):
p_x, p_y = player.position()
if abs(p_x - x) > abs(p_y - y):
ball.dx *= -1
else:
ball.dy *= -1
break
screen.update()

Clarification on Collision Detection and Updating Labels

I am trying to work on a paddle ball game that entails keeping a ball bouncing away from the bottom for as long as possible. In this game, there are five lives, which can get depleted when the ball hits the bottom of the screen, and resets itself once it has reached 0 lives. However, the ball does not bounce off of the paddle as it should, nor does the label for the score update as it ought to. The code for how I am trying to achieve the collision currently is tied to the vertical placement of the ball, the relative section of which is as follows:
if vertical_direction == "south":
top_y += dy
if top_y >= (self.canvas_height - ball_diameter) - 20:
if self.top_paddle <= top_y and self.top_paddle + 80 >= top_y:
top_y = self.canvas_height - ball_diameter
vertical_direction = "north"
elif top_y >= self.canvas_height - ball_diameter:
lives -= 1
if (lives >= 0):
top_x = 2
top_y = 2
self.canvas.delete("ball")
ball = self.canvas.create_oval(top_x, top_y, top_x + ball_diameter,
top_y + ball_diameter, fill = "blue", tags = "ball")
var.set("Lives: " +lives_Label)
else:
lives= 5
top_x = 2
top_y = 2
self.canvas.delete(ball)
ball = self.canvas.create_oval(top_x, top_y, top_x + ball_diameter,
top_y + ball_diameter, fill = "blue", tags = "ball")
I have looked at a bit of code which I found to be most similar to mine, and tried to implement its methods for detecting collision as displayed above. My only guess is there is some obvious logical inconsistency I failed to notice that is obvious to a more experienced coder, and that is the cause of both of my problems.
For reference, here is the complete code thus far:
from tkinter import *
import tkinter.font
class BallBounce (Frame):
def __init__(self):
Frame.__init__(self)
self.master.title("Bouncing Ball")
self.grid()
lives = 5
lives_Label = str(lives)
var = StringVar()
font = tkinter.font.Font(family = "Verdana", size = 20)
self._label = Label(self, font = font, textvariable = var)
var.set("Lives: "+lives_Label)
self._label.grid(row = 0, column = 0)
self.canvas_width = 800
self.canvas_height = 400
self.canvas = Canvas(self, width = self.canvas_width, height = self.canvas_height,
bg = "white")
self.canvas.grid(row = 1, column = 0)
frame = Frame(self)
frame.grid(row = 1, column = 0)
top_x = 0
top_y = 0
ball_diameter = 20
self.canvas.create_oval(top_x, top_y, ball_diameter, ball_diameter, fill = "blue", tags = "ball")
horizontal_direction = "east"
vertical_direction = "south"
self.canvas.create_rectangle (self.canvas_width / 2, self.canvas_height - 20, self.canvas_width / 2 + 80,
self.canvas_height, fill = "black", tags = "paddle")
self.top_paddle = self.canvas_width/2
self.canvas.bind("<Left>", lambda event: self.canvas.move("paddle", -5, 0))
self.canvas.bind("<Right>", lambda event: self.canvas.move("paddle", 5, 0))
self.canvas.focus_set()
dx = 2
dy = 2
while True:
if horizontal_direction == "east":
top_x += dx # dx is 2 because the ball moves 2 pixels horizontally every 15 milliseconds
if top_x >= self.canvas_width - ball_diameter: # ball has hit east wall
top_x = self.canvas_width - ball_diameter
horizontal_direction = "west" # change direction
self.canvas.move("ball", dx, 0) # move ball horizontally dx pixels to the right/east
else: # i.e., horizontal_direction is "west"
top_x -= dx
if top_x <= 0: # ball has hit west wall
top_x = 0 # you may need to adjust this a little
horizontal_direction = "east" # change direction
self.canvas.move("ball", -dx, 0) # move ball horizontally dx pixels to the left/west
if vertical_direction == "south":
top_y += dy
if top_y >= (self.canvas_height - ball_diameter) - 20:
if self.top_paddle <= top_y and self.top_paddle + 80 >= top_y:
top_y = self.canvas_height - ball_diameter
vertical_direction = "north"
elif top_y >= self.canvas_height - ball_diameter:
lives -= 1
if (lives >= 0):
top_x = 2
top_y = 2
self.canvas.delete("ball")
ball = self.canvas.create_oval(top_x, top_y, top_x + ball_diameter,
top_y + ball_diameter, fill = "blue", tags = "ball")
var.set("Lives: " +lives_Label)
else:
lives= 5
top_x = 2
top_y = 2
self.canvas.delete(ball)
ball = self.canvas.create_oval(top_x, top_y, top_x + ball_diameter,
top_y + ball_diameter, fill = "blue", tags = "ball")
self.canvas.move("ball", 0, dy)
else:
top_y -= dy
if top_y <= 0:
top_y = 0
vertical_direction = "south"
self.canvas.move("ball", 0, -dy)
self.canvas.after(15)
self.canvas.update()
def main():
BallBounce().mainloop()
main()

Ball bounce in pong

I have written some code but can't get the ball to bounce on the floor or the ceiling naturally. Please help!
I've already tried getting the ball heading with ball_heading = ball.heading, but that didn't work
#Python 3.6.3
from turtle import *
import math
import random
#Screen Setup
bgcolor("black")
wn = Screen()
wn.title("Pong")
#Drawing Border
bd = Turtle()
bd.pencolor("white")
bd.pensize(3)
bd.hideturtle()
bd.penup()
bd.setposition(-400, -300)
bd.pendown()
bd.speed(0)
bd.pendown()
for line in range(2):
bd.forward(800)
bd.left(90)
bd.forward(600)
bd.left(90)
bd.penup()
bd.setposition(0, 300)
bd.setheading(270)
bd.pendown()
for dash in range(30):
bd.forward(10)
bd.penup()
bd.forward(10)
bd.pendown()
#Creating Paddles
#Paddle 1
player1 = Turtle()
player1.color("white")
player1.shape("square")
player1.shapesize(stretch_wid=5, stretch_len=1)
player1.penup()
player1.setposition(-370, 0)
#Paddle 2
player2 = Turtle()
player2.color("white")
player2.shape("square")
player2.shapesize(stretch_wid=5, stretch_len=1)
player2.penup()
player2.setposition(370, 0)
#Creating the ball
ball = Turtle()
ball.color("white")
ball.shape("square")
ball.speed(0)
ball.penup()
ball.setposition(0, 0)
ball.setheading(random.randint(0, 360))
#Moving the player
playerspeed = 15
#p1
def move_up():
y = player1.ycor()
y += playerspeed
#Setting the boundries
if y > 245:
y = 245
player1.sety(y)
def move_down():
y = player1.ycor()
y -= playerspeed
#Setting the boundries
if y < -245:
y = -245
player1.sety(y)
#p2
def move_up2():
y = player2.ycor()
y += playerspeed
#Setting the boundries
if y > 245:
y = 245
player2.sety(y)
def move_down2():
y = player2.ycor()
y -= playerspeed
#Setting the boundries
if y < -245:
y = -245
player2.sety(y)
#Ball movement
def ball_fd():
ball.forward(3)
#Ball ceiling / floor bounce
def ball_bounce():
by = ball.ycor()
if by > 279:
by = 279
ball.sety(by)
bx = ball.ycor()
if bx < -279:
bx = -279
ball.setx(bx)
#binding
listen()
onkey(move_up, "Up")
onkey(move_down, "Down")
onkey(move_up2, "w")
onkey(move_down2, "s")
#Making the ball move / main game loop
while True:
ball_fd()
ball_bounce()
Sorry the code is kind of long, but feel free to copy + paste it into IDLE or whatever.
Thank you
You didn't turn the ball when it hit the floor or ceiling.
while True:
ball.fd(3)
by = ball.ycor()
if abs(by) > 279:
ball.setheading(-ball.heading())

Categories