How to write it
game.plot(x, y, color="#ffffff", size=2)
- x, y
- Where the dot goes, in game coordinates: x from the left, y from the top (y grows downward).
- color
- Any CSS colour: a name like
"red", a hex code like"#22d3a5", or"rgb(255, 120, 0)". White if you leave it out. - size
- How wide the dot is, in pixels. It is round.
1is a fine grain,2(the default) is easy to see.
The dot appears at the next game.frame(), and then it stays until you rub it out with game.wipe() or game.fade().
A full example: the Sierpinski triangle
This is the "chaos game". Start anywhere, pick one of three corners at random, jump halfway towards it, plot a dot, repeat. Out of pure randomness, a perfect fractal appears:
import game
import random
game.window(480, 420, background="#0b1020")
corners = [(240, 20), (20, 400), (460, 400)]
colors = ["#ff4d6d", "#4dabf7", "#69db7c"]
x, y = 240, 200
dots = 0
board = game.label("Dots: 0", 70, 20, size=16, color="#ffffff")
while game.playing():
for i in range(500): # 500 dots every frame
c = random.randint(0, 2)
cx, cy = corners[c]
x = (x + cx) / 2 # jump halfway to the corner
y = (y + cy) / 2
game.plot(x, y, colors[c], size=1)
dots = dots + 500
board.content = "Dots: " + str(dots)
game.frame()
Why not just use sprites?
You could make every dot a game.sprite() or a game.circle(). It is perfectly good Python, and it works for the first few hundred. Then it slows down. Then it crawls.
That is because sprites are redrawn from scratch every frame. That's what lets you move them, spin them and check what they touch. With 5,000 sprites on screen, every single frame draws 5,000 things, even though none of them moved.
game.plot() is drawn once. The dot is stamped onto an ink layer under your sprites, and after that it is just pixels: it costs nothing to keep it there. So the 100th dot and the 100,000th dot are just as cheap.
The rule of thumb: if a thing needs to move, collide or be clicked, make it a sprite. If it just needs to be there, plot it.
The rest of the ink family
game.plot() has a few relatives that all draw on the same ink layer:
game.line(x1, y1, x2, y2, color, width=2)stamps a straight line. Use it for trails behind something fast: a dot every frame leaves gaps, a line from the old position to the new one doesn't.game.fade(0.05)rubs out a little of the ink each time you call it, so trails die away like a comet tail. Call it once a frame.game.wipe()rubs out all the ink at once and leaves the sprites alone.game.save_image("ink")saves just the drawing as a PNG, with no score or sprites on top.
game.line(old_x, old_y, ship.x, ship.y, "#4ea8ff") # a trail behind the ship old_x, old_y = ship.x, ship.y game.fade(0.03) # that slowly fades away game.frame()
Why isn't my dot showing?
- There's no
game.frame()after it. Dots are stamped when the frame is drawn. A program that plots and then ends without a frame shows nothing. - It's off the screen. Dots outside the window are drawn, but you can't see them. Print
xandyto check. - It's the same colour as the background, or so small you can't see it. Try
size=4and"red"while testing. - A sprite is on top of it. Ink sits underneath every sprite and label.
- Something calls
game.wipe()orgame.fade()every frame, so the dot is rubbed out as fast as it's drawn.