After a few seconds, one turtle stops and the other goes faster - python

After weeks of trying, I have not come up with a solution to this issue, in which one turtle comes to a complete stop and the other goes 2x - 3x faster. How can I fix this? You must move them both around for a little bit to encounter the issue. Also this is on the site: repl.it
I have tried moving the wn.listen() command but that only switched which turtle stopped and which one didn't. I have unsuccessfully tried to switch the forward() command to goto() and I have tried to use direction specific movement (also unsuccessfully):
import turtle
import sys
player1 = turtle.Turtle()
player1.up()
player1.goto(0,350)
player1.right(90)
player1.down()
player2 = turtle.Turtle()
wn = turtle.Screen()
#preGame setup
player2.up()
player2.goto(0,-350)
player2.left(90)
player2.down()
player2.color("blue")
player1.color("red")
#main game loop
player1.speed(0)
player2.speed(0)
k = 0
def kr():
player1.left(90)
def kl():
player1.right(90)
wn.onkey(kr, "d")
wn.onkey(kl, "a")
def k1():
player2.right(90)
def k2():
player2.left(90)
wn.onkey(k1, "k")
wn.onkey(k2, "l")
wn.listen()
while True:
player1.forward(1)
player2.forward(1)
while player1.xcor() < (-350) or player1.xcor() > (350) or player1.ycor() > (350) or player1.ycor() < (-350):
player1.back(30)
while player2.xcor() < (-350) or player2.xcor() > (350) or player2.ycor() > (350) or player2.ycor() < (-350):
player2.back(30)
if player1.pos() == player2.pos():
print ("DONT CRASH INTO THE OTHER PLAYER")
sys.exit()
I expected them both to continue moving indefinitely, but one always stops, and the other is going 2x the speed.

Move the keylisteners outside your loop - having them inside the while loop will reattach them and redefine the functions all the time and confuse turtle.
You need to set them up once not every few milliseconds:
import turtle
player1 = turtle.Turtle()
player2 = turtle.Turtle()
player1.goto(350, 0)
player2.goto(-350, 0)
player1.right(180)
wn = turtle.Screen()
def kl():
player1.left(90)
def kr():
player1.right(90)
def k1():
player2.right(90)
def k2():
player2.left(90)
wn.onkey(kl, "d") # changed to lowercase
wn.onkey(kr, "a")
wn.onkey(k1, "j") # changed to other letters
wn.onkey(k2, "l")
wn.listen()
while True: # not changing k so just use while True
player1.forward(1) # changed speed
player2.forward(1)

Your nested while loop structure is working against you and isn't valid for an event-driven environment like turtle. Here's a rework of your program to fix this issue and clean up the code:
from turtle import Screen, Turtle
import sys
# preGame setup
player1 = Turtle()
player1.hideturtle()
player1.up()
player1.goto(0, 350)
player1.down()
player1.right(90)
player1.color('red')
player1.speed('fastest')
player1.showturtle()
def r1():
player1.left(90)
def l1():
player1.right(90)
player2 = Turtle()
player2.hideturtle()
player2.up()
player2.goto(0, -350)
player2.down()
player2.left(90)
player2.color('blue')
player2.speed('fastest')
player2.showturtle()
def r2():
player2.right(90)
def l2():
player2.left(90)
# main game loop
def move():
player1.forward(5)
if not (-350 < player1.xcor() < 350 and -350 < player1.ycor() < 350):
player1.backward(30)
player2.forward(5)
if not (-350 < player2.xcor() < 350 and -350 < player2.ycor() < 350):
player2.backward(30)
if player1.distance(player2) < 5:
print("DON'T CRASH INTO THE OTHER PLAYER!")
sys.exit()
screen.ontimer(move, 100)
screen = Screen()
screen.onkey(r1, 'd')
screen.onkey(l1, 'a')
screen.onkey(r2, 'k')
screen.onkey(l2, 'l')
screen.listen()
move()
screen.mainloop()
See if this behaves more like you expect/desire.

Related

Python Turtle becomes unresponsive and hangs after using a while loop

