Rpsteams (#426)
* add rps teams project * renamed project page * fixed summary
This commit is contained in:
parent
94753dfc4e
commit
39edf10ada
@ -23,9 +23,10 @@
|
||||
* [Reaction Time](/projects/reaction-time)
|
||||
* [States of Matter](/projects/states-of-matter)
|
||||
* [Hot Or Cold](/projects/hot-or-cold)
|
||||
* [Voting Machine](/projects/voting-machine)
|
||||
* [Voting Machine](/projects/voting-machine)
|
||||
* [Infection](/projects/infection)
|
||||
* [Fireflies](/projects/fireflies)
|
||||
* [Rock Paper Scissors Teams](/projects/rps-teams)
|
||||
* [Inchworm](/projects/inchworm)
|
||||
* [Milk Carton Robot](/projects/milk-carton-robot)
|
||||
* [Milk monster](/projects/milky-monster)
|
||||
|
@ -52,6 +52,10 @@ Fun games to build with your @boardname@.
|
||||
"name": "Voting Machine",
|
||||
"url": "/projects/voting-machine",
|
||||
"imageUrl": "/static/mb/projects/voting-machine.png"
|
||||
}, {
|
||||
"name": "Rock Paper Scissors Teams",
|
||||
"url": "/projects/rps-teams",
|
||||
"imageUrl": "/static/mb/projects/rpsteams.png"
|
||||
}]
|
||||
```
|
||||
|
||||
@ -158,4 +162,5 @@ Fun games to build with your @boardname@.
|
||||
[Flashing Heart](/projects/flashing-heart), [Smiley Buttons](/projects/smiley-buttons), [Love Meter](/projects/love-meter), [Rock Paper Scissors](/projects/rock-paper-scissors), [Compass](/projects/compass), [Hack your headphones](/projects/hack-your-headphones), [Banana keyboard](/projects/banana-keyboard), [Telegraph](/projects/telegraph), [Guitar](/projects/guitar), [Wallet](/projects/wallet), [Watch](/projects/watch),
|
||||
[Milk Monster](/projects/milky-monster), [Karel the LED](/projects/karel), [Infection](/projects/infection), [Voting Machine](/projects/voting-machine)
|
||||
[Fireflies](/projects/fireflies), [Soil Moisture](/projects/soil-moisture),
|
||||
[States Of Matter](/projects/states-of-matter), [Reaction Time](/projects/reaction-time)
|
||||
[States Of Matter](/projects/states-of-matter), [Reaction Time](/projects/reaction-time),
|
||||
[Rock Paper Scissors Teams](/projects/rps-teams)
|
||||
|
221
docs/projects/rps-teams.md
Normal file
221
docs/projects/rps-teams.md
Normal file
@ -0,0 +1,221 @@
|
||||
# Rock Paper Scissors Teams
|
||||
|
||||
### ~avatar avatar
|
||||
|
||||
Massively multi-player rock paper scissors!
|
||||
|
||||
### ~
|
||||
|
||||
Playing rock paper scissors is usually a two player game... but it works with much more players too!
|
||||
When playing with more than two players, it becomes a team game: all players shake at the same time,
|
||||
then the number of **rock**, **paper**, **scissors** is tallied between all the players.
|
||||
The team with the most players wins the game.
|
||||
|
||||
Starting from the [basic version of the RPS game](/projects/rock-paper-scissors), we are going
|
||||
to change the code so that the @boardname@ counts and displays the number of players in the same team.
|
||||
Using the **radio** communication, the @boardname@ will send its status and receive the status of other boards.
|
||||
|
||||
Let's get started!
|
||||
|
||||
## Starting blocks
|
||||
|
||||
Let's start form a . The basic version picks the weapon in a ``|on shake|``
|
||||
event and display an icon accordingly. Take a peek at the code below to refresh your memory on that game.
|
||||
|
||||
```blocks
|
||||
let weapon = 0
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
weapon = Math.random(3)
|
||||
if (weapon == 0) {
|
||||
basic.showIcon(IconNames.SmallSquare)
|
||||
} else if (weapon == 1) {
|
||||
basic.showIcon(IconNames.Square)
|
||||
} else {
|
||||
basic.showIcon(IconNames.Scissors)
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Step 1: Refactoring the rendering
|
||||
|
||||
**Refactoring** is a funny word used in coding which pretty much means ``reorganizing``. In this case,
|
||||
we are going to move the code that displays the rock/paper/scissor icon into its own ``|forever|`` loop.
|
||||
|
||||
```blocks
|
||||
let weapon = 0
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
weapon = Math.random(3)
|
||||
})
|
||||
|
||||
basic.forever(() => {
|
||||
if (weapon == 0) {
|
||||
basic.showIcon(IconNames.SmallSquare)
|
||||
} else if (weapon == 1) {
|
||||
basic.showIcon(IconNames.Square)
|
||||
} else {
|
||||
basic.showIcon(IconNames.Scissors)
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Step 2: send status via radio
|
||||
|
||||
We send the value of ``weapon`` via radio to other @boardname@ in the ``|forever|``.
|
||||
Since radio packet may or may not arrive, it's a good idea to keep sending them.
|
||||
|
||||
We also set the radio group and send the device serial number (a number that uniquely identifies a @boardname@) as we will need that later.
|
||||
|
||||
```blocks
|
||||
let weapon = 0
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
weapon = Math.random(3)
|
||||
})
|
||||
|
||||
basic.forever(() => {
|
||||
radio.sendNumber(weapon)
|
||||
if (weapon == 0) {
|
||||
basic.showIcon(IconNames.SmallSquare)
|
||||
} else if (weapon == 1) {
|
||||
basic.showIcon(IconNames.Square)
|
||||
} else {
|
||||
basic.showIcon(IconNames.Scissors)
|
||||
}
|
||||
});
|
||||
radio.setGroup(10)
|
||||
radio.setTransmitSerialNumber(true)
|
||||
```
|
||||
|
||||
## Step 3: the team roster
|
||||
|
||||
So all players are constantly broadcasting which face they picked to other players.
|
||||
Let's add the code that receives those status and counts them.
|
||||
|
||||
We are going to add an **Array** variable that contains all the players in the same team as the current player.
|
||||
That array, named ``players``, is like your team roster: it contains the list of @boardname@ serial numbers
|
||||
that have the same weapon as you.
|
||||
|
||||
```block
|
||||
let players: number[] = [0]
|
||||
```
|
||||
|
||||
## Step 4: Receiving a message (part 1)
|
||||
|
||||
In an the ``|on radio received|`` event, we receive the status from another @boardname@. Click on the **gearwheel*
|
||||
to add the ``serial`` parameter as we will need it to identify who sent that packet.
|
||||
|
||||
We compute three values from the data received:
|
||||
|
||||
* ``match``, a boolean value indicating whether the weapon of the other @boardname@ matches our current weapon
|
||||
* ``player_index``, the position in the array of the other board's serial number. It will be -1 if it is not in the array
|
||||
* ``found``, a boolean value indicating whether the @boardname@ serial number is part of the ``players`` array
|
||||
|
||||
```blocks
|
||||
let match = false
|
||||
let player_index = 0
|
||||
let players: number[] = [0]
|
||||
let weapon = 0
|
||||
let found = false
|
||||
radio.onDataPacketReceived(({ receivedNumber, serial }) => {
|
||||
match = weapon == receivedNumber
|
||||
player_index = players.indexOf(serial)
|
||||
found = player_index >= 0
|
||||
})
|
||||
```
|
||||
|
||||
## Step 5: Receiving a message (part 2)
|
||||
|
||||
There are two cases that we need to handle when looking at ``match`` and ``found``:
|
||||
|
||||
* **if** we have a ``match`` **and** the player is ``not found`` in the list, **then** we **add** it to ``players``
|
||||
* **if** we don't have a ``match`` **and** the player is ``found`` in the list, **then** we **remove** it from ``players``
|
||||
|
||||
We turn the two rules above into two ``if`` statement where the serial number is added or removed.
|
||||
|
||||
```blocks
|
||||
let match = false
|
||||
let player_index = 0
|
||||
let players: number[] = [0]
|
||||
let weapon = 0
|
||||
let found = false
|
||||
let temp = 0
|
||||
radio.onDataPacketReceived(({ receivedNumber, serial }) => {
|
||||
match = weapon == receivedNumber
|
||||
player_index = players.indexOf(serial)
|
||||
found = player_index >= 0
|
||||
if (match && !(found)) {
|
||||
players.push(serial)
|
||||
}
|
||||
if (!(match) && found) {
|
||||
temp = players.removeAt(player_index)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Step 6: reseting the team
|
||||
|
||||
What if another player would leave the game? He would stop broadcasting its status and it would stay in our
|
||||
list of players. To avoid this problem, we reset the ``players`` array each time we shake:
|
||||
|
||||
```block
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
let players: number[] = [0]
|
||||
let weapon = Math.random(3)
|
||||
})
|
||||
```
|
||||
|
||||
## Step 7: showing team score
|
||||
|
||||
The team score is the number of players in that team... which boils down to the ``length`` of the ``players``
|
||||
array. We add a ``|show number|`` block in the ``|forever|`` loop to display it.
|
||||
|
||||
```block
|
||||
let players: number[] = [0]
|
||||
let weapon = 0
|
||||
basic.forever(() => {
|
||||
basic.showNumber(players.length)
|
||||
})
|
||||
```
|
||||
|
||||
## The final code
|
||||
|
||||
Now it's time to glue all together the pieces of our program.
|
||||
Go carefully through all the steps and assemble the various features. Eventually, it should look
|
||||
like the following program. Download it and plays with your friend**ssss**!
|
||||
|
||||
```blocks
|
||||
let temp = 0
|
||||
let found = false
|
||||
let player_index = 0
|
||||
let weapon = 0
|
||||
let match = false
|
||||
let players: number[] = []
|
||||
input.onGesture(Gesture.Shake, () => {
|
||||
players = [0]
|
||||
weapon = Math.random(3)
|
||||
})
|
||||
radio.onDataPacketReceived( ({ receivedNumber, serial }) => {
|
||||
match = weapon == receivedNumber
|
||||
player_index = players.indexOf(serial)
|
||||
found = player_index >= 0
|
||||
if (match && !(found)) {
|
||||
players.push(serial)
|
||||
}
|
||||
if (!(match) && found) {
|
||||
temp = players.removeAt(player_index)
|
||||
}
|
||||
})
|
||||
basic.forever(() => {
|
||||
radio.sendNumber(weapon)
|
||||
if (weapon == 0) {
|
||||
basic.showIcon(IconNames.SmallSquare)
|
||||
} else if (weapon == 1) {
|
||||
basic.showIcon(IconNames.Square)
|
||||
} else {
|
||||
basic.showIcon(IconNames.Scissors)
|
||||
}
|
||||
basic.showNumber(players.length)
|
||||
})
|
||||
players = [0]
|
||||
radio.setGroup(10)
|
||||
radio.setTransmitSerialNumber(true)
|
||||
```
|
BIN
docs/static/mb/projects/rpsteams.png
vendored
Normal file
BIN
docs/static/mb/projects/rpsteams.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Loading…
Reference in New Issue
Block a user