Why does the turtle window stops responding? - python

I am trying to use the turtle module for a python, but it stops responding in further compilations after the first successful compilation. I have tried this both in Spyder and Jupyter but the result is the same.
Edit 1: This is the code I used, it is not self-made I learnt it from youtube.
Edit 2: The kernel keeps dying after I close the turtle window due to it not responding
import turtle
wn=turtle.Screen()
wn.title("Made by ")
wn.bgcolor("black")
wn.setup(width=800,height=600)
wn.tracer(0) #Keeps the screen up
#Paddle A
paddle_a=turtle.Turtle() #object of turtle
paddle_a.speed(0) #speed of animation
paddle_a.shape("square")
paddle_a.color("red")
paddle_a.shapesize(stretch_wid=5, stretch_len=1) #default size is 20*20
paddle_a.penup() #not to draw lines
paddle_a.goto(-350,0)
#Paddle B
paddle_b=turtle.Turtle() #object of turtle
paddle_b.speed(0) #speed of animation
paddle_b.shape("square")
paddle_b.color("blue")
paddle_b.shapesize(stretch_wid=5, stretch_len=1) #default size is 20*20
paddle_b.penup() #not to draw lines
paddle_b.goto(350,0)
#Ball
ball=turtle.Turtle() #object of turtle
ball.speed(0) #speed of animation
ball.shape("circle")
ball.color("white")
ball.penup() #not to draw lines
ball.goto(0,0)
ball.dx=0.09 #moves by 2 pixels
ball.dy=0.09
#Function
def paddle_a_up():
y=paddle_a.ycor() #mentions the y coordinate
y=y+20
paddle_a.sety(y) #set y coordinate to new y
def paddle_a_down():
y=paddle_a.ycor() #mentions the y coordinate
y=y-20
paddle_a.sety(y) #set y coordinate to new y
def paddle_b_up():
y=paddle_b.ycor() #mentions the y coordinate
y=y+20
paddle_b.sety(y) #set y coordinate to new y
def paddle_b_down():
y=paddle_b.ycor() #mentions the y coordinate
y=y-20
paddle_b.sety(y) #set y coordinate to new y
#Keyboard binding
wn.listen() #listen keyboard input
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 loop
running=True
while running:
wn.update() #updates the screen
#movement the ball
ball.setx(ball.xcor()+ball.dx)
ball.sety(ball.ycor()+ball.dy)

This is the code I used, it is not self-made I learnt it from youtube.
It would have helped if the person who posted it on YouTube had learnt turtle properly. The main loop of this code is potentially blocking tkinter events. The code also does more work than necessary by not oriented the turtles to its advantage. See if my rewrite works better for you:
from turtle import Screen, Turtle
# Functions
def paddle_a_up():
paddle_a.forward(20)
def paddle_a_down():
paddle_a.backward(20)
def paddle_b_up():
paddle_b.forward(20)
def paddle_b_down():
paddle_b.backward(20)
# Main loop
def move():
x, y = ball.position()
ball.setposition(x + ball.dx, y + ball.dy)
screen.update()
screen.ontimer(move)
screen = Screen()
screen.bgcolor('black')
screen.setup(width=800, height=600)
screen.tracer(False)
# Paddle A
paddle_a = Turtle()
paddle_a.shape('square')
paddle_a.shapesize(stretch_wid=1, stretch_len=5)
paddle_a.setheading(90)
paddle_a.penup()
paddle_a.color('red')
paddle_a.setx(-350)
# Paddle B
paddle_b = paddle_a.clone()
paddle_b.color('blue')
paddle_b.setx(350)
# Ball
ball = Turtle()
ball.shape('circle')
ball.color('white')
ball.penup()
ball.dx = 1 # user defined object properties
ball.dy = 1
# Keyboard binding
screen.onkeypress(paddle_a_up, 'w')
screen.onkeypress(paddle_a_down, 's')
screen.onkeypress(paddle_b_up, 'Up')
screen.onkeypress(paddle_b_down, 'Down')
screen.listen()
move()
screen.mainloop()
Running under Spyder and/or Jupyter adds further complications when you restart a turtle program. The above was only tested at the command line.

Related

Why my python kept crashing when it tried to run the turtle.tracer() method in turtle module?