I'm trying to make a program that is essentially an etchasketck, with some minor tweaks for my school project(the required use of a main function, wasd as movement controls, and q to quit the program and p to pick up or drop down the turtle pen). I was testing this code in trinket.io and it was working fine. You can see it working there with this link: https://trinket.io/python/99fd3ec305. However, when I go to run it from pycharm, cmd, or the python IDLE, it always leaves the turtle hanging and unresponsive. I get no errors, just the turtle to pop up for a few seconds, then it hangs, and I'm unable to do anything.
Here's my code:
import sys
import turtle
arg_len = len(sys.argv)
# store length of arguments
if arg_len < 3:
print("Too less arguments, using default values..")
WIDTH = 200
HEIGHT = 200
else:
WIDTH = int(sys.argv[1])
HEIGHT = int(sys.argv[2])
screen = turtle.Screen()
screen.setup(WIDTH, HEIGHT)
# create a turtle instance
t = turtle.Turtle()
t.speed(0)
# slow down the turtle
# declare flags
move = False
exit_flag = False
def up():
global move
move = True
t.setheading(90)
def down():
global move
move = True
t.setheading(270)
def left():
global move
move = True
t.setheading(180)
def right():
global move
move = True
t.setheading(0)
# toggle pen up and down
def toggle_pen():
if t.isdown():
t.penup()
else:
t.pendown()
# set exit flag
def quit_program():
global exit_flag
exit_flag = True
def check_border():
if t.xcor() == WIDTH / 2:
t.penup()
t.setx(-WIDTH / 2)
elif t.xcor() == -WIDTH / 2:
t.penup()
t.setx(WIDTH / 2)
if t.ycor() == HEIGHT / 2:
t.penup()
t.sety(-HEIGHT / 2)
elif t.ycor() == -HEIGHT / 2:
t.penup()
t.sety(HEIGHT / 2)
def listen_keys():
screen.listen()
screen.onkey(up, "w")
screen.onkey(down, "s")
screen.onkey(left, "a")
screen.onkey(right, "d")
screen.onkey(toggle_pen, "p")
screen.onkey(quit_program, "q")
# main loop
def main():
listen_keys()
while not exit_flag:
global move
if move:
t.forward(0.5)
screen.update()
check_border()
else:
t.done()
main()
I'm using python 3.10, and I mainly use pycharm for the running.
I was trying to get the turtle to move indefinitly without user input after the first user input, I was going to achieve this with the while loop, but it just leaves my program unresponsive. Can anyone tell me what's wrong that I'm not seeing?
You've effectively put a while True: loop in an event-driven program where one should never be used. If I were writing this for the command line, with the constraints listed, I might go about it this way (dropping command line processing for example simplicity):
from turtle import Screen, Turtle
WIDTH, HEIGHT = 200, 200
def up():
turtle.setheading(90)
start_motion()
def down():
turtle.setheading(270)
start_motion()
def left():
turtle.setheading(180)
start_motion()
def right():
turtle.setheading(0)
start_motion()
def toggle_pen():
if turtle.isdown():
turtle.penup()
else:
turtle.pendown()
def quit_program():
screen.bye()
def check_border():
x, y = turtle.position()
if x >= WIDTH / 2:
turtle.penup()
turtle.setx(-WIDTH / 2)
elif x <= -WIDTH / 2:
turtle.penup()
turtle.setx(WIDTH / 2)
if y >= HEIGHT / 2:
turtle.penup()
turtle.sety(-HEIGHT / 2)
elif y <= -HEIGHT / 2:
turtle.penup()
turtle.sety(HEIGHT / 2)
def main():
screen.onkey(up, 'w')
screen.onkey(down, 's')
screen.onkey(left, 'a')
screen.onkey(right, 'd')
screen.onkey(toggle_pen, 'p')
screen.onkey(quit_program, 'q')
screen.listen()
screen.mainloop()
def move():
turtle.forward(1)
check_border()
screen.ontimer(move, 25)
moving = False
def start_motion():
global moving
if not moving:
moving = True
move()
screen = Screen()
screen.setup(WIDTH, HEIGHT)
turtle = Turtle()
turtle.speed('fastest')
main()
See if this still works with trinket.io, IDLE and PyCharm, or if it can be made to do so.

