Moving Sprites
In this article, we will focus on sprite movement.
We will improve the DemonSprite class that we created in the previous article.
Improving the DemonSprite Class
First, we add two new member variables, vx and vy, to the constructor of the DemonSprite class.
These variables represent the velocity of the sprite and are used to change its position on every frame.
# sprite.py (excerpt)
def __init__(self, cvs, x, y, r):
self.x = x
self.y = y
self.r = r
self.vx = 0 # velocity in the x direction
self.vy = 0 # velocity in the y direction
# circle
self.oval = cvs.create_oval(
x - r, y - r,
x + r, y + r,
fill="white", width=0
)
Next, inside the update() method of the DemonSprite class,
we add vx to the x coordinate and vy to the y coordinate.
Since update() is called every 30 milliseconds,
the position changes little by little, making the sprite appear to move.
# sprite.py (excerpt)
# update position
self.x = self.x + self.vx # add vx to x
self.y = self.y + self.vy # add vy to y
Now, we add a new method called move().
This method receives:
-
spdas the speed -
degas the direction angle (in degrees)
Using these values, we calculate vx (x-direction velocity) and vy (y-direction velocity).
These are the components of a velocity vector.
(It may sound difficult, but for now, you can think of it as “speed with direction.”)
# sprite.py (excerpt)
def move(self, spd, deg):
radian = deg * math.pi / 180 # convert degrees to radians
self.vx = spd * math.cos(radian)
self.vy = spd * math.sin(radian)
Finally, we add a stop() method.
This method is very simple: it calls move() with speed 0 and angle 0,
which means the sprite stops moving.
# sprite.py (excerpt)
def stop(self):
self.move(0, 0) # speed 0, angle 0 (stop)
Using the Improved DemonSprite
In main.py, many DemonSprite objects are created inside the init() function.
At this point, we call the newly added move() method.
We also randomize both the speed and the direction.
# main.py (excerpt)
# demon army
for i in range(TOTAL_DEMONS):
x = random.random() * W
y = random.random() * H
demon = sprite.DemonSprite(cvs, x, y, 20)
spd = random.randint(1, 4) # random speed
deg = random.randint(0, 360) # random direction
demon.move(spd, deg)
demons.append(demon)
When you run the program now, the DemonSprite objects start moving.
However, if you watch for a while,
you will notice that all sprites eventually move off the screen…
(We will fix this in the next article!)
Complete Code
Below is the complete code with sprite movement implemented.
# sprite.py
import math
import random
import tkinter
class DemonSprite:
def __init__(self, cvs, x, y, r):
self.x = x
self.y = y
self.r = r
self.vx = 0
self.vy = 0
self.oval = cvs.create_oval(
x - r, y - r,
x + r, y + r,
fill="white", width=0
)
def update(self, cvs):
self.x = self.x + self.vx
self.y = self.y + self.vy
cvs.coords(
self.oval,
self.x - self.r, self.y - self.r,
self.x + self.r, self.y + self.r
)
def move(self, spd, deg):
radian = deg * math.pi / 180
self.vx = spd * math.cos(radian)
self.vy = spd * math.sin(radian)
def stop(self):
self.move(0, 0)
# main.py
import math
import random
import sprite
import tkinter
W, H = 480, 320
F_RATE = 30
F_INTERVAL = int(1000 / F_RATE)
FONT = ("Arial", 16)
mx, my = 0, 0
bg_photo, bg_image = None, None
TOTAL_DEMONS = 10
demons = []
def init():
global bg_photo, bg_image
bg_photo = tkinter.PhotoImage(file="images/bg_jigoku.png")
bg_image = cvs.create_image(W / 2, H / 2, image=bg_photo)
for i in range(TOTAL_DEMONS):
x = random.random() * W
y = random.random() * H
demon = sprite.DemonSprite(cvs, x, y, 20)
spd = random.randint(1, 4)
deg = random.randint(0, 360)
demon.move(spd, deg)
demons.append(demon)
def update():
cvs.delete("hud")
msg = "x:{}, y:{}".format(mx, my)
cvs.create_text(
mx, my,
text=msg,
fill="white",
font=FONT,
tag="hud"
)
for demon in demons:
demon.update(cvs)
root.after(F_INTERVAL, update)
def on_mouse_clicked(e):
pass
def on_mouse_moved(e):
global mx, my
mx, my = e.x, e.y
root = tkinter.Tk()
root.title("Hello, Tkinter!!")
root.resizable(False, False)
root.bind("<Button>", on_mouse_clicked)
root.bind("<Motion>", on_mouse_moved)
cvs = tkinter.Canvas(width=W, height=H, bg="black")
cvs.pack()
init()
update()
root.mainloop()
What’s Next?
Thank you for reading!
In the next article, we will keep the sprites inside the screen.
Stay tuned!

Top comments (0)