I was coding a Snake Game using turtle module but when I add this line into my code the turtle screen and python crashed:
turtle.tracer(0)
can somebody help me so I can complete the game? Thanks a lot
my code:
from turtle import Turtle, Screen, colormode
screen = Screen()
screen.bgcolor("black")
screen.setup(width=600, height=600)
screen.title("My Snake Game")
screen.tracer(0)
x = 0
segments = []
for turtle in range(3):
turtle = Turtle("square")
turtle.color("white")
turtle.penup()
turtle.goto(0-x, 0)
x += 20
segments.append(turtle)
game_is_on = True
screen.update()
while game_is_on:
for segment in segments:
segment.forward(20)
screen.exitonclick()
I think we need to know more about what you mean by 'crashed'. If you mean everything froze, that's the code you wrote. Once you introduce tracer() you need to provide an update() for every change you want the user to see. But you don't have any update() calls in your loop so everything visually remains as it was before the loop. If you want to see the segments move, you need to do something like:
from turtle import Turtle, Screen
screen = Screen()
screen.bgcolor('black')
screen.setup(width=600, height=600)
screen.title("My Snake Game")
screen.tracer(0)
x = 0
segments = []
for turtle in range(3):
turtle = Turtle('square')
turtle.color('white')
turtle.penup()
turtle.setx(x)
x -= 20
segments.append(turtle)
screen.update()
game_is_on = True
while game_is_on:
for segment in segments:
segment.forward(20)
screen.update()
screen.exitonclick() # never reached
If you mean by 'crashed' that Python quit back to the operating system, then you need to describe the environment under which you're running this code.

Is there a way to avoid the recursion limit in my Turtle-program?

import turtle
from turtle import Turtle
WIDTH = 1000
HEIGHT = 1000
#Screen setup
screen = turtle.Screen()
screen.setup(WIDTH, HEIGHT)
screen.title(" " *150 + "Test_GIU")
screen.bgcolor("black")
screen.setup(1000, 1000)
#Pen
pen = Turtle("circle")
pen.pensize = 5
pen.color("green")
pen.speed(-1)
def dragging(x, y): # These parameters will be the mouse position
pen.ondrag(None)
pen.setheading(pen.towards(x, y))
pen.goto(x, y)
pen.ondrag(dragging)
def click_on_c():
screen.reset()
pen = Turtle("circle")
pen.pensize = 5
pen.color("green")
pen.speed(-1)
pen.ondrag(dragging)
def main(): # This will run the program
turtle.listen()
pen.ondrag(dragging) # When we drag the turtle object call dragging
turtle.onkeypress(click_on_c, "c")
screen.mainloop() # This will continue running main()
main()
This is my code, im pretty new to it, so its not very good, but its my first real project. I´ve already tried to increase the recursin limit, but it crashes even if I set it to 10000. I also tried to catch the error with an try and exept block, but it also doesnt work.
Let's try a simpler design where instead of calling screen.reset() and recreating the turtle, we instead call pen.reset() to clear the drawing:
from turtle import Screen, Turtle
WIDTH = 1000
HEIGHT = 1000
def dragging(x, y): # Parameters are the mouse position
pen.ondrag(None)
pen.setheading(pen.towards(x, y))
pen.goto(x, y)
pen.ondrag(dragging)
def click_on_c():
pen.reset()
pen.pensize = 5
pen.color("green")
pen.speed('fastest')
# Screen setup
screen = Screen()
screen.setup(WIDTH, HEIGHT)
screen.title("Test_GUI")
screen.bgcolor("black")
# Pen
pen = Turtle("circle")
pen.pensize = 5
pen.color("green")
pen.speed('fastest')
pen.ondrag(dragging)
screen.onkeypress(click_on_c, "c")
screen.listen()
screen.mainloop()
We have to reset some aspects of the pen after calling reset() as that call clears the settings back to the defaults.

Entire screen not moving with the turtle

