Over 100 great recipes for creating and animating graphics using Python
Because we are not altering and manipulating the actual properties of the images we do not need the Python Imaging Library (PIL) in this chapter. We need to work exclusively with GIF format images because that is what Tkinter deals with.
We will also see how to use “The GIMP” as a tool to prepare images suitable for animation.
We want to animate a raster image, derived from a photograph.
To keep things simple and clear we are just going to move a photographic image (in GIF format) of a beach ball across a black background.
We need a suitable GIF image of an object that we want to animate. An example of one, named beachball.gif has been provided.
Copy a .gif fle from somewhere and paste it into a directory where you want to keep your work-in-progress pictures.
Ensure that the path in our computer’s fle system leads to the image to be used. In the example below, the instruction, ball = PhotoImage(file = “constr/pics2/beachball.gif”) says that the image to be used will be found in a directory (folder) called pics2, which is a sub-folder of another folder called constr.
Then execute the following code.
# photoimage_animation_1.py
#>>>>>>>>>>>>>>>>>>>>>>>>
from Tkinter import *
root = Tk()
cycle_period = 100
cw = 300 # canvas width
ch = 200 # canvas height
canvas_1 = Canvas(root, width=cw, height=ch, bg=”black”)
canvas_1.grid(row=0, column=1)
posn_x = 10
posn_y = 10
shift_x = 2
shift_y = 1
ball = PhotoImage(file = “/constr/pics2/beachball.gif”)
for i in range(1,100): # end the program after 100 position shifts.
posn_x += shift_x
posn_y += shift_y
canvas_1.create_image(posn_x,posn_y,anchor=NW, image=ball)
canvas_1.update() # This refreshes the drawing on the canvas.
canvas_1.after(cycle_period) # This makes execution pause for 100 milliseconds.
canvas_1.delete(ALL) # This erases everything on the canvas.
root.mainloop()
The image of the beach ball is shifted across a canvas. The photo type images always occupy a rectangular area of screen. The size of this box, called the bounding box, is the size of the image. We have used a black background so the black corners on the image of our beach ball cannot be seen.
We make a pair of walking legs using the vector graphics. We want to use these legs together with pieces of raster images and see how far we can go in making appealing animations. We import Tkinter, math, and time modules. The math is needed to provide the trigonometry that sustains the geometric relations that move the parts of the leg in relation to each other.
We will be using Tkinter and time modules to animate the movement of lines and circles. You will see some trigonometry in the code. If you do not like mathematics you can just cut and paste the code without the need to understand exactly how the maths works. However, if you are a friend of mathematics it is fun to watch sine, cosine, and tangent working together to make a child smile.
Execute the program as shown in the previous image.
# walking_creature_1.py
# >>>>>>>>>>>>>>>>
from Tkinter import *
import math
import time
root = Tk()
root.title(“The thing that Strides”)
cw = 400 # canvas width
ch = 100 # canvas height
#GRAVITY = 4
chart_1 = Canvas(root, width=cw, height=ch, background=”white”)
chart_1.grid(row=0, column=0)
cycle_period = 100 # time between new positions of the ball (milliseconds).
base_x = 20
base_y = 100
hip_h = 40
thy = 20
#===============================================
# Hip positions: Nhip = 2 x Nstep, the number of steps per foot per stride.
hip_x = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 60, 60] #15
hip_y = [0, 8, 12, 16, 12, 8, 0, 0, 0, 8, 12, 16, 12, 8, 0] #15
step_x = [0, 10, 20, 30, 40, 50, 60, 60] # 8 = Nhip
step_y = [0, 35, 45, 50, 43, 32, 10, 0]
# The merging of the separate x and y lists into a single sequence.
#==================================
# Given a line joining two points xy0 and xy1, the base of an isosceles triangle,
# as well as the length of one side, “thy” . This returns the coordinates of
# the apex joining the equal-length sides.
def kneePosition(x0, y0, x1, y1, thy):
theta_1 = math.atan2((y1 – y0), (x1 – x0))
L1 = math.sqrt( (y1 – y0)**2 + (x1 – x0)**2)
if L1/2 < thy:
# The sign of alpha determines which way the knees bend.
alpha = -math.acos(L1/(2*thy)) # Avian
#alpha = math.acos(L1/(2*thy)) # Mammalian
else:
alpha = 0.0
theta_2 = alpha + theta_1
x_knee = x0 + thy * math.cos(theta_2)
y_knee = y0 + thy * math.sin(theta_2)
return x_knee, y_knee
def animdelay():
chart_1.update() # This refreshes the drawing on the canvas.
chart_1.after(cycle_period) # This makes execution pause for 200 milliseconds.
chart_1.delete(ALL) # This erases *almost* everything on the canvas.
# Does not delete the text from inside a function.
bx_stay = base_x
by_stay = base_y
for j in range(0,11): # Number of steps to be taken – arbitrary.
astep_x = 60*j
bstep_x = astep_x + 30
cstep_x = 60*j + 15
aa = len(step_x) -1
for k in range(0,len(hip_x)-1):
# Motion of the hips in a stride of each foot.
cx0 = base_x + cstep_x + hip_x[k]
cy0 = base_y – hip_h – hip_y[k]
cx1 = base_x + cstep_x + hip_x[k+1]
cy1 = base_y – hip_h – hip_y[k+1]
chart_1.create_line(cx0, cy0 ,cx1 ,cy1)
chart_1.create_oval(cx1-10 ,cy1-10 ,cx1+10 ,cy1+10, fill=”orange”)
if k >= 0 and k <= len(step_x)-2:
# Trajectory of the right foot.
ax0 = base_x + astep_x + step_x[k]
ax1 = base_x + astep_x + step_x[k+1]
ay0 = base_y – step_y[k]
ay1 = base_y – step_y[k+1]
ax_stay = ax1
ay_stay = ay1
if k >= len(step_x)-1 and k <= 2*len(step_x)-2:
# Trajectory of the left foot.
bx0 = base_x + bstep_x + step_x[k-aa]
bx1 = base_x + bstep_x + step_x[k-aa+1]
by0 = base_y – step_y[k-aa]
by1 = base_y – step_y[k-aa+1]
bx_stay = bx1
by_stay = by1
aknee_xy = kneePosition(ax_stay, ay_stay, cx1, cy1, thy)
chart_1.create_line(ax_stay, ay_stay ,aknee_xy[0], aknee_xy[1], width = 3, fill=”orange”)
chart_1.create_line(cx1, cy1 ,aknee_xy[0], aknee_xy[1], width = 3, fill=”orange”)
chart_1.create_oval(ax_stay-5 ,ay1-5 ,ax1+5 ,ay1+5, fill=”green”)
chart_1.create_oval(bx_stay-5 ,by_stay-5 ,bx_stay+5 ,by_stay+5, fill=”blue”)
bknee_xy = kneePosition(bx_stay, by_stay, cx1, cy1, thy)
chart_1.create_line(bx_stay, by_stay ,bknee_xy[0], bknee_xy[1], width = 3, fill=”pink”)
chart_1.create_line(cx1, cy1 ,bknee_xy[0], bknee_xy[1], width = 3, fill=”pink”)
animdelay()
root.mainloop()
Without getting bogged down in detail, the strategy in the program consists of defning the motion of a foot while walking one stride. This motion is defned by eight relative positions given by the two lists step_x (horizontal) and step_y (vertical). The motion of the hips is given by a separate pair of x- and y-positions hip_x and hip_y.
Trigonometry is used to work out the position of the knee on the assumption that the thigh and lower leg are the same length. The calculation is based on the sine rule taught in high school. Yes, we do learn useful things at school!
The time-animation regulation instructions are assembled together as a function animdelay().
In Python math module, two arc-tangent functions are available for calculating angles given the lengths of two adjacent sides. atan2(y,x) is the best because it takes care of the crazy things a tangent does on its way around a circle – tangent ficks from minus infnity to plus infnity as it passes through 90 degrees and any multiples thereof.
A mathematical knee is quite happy to bend forward or backward in satisfying its equations. We make the sign of the angle negative for a backward-bending bird knee and positive for a forward bending mammalian knee.
This animated walking hips-and-legs is used in the recipes that follow this to make a bird walk in the desert, a diplomat in palace grounds, and a spider in a forest.
We now coordinate the movement of four GIF images and the striding legs to make an Apteryx (a fightless bird like the kiwi) that walks.
We need the following GIF images:
The images used are karroo.gif, apteryx1.gif, and shoe1.gif. Note that the images of the bird and the shoe have transparent backgrounds which means there is no rectangular background to be seen surrounding the bird or the shoe. In the recipe following this one, we will see the simplest way to achieve the necessary transparency.
Execute the program shown in the usual way.
# walking_birdy_1.py
# >>>>>>>>>>>>>>>>
from Tkinter import *
import math
import time
root = Tk()
root.title(“A Walking birdy gif and shoes images”)
cw = 800 # canvas width
ch = 200 # canvas height
#GRAVITY = 4
chart_1 = Canvas(root, width=cw, height=ch, background=”white”)
chart_1.grid(row=0, column=0)
cycle_period = 80 # time between new positions of the ball (milliseconds).
im_backdrop = “/constr/pics1/karoo.gif”
im_bird = “/constr/pics1/apteryx1.gif”
im_shoe = “/constr/pics1/shoe1.gif”
birdy =PhotoImage(file= im_bird)
shoey =PhotoImage(file= im_shoe)
backdrop = PhotoImage(file= im_backdrop)
chart_1.create_image(0 ,0 ,anchor=NW, image=backdrop)
base_x = 20
base_y = 190
hip_h = 70
thy = 60
#==========================================
# Hip positions: Nhip = 2 x Nstep, the number of steps per foot per stride.
hip_x = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 60, 60] #15
hip_y = [0, 8, 12, 16, 12, 8, 0, 0, 0, 8, 12, 16, 12, 8, 0] #15
step_x = [0, 10, 20, 30, 40, 50, 60, 60] # 8 = Nhip
step_y = [0, 35, 45, 50, 43, 32, 10, 0]
#=============================================
# Given a line joining two points xy0 and xy1, the base of an isosceles triangle,
# as well as the length of one side, “thy” this returns the coordinates of
# the apex joining the equal-length sides.
def kneePosition(x0, y0, x1, y1, thy):
theta_1 = math.atan2(-(y1 – y0), (x1 – x0))
L1 = math.sqrt( (y1 – y0)**2 + (x1 – x0)**2)
alpha = math.atan2(hip_h,L1)
theta_2 = -(theta_1 – alpha)
x_knee = x0 + thy * math.cos(theta_2)
y_knee = y0 + thy * math.sin(theta_2)
return x_knee, y_knee
def animdelay():
chart_1.update() # Refresh the drawing on the canvas.
chart_1.after(cycle_period) # Pause execution pause for X millise-conds.
chart_1.delete(“walking”) # Erases everything on the canvas.
bx_stay = base_x
by_stay = base_y
for j in range(0,13): # Number of steps to be taken – arbitrary.
astep_x = 60*j
bstep_x = astep_x + 30
cstep_x = 60*j + 15
aa = len(step_x) -1
for k in range(0,len(hip_x)-1):
# Motion of the hips in a stride of each foot.
cx0 = base_x + cstep_x + hip_x[k]
cy0 = base_y – hip_h – hip_y[k]
cx1 = base_x + cstep_x + hip_x[k+1]
cy1 = base_y – hip_h – hip_y[k+1]
#chart_1.create_image(cx1-55 ,cy1+20 ,anchor=SW, image=birdy, tag=”walking”)
if k >= 0 and k <= len(step_x)-2:
# Trajectory of the right foot.
ax0 = base_x + astep_x + step_x[k]
ax1 = base_x + astep_x + step_x[k+1]
ay0 = base_y – 10 – step_y[k]
ay1 = base_y – 10 -step_y[k+1]
ax_stay = ax1
ay_stay = ay1
if k >= len(step_x)-1 and k <= 2*len(step_x)-2:
# Trajectory of the left foot.
bx0 = base_x + bstep_x + step_x[k-aa]
bx1 = base_x + bstep_x + step_x[k-aa+1]
by0 = base_y – 10 – step_y[k-aa]
by1 = base_y – 10 – step_y[k-aa+1]
bx_stay = bx1
by_stay = by1
chart_1.create_image(ax_stay-5 ,ay_stay + 10 ,anchor=SW, im-age=shoey, tag=”walking”)
chart_1.create_image(bx_stay-5 ,by_stay + 10 ,anchor=SW, im-age=shoey, tag=”walking”)
aknee_xy = kneePosition(ax_stay, ay_stay, cx1, cy1, thy)
chart_1.create_line(ax_stay, ay_stay-15 ,aknee_xy[0], aknee_xy[1],
width = 5, fill=”orange”, tag=”walking”)
chart_1.create_line(cx1, cy1 ,aknee_xy[0], aknee_xy[1], width = 5,
fill=”orange”, tag=”walking”)
bknee_xy = kneePosition(bx_stay, by_stay, cx1, cy1, thy)
chart_1.create_line(bx_stay, by_stay-15 ,bknee_xy[0], bknee_xy[1],
width = 5, fill=”pink”, tag=”walking”)
chart_1.create_line(cx1, cy1 ,bknee_xy[0], bknee_xy[1], width = 5,
fill=”pink”, tag=”walking”)
chart_1.create_image(cx1-55 ,cy1+20 ,anchor=SW, image=birdy, tag=”walking”)
animdelay()
root.mainloop()
The same remarks concerning the trigonometry made in the previous recipe apply here. What we see here now is the ease with which vector objects and raster images can be combined once suitable GIF images have been prepared.
For teachers and their students who want to make lessons on a computer, these techniques offer all kinds of possibilities like history tours and re-enactments, geography tours, and, science experiments. Get the students to do projects telling stories. Animated year books?
I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…
Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…
Once we learn how to deploy an Ubuntu server, how to manage users, and how…
Key-takeaways: Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…
While developing a web application, or setting dynamic pages and meta tags we need to deal with…
Software architecture is one of the most discussed topics in the software industry today, and…