Red light green light radio game (#1438)
* added new game * added suggestion * updated summary * added tips * RSSI info
This commit is contained in:
		@@ -47,6 +47,7 @@
 | 
			
		||||
    * [Light Level Meter](/projects/light-level-meter)
 | 
			
		||||
    * [Radio bridge](/projects/radio-bridge)
 | 
			
		||||
    * [Snap the dot](/projects/snap-the-dot)
 | 
			
		||||
    * [Red light green light](/projects/red-light-green-light)
 | 
			
		||||
 | 
			
		||||
## #examples
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -28,16 +28,16 @@ Here are some cool projects that you can build with your @boardname@!
 | 
			
		||||
  "url": "/projects/fireflies",
 | 
			
		||||
  "description": "Simulate fireflies with micro:bits, try it in the dark!",
 | 
			
		||||
  "imageUrl": "/static/mb/projects/fireflies.png"
 | 
			
		||||
}, {
 | 
			
		||||
  "name": "Infection",
 | 
			
		||||
  "url": "/projects/infection",
 | 
			
		||||
  "description": "An epidemic has broken out, see who will survive.",
 | 
			
		||||
  "imageUrl": "/static/mb/projects/infection.png"
 | 
			
		||||
}, {
 | 
			
		||||
  "name": "Hot or Cold",
 | 
			
		||||
  "url": "/projects/hot-or-cold",
 | 
			
		||||
  "description": "Find the hidden player by seeing if your close or not.",
 | 
			
		||||
  "imageUrl": "/static/mb/projects/hot-or-cold.jpg"
 | 
			
		||||
}, {
 | 
			
		||||
  "name": "Red Light Green Light",
 | 
			
		||||
  "url": "/projects/red-light-green-light",
 | 
			
		||||
  "description": "Play the classic game with your @boardname@.",
 | 
			
		||||
  "imageUrl": "/static/mb/projects/red-light-green-light.png",
 | 
			
		||||
}, {
 | 
			
		||||
  "name": "Voting Machine",
 | 
			
		||||
  "url": "/projects/voting-machine",
 | 
			
		||||
@@ -48,5 +48,10 @@ Here are some cool projects that you can build with your @boardname@!
 | 
			
		||||
  "url": "/projects/rps-teams",
 | 
			
		||||
  "description": "The Rock-Paper-Scissors game with lots and lots of players.",
 | 
			
		||||
  "imageUrl": "/static/mb/projects/rpsteams.png"
 | 
			
		||||
}, {
 | 
			
		||||
  "name": "Infection",
 | 
			
		||||
  "url": "/projects/infection",
 | 
			
		||||
  "description": "An epidemic has broken out, see who will survive.",
 | 
			
		||||
  "imageUrl": "/static/mb/projects/infection.png"
 | 
			
		||||
}]
 | 
			
		||||
```
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										212
									
								
								docs/projects/red-light-green-light.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								docs/projects/red-light-green-light.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,212 @@
 | 
			
		||||
# Red Light Green Light
 | 
			
		||||
 | 
			
		||||
This is a classic game where the game master is looking the opposite direction and saying commands to player.
 | 
			
		||||
When the game master says "red light" and turns around, all players should stop. If the game master stops a moving player, he has to go back to the start.
 | 
			
		||||
When the game master turns around and says "green light", all players move and try to touch the game master.
 | 
			
		||||
 | 
			
		||||
In this remake, we will use @boardname@, the radio and the accelerometer to enforce those rules!
 | 
			
		||||
 | 
			
		||||
## The game master
 | 
			
		||||
 | 
			
		||||
Let's start with the code running on the game master @boardname@. Don't use this code for players!
 | 
			
		||||
 | 
			
		||||
### States
 | 
			
		||||
 | 
			
		||||
We define two states, ``GREENLIGHT`` and ``REDLIGHT`` and a ``state`` variable to store the current game state.
 | 
			
		||||
When the game master presses ``A``, the game goes into "green light" mode. When he presses ``B``, 
 | 
			
		||||
the state goes in "red light" mode.
 | 
			
		||||
 | 
			
		||||
```blocks
 | 
			
		||||
let REDLIGHT = 0
 | 
			
		||||
let state = 0
 | 
			
		||||
let GREENLIGHT = 0
 | 
			
		||||
GREENLIGHT = 1
 | 
			
		||||
