How to write it
sprite.anchor = (across, down)
- across
- How far across the sprite the handle is, from
0(left edge) to1(right edge).0.5is the middle. - down
- How far down the sprite the handle is, from
0(top edge) to1(bottom edge).0.5is the middle.
Every sprite starts at (0.5, 0.5), the middle. A few handy ones:
(0.5, 1): bottom middle. The sprite stands with its feet ony.(0, 0): the top-left corner.(0.2, 1): the bottom edge, near the left. On a car facing right, that's just over the back wheel.
It goes hand in hand with sprite.angle, which turns the sprite by that many degrees. Bigger numbers turn it clockwise, and the anchor is the point that stays still while it turns.
A full example
Three anchors at once: a kid who stands on the grass, a hammer swinging from the end of its handle, and a car that does a wheelie on its back wheel when you hold the space bar. The hammer and the car are made of plain boxes and circles. The left and right arrows walk the kid.
import game
import math
game.window(480, 360, background="#87ceeb")
GROUND = 300
game.box(240, 330, 480, 60, "#3a7d44") # the grass
# A kid standing ON the grass, not sunk into it
kid = game.sprite("kid", 70, GROUND, size=70)
kid.anchor = (0.5, 1) # feet on (x, y)
# A hammer: a handle and a head that share one pivot
handle = game.box(200, GROUND, 10, 100, "#8b5a2b")
handle.anchor = (0.5, 1) # swings from its bottom end
head = game.box(200, GROUND, 46, 20, "#555555")
head.anchor = (0.5, 5.5) # pivot 5 heads below: the handle's end
# A car that pops a wheelie: a body and two wheels sharing one pivot
car = game.box(380, GROUND - 15, 100, 30, "#e63946")
car.anchor = (0.2, 1) # pivot: low down, over the back wheel
back = game.circle(380, GROUND - 15, 30, color="#222222") # right on the pivot
front = game.circle(380, GROUND - 15, 30, color="#222222")
front.anchor = (-1.5, 0.5) # pivot 2 wheels behind it: 60 px back
game.debug(True) # red boxes: what touches() checks
t = 0
while game.playing():
t = t + 1
if game.pressed("left"):
kid.x = kid.x - 4
if game.pressed("right"):
kid.x = kid.x + 4
swing = 70 * math.sin(t / 10)
handle.angle = swing
head.angle = swing
if game.pressed("space"):
tilt = max(car.angle - 3, -30) # front lifts
else:
tilt = min(car.angle + 3, 0) # and drops back
car.angle = tilt
front.angle = tilt
game.frame()
Click the game first so it hears the keys. Then try handle.anchor = (0.5, 0.5): the handle spins around its middle like a propeller, and comes apart from its head.
How it works
- It's where the sprite is.
xandyalways tell you where the anchor point is. With(0.5, 1),kid.y = GROUNDputs the feet on the ground, whatever size the kid is. - It's what the sprite turns around. Change
angleand the anchor point stays put while the rest swings around it, like a door on its hinge. - The collision box follows.
touches()andat_mouse()use a box that moves and turns with the anchor, so a swinging hammer really hits what it looks like it hits.game.debug(True)draws those boxes in red so you can see. - You can go past the edges. Numbers below
0or above1put the handle outside the sprite. That's the trick behind the hammer head:(0.5, 5.5)puts its pivot far below it, at the end of the handle, so the two parts swing together. The car's front wheel does the same, with its pivot back at the rear wheel. Give every part the samex,yandangle, and they move as one.
When to use it
- Things that stand on the ground: players, plants, trees, buildings. Use
(0.5, 1), then setyto the ground. - Things that swing or turn on a hinge: a hammer, a sword, a door, a clock hand, a flipper.
- A sprite that plays the mouse pointer: set the anchor to its tip, so the tip is exactly where you click.
Why isn't my anchor working?
- I get a
TypeError. You can't pass it togame.sprite(). Make the sprite first, then set it on the next line:kid.anchor = (0.5, 1). - It went to the wrong corner. The order is across, then down, and down grows towards the bottom, the same as
yon the screen.(0.5, 0)is the top middle, not the bottom. - The numbers are pixels. They're fractions of the sprite, not pixels.
(20, 60)puts the handle 20 sprite-widths away. Use(0.2, 0.6). - My sprite floats a little above the ground. The anchor is measured on the sprite's whole square (
sizebysize), and some built-in pictures don't fill their square. A wide, low one like"car"has empty space under it. Move it down a few pixels, or usegame.debug(True)to see where it really is. - It spins around the middle anyway. Check you set
anchoron the same sprite whoseangleyou change.