Python, part 11
Getting fancier.
Let's go back to our old orange ball rolling across the green lawn
program.
Suppose we want the ball to move more and more slowly as we go.
You
should recall that time.sleep(0.1) says to pause for 0.1 seconds.
This meant
that the next iteration, where we move the ball over 5 pixels and
redrew it
occurred 0.1 seconds later. If the pause had been 1 second per 5
pixels moved,
since the canvas is 400 pixels wide, it would have taken almost 80
seconds to
move the ball across (the final spot was at 390 in the while
loop: 390/5 equals
78, hence 78 iterations/78 seconds). So we'll create a variable
to start BEFORE
the while loop:
sleeptime = 0.1
Then, when we increment oldx by 5 to move the circle, we'll also
increment
sleeptime. If you increment sleeptime by 0.1 each iteration,
we're going to
quickly reach 1.0 seconds per iteration, then 2.0--perhaps a bit
boring. So we'll
try
sleeptime = sleeptime + 0.005
Experiment! Try
it! rolling2
-----------------------------------------------------
Some fun with basic old trig stuff--sines and cosines. This was
motivated by my
desire to have a ball that spun around in a loop--rather like the earth
around the
sun. The trick was how to figure out easily--without having to
use a compass and
graph paper, for example, where the ball would be at all times.
The degrees of a
compass run from 0 to 360, with 0 being at twelve o'clock on a clock
face, 90 at
3 o'clock, 180 at 6 o'clock, 270 at 9 o'clock. We can increment
degrees nicely,
say 10 degrees at a time. So suppose our center (e.g. the
sun) is at (200,200) on our
canvas. Suppose we want the ball to have radius 100--i.e. 100
pixels out from
(200,200) at all times. So at 0 degrees we want the ball to be at
(200,100)--i.e.
100 pixels directly above the (200,200) center. At 90 degrees we
want the ball to
be at (300,200)--i.e. 100 pixels to the right of the center, and at 180
degrees the
ball should be at (200,300)--100 pixels directly below the center,
etc. The sine
and cosine functions can be used to tell us where the ball should
be. We need:
import
math
this brings in the math library, sine, cosine, etc.
We can then use math.cos and math.sin
These two functions except values in
radians, not degrees. So to convert degrees to radians:
degrees *
math.pi/180
math.pi is 3.1415
So:
math.cos(degrees * math.pi/180)
math.sin(degrees * math.pi/180)
Sine and cosine are values between -1.0 and +1.0, so consequently:
100 * math.cos(degrees * math.pi/180)
100 * math.sin(degrees * math.pi/180)
have values between -100.0 and + 100.0. One small
glitch--these are not the
nice integers we need--they are floating-point decimals. Luckily
python lets
us convert: int(x)
is a function that converts the value x to an integer--for
eaxmple, int(3.14159) would be the integer 3. So putting
everything together,
and remember that (200,200) is our center:
xpt = 200 + int(100 * math.cos(degrees * math.pi/180))
ypt = 200 + int(100 * math.sin(degrees * math.pi/180))
For and value of degrees--such as 0, 180, 115, 305, etc--this will give
us the
appropriate x and y coordinates. (we're assuming below our orange
canvas).
degrees = 270
for i in range(200):
xpt = 200 + int(100 *
math.cos(degrees * math.pi/180))
ypt = 200 + int(100 *
math.sin(degrees * math.pi/180))
myCanvas.create_oval(xpt,ypt,xpt+25,ypt+25,fill="white",outline="white")
myCanvas.pack()
myCanvas.update()
time.sleep(0.1)
myCanvas.create_oval(xpt,ypt,xpt+25,ypt+25,fill="orange",outline="orange")
degrees = degrees + 10
spinloop
You don't need to wrack your brains about sine and cosine here--just
run the
program and watch the effect.
---------------------------------------
VARIATION. We can have 2 balls spinning at the same time.
If we want them
to spin in opposite directions, we'll need degrees and degrees2--with
degrees
incrementing by 10 each time through the loop and degrees2 decrementing
by
10. To move in the same direction, just degrees suffices.
To move in the same
direction but at different starting points, then typically degrees = 0
and
degrees2 = 180 or the like. You get the idea. We also need
to figure out where
the centers should be. For example,
(100,200) and (300,200) puts the two
centers on the same horizontal line
200 pixels apart from each other. You'll need 2 create_ovals, one
for each
ball, and then another 2 to change them back to orange again. You
need xpt,
ypt, xpt2, and ypt2 to get 2 pairs of x-y
coordinates. spinloop2
------------------------------------------
VARIATION--HARDER! The solar system out as far as Earth--i.e.
the sun, Mercury, Venus, and Earth. Assume nice circular
orbits--it's much
easier. We need different rotation speeds--so, for example, every
0.1 seconds
Mercury moves through 10 degrees, Venus through 5 degrees, and Earth 2
degrees.
MercuryDegrees = MercuryDegrees + 10
VenusDegrees = VenusDegrees + 5
EarthDegrees = EarthDegrees + 2
You also want the planets different distances from the sun! solarsystem
------------------------------------------------
PAC-MAN pacman
pacman2
Suppose we want to create a pacman-like figure, with the mouth opening
and
closing. We can draw a large circle centered on (200,200) of
radius 100:
create_oval(100,100,300,300,fill="orange"). We can draw an
eyeball using
create_oval. For the mouth, a triangle of the same color as the
canvas:
create_polygon(200,200,300,190,300,210,fill="blue or whatever) creates a
triangle from the center of the pacman circle to the outside of
pacman. This
triangle is not a very wide mouth. We pack and update and
pause. Then we
again do create_polygon(200,200,300,180,300,220,fill="etc). This
makes the
triangle wider, and so the mouth gets wider. We continue this a
few more times
so the mouth gets suitably wide. We then go back to the top of
our loop which
redraws the pacman circle--this makes the mouth appear to snap shut,
and we
repeat the process.
pacman
is a simpler version of pacman2.
In pacman,
the mouth opens wide
closes quickly, and the eye is simple. pacman2
has the mouth open in increments,
and the eye is more complex--first drawing a white oval, then (not
before!)
drawing a red eye in the white oval.
If I had lots of spare time I could probably make pacman move across
the screen
gobbling as he goes. How? Make pacman smaller, start pacman
at, say, (40,200)
and make the coordinates relative to the main coordinate rather than
fixed.
Actually--not too bad--the simpler pacman now moves and gobbles: pacman3