Python Turtle race game. Ending game function does not seem to work

I have got a problem with how to end my turtle python game. The code seems to function if I place the turtles at the starting/ending point from the beginning of the code, but it does not register when the turtle reaches the endpoint in gameplay. From what I know I think my maths for the end function is right. I am new and appreciate the help. I am currently offline though.
CODE:
import time
import turtle
from turtle import *
wn = turtle.Screen()
name=textinput("Question", "what is your name")
#display
pencolor("white")
penup()
goto(0,170)
write("hello " +name,align='center',font=('Comic Sans', 20))
#wn = turtle.screen() if the code doesn't work
#diffrent turtles here
t1 = turtle.Turtle()
t2 = turtle.Turtle()
t3 = turtle.Turtle()
#starting psoition
turtle.penup()
t1.penup()
turtle.goto(-1, -230)
t1.goto(-1, -170)
#starting line postion
def f():
fd(10)
def b():
bk(10)
def l():
left(10)
def r():
right(10)
#testing
def fo():
t1.fd(10)
def ba():
t1.bk(10)
def le():
t1.left(10)
def ri():
t1.right(10)
#turtle coordinates
first=turtle.ycor()
second=turtle.xcor()
third=t1.ycor()
fourth=t1.xcor()
#when to end the game
if (turtle.ycor()>= (-160)) and (turtle.ycor()<= (-240)):
if (turtle.xcor()>= (0)) and (turtle.xcor()<= (11)):
print("Finally working")
#replaced with write who the winner is later
if (t1.ycor()>= (-160)) and (t1.ycor()<= (-240)):
if (t1.xcor()>= (0)) and (t1.xcor()<= (11)):
print("Finally")
# onkey creates the key board = turtle.onkey("function, key") You have to keep pressing keys for it to move
turtle.onkey(f, "w")
turtle.onkey(b, "s")
turtle.onkey(l, "a")
turtle.onkey(r, "d")
wn.onkey(fo, "Up")
wn.onkey(ba, "Down")
wn.onkey(le, "Left")
wn.onkey(ri, "Right")
listen()
#WINDOW SETUP
window = Screen()
window.setup(800, 800)
window.title("Turtle game")
turtle.bgcolor("forestgreen")
t3.color("black")
t3.speed(0)
t3.penup()
t3.setpos(-140, 250)
t3.write("THE TURTLE RACE", font=("Comic Sans", 30, "bold"))
t3.penup()
#turtle ask name
#add images here
#turtle controls
# def creates a function. : means opperation f means move turtle foward. fd push turtle forward
# onkey creates the key board = turtle.onkey("function, key") You have to keep pressing keys for it to move
t2.speed(0)
t2.color("grey")
t2.pensize(100)
t2.penup()
t2.goto(-200, -200)
t2.left(90)
t2.pendown()
t2.forward(300)
t2.right(90)
t2.forward(500)
t2.right(90)
t2.forward(300)
t2.right(90)
t2.forward(500)
turtle.penup()
Firstly, your maths is not quite right - a coordinate can never be both <= -240 and >= -160. It should be t.ycor() >= -240 and t.ycor() <= -160, or more briefly, -240 <= t.ycor() <= -160.
Secondly, the condition as it stands is only checked once, when the code is first run. Instead, you need to get the program to check it regularly. You can do this by adding a general onkeypress event handler which is checked every time any key is pressed.
def check_status():
for player, t in enumerate([turtle, t1]):
if 0 <= t.xcor() <= 11 and -240 <= t.ycor() <= -160:
print(f"Player {player} is at the endpoint")
...
wn.onkeypress(check_status)
listen()

Python Turtle code seems to be in an infinite loop

