I am creating a game in python using turtle but I am unable to control the speed of the turtle in the loop as the speed of the turtle is 0. It is supposed to run like flash but it is running at normal speed
import turtle
c=turtle.Screen()
a=turtle.Turtle()
a.speed(0)
b=True
def ch( a , d):
global b
b = False
while b:
a.fd(1)
c.onclick(ch)
c.mainloop()
speed(0) can only speed up the animations a bit.
Try using c.tracer(0, 0)
This fully disables all animations, and should result it a bit more of a speed up. Although, to refresh the screen you'll need to call c.update()
First, your code is structured incorrectly. You don't need to call onclick() in a loop, it simply sets a handler function so only needs to be called once. Also, mainloop() should be running the events, not called after the events are over.
I don't believe you're going get any more speed out of this code unless you increase the forward distance. Simply increading to fd(3) will make a noticeable differece. My rework of your code:
from turtle import Turtle, Screen
def click_handler(x, y):
global flag
flag = False
def turtle_forward():
if flag:
turtle.forward(3)
screen.ontimer(turtle_forward, 0)
flag = True
screen = Screen()
screen.onclick(click_handler)
turtle = Turtle()
turtle.speed('fastest')
turtle_forward()
screen.mainloop()
Related
I'm new to python and decided to practice by building a game similar to snake with the turtle library. I was able to initiate the turtle to continually move forward with a while True loop, but now I'm having trouble with getting the turtle to break this loop to make turns.
I have tried various different ways of writing my conditionals but I can't seem to figure out where the issue is. Thanks in advance!
import turtle
window = turtle.Screen()
snake = turtle.Turtle()
snake.speed(1)
snake.penup()
#Functions that move the snake:
def forward():
while True:
snake.forward(.7)
def left():
snake.left(90)
def right():
snake.right(90)
#Movement functions all put together:
def movesnake():
while True:
entry = input()
if entry == 'w':
forward()
if entry == 'a':
left()
if entry == 'd':
right()
movesnake()
Try this approach to move:
def forward():
turtle.forward(how-many-pixels-forward)
turtle.onkey(forward,'what-key-you-want-to-listen-to') #when key pressed call forward function
https://www.geeksforgeeks.org/turtle-onkey-function-in-python/
The turtle module provides turtle graphics primitives, in both object-oriented and procedure-oriented ways. Because it uses Tkinter for the underlying graphics, it needs a version of Python installed with Tk support.
turtle.onkey()
This function is used to bind fun to the key-release event of the key. In order to be able to register key-events, TurtleScreen must have focus.
You can try increasing the value of the forward function:
def forward():
while True:
snake.forward(5)
Take a look at this book
https://argentinaenpython.com/quiero-aprender-python/doma-de-serpientes-para-ninos_swfk-es-linux-0.0.4.pdf
I have used the onkey function for the right and left:
sc.onkey(user_left,"left")
sc.onkey(user_right,"right")
I have also set the screen after setting the turtle and importing turtle:
sc=Screen()
But when I use the same format for up and down:
sc.onkey(user_up,"up")
sc.onkey(user_down,"down")
It does nothing. I also have my functions:
def user_right:
t3.forward(5)
def user_left:
t3.backward(5)
t3 is my user turtle, and it is sideways, the shape is turtle, and its head is facing right. t3 is automatically set to make its head facing the right side when the code runs. By the way, I import from turtle import*
I see several issues here. First, this can't work as you claim:
def user_right:
t3.forward(5)
def user_left:
t3.backward(5)
It would need to be:
def user_right():
t3.forward(5)
def user_left():
t3.backward(5)
Next, this won't work in turtle in standard Python:
sc.onkey(user_left,"left")
sc.onkey(user_right,"right")
These keys would have to be "Left" and "Right". Are you using a non-standard turtle implementation? (E.g. the one on repl.it) You show your two event handlers that work, but fail to show the two that don't which would be of more interest when trying to debug your code.
Finally, your missing a call to the screen's listen() method, so your keystrokes are ignored. Here's how I might implement the functionality your code is hinting at:
from turtle import Screen, Turtle
def user_right():
turtle.forward(5)
def user_left():
turtle.backward(5)
def user_up():
turtle.sety(turtle.ycor() + 5)
def user_down():
turtle.sety(turtle.ycor() - 5)
turtle = Turtle()
turtle.shape('turtle')
screen = Screen()
screen.onkey(user_left, 'Left')
screen.onkey(user_right, 'Right')
screen.onkey(user_up, 'Up')
screen.onkey(user_down, 'Down')
screen.listen()
screen.mainloop()
In this piece of code, I've created a program using the Turtle Module for Python, which I heard was built with Tkinter. This working code will make the turtle say "Ah!" when you click on it, then teleport. What perplexes me the most is the t.onclick() method. How does it manage to keep listening for clicks on the turtle while allowing the rest of the code to run, unlike the input() function, which waits for the user to enter an input before proceeding?
Additionally, how does an event handler work in Python? Does it constantly check for clicks in the background with some sort of forever loop? Is there a mechanism that allows it to stay idle and somehow activate when a click is received? Or is there something else entirely that makes it work the way it does?
from turtle import *
from time import sleep
from random import randint
t = Turtle()
t.color("red")
t.penup()
t.shape("turtle")
t.speed(100)
t.points = 0
w = 200
h = 150
def rand_move():
t.goto(randint(-w, w), randint(-h, h))
def catch(x, y):
t.write("Ah!", font=("Arial", 14, "normal"))
t.points = t.points + 1
rand_move()
t.onclick(catch)
while t.points < 3:
sleep(1.5)
rand_move()
t.write("WOW! You're good at catching me!", font=('Arial', 16, 'bold'))
t.hideturtle()
I have tried looking up the Turtle source code but failed to decipher it, and even googled quite a number of sites, but none seem to be specific enough to this question. Any help in clearing this up will be greatly appreciated!
The input() function is a Python built-in and not part of tkinter. The latter has its own mainloop() which normally handles all user input — unless its processing is interfered with by some function (such as input() or any long-running function). When that happens the GUI will "freeze".
I believe part of what makes it hard to understand how turtle events work is this code which doesn't belong in a event-driven turtle program:
while t.points < 3:
sleep(1.5)
rand_move()
Instead, we should be handing off control to mainloop(), either explicitly, or, in some programing environments, implicitly. Let's rewrite your code as an event-driven turtle program:
from turtle import Screen, Turtle
from random import randint
WIDTH, HEIGHT = 640, 480
CURSOR_SIZE = 20
def rand_move():
turtle.goto(randint(CURSOR_SIZE - WIDTH//2, WIDTH//2 - CURSOR_SIZE), randint(CURSOR_SIZE - HEIGHT//2, HEIGHT//2 - CURSOR_SIZE))
if turtle.points < 3:
screen.ontimer(rand_move, 1000) # delay in milliseconds
else:
turtle.home()
turtle.write("WOW! You're good at catching me!", align='center', font=('Arial', 16, 'bold'))
turtle.hideturtle()
def catch(x, y):
turtle.write("Ah!", font=('Arial', 14, 'normal'))
turtle.points += 1
screen = Screen()
screen.setup(WIDTH, HEIGHT)
turtle = Turtle()
turtle.shape('turtle')
turtle.color('red')
turtle.speed('fastest')
turtle.penup()
turtle.onclick(catch)
turtle.points = 0 # user defined property
rand_move()
screen.mainloop()
how does an event handler work in Python? Does it constantly check for
clicks in the background with some sort of forever loop? Is there a
mechanism that allows it to stay idle and somehow activate when a
click is received?
This desciption isn't far off. Turtle events fire from mainloop() which waits around for events to fire, such as mouse clicks, keyboard input, window closing, timer events, etc. See this answer for more information about mainloop() does in a turtle program.
The onclick() method only registers code for the main loop to call if/when a turtle-specific click comes in. Just as ontimer registers code for the main loop to call some time in the future. When we mix while ...: sleep() loops with turtle's main loop, we risk missing events during the sleep cycle.
I am using Python 2.7 turtle graphics to make a simple mouse sensor that draws whenever you hold down the mouse button. Since my function is based on the user, it crashes right when you run it. I found out that turtle.exitonclick() will help keep the interface on, but I can't draw because my draw is bound to the left mouse button click. Is there any solution to get around this or is it possible to rebind turtle.exitonclick() to something else? Here's my code:
import turtle
wn = turtle.Screen()
wn.bgcolor("lightblue")
#wn.screensize(400,300)
turtle.setup(400,300)
draw = turtle.Turtle()
def gothere(event):
draw.penup()
draw.goto(event.x-360, 340-event.y)
draw.pendown()
#draw.color(blue)
def movearound(event):
draw.goto(event.x-360, 340-event.y)
draw.color(blue)
def release(event):
draw.penup()
def reset(event):
draw.clear()
cavset = turtle.getcanvas()
cavset.bind("<Button-2>", gothere)
cavset.bind("<B1-Motion>", movearound)
cavset.bind("<ButtonRelease-2>", release)
cavset.bind("<Escape>", reset)
wn.listen()
wn.exitonclick()
(I am running through command prompt, BTW.)
What you most likely want is:
turtle.mainloop()
instead of:
wn.exitonclick()
as that's what exitonclick() calls after setting up a handler for the "onclick" part.
However, there are other issues. You seem to be mixing three different coding models: functional interface to turtle; object-oriented interface to turtle; calling into turtle's Tkinter underpinnings.
Let's simplify and just use the object-oriented interface to turtle:
from turtle import Turtle, Screen, mainloop
def gothere(x, y):
draw.penup()
draw.goto(x, y)
draw.pendown()
def movearound(x, y):
draw.ondrag(None) # disable handler in handler!
draw.color("blue")
draw.goto(x, y)
draw.ondrag(movearound)
def release(x, y):
draw.penup()
def reset():
draw.clear()
wn = Screen()
wn.setup(400, 300)
wn.bgcolor("lightblue")
draw = Turtle()
wn.onclick(gothere, 2)
draw.ondrag(movearound)
draw.onrelease(release, 2)
wn.onkey(reset, "Escape")
wn.listen()
mainloop()
I believe Python 3 turtle tweaks the turtle event interface to add some methods and use clearer names for others.
I've been trying to make a paint program in Python Turtle and for some reason it won't work. I'm using the pen() tool and my code looks like this
from turtle import *
import random
pen()
bgcolor('black')
pencolor('white')
pen.ondrag(pen.goto)
listen()
mainloop()
I've look at this http://docs.python.org/2/library/turtle.html and it says to type turtle.ondrag(turtle.goto) but since I'm using the pen it should work as pen.ondrag but it doesn't, so can someone please clear this up.
Thanks Jellominer
I will simplify and clarify the code given by the questionner:
from turtle import *
ts = Screen(); tu = Turtle()
ts.listen()
ondrag(tu.goto)
mainloop()
This works. You have to click on the turtle and drag it.
First, pen() is not the function you want. Second, although Pen is a synonym for Turtle, pen is not a synonym for turtle. Here's how to go about using ondrag() if you'd like to use Pen instead of Turtle:
from turtle import Pen, Screen, mainloop
def ondrag_handler(x, y):
pen.ondrag(None) # disable handler inside handler
pen.setheading(pen.towards(x, y)) # turn toward cursor
pen.goto(x, y) # move toward cursor
pen.ondrag(ondrag_handler)
screen = Screen()
screen.bgcolor('black')
pen = Pen()
pen.color('white')
pen.shapesize(2) # make it larger so it's easier to drag
pen.ondrag(ondrag_handler)
screen.listen()
mainloop() # screen.mainloop() preferred but not in Python 2
The turtle.ondrag(turtle.goto) makes for a nice short example in the documentation but in reality isn't practical. You want to disable the event handler while handling the event otherwise the events stack up against you. And it's nice to turn the mouse towards your cursor as you drag it.
from turtle import *
ts = Screen()
ondrag(goto)
shapesize(10)
pensize(40)
speed(0)
mainloop()
I think this will surely work.
You can change the size and other things
In here you are using the default turtle .
Sorry but you'll need to take care of the indentation