REDLIGHT = 2
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Communication
 | 
			
		||||
 | 
			
		||||
The radio group is set to ``1``. We will set the same group in the player code. The game state is streamed in a forever loop so that players receive constantly.
 | 
			
		||||
 | 
			
		||||
```blocks
 | 
			
		||||
let state = 0;
 | 
			
		||||
radio.setGroup(1)
 | 
			
		||||
basic.forever(function () {
 | 
			
		||||
    radio.sendNumber(state)
 | 
			
		||||
})
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Red light, green light
 | 
			
		||||
 | 
			
		||||
Use the ``||radio:on button pressed`` block to run code when button ``A`` and ``B`` are pressed.
 | 
			
		||||
When ``A`` is pressed, the game goes into ``GREENLIGHT`` mode. When ``B`` is pressed, the game
 | 
			
		||||
goes into ``B`` mode. We also use ``||basic:show icon||`` to display the current state.
 | 
			
		||||
 | 
			
		||||
```blocks
 | 
			
		||||
let REDLIGHT = 0
 | 
			
		||||
let state = 0
 | 
			
		||||
let GREENLIGHT = 0
 | 
			
		||||
input.onButtonPressed(Button.A, function () {
 | 
			
		||||
    state = GREENLIGHT
 | 
			
		||||
    basic.showIcon(IconNames.Yes)
 | 
			
		||||
})
 | 
			
		||||
input.onButtonPressed(Button.B, function () {
 | 
			
		||||
    state = REDLIGHT
 | 
			
		||||
    basic.showIcon(IconNames.No)
 | 
			
		||||
})
 | 
			
		||||
GREENLIGHT = 1
 | 
			
		||||
REDLIGHT = 2
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Game master code
 | 
			
		||||
 | 
			
		||||
All together the game master code looks like this:
 | 
			
		||||
 | 
			
		||||
```blocks
 | 
			
		||||
let REDLIGHT = 0
 | 
			
		||||
let state = 0
 | 
			
		||||
let GREENLIGHT = 0
 | 
			
		||||
input.onButtonPressed(Button.A, function () {
 | 
			
		||||
    state = GREENLIGHT
 | 
			
		||||
    basic.showIcon(IconNames.Yes)
 | 
			
		||||
})
 | 
			
		||||
input.onButtonPressed(Button.B, function () {
 | 
			
		||||
    state = REDLIGHT
 | 
			
		||||
    basic.showIcon(IconNames.No)
 | 
			
		||||
})
 | 
			
		||||
GREENLIGHT = 1
 | 
			
		||||
REDLIGHT = 2
 | 
			
		||||
radio.setGroup(1)
 | 
			
		||||
basic.forever(function () {
 | 
			
		||||
    radio.sendNumber(state)
 | 
			
		||||
})
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### ~ hint
 | 
			
		||||
 | 
			
		||||
Make sure to rename this program to ``game master`` or something so that you don't confuse it with the player program!
 | 
			
		||||
 | 
			
		||||
### ~
 | 
			
		||||
 | 
			
		||||
### Improve the game
 | 
			
		||||
 | 
			
		||||
* Use ``||music:ring tone||`` to play a sound while the game is in ``GREENLIGHT`` mode.
 | 
			
		||||
* Attach a servo and move the arm based on the game state
 | 
			
		||||
 | 
			
		||||
## The players
 | 
			
		||||
 | 
			
		||||
The code for players needs to listen for the game master state.
 | 
			
		||||
 | 
			
		||||
### States
 | 
			
		||||
 | 
			
		||||
First, we redefine the state constant, ``GREENLIGHT``, ``REDLIGHT`` and set the radio to ``1``. 
 | 
			
		||||
We also add a ``state`` variable that will store the state of the game.
 | 
			
		||||
 | 
			
		||||
```blocks
 | 
			
		||||
let RED = 0
 | 
			
		||||
let state = 0
 | 
			
		||||
let GREEN = 0
 | 
			
		||||
GREEN = 1
 | 
			
		||||
RED = 2
 | 
			
		||||
radio.setGroup(1)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Communication
 | 
			
		||||
 | 
			
		||||
We use the ``radio:on received number`` block to store the game master state into the ``state`` variable.
 | 
			
		||||
 | 
			
		||||