I want to make a code for turtles to conquer asteroids. But if you run the code, it falls into an infinite loop and doesn't work. Maybe the while part is the problem, but I don't know how to solve it. Please help me.
I'm so sorry for the long post because it's my first time posting.
I really want to fix the error. Thank you.
import turtle
import random
import math
player_speed = 2
score_num = 0
player = turtle.Turtle()
player.color('blue')
player.shape('turtle')
player.up()
player.speed(0)
screen = player.getscreen()
ai1_hide = False
ai1 = turtle.Turtle()
ai1.color('blue')
ai1.shape('circle')
ai1.up()
ai1.speed(0)
ai1.goto(random.randint(-300, 300), random.randint(-300, 300))
score = turtle.Turtle()
score.speed(0)
score.up()
score.hideturtle()
score.goto(-300,300)
score.write('score : ')
def Right():
player.setheading(0)
player.forward(10)
def Left():
player.setheading(180)
player.forward(10)
def Up():
player.setheading(90)
player.forward(10)
def Down():
player.setheading(270)
player.forward(10)
screen.onkeypress(Left, "Left")
screen.onkeypress(Right, "Right")
screen.onkeypress(Up, "Up")
screen.onkeypress(Down, "Down")
screen.listen()
Code thought to be an error :
while True:
distance = math.sqrt(math.pow(player.xcor() - ai1.xcor(), 2) + math.pow(player.ycor() - ai1.ycor(), 2))
if distance <= 20:
ai1.hideturtle()
score.clear()
if ai1_hide == False:
score_num += 1
ai1_hide = True
ai1.goto(0, 0)
score.write('score : ' + str(scoreNum))
if ai1.isvisible() != True:
break
You forgot to add update() method for screen
while True:
distance = math.sqrt(math.pow(player.xcor() - ai1.xcor(), 2) + math.pow(player.ycor() - ai1.ycor(), 2))
if distance <= 20:
ai1.hideturtle()
score.clear()
if ai1_hide == False:
score_num += 1
ai1_hide = True
ai1.goto(0, 0)
score.write('score : ' + str(scoreNum))
if not ai1.isvisible(): # boolean condition can also be simplified.
break
screen.update() # ADD this to your code
Add a variable
running = True
Then your loop can be
while running:
Over time you can change the variable so your loop can stop or the opposite.
Also, the break function won't work since your loop is a while true.

Turtle Clear Screen

I'm not sure how to get rid of the black arrow, if you could help that would be great! Thanks, also if you have any other modifications to make the game better that would be awesome as well! Thanks again!
It says I need to write more detail, so I m just going to keep typing fora bit and hope that I have enough words to write. It should be good right around here.
import math
import random
score = 0
print ("\n" * 40)
print("Welcome Player, I Hope You Have What it Takes to be the Next WARLORD BOSS")
print("Enemies Killed:\n0")
#Title
t=turtle.Pen()
t.pencolor("magenta")
t.hideturtle()
t.penup()
t.setposition(-300,350)
t.write("Catch 40 turtles for a suprise ( ͡° ͜ʖ ͡°)", font=("Verdana", 18))
#Tip
text=turtle.Pen()
t.pencolor("magenta")
t.hideturtle()
turtle.clear()
t.penup()
t.setposition(-100, -350)
t.write("TOUCH THE EDGES, I DARE YOU", font=("Verdana", 18))```
#Set up screen
wn = turtle.Screen()
wn.bgcolor("dim gray")
wn.title("EXEXEXEXEEXXEXEXE HACK COMMENCING␀␀␀␀␀")
#Draw border
mypen = turtle.Turtle()
mypen.penup()
mypen.speed(10)
mypen.hideturtle()
mypen.setposition(-300,-300)
mypen.pendown()
mypen.pensize(3)
for side in range(4):
mypen.color("crimson")
mypen.forward(300)
mypen.color("gold")
mypen.forward(300)
mypen.left(90)
mypen.hideturtle()
#Create player turtle
player = turtle.Turtle()
player.color("powder blue")
player.shape("arrow")
player.penup()
player.speed(0)
#Create goal
goal = turtle.Turtle()
goal.color("red")
goal.shape("turtle")
goal.penup()
goal.speed(0)
goal.setposition(-100, -100)
#Set speed
speed = 1
#Define functions
def turnleft():
player.left(30)
def turnright():
player.right(30)
def increasespeed():
global speed
speed +=0.5
def decreasespeed():
global speed
speed -= 1
#Set keyboard binding
turtle.listen()
turtle.onkey(turnleft, "Left")
turtle.onkey(turnright, "Right")
turtle.onkey(increasespeed, "Up")
turtle.onkey(decreasespeed, "Down")
while True:
player.forward(speed)
#Boundary check
if player.xcor() > 300 or player.xcor() < -300:
print("I Knew you could never be a WARLORD... Try Again")
quit()
if player.ycor() > 300 or player.ycor() < -300:
print("I Knew you could never be a WARLORD... Try Again")
quit()
#Collision checking
d= math.sqrt(math.pow(player.xcor()-goal.xcor(),2) + math.pow(player.ycor()-goal.ycor(),2))
if d < 20 :
goal.setposition(random.randint(-300,300), random.randint(-300, 300))
score = score + 1
print ("\n" * 40)
print("Wow, You Actually got one!")
print("I think you Might Have What it Takes to be the Next WARLORD BOSS")
print("Enemies Killed")
print (score)
This code is your problem:
text=turtle.Pen()
t.pencolor("magenta")
t.hideturtle()
turtle.clear()
t.penup()
t.setposition(-100, -350)
t.write("TOUCH THE EDGES, I DARE YOU", font=("Verdana", 18))
You copied and pasted but forgot to update t. to instead be text. Also, turtle.clear() doesn't make sense as that refers to a different turtle altogether:
text = turtle.Pen()
text.hideturtle()
text.pencolor("magenta")
text.penup()
text.setposition(-100, -350)
text.write("TOUCH THE EDGES, I DARE YOU", font=("Verdana", 18))

Python: How come the math operators won't work?

I've been following a tutorial that shows beginners how to make a "Space Invaders" game. I mostly just wanted a way to play around with the turtle graphics or something of the sort. Everything was going smoothly until I noticed that my if statement, founded where I defined my move_left function, does not work. The problem however is not the if statement itself. It is that any math operation I try to do under it just gets completely ignored by the program with no error messages or anything. I even attempted to make a print statement under the if statement just to see rather or not the actual statement was responsive and saw that indeed, the statement printed as I planned. So what gives? How come I cannot do any math equations or anything of the like under those two functions?
So, here is the code that I had followed below:
import turtle
import os
def main():
#Set up the screen
wn = turtle.Screen()
wn.bgcolor("black")
wn.title("Space Invaders")
#Draw Border
border_pen = turtle.Turtle()
border_pen.speed(0)
border_pen.color("white")
border_pen.penup()
border_pen.setposition(-300, -300)
border_pen.pendown()
border_pen.pensize(3)
for side in range (4):
border_pen.fd(600)
border_pen.lt(90)
border_pen.hideturtle()
#create the player turtle
player = turtle.Turtle()
player.color("blue")
player.shape('triangle')
player.penup()
player.speed(0)
player.setposition(0, -250)
player.setheading(90)
#Player controls
playerspeed = 15
def move_left():
x = player.xcor()
x -= playerspeed
player.setx(x)
print(x)
if x < -280:
print("Reached") #It is here I tested rather or not the if statement
#above works, which it does
x = -280 #The following code here will not take effect. I tried all
#of different signs to use. Nothing happens. Not even an
#error
def move_right(): #I did not put the if statement here since I noticed the
#problem with the left side first
x = player.xcor()
x += playerspeed
player.setx(x)
if x > 280:
x = 280
turtle.listen()
turtle.onkey(move_left, "Left")
turtle.onkey(move_right, "Right")
turtle.mainloop()
main()
The reason the code has no affect is because you modify the value of x, a local variable to the function scope, and not the player position. Call player.setx(x) to actually update the player position after updating the local variable x. If you want to bound your positions you could also use the built in min/max methods:
def move_left():
x = player.xcor()
x -= playerspeed
player.setx(max(x, -280))
def move_right():
x = player.xcor()
x += playerspeed
player.setx(min(x, 280))

Categories

Resources