I am making a game in python using the turtle module in python.
I want the screen to move with the turtle. Is there any way to do it? Thanks
The problem is that the screen isn't moving with the turtle ... Does
anyone know why?
I know why. First, #martineau is correct, as usual +1, about passing the wrong range of values to yview_moveto(). But there's another piece to this puzzle: tkinter and turtle do not use the same coordinate system! You need to correct for the coordinate system difference, then turn the value into a percentage.
Here's a stripped down example based on your code and desired behavior. It keeps the ball in the middle of the window but you can tell from the numbers, and the vertical scroll bar, it's falling. Tap the the up arrow to slow it down -- tap it again to stop the motion. Tap it once more to start rising. Or use the down arrow to reverse your movement again:
from turtle import Screen, Turtle
WIDTH, DEPTH = 300, 10_000
CURSOR_SIZE = 20
vy = -10
def rise():
global vy
vy += 5
def fall():
global vy
vy -= 5
def move():
global vy
if abs(ball.ycor()) < DEPTH/2:
ball.forward(vy)
canvas.yview_moveto((DEPTH/2 - ball.ycor() - WIDTH/2 + CURSOR_SIZE) / DEPTH)
screen.update()
screen.ontimer(move)
screen = Screen()
screen.setup(WIDTH, WIDTH) # visible window
screen.screensize(WIDTH, DEPTH) # area window peeps into
screen.tracer(False)
canvas = screen.getcanvas()
marker = Turtle()
marker.hideturtle()
marker.penup()
marker.setx(-WIDTH/4) # so we can see we're moving
for y in range(-DEPTH//2, DEPTH//2, 100):
marker.sety(y)
marker.write(y, align='right')
ball = Turtle('circle')
ball.speed('fastest')
ball.setheading(90)
ball.penup()
screen.onkey(rise, 'Up')
screen.onkey(fall, 'Down')
screen.listen()
move()
screen.mainloop()

Python turtle not moving on arrow press

I am trying to make my turtle (main_ship) move across the bottom of my screen according to when the user presses the left and right arrow keys but the turtle is not moving. I have used the same code before when making Pong so I'm not sure why it's not working.
import turtle
wn = turtle.Screen()
wn.title("Game")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)
main_ship = turtle.Turtle()
main_ship.speed(0)
main_ship.shape("turtle")
main_ship.color("green")
main_ship.shapesize(stretch_wid=2, stretch_len=4)
main_ship.penup()
main_ship.goto(0, -290)
main_ship.left(90)
def main_ship_right():
x = main_ship.xcor()
x += 20
main_ship.setx(x)
def main_ship_left():
x = main_ship.xcor()
x -= 20
main_ship.setx(x)
while True:
wn.update()
wn.mainloop()
wn.listen()
wn.onkeypress(main_ship_right, "Right")
wn.onkeypress(main_ship_left, "Left")
When I press the arrow keys, nothing happens but the code still runs and there are no error messages.
You have to assign keys before mainloop() which runs all time till you close window.
You don't need while True because mainloop() already runs internal loop.
You may have to remove wm.tracer(0) or you will have to run wn.update() to refresh elements in window.
import turtle
# --- functions ---
def main_ship_right():
x = main_ship.xcor()
x += 20
main_ship.setx(x)
wn.update()
def main_ship_left():
x = main_ship.xcor()
x -= 20
main_ship.setx(x)
wn.update()
# --- main ---
wn = turtle.Screen()
wn.title("Game")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0)
main_ship = turtle.Turtle()
main_ship.speed(0)
main_ship.shape("turtle")
main_ship.color("green")
main_ship.shapesize(stretch_wid=2, stretch_len=4)
main_ship.penup()
main_ship.goto(0, -290)
main_ship.left(90)
wn.update()
wn.listen()
wn.onkeypress(main_ship_right, "Right")
wn.onkeypress(main_ship_left, "Left")
wn.mainloop()
For this style of motion, there's another way to implement it. The idea is to leave the cursor moving in it's original orientation, but use settiltangle() to make it look like it's facing upward.
This lets us use forward(20) and backward(20) to move our cursor, and not have to write:
x = main_ship.xcor()
x += 20
main_ship.setx(x)
Works great for Space Invader style games, where the player faces upwards but moves sideways:
from turtle import Screen, Turtle
from functools import partial
screen = Screen()
screen.title("Game")
screen.bgcolor('black')
screen.setup(width=800, height=600)
main_ship = Turtle('turtle')
main_ship.speed('fastest')
main_ship.color('green')
main_ship.shapesize(stretch_wid=2, stretch_len=4)
main_ship.settiltangle(90)
main_ship.penup()
main_ship.sety(-290)
screen.onkeypress(partial(main_ship.forward, 20), 'Right')
screen.onkeypress(partial(main_ship.backward, 20), 'Left')
screen.listen()
screen.mainloop()
Only works in the turtle library that comes with Python -- online Python development sites usually provide limited turtle implementations that don't include methods like settiltangle().

Turtle stops when I shoot

I have gotten an issue where an enemy turtle stops when I shoot. I am relatively new to python so I know that my code is pretty bad. I cant seem to spot why this happens but I'm assuming its got something to do with the while loop.
here is the code:
(i have added notes so it is easy to skip to important parts of it)
import turtle
import os
#wn is window
#bp = border
bullet = 'ready'
#screen setup
wn = turtle.Screen()
wn.bgcolor('black')
wn.title('SPACE.INVADERS')
#border
bp = turtle.Turtle()
bp.speed(0)
bp.color('green')
bp.penup()
bp.setposition(-300,-300)
bp.pendown()
count=0
while count != 5:
count= (count+1)
bp.fd(600)
bp.lt(90)
bp.hideturtle()
#player
p = turtle.Turtle()
p.color('red')
p.shape('triangle')
p.penup()
p.speed(0)
p.setposition(0,-250)
p.setheading(90)
#enemy
e = turtle.Turtle()
e.penup()
e.speed(0)
e.shape('square')
e.shapesize(1.25,1.25)
e.color('orange')
e.setpos(-250,250)
e.speed(1)
#p = player
#ps = player speed
ps = 15
#moving left and right
def left_mov():
x = p.xcor()
x -= ps
p.setx(x)
def right_mov():
x = p.xcor()
x += ps
p.setx(x)
#shooting
def shoot():
global bullet
if bullet == 'ready':
bullet = 'fire'
shot= turtle.Turtle()
shot.penup()
shot.speed(0)
shot.goto(p.pos())
shot.color('white')
shot.shape('triangle')
shot.shapesize(0.5)
shot.lt(90)
shot.speed(1)
shot.fd(550)
bullet = 'ready'
#bindings
turtle.listen()
turtle.onkey(left_mov, 'Left')
turtle.onkey(right_mov, 'Right')
turtle.onkey(shoot, 'space')
#enemy movement
while True:
e.fd(500)
e.rt(90)
e.fd(25)
e.rt(90)
e.fd(500)
e.lt(90)
e.fd(25)
e.lt(90)
I'm assuming its got something to do with the while loop
Yes, it shouldn't be there! In an event-driven world like turtle, there should never be a while True: loop. Instead, we need a timer event that fires off on regular intervals that does incremental updates of the objects in motion (enemy and bullet) so they appear to move at the same time. Below is my rework of your code using a timer event:
from turtle import Screen, Turtle
# moving left and right
def left_move():
player.setx(player.xcor() - player_speed)
def right_move():
player.setx(player.xcor() + player_speed)
# screen setup
screen = Screen()
screen.bgcolor('black')
screen.title('SPACE.INVADERS')
# border
border = Turtle(visible=False)
border.speed('fastest')
border.color('green')
border.penup()
border.setposition(-300, -300)
border.pendown()
for _ in range(4):
border.forward(600)
border.left(90)
# player
player = Turtle('triangle')
player.speed('fastest')
player.color('red')
player.penup()
player.setposition(0, -250)
player.setheading(90)
player_speed = 15
# enemy
enemy = Turtle('square')
enemy.speed('fast')
enemy.shapesize(1.25)
enemy.color('orange')
enemy.penup()
enemy.setpos(-250, 250)
enemy_speed = 6 # enemy speed
enemy_direction = 1 # enemy direction
# bullet
bullet = Turtle('triangle', visible=False)
bullet.speed('fastest')
bullet.color('white')
bullet.shapesize(0.5)
bullet.penup()
bullet.left(90)
bullet_speed = 9 # bullet speed
# shooting
def shoot():
if not bullet.isvisible():
bullet.goto(player.position())
bullet.showturtle()
def move():
global enemy_direction
if bullet.isvisible():
if bullet.ycor() > 275:
bullet.hideturtle()
else:
bullet.forward(bullet_speed)
# enemy movement
enemy.forward(enemy_direction * enemy_speed)
enemy.settiltangle(enemy.tiltangle() + 3) # just for fun
x, y = enemy.position()
if x > 250 or x < -250:
enemy_direction *= -1
enemy.sety(y - 25)
screen.ontimer(move, 50)
# bindings
screen.onkey(left_move, 'Left')
screen.onkey(right_move, 'Right')
screen.onkey(shoot, 'space')
screen.listen()
move()
screen.mainloop()
This should give you the basic functionality you need to move forward and add collision detection (bullet to enemy, enemy to player, player to wall) and scoring.
Also note that turtles are global entities so creating a new bullet every time you need one is a bad idea. Even if you evenually allow overlapping bullets, keep a reusable set of bullets for that purpose.

Categories