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