```blocks
 | 
			
		||||
let state = 0
 | 
			
		||||
radio.onReceivedNumber(function (receivedNumber) {
 | 
			
		||||
    state = receivedNumber
 | 
			
		||||
})
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Display
 | 
			
		||||
 | 
			
		||||
In a forever loop, we display different icons based on the game state. Use a ``||logic:if||`` and
 | 
			
		||||
``||basic:show icon||`` blocks to display the game state.
 | 
			
		||||
 | 
			
		||||
```blocks
 | 
			
		||||
let REDLIGHT = 0
 | 
			
		||||
let state = 0
 | 
			
		||||
let GREENLIGHT = 0
 | 
			
		||||
basic.forever(function () {
 | 
			
		||||
    if (state == GREENLIGHT) {
 | 
			
		||||
        basic.showIcon(IconNames.Yes)
 | 
			
		||||
    } else if (state == REDLIGHT) {
 | 
			
		||||
        basic.showIcon(IconNames.No)
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Movement check
 | 
			
		||||
 | 
			
		||||
If the ``state`` is equal to ``REDLIGHT``, we need to check that the player is not moving. 
 | 
			
		||||
This is where the accelerometer comes into play. The accelerometer measures forces applied to the @boardname@.
 | 
			
		||||
If the player moves, it is likely that some small forces will be applied and the accelerometer will detect it.
 | 
			
		||||
At all times, gravity is applied to the @boardname@, so the acceleration strength at rest always near ``1000``mg.
 | 
			
		||||
If the acceleration strength is far from that value, say ``1100`` or ``900``, we can assume that the player is moving. To compute this we use this formula:
 | 
			
		||||
 | 
			
		||||
    moving = | acc strength - 1000 | > 1000
 | 
			
		||||
 | 
			
		||||
Now that we know the math, we can turn this into code.
 | 
			
		||||
 | 
			
		||||
```block
 | 
			
		||||
let REDLIGHT = 0
 | 
			
		||||
let state = 0
 | 
			
		||||
let GREENLIGHT = 0
 | 
			
		||||
let moving = false
 | 
			
		||||
if (state == REDLIGHT) {
 | 
			
		||||
    moving = Math.abs(input.acceleration(Dimension.Strength) - 1000) > 100
 | 
			
		||||
    if (moving) {
 | 
			
		||||
        game.gameOver()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Player code
 | 
			
		||||
 | 
			
		||||
All together:
 | 
			
		||||
 | 
			
		||||
```blocks
 | 
			
		||||
let moving = false
 | 
			
		||||
let REDLIGHT = 0
 | 
			
		||||
let state = 0
 | 
			
		||||
let GREENLIGHT = 0
 | 
			
		||||
radio.onReceivedNumber(function (receivedNumber) {
 | 
			
		||||
    state = receivedNumber
 | 
			
		||||
})
 | 
			
		||||
GREENLIGHT = 1
 | 
			
		||||
REDLIGHT = 2
 | 
			
		||||
radio.setGroup(1)
 | 
			
		||||
basic.forever(function () {
 | 
			
		||||
    if (state == GREENLIGHT) {
 | 
			
		||||
        basic.showIcon(IconNames.Yes)
 | 
			
		||||
    } else if (state == REDLIGHT) {
 | 
			
		||||
        basic.showIcon(IconNames.No)
 | 
			
		||||
    }
 | 
			
		||||
    if (state == REDLIGHT) {
 | 
			
		||||
        moving = Math.abs(input.acceleration(Dimension.Strength) - 1000) > 100
 | 
			
		||||
        if (state == REDLIGHT && moving) {
 | 
			
		||||
            game.gameOver()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### ~ hint
 | 
			
		||||
 | 
			
		||||
Make sure to rename this program to ``player`` or something so that you don't confuse it with the game master program!
 | 
			
		||||
 | 
			
		||||
### ~
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
### Tuning
 | 
			
		||||
 | 
			
		||||
Does the movement check work? Try changing the ``100`` value to tune the detection sensivity. Try ``64``.
 | 
			
		||||
 | 
			
		||||
### Improve the game
 | 
			
		||||
 | 
			
		||||
* Use ``||music:ring tone||`` to play a tone while in green mode.
 | 
			
		||||
* Use the packet signal strength to detect that you've reached the game master.
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								docs/static/mb/projects/red-light-green-light.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								docs/static/mb/projects/red-light-green-light.png
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 18 KiB  | 
		Reference in New Issue
	
	Block a user