Microbit Game - Snowball Fight
Snowball Fi-i-i-ight!
You are going to throw a snowball at your classmates. How many times will YOU get SPLATTED!
Step 1. An introduction to Radio on the micro:bit
The micro:bit has a radio chip that can be used to send and receive messages. You can set each micro:bit to a 'radio group' so that it will only send and receive messages within that group. This is very handy - imagine you and your friend are playing a game on two micro:bits sending messages to each other. If another pair of people are playing the same game then your micro:bits might receive their messages as well and this would spoil the game. But if each group of players is on a different radio group then they will only send and receive messages in their own group and so won't interfere with nearby players and so, all the games will work.
We are going to take advantage of that by setting every micro:bit to a different radio group and then when we want to send a message to someone else we will temporarily change our group so it matches the person we want to send to and then we can send them a message. That way we know only one person will receive our message.
Step 2. Setting up the basic variables
Let's write some start code that sets up a different number for each player and also says how many people are playing - we'll need that later.
STOP - Did you just copy that code?
Remember we said earlier that we are going to assign each micro:bit to a different radio group. Well, if we all just copied the code above, what has happened? - everyone has set their radio to group 0.
Everyone needs to have a different value for mynumber. So, agree who will be 0, 1, 2 ,3 etc. - the numbers should start with 0 and be in order with no gaps.
Also note the variable:
- this holds the number of people in our snowball fight. I've guessed there will be 7 or us here today (so the last player will be number 6 - remember we started at 0) If there isn't 7 players then change this. It should be the same value for everyone.
We'll add a long 5 second pause to make sure we can all check we have the correct player number.
If we are going to have a snowball fight - someone needs a snowball. We could give everyone a snowball but chaos would happen. So let's give just one player a snowball to start with so he can throw it to someone else.
We will give it to player 0 and we will also set a variable to say that he currently has the snowball. For everyone else we will tell the code that they don't have the snowball. We will do this using something called a Boolean variable (named after a Victorian called George Boole who first thought of this sort of thing). A Boolean variable is just like any other variable but it doesn't hold a number or a string, it holds either the value True or the value False. So we will make a variable called ihavethesnowball and player 0 will set it to true and everyone else will set it to false.
We could write different code for player 0 to set ihavethesnowball to true. But it is easier if we all have the same code - so let's test the value of the mynumber variable and make the code to be different for player 0. Let's also give player 0 a great fat snowball on their screen, and since no-one else has a snowball we'll clear their screens.
Here's the complete on start code:
Remember your code may have a different value of mynumber and if there aren't 7 of us here today then lastplayer will be different too.
Step 3. Throwing the snowball
We will shake the microbit to throw the snowball. But you can't throw the snowball if you don't have it, so we will make the on shake code do something only for the player who currently has the snowball - like this:
Note. Does that if test look strange?
Normally when we do an if test we need to have an = or > or similar sign in, like "if score=10" or "if tries > 2". Because the ihavethesnowball variable is a Boolean variable that can only have the values true or false we could say "if ihavethesnowball = true" here and this would work, in fact it would be exactly the same. But I think the simpler "if ihavethesnowball" makes slightly more sense. What do you think? If you prefer "if ihavethesnowball = true" then you can change the code.
We need to decide who to throw it to. For now we can select a random person. This is easy we can just use:
But there is a problem?
STOP - Can you see the problem?
That code can pick any player - including the player who is throwing the snowball. Now, not only is it stupid to throw the snowball and splat yourself but the micro:bit radio code doesn't allow messages to go to the player who sent them, so the message will just get lost and the snowball disappear into space.
We need to write some code to pick a random number but make sure it isn't our own number.
STOP - how would you do this?
There are several way but the way we'll use is to pick a random number and it is our own player number we'll pick another one and keep doing so until we get a different player.
One way to write this in micro:bit code is to deliberately set the throwto variable to our own number (the very thing we don't want!) and then loop round picking random numbers until we get one which isn't our number. Like this:
So we have someone to throw the snowball to (the player number indicated by the variable throwto)
When we are ready to throw the snowball we will change our radio group to match the radio group of the person we are throwing to. Since they are the only other person in that radio group when we send a message only they will get it.
Once we've thrown the snowball (that is, sent the message) we will change our radio group back to our own player number.
Also in the message we send we'll put our own player number, so they know who threw the snowball at them.
Of course, once we have thrown the snowball we don't have it any more! So we better remove the snowball off our screen and tell our code that we don't have it.
So the code is going to be like this
This is quite complicated so let's just check what that code does - if we don't have the snowball it does nothing. Easy! If we do have the snowball we pick another player and switch to their radio group so we can throw the snowball at them (i.e. send them a radio message). Then we set the radio group back to the one we assigned at start. This is important because it now means we are back in a radio group with just us in it, so we are ready for any snowballs being thrown our way in the future. And finally - we don't have the snowball anymore so we clear the screen and tell the code.
Step 4. Getting hit!
We know we've just been hit by the snowball when we get a radio message. Remember the code is designed so we are the only one that will get a message. The message contains the number of the player who threw the snowball but we won't use that information just yet, we'll just react to being hit (that is receiving a radio message)
The code is really easy - when we receive a radio message we just plop a big snowball on the screen and tell our code we have the snowball (by setting the variable ihavethesnowball to true). Just to slow things down a little we'll also add a pause, otherwise the snowball will zip around the group a bit fast.
Here's the code:
Let's have a SNOWBALL FI-I-IGHT!
Challenge 1: A better SPLAT!
Let's put some simple animation to look like the snowball is coming to get us. Here's my code - can you make something that looks better?
Challenge 2: Counting the splats!
Let's count how many times each of us get hit and as soon as someone gets 6 hits end the game. We just need to count each time we received a snowball.
Let's do the count code first - when do we know we've been splatted?
The answer is every time we receive a radio message - so in the on Radio Received code we can just add one to the count. First we need to set the count to 0 and the best place to do that will be On Start. We will also set a variable maxsplats to say how many splats a player can get before the game ends
Note - setting a variable like maxsplats makes tidier code
We could just test for the number 6 in the code, but if we wanted to make the game longer or shorter we would have to hunt around in the code and find this number and change it. By having a variable with an obvious name right at the top of our On Start code it makes it much easier to change things in the future
and then just add 1 when we receive a snowball splat
So now all we need to is check when splats = maxsplats and end the game.
STOP - can you think of a problem about ending the game?
It is easy to end the game on our micro:bit, we can just check if we've been splatted the maximum number of times and put out a message. Like this:
But how do we tell everyone else to stop?
The only way we can communicate with them is to send them another radio message. Let's send them an unusual number - like 99, to say the game has ended. We need to send this message to every other radio group. It's a bit easier than the random code. Can you think what the code is like?
This code will work:
We loop around for all the player numbers and for every number that is not our own we set the radio group to that number and send a 99. So every other player should receive a 99 radio message.
Now we have to write some code to handle that special radio message telling us the game has ended.
We can simple check when we receive a radio message whether it is 99 and so we have to end the game, if it isn't then it must be an incoming snowball and we get splatted as usual. So our radio receive code now starts like this:
And that's it!
Not quite - the player who last got a Snowball still has it, and so if he shakes then it will get thrown and the game will continue. This is a nasty code bug which, fortunately is easy to fix. All we need do is tell the player when he gets splatted the maximum number of times that he no longer has the snowball - the game is over and the snowball has melted!
We'll add that into the end of the radio receive code which will now look like:
Now that really is it?
STOP - can you still see a potential bug?
What would happen if there were more than 99 players in this game? The snowball could never get thrown from player 99 - if it did then the receiver would get a radio message with the thrower's number 99 and the code would tell that player it is the end of the game.
In reality we are not likely to play this game with 99 players or more so our code is probably OK but we need to bear this in mind as a possible problem. Often in computer programs bugs occur because the person who wrote the code though "Oh, this could never happen, so I won't bother writing a lot of code just in case it does".
I think we are safe in assuming our Code Club won't get 99 members so -
Let's go and Snowball Fi-i-i-ght!
Complete Code
Download the code here:
https://makecode.microbit.org/_ccjDyAAtH4kR
Expansion (Teacher's note)
A really nice expansion for this would be to change the randow throw to allow the player with the snowball to point the micro:bit at the person they want to splat! If the players were in a circle and of known compass orientation then the micro:bit could use the compass bearing to know in which direction it was pointing before being shaken and so calculate which player gets splatted!