Yesterday we learned how to load images from disk, and draw them into a pixel display. Today we're going to load images the same way, but draw them very differently: as "sprites," which can be efficiently moved, rotated, scaled, and even tinted a different color!
As always, you should have your Mini Micro Cheat Sheet on hand. But here's the key section for today:
It's only a handful of methods and properties, but they provide so much power!
Let's begin by creating a Sprite object, and assigning its image:
heart = new Sprite
heart.image = File.loadImage("/sys/pics/Heart.png")
Notice that the image we're assigning comes from File.loadImage
, which is the same method we used yesterday.
Next we need to prepare the sprite display. A common pattern in Mini Micro, when working with display modes, is to first set the display mode on a particular layer, and then assign it to some convenient variable so you can refer to it more easily. (You don't need to do this with the default text or pixel displays, because we already have text
and gfx
to refer to those. But there are no default references for other display modes.)
So we need three more lines:
display(4).mode = displayMode.sprite
disp = display(4)
disp.clear
The first line above makes sure that display(4) is set to Sprite mode. The second line assigns display(4) (which is now a sprite display) to a variable we call disp
, and the last line clears all sprites from that display.
Now we can display that heart sprite we created above, by simply adding it to the display's sprites
list:
disp.sprites.push heart
What's that red thing that just appeared behind your text? It's a heart! It's just mostly off screen. That's because its x and y properties (its position on screen) are 0,0, i.e. the lower-left corner of the screen.
But here's the fun bit: you can move a sprite anywhere on the screen, simply by assigning new values to its x and y properties! Recall that the screen is 960 pixels wide and 640 pixels tall. So, to position the heart in the center of the screen, simply assign half those values to its x and y position:
heart.x = 480
heart.y = 320
Notice how the moment you assign a new value to x or y, the sprite immediately moves accordingly. And it moves cleanly, not leaving behind any old images of itself (unlike drawing repeatedly with gfx.drawImage
would do).
You've probably already realized that you can make an animation, just by changing these properties in a loop. Try it!
for x in range(50, 900, 3)
heart.x = x
wait 0.01
end for
Note that we need a wait
in there, in order to make the animation slow enough to see. You could also use yield
, which waits until the next frame, normally about 1/60th of a second.
What else can you do with sprites? Well, how about scaling? Try these:
heart.scale = 0.5
heart.scale = 2
A scale of 1 (the default) means, "standard size" — 1 pixel in the sprite image appears as 1 pixel on screen. If you set the scale to 0.5, it shrinks the image down to 50% of standard size. And when you set the scale to 2, it appears twice as big. Of course you can use any value. But here's an advanced trick: instead of a single number, you can assign a list of two numbers, which will be used to scale the sprite differently in x and y. Try it:
heart.scale = [0.5, 2]
This sets the heart scale to 0.5 in x, and 2 in y — a narrow, tall heart! Experiment with other combinations until you're sure you've got it. Then set the scale back to 1 for the next bit.
heart.rotation = 45
Here we've set the sprite rotation to 45 degrees. The result is as you'd expect:
Note that rotation is given in degrees (not radians) counter-clockwise. Again, we could animate:
for rot in range(0, 360, 5)
heart.rotation = rot
wait 0.01
end for
Finally let's talk about tint: a color applied to the color of the sprite. It doesn't replace the sprite's original colors; it sort of multiplies in. If the original sprite is white — as many of the built-in images are — then the result will be exactly the tint color. But in this case, our heart is mostly red, so any tint we apply will be multiplied by those red color values. So let's try a few:
heart.tint = color.gray
Any color, when multiplied by gray, gets darker. So this gives us a darker heart. Or try this one:
heart.tint = color.aqua
This produces a dark green heart. To restore any sprite to its original full-color glory, tint it white (which is no tint at all):
heart.tint = color.white
And you now know pretty much everything there is to know about sprites! At this point you should load up and run the spriteDemo.ms program, located in /sys/demo:
load "/sys/demo/spriteDemo"
run
You should now be able to recognize what's going on here:
- There are two sprites on the sprite display: the wumpus, and a heart.
- The standard text display is used to print the instructions at the top of the screen.
- The standard graphics display is used to display little stars (pixels), with more drawn every time you catch the heart.
Play a bit, then press Escape to exit the program. And then edit
to inspect the code. You should be able to understand pretty much everything you see now. There are some things we haven't talked about yet, like the key.pressed
method, but you can probably guess what that stuff does.
What do you think? Are sprites the coolest thing since sliced bread, or what?