Turtle graphics speed(). Seems broken
Alf P. Steinbach
alfps at start.no
Sun Feb 28 00:49:22 EST 2010
* Dr. Phillip M. Feldman:
>
> Stefan Behnel-3 wrote:
>> Alexander.Oot at gmail.com wrote:
>>> I think the speed function may be broken from the turtle graphics package
>>>
>>>
>>> "from turtle import *
>>>
>>> speed('fastest')
>>>
>>> forward(50)"
>>>
>>>
>>> I have tried all of the different speed settings, but I get no change
>>> in the turtle's speed.... does anyone know how to fix this?
>> Use "xturtle"? :)
>>
>> http://ada.rg16.asn-wien.ac.at/~python/xturtle/
>>
>> Stefan
>> --
>> http://mail.python.org/mailman/listinfo/python-list
>>
>>
>
> The Python library's implementation of turtle graphics is slow to the point
> that many applications are simply impractical. I recently converted a
> program to Python/turtle graphics that was originally written by my son
> using Processing; the result of the conversion is that the time to draw the
> balls increased by a factor of roughly 50! (The Processing version takes
> less than 0.1 seconds to generate the image, while the Python version takes
> almost 5 seconds on the same computer). It would be good if this
> performance problem can be fixed, either by patching the current
> implementation of turtle graphics, or by replacing it with xturtle if that
> is better. http://old.nabble.com/file/p27732940/balls.py balls.py
Try to add
turtle.tracer( 0 )
before generating the graphics, and
turtle.update()
after.
It sort of speeds things up. :-)
To test it I had to rewrite your code a little, getting rid of the numpy
dependency since I don't have numpy installed. Looks like this:
<code>
#from numpy import *
def array( data, dtype ): return data # Emulate numpy array constructor
import random
from math import *
import sys
from time import time
import turtle # turtle graphics module
class Timer:
"""Track and record elapsed time, allowing an arbitrary number of timers."""
from time import time
# Constructor:
def __init__(self):
self.start= time()
# Report elapsed time:
def time(self):
# Compute elapse time:
elapsed= time() - self.start
# Print elapsed time in seconds:
print str(elapsed) + ' s',
# If total elapsed time exceeds 60 seconds, also print time as
# as minutes and seconds:
if elapsed >= 60.0:
minutes= numpy.floor(elapsed / 60.0)
elapsed-= 60 * minutes
print '= ' + num2str(minutes,0) + ' m ' + num2str(elapsed,3) + ' s'
else:
print
def main():
# Section 1: User inputs. All four arrays should have the same dimensions.
balls_of_type = array([20, 20], dtype=int)
radius_of_type= array([35, 25], dtype=float)
mass_of_type = array([4 , 2], dtype=float)
color_of_type = array([0 , 1], dtype=int)
canvas_width = 1000 # canvas width in pixels
canvas_height= 800 # canvas height in pixels
# Section 2: Setup.
# Section 2.1: Initialize graphics.
turtle.setup(width=canvas_width, height=canvas_height)
# Use units of pixels for specifying locations on the screen:
turtle.setworldcoordinates(0.0, 0.0, canvas_width, canvas_height)
# Set background color to black:
turtle.bgcolor("black")
# We want to specify R, G, and B using whole numbers from 0 to 255:
turtle.colormode(255)
# Turn off animation and hide the turtle to get maximum drawing speed:
turtle.speed('fastest')
turtle.tracer( 0 )
turtle.hideturtle()
# Section 2.2: Preliminaries.
ball_types= len(balls_of_type)
max_tries= 1000
tries= 0
# The following variable counts the number of time ticks:
tick= 0
colors= [
(255, 0, 0), # red
( 64, 64, 230), # blue, cobalt blue
(125, 0, 0), # maroon
( 0, 255, 255), # cyan,baby blue
(255, 140, 0), # orange
( 0, 255, 0), # green, light green
(204, 128, 0), # brown
(255, 200, 120), # light orange
(255, 255, 140), # cream
(0, 128, 0), # dark green, forest green
(255, 128, 128), # peach
(255, 255, 0), # yellow
(0, 0, 204), # dark blue, navy blue
(150, 355, 150), # light green
(128, 0, 230), # purple
(77, 204, 0), # avocado
(255, 128, 255), # magenta, pink
(0, 204, 204), # aqua, turquoise
(230, 192, 0), # gold
(255, 255, 255), # white
]
# Allocate 2-element lists for basis and velocity vectors:
u_hat= [0,0]
v_hat= [0,0]
uv_speed1b= [0,0]; # before the collision
uv_speed2b= [0,0]; # before the collision
uv_speed1a= [0,0]; # after the collision
uv_speed2a= [0,0]; # after the collision
# Section 2.3: Calculate the number of balls and allocate arrays whose sizes
# depend on this.
# `balls` is the total number of balls:
balls= sum( balls_of_type )
x = balls*[0.0] #zeros(balls, dtype=float)
y = balls*[0.0] #zeros(balls, dtype=float)
x_speed = balls*[0.0] #zeros(balls, dtype=float)
y_speed = balls*[0.0] #zeros(balls, dtype=float)
radius = balls*[0.0] #zeros(balls, dtype=float)
mass = balls*[0.0] #zeros(balls, dtype=float)
ball_type = balls*[0] #zeros(balls, dtype=int)
ball_color= [] # empty list
# Section 2.4: Assign a ball type, radius, mass, color, initial position,
# and initial velocity to each ball.
n= -1
for i in range(ball_types):
# Valid color numbers are 0-19. If the color number of a ball type is
# greater than 19, the following line of code fixes the problem by randomly
# assigning acolor number.
if color_of_type[i] >= 20: color_of_type[i]= random.randint(0, 20)
# In the following loop, j is the ball number for the ith type of ball:
for j in range(balls_of_type[i]):
# After the following statement executes, `n` will be one less than the
# number of balls generated.
n+= 1
ball_type[n]= i
radius[n]= radius_of_type[i]
mass [n]= mass_of_type [i]
ball_color.append( colors[color_of_type[i]] )
# Continue loop until center coordinates for ball[n] are such that this
# ball does not overlap any previously generated ball. If the number of
# iterations exceeds max_tries, then the program stops the loop if this
# happens, the program doesn't work because there is not enough space
# for all the balls in the container.
for tries in range(max_tries):
# generate random ball center coordinates:
keepout= radius[n] + 2.0
x[n]= random.uniform(keepout, canvas_width - keepout)
y[n]= random.uniform(keepout, canvas_height - keepout)
# Check to see if two balls have been generated on top of each other.
# First, we set good to True. True means that this ball does not
# overlap any of the other balls that we have checked so far. At the
# end of the inner loop, if good= False, this means that the ball did
# overlap at least one of the previous balls, and the program goes back
# to the top of the outer loop and generates new coordinates for the
# current ball.
good= True
for m in range(n): # innermost loop
dx= x[m] - x[n]
dy= y[m] - y[n]
d= sqrt(dx*dx + dy*dy)
if (d <= radius[m] + radius[n] + 10):
good= False
break
# end for inner for loop
if good: break
# end of loop over tries
if not good:
print "\nERROR: Not enough space for balls.\n"
sys.exit()
# Assign a random initial velocity to the current ball:
theta= random.uniform(0.0, 2.0*pi)
x_speed[n]= 2. * cos(theta)
y_speed[n]= 2. * sin(theta)
# end of loop over j (number of ball of current ball type)
# end of loop over i (number of ball type)
# Section 3: Draw the balls.
# Initialize timer:
t= Timer()
for n in range(balls):
turtle.penup()
turtle.goto(x[n], y[n])
turtle.pendown()
turtle.color(ball_color[n])
turtle.begin_fill()
turtle.circle(radius[n])
turtle.end_fill()
turtle.update()
# Display elapsed time:
print "Total drawing time: ",
t.time()
raw_input('Hit Enter to close figure window.')
if __name__ == "__main__":
msg = main()
print(msg)
</code>
Cheers & hth.,
- Alf
More information about the Python-list
mailing list