
In this post we'll create a "coin collector" game for theMini Micro.
The idea is taken from the bookComputer Coding Python Games for Kids.
Rules
The game works as follows:
- There is a fox and a coin on the screen.
- You move the fox with the arrow keys.
- When the fox collects the coin, the score is increased and a new coin is placed somewhere else on the screen.
- You have a certain amount of time to collect as many coins as possible.
- When the time is up the game is over and you are shown the final score.
By the way, if you are already Mini Micro expert you might try implementing the game with these rules and then comparing with the implementation on this post! Otherwise, keep reading ...
Assets
I'll be using theassets made available for readers of the book (which I borrowed from my local library).
I didn't read anywhere that they could not be used for other languages other than Python. As I understand it, we'll be using these assets for personal / fair use - as they are freely available on the Internet.
What I willnot be doing is re-publishing these assets somewhere else; nor claiming these to be my own. Neither should you. So I think we all should be fine.
Project setup
Download the assets file.
Create a project folder and navigate there. Alternatively create a new "usr" folder and mount it.
Put the two images (fox and coin) of the coin collector game in your project folder.
Within Mini Micro, save an empty file "game.ms" on your project location.
Placing the fox
Let's start by loading the fox's image and placing it as a sprite on the screen:
// Fox SpritefoxImg = file.loadImage("fox.png")fox = new Spritefox.image = foxImgfox.x = 200fox.y = 200// Game setupcleargfx.clear "#308A37"sprd = display(4)sprd.sprites.push fox
Note the following:
- We created to "sections" to organize our code ("Fox Sprite" and "Game setup")
- We are making use of thepre-definedSpriteDisplay at slot 4
- We are making use of thepre-definedPixelDisplay accessible via the global "gfx". We only use it to fill (clear) it with a background color (same as in the original implementation)
Running this should show the fox on the screen.
Moving the fox around
Modify the fox-sprite block to add a "speed" property:
fox = new Spritefox.image = foxImgfox.speed = 10...
And at the end of the program add the following while-loop:
// Game Loopwhile true if key.pressed("left") then fox.x -= fox.speed else if key.pressed("right") then fox.x += fox.speed else if key.pressed("up") then fox.y += fox.speed else if key.pressed("down") then fox.y -= fox.speed end if yieldend while
When running the program the fox should now move with the arrow keys.
(In order to keep this post short and the program simple we won't be checking if the fox leaves the screen. It's up to you to keep it inside!)
Showing the coin
Now it's turn to show the coin somewhere on the screen.
Let's add this new section after the "Fox Sprite" one, before the "Game Setup":
// Coin SpritecoinImg = file.loadImage("coin.png")coin = new Spritecoin.image = coinImgcoin.x = 500coin.y = 500
And we should not forget to add the coin sprite to the sprite-display. In the "Game Setup" section add this line:
sprd.sprites.push coin
This should give you a movable fox and a static coin.
Collision detection
As a next step we need to addlocal bounds so thatcollision detection works.
First we add local bounds to the fox sprite. These lines could go right after assigning the image:
fox.localBounds = new Boundsfox.localBounds.width = foxImg.widthfox.localBounds.height = foxImg.height
Same thing for the coin sprite:
coin.localBounds = new Boundscoin.localBounds.width = coinImg.widthcoin.localBounds.height = coinImg.height
Let's test if collision detection works. Add this check inside the while-loop, before the "yield":
if fox.overlaps(coin) then print "Fox gets coin!"end if
Try it out. You should see the text written many times (as the collision is detected many times per second).
Placing the coin randomly
Now, let's start fleshing out the proper game logic. Replace the above lines with these ones:
if fox.overlaps(coin) then coin.moveToRandomLocationend if
We of course need to write this new methodmoveToRandomLocation
for the coin object. Add this to the "Coin Sprite" section:
coin.moveToRandomLocation = function self.x = floor(rnd * 960) self.y = floor(rnd * 640)end function
Note the usage of the "rnd" and "floor" intrinsic functions.
Try it out. You will see that except for the score and timer it looks like the game we want to have!
Score
Let's add a new section "Score" before "Game Setup". We will write a small object to take care of the score.
// Scorescore = {}score.value = 10
For printing the score we will use the pre-allocatedTextDisplay. Because we will be updating the score text on the screen many times, we will also some way of deleting the old content.
Let's start by creating a new section with these helper functions:
// Text helper functionseraseText = function(row,column,length) text.row = row text.column = column // Print "length" amount of spaces, with no "newline" print " " * length, ""end functionprintTextAtPosition = function(txt,row,column,txtColor) // Save current color and set color from parameter previousColor = text.color text.color = txtColor // Move to position and print text text.row = row text.column = column print txt // Restore previous color text.color = previousColorend function
With these helper functions we can easily implement the score-rendering. Add this method to the "Score" section:
score.print = function eraseText 25, 5, "SCORE: 999999".len printTextAtPosition "SCORE: "+self.value, 25, 5, color.whiteend function
As you can see we reserve an area for quite a big score number, which we'll probably never reach.
Finally, add a first "score.print" call at the end of the "Game Setup" section:
score.print// Game Loop ...
Try it out.
Updating the score
The score now appears on the screen, but is not is not yet updated when coins are collected. We will now change that.
Let's add a method to increase and update the score on screen:
score.increase = function score.value += 10 score.printend function
Of course this alone is not enough. The method needs to be invoked when the fox collects a coin. Modify the corresponding if-block in the game-loop to read like this:
if fox.overlaps(coin) then coin.moveToRandomLocation score.increaseend if
Displaying the countdown
The fox can now collect coins at leisure ... but that's about to change. Now we'll add a timer to put some pressure.
We will start slow and just showing a countdown on screen.
Let's create a "Countdown" section right after the "Score" one, initially with these lines:
// Countdowncountdown = {}// Countdown value in secondscountdown.value = 0
As a first step, let's write a "start" method with which we can start / initialize the countdown:
countdown.start = function(initialValue) self.value = initialValue self.printend function
Accordingly we'll add the method to render the countdown text on screen:
countdown.print = function eraseText 25, 50, "TIME: 9999".len printTextAtPosition "TIME: "+self.value, 25, 50, color.whiteend function
Again, for reserving a printable area (erasing the previous text) we are choosing a very generous time value.
Now let's add an invocation to this "start" step when setting up the game. In the "Game Setup" section add this:
countdown.start 20
Feel free to decide the amount of seconds which best work for you.
If you try this out you should see the countdown being displayed on screen. But it does nothing yet. We'll change that in the next section.
Counting down
At this point we need to stop and think: how would the countdown logic work?
We can do the following:
- The countdown starts with an initial value (of seconds)
- Inside the game-loop we'll call an "update" method on the countdown object
- The method will check how much time it elapsed since it has last decreased its value
- If more than one second elapsed, the countdown will decrease its value and register this new "last decrease timestamp".
The strategy is clear, but some important pieces are missing. Besides the obvious "update" method we need to add a new property to keep track of "decrease events".
Add this after the "value" property to the countdown object:
countdown.lastDecreaseTs = -1
We use some weird value like "-1" to make clear that it needs to be initialized. We will do just that now. Modify the "start" method to read like this:
countdown.start = function(initialValue) self.value = initialValue self.lastDecreaseTs = time self.printend function
By initializing it to the current timestamp we will have one full second before we need to decrease its value for the first time.
Now we are in position to implement our countdown logic inside the "update" method. Add this method to the countdown object:
countdown.update = function currentTs = time elapsed = currentTs - self.lastDecreaseTs // A second elapsed since last check if elapsed > 1 then self.decrease self.lastDecreaseTs = currentTs end ifend function
It references a "decrease" method which we do not yet have. That method should decrease the value internally and update it on screen. Let's add it now:
countdown.decrease = function self.value -= 1 if self.value < 0 then self.value = 0 self.printend function
Because we do not want negative numbers in our countdown, we add a corresponding check.
Finally we need to update our game-loop to regularly call the "update" method. We can put that invocation right at the top of our while-loop:
while true countdown.update if ...
When you try it out you will see that our game is almost done!
Stopping the game
If you play the game in its current state you will merrily be able to still collect coins even if the time is up. Time to change that.
Let's add a small method to the countdown to indicate that it is finished:
countdown.isFinished = function return self.value <= 0end function
And now let's add a check in the game loop. Right after decreasing the countdown we will add this line:
if countdown.isFinished then break
This will effectively get us out of the while-loop when the countdown is done. As it is, the game just ends. You can of course see your final score on the screen.
But we should be able to make it nicer.
A better ending
First, let's add this function to our "Text helper functions" section which will allow us to print text centered on the screen:
printTextCentered = function(txt,row,txtColor) totalColumns = 68 column = totalColumns / 2 - txt.len / 2 printTextAtPosition txt,row,column,txtColorend function
With this let's print the final score and ask the user to play again or not. Add this outside (after) our game-loop:
// Game endingprintTextCentered "FINAL SCORE: " + score.value, 16, color.whiteprintTextCentered "Do you want to play again? (y/n)", 14, color.white
The user should press either key "y" or key "n". Because the user will probably still fiercely holding an arrow key, we need to "consume" these until we detect any of the keys we want.
Add this next to our section:
while true k = key.get.lower if k == "y" then run if k == "n" then breakend while
If the user presses "y" the program will be run again.
But if the user presses "n" this while-loop is exited and the program is over. Before that happens, let's add a short farewell message. Add this after this while-loop:
printprint "Bye!"
And you could say we are done!
Try it out and have fun!
Final words
Glad you made it this far. Did you like this game tutorial? Did you learn something new? How many coins can you collect? Let us know in the comments.
Happy coding in Mini Micro!
Top comments(4)

- EducationMS in CS at Colorado State University; MS in Neuroscience at UCSD
- Workconnectomics engineer at Zetta.AI
- Joined
I love it! This is a great tutorial. It shows a lot of key concepts central to almost any game.
One suggestion: rather than explicitly checking for the arrow keys, you might usekey.axis
, like so:
fox.x += key.axis("Horizontal") * fox.speed fox.y += key.axis("Vertical") * fox.speed
It's not only less code, but also lets the user use WASD or a gamepad if they so choose.
But in any case, it's a fantastic post and I hope you'll do more!

- LocationGermany
- WorkSenior Software Engineer
- Joined
As always, there is no shortage of things to learn about Mini Micro.
Thanks for the suggestion! I am planning on writing shorter "recipes" tutorials for Mini Micro and one will be "moving things around", so this will come in handy.
I'm glad you liked the tutorial.

- LocationGermany
- WorkSenior Software Engineer
- Joined
I don't seem to be able to score more than 160 ...

- LocationGermany
- WorkSenior Software Engineer
- Joined
By the way, the complete code can be found here:gist.github.com/sebnozzi/94c7890fc...
For further actions, you may consider blocking this person and/orreporting abuse