Coin Collector Game
Tags: minimicro, miniscript, beginners, tutorial
Published: 2024-05-04 14:11:51

---
title: Coin Collector Game
published: true
description: Making a very small "coin collector" game on the Mini Micro
tags: minimicro, miniscript, beginner, tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o51o4irj9ks20siwmqyk.png
# Use a ratio of 100:42 for best results.
# published_at: 2024-04-30 21:08 +0000
---

In this post we'll create a "coin collector" game for the [Mini Micro](https://miniscript.org/MiniMicro).

![Coin collector game screenshot](https://res.cloudinary.com/dk-hub/image/upload/v1527754326/coin-collector_s2bzsv.png)

The idea is taken from the book [Computer Coding Python Games for Kids](https://www.dk.com/uk/book/9780241317792-computer-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 the [assets](https://www.dk.com/uk/information/the-python-games-resource-pack/) 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 will _not_ 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 Sprite

foxImg = file.loadImage("fox.png")

fox = new Sprite
fox.image = foxImg
fox.x = 200
fox.y = 200

// Game setup

clear

gfx.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 the [pre-defined](https://miniscript.org/wiki/Display) [SpriteDisplay](https://miniscript.org/wiki/SpriteDisplay) at slot 4
- We are making use of the [pre-defined](https://miniscript.org/wiki/Display) [PixelDisplay](https://miniscript.org/wiki/PixelDisplay) accessible via the global "gfx". We only use it to fill ([clear](https://miniscript.org/wiki/PixelDisplay.clear)) it with a background color (same as in the original implementation)
 
Running this should show the fox on the screen.

![Fox sprite on the screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6pk3qk4bfvuaah389tm9.png)

## Moving the fox around

Modify the fox-sprite block to add a "speed" property:

```
fox = new Sprite
fox.image = foxImg
fox.speed = 10
...
```

And at the end of the program add the following while-loop:

```
// Game Loop

while 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
	
	yield
end while
```

When running the program the fox should now move with the arrow keys.

![Fox moving around](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ihby2ers76evwdpoj68.gif)

(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 Sprite

coinImg = file.loadImage("coin.png")

coin = new Sprite
coin.image = coinImg
coin.x = 500
coin.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.

![Fox and coin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1bvtkspw3ekogncip2ou.png)

## Collision detection

As a next step we need to add [local bounds](https://miniscript.org/wiki/Sprite.localBounds) so that [collision detection](https://miniscript.org/wiki/Sprite.overlaps) works.

First we add local bounds to the fox sprite. These lines could go right after assigning the image:

```
fox.localBounds = new Bounds
fox.localBounds.width = foxImg.width
fox.localBounds.height = foxImg.height
```

Same thing for the coin sprite:

```
coin.localBounds = new Bounds
coin.localBounds.width = coinImg.width
coin.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).

![Fox gets the coin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bsa3kb58z9i3i7ubkzan.gif)

## 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.moveToRandomLocation
end if
```

We of course need to write this new method `moveToRandomLocation` 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](https://miniscript.org/wiki/Rnd)" and "[floor](https://miniscript.org/wiki/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!

![Coin at random locations](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u0f14d0kyz36v4z1fwh8.gif)

## Score

Let's add a new section "Score" before "Game Setup". We will write a small object to take care of the score.

```
// Score

score = {}
score.value = 10
```

For printing the score we will use the pre-allocated [TextDisplay](https://miniscript.org/wiki/TextDisplay). 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 functions

eraseText = function(row,column,length)
	text.row = row
	text.column = column
	// Print "length" amount of spaces, with no "newline"
	print " " * length, ""
end function

printTextAtPosition = 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 = previousColor
end 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.white
end 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.

![Initial score](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ze2a3lnh0gr9w7wps0an.png)

## 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.print
end 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.increase
end if
```

![Coins increasing score](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4lwr8o4mfc3d4v1dlvad.gif)

## 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:

```
// Countdown

countdown = {}
// Countdown value in seconds
countdown.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.print
end 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.white
end 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.

![Static countdown](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/48mgirfrsvj9qku678mo.png)

## 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.print
end 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 if
end 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.print
end 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!

![Collecting coins with no limit](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t7e752lxoefgr76sbzew.gif)

## 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 <= 0
end 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,txtColor
end 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 ending

printTextCentered "FINAL SCORE: " + score.value, 16, color.white
printTextCentered "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 break
end 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:

```
print
print "Bye!"
```

And you could say we are done!

![Complete gameplay](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vivo5zwnqe9sqpyhuxay.gif)

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!