Reputation: 328
So I decided to model a differential equation in python turtle, but if the turtle is moving fast it starts to "cut", with the circle repeatedly being cutoff at points
I tried to make it smoother by using tracer(0, 0) and updating it only when I need to but that still doesn't work
from turtle import *
import time
from threading import Thread
import math
setup(500, 500)
bgcolor("black")
b = Turtle()
s = b.getscreen()
tracer(0, 0)
b.color("sky blue")
b.shape("circle")
b.up()
b.goto(0, -100)
s.update()
globals()['lastt'] = 0
globals()['auto'] = 0
globals()['angle'] = 0
globals()['speed'] = 0
globals()['accel'] = 0
globals()['air'] = .5
#Starting speed
def measurespeed():
while True:
time.sleep(.01)
while globals()['auto'] == 0:
past = globals()['angle']
time.sleep(.01)
globals()['speed'] = (angle - past)/.01
dspeed = Thread(target=measurespeed)
dspeed.start()
#Auto
def equation():
while True:
time.sleep(.01)
while globals()['auto'] == 1:
globals()['accel'] = -5 * math.sin(angle) - (air * speed)
globals()['speed'] += accel * .01
globals()['angle'] += speed * .01
time.sleep(.01)
b.goto(100 * math.cos(angle - (math.pi / 2)), 100 * math.sin(angle - (math.pi / 2)))
s.update()
move = Thread(target=equation)
move.start()
#Dragging
def drag(x, y):
if x == 0:
if y >= 0:
b.goto(0, 100)
else:
b.goto(0, -100)
elif x > 0:
globals()['angle'] = math.atan(y/x) + (math.pi / 2)
else:
globals()['angle'] = math.atan(y/x) + (3 * math.pi / 2)
b.goto(100 * math.cos(angle - (math.pi / 2)), 100 * math.sin(angle - (math.pi / 2)))
s.update()
def static(x, y):
globals()['auto'] = 0
globals()['speed'] = 0
def resume(x, y):
globals()['auto'] = 1
b.ondrag(drag)
b.onclick(static)
b.onrelease(resume)
s.mainloop()
Sorry for the lack of comments, this was supposed to be a quick experiment
Upvotes: 0
Views: 824
Reputation: 41905
I took a crack at this: I turned off the drag handler while inside the drag handler as this can cause problems including faux recursion stack overflow.
Other changes not directly affecting function include using standard Python global
notation and other style stuff like parentheses reduction:
from turtle import Screen, Turtle
from threading import Thread
from time import sleep
import math
AIR = 0.5
auto = False
angle = 0
speed = 0
accel = 0
# Starting speed
def measurespeed():
global speed
while True:
sleep(0.01)
while not auto:
past = angle
sleep(0.01)
speed = (angle - past) / 0.01
# Auto
def equation():
global accel, angle, speed
while True:
sleep(0.01)
while auto:
accel = -5 * math.sin(angle) - AIR * speed
speed += accel * 0.01
angle += speed * 0.01
sleep(0.01)
turtle.goto(100 * math.cos(angle - math.pi/2), 100 * math.sin(angle - math.pi/2))
screen.update()
# Dragging
def drag(x, y):
global angle
turtle.ondrag(None) # disable handler inside handler
if x == 0:
if y >= 0:
turtle.goto(0, 100)
else:
turtle.goto(0, -100)
elif x > 0:
angle = math.atan(y / x) + math.pi/2
else:
angle = math.atan(y / x) + 3 * math.pi/2
turtle.goto(100 * math.cos(angle - math.pi/2), 100 * math.sin(angle - math.pi/2))
screen.update()
turtle.ondrag(drag) # reenable handler
def static(x, y):
global auto, speed
auto = False
speed = 0
def resume(x, y):
global auto
auto = True
screen = Screen()
screen.setup(500, 500)
screen.bgcolor('black')
screen.tracer(False)
turtle = Turtle()
turtle.shape('circle')
turtle.color("sky blue")
turtle.penup()
turtle.sety(-100)
screen.update()
dspeed = Thread(target=measurespeed)
dspeed.start()
move = Thread(target=equation)
move.start()
turtle.ondrag(drag)
turtle.onclick(static)
turtle.onrelease(resume)
screen.mainloop()
Another issue to consider is that traditionally you could only do turtle graphic operations like goto()
from the main thread. However, this seems to work better in the latest Python and latest tkinter. If you're still having issues, make sure to upgrade to current software. If that doesn't help, search for some of the turtle and threading questions on SO.
In the context of a drag, the click and release events appear to work fine, but on their own they don't work the way you'd expect -- both are invoked on each down and each up of the button.
Upvotes: 1