感染是一种引人入胜的游戏,建议在室外或大型开放区域播放,以便为活动提供更多空间
目录
规则
感染是一种模拟疾病传播的分布式游戏。目标是在每个玩家死亡之前停止爆发!
- 角色数量: 1名法师,4名或更多额外角色。“主”和所有其他玩家需要一个带电池组的micro:bit。
在这个游戏中,“主”micro:bit感染了一个单独的初始玩家(“患者零”)。受感染的玩家会立即感染,但在孵化期间不会出现任何疾病迹象。当两个micro:bits彼此足够接近以“收缩疾病”时,疾病就会传播。孵化期后,屏幕上出现一张悲伤的脸。疾病期过后,玩家最终会死亡,并且屏幕上会显示一个头骨。死亡的玩家已退出游戏。
如果至少有一名玩家幸免于爆发,则赢得比赛。
按A+B
进入“主”模式(游戏中只有一个主)。
等待玩家配对。配对播放器的数量将显示在屏幕上。配对时,播放器屏幕上会出现一个字母,这封信是玩家的身份。
一旦您的所有玩家都注册了,请按A+B
开始感染游戏。游戏随机挑选一名玩家作为患者零。
如果足够接近(检测到足够的RSSI
),并且如果TRANSMISSIONPROB
达到疾病转移的某个概率(),则运动员将疾病传播给另一个运动员。在孵化阶段(INCUBATION
)期间,玩家不会出现任何疾病迹象(幸福的脸)。在那个阶段之后,玩家生病并在屏幕上显示一张悲伤的脸。在生病(悲伤)的脸后,玩家死了,头骨出现了。
一旦游戏结束,微:位将显示玩家的ID( ,,A
…),健康,谁传染这些玩家的ID。Master micro:bit将显示患者零的身份。
游戏中使用的图标:
- 配对:
IconNames.Ghost
- 配对:
IconNames.Happy
- 死:
IconNames.Skull
- 生病:
IconNames.Sad
- 孵化:
IconNames.Confused
- 健康:
IconNames.Happy
项目分享
此代码使用块中不支持的语言功能,例如switch
或enum
。因此,它不会转换回块。
https://makecode.microbit.org/_gymCJCWPbiDu
JavaScript代码
/**
* Infection game
*
* Flash all micro:bit will this script
*
* Press A+B to enter master mode (1 per game)
*
* Wait for players to be paired. The number of paired player will display on screen.
* An icon will appear on player's screen.
*
* Press A+B to start the infection game. The master will pick a random
* player as patient zero.
*
* A player will transmit the disease if close enough (RSSI)
* and with a certain probability (TRANSMISSIONPROB).
* During the incudation phase (INCUBATION), the player does not show any sign
* of illness. After that phase, the sad face shows up.
*
* The game will automatically stop once all players are dead or healthy. The master can
* also press A+B again to stop the game.
*
* Once the game is over, the micro:bit will show the player id (A,B,C...), health and
* who infected him.
*
* Icons used in the game:
*
* Pairing: IconNames.Ghost
* Paired: IconNames.Happy
* Dead: IconNames.Skull
* Sick: IconNames.Sad
* Incubating: IconNames.Confused
* Healthy: IconNames.Happy
*
*/
const
INCUBATION =
20000
;
// time before showing symptoms
const
DEATH =
40000
;
// time before dying off the disease
const
RSSI =
-45
;
// db
const
TRANSMISSIONPROB =
40
;
// % probability to transfer disease
enum
GameState {
Stopped,
Pairing,
Running,
Over
}
enum
HealthState {
Healthy,
Incubating,
Sick,
Dead
}
const
GameIcons = {
Pairing: IconNames.Ghost,
Paired: IconNames.Happy,
Dead: IconNames.Skull,
Sick: IconNames.Sad,
Incubating: IconNames.Confused,
Healthy: IconNames.Happy
}
const
playerIcons =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
;
class
Player {
id: number
;
icon: number
;
health: HealthState;
show() {
basic.showString(playerIcons[this
.icon]);
}
}
// common state
let
state = GameState.Stopped;
// master state
let
master =
false
;
let
patientZero: Player;
const
players: Player[] = [];
// player state
let
paired =
false
;
let
infectedBy =
-1
;
// who infected (playerIcon)
let
infectedTime =
0
;
// local time when infection happened
let
playerIcon =
-1
;
// player icon and identity
let
health = HealthState.Healthy;
// get a player instance (creates one as needed)
function
player
(
id:
number
):
Player
{
for
(
const
p of players)
if
(p.id == id)
return
p;
// add player to game
let
p =
new
Player();
p.id = id;
p.icon = (players.length + 1
) % playerIcons.length;
p.health = HealthState.Healthy;
players.push(p);
serial.writeLine(`player ==>
${p.id}
`
)
return
p;
}
function
allDead
():
boolean
{
for
(
const
p of players)
if
(p.health != HealthState.Dead)
return
false
;
return
true
;
}
function
gameOver
()
{
state = GameState.Over;if
(patientZero)
patientZero.show();
}
function
gameFace
()
{
switch
(state) {
case
GameState.Stopped:
basic.showIcon(GameIcons.Pairing);break
;
case
GameState.Pairing:
if
(playerIcon >
-1
)
basic.showString(playerIcons[playerIcon]);else
basic.showIcon(paired ? GameIcons.Paired : GameIcons.Pairing,
1
);
break
;
case
GameState.Running:
switch
(health) {
case
HealthState.Dead:
basic.showIcon(GameIcons.Dead, 1
);
break
;
case
HealthState.Sick:
basic.showIcon(GameIcons.Sick, 1
);
break
;
default
:
basic.showIcon(GameIcons.Healthy, 1
);
break
;
}break
;
case
GameState.Over:
// show id
basic.showString(playerIcons[playerIcon]);
basic.pause(
2000
);
// show health
switch
(health) {
case
HealthState.Dead:
basic.showIcon(GameIcons.Dead, 2000
);
break
;
case
HealthState.Sick:
basic.showIcon(GameIcons.Sick, 2000
);
break
;
case
HealthState.Incubating:
basic.showIcon(GameIcons.Incubating, 2000
);
break
;
default
:
basic.showIcon(GameIcons.Healthy, 2000
);
break
;
}// show how infected
if
(infectedBy >
-1
) {
basic.showString(" INFECTED BY"
);
basic.showString(playerIcons[infectedBy]);
basic.pause(2000
);
} else
{
basic.showString(" PATIENT ZERO"
);
basic.pause(2000
);
}// show score
game.showScore();
basic.pause(
1000
);
break
;
}
}
// master button controller
input.onButtonPressed(Button.AB, () => {
// register as master
if
(state == GameState.Stopped && !master) {
master = true
;
paired = true
;
state = GameState.Pairing;
serial.writeLine("registered as master"
);
radio.setTransmitPower(7
);
// beef up master signal
basic.showString(
"0"
);
return
;
}
if
(!master)
return
;
// master only beyond this
// launch game
if
(state == GameState.Pairing) {
// pick 1 player and infect him
patientZero = players[
Math
.random(players.length)];
while
(patientZero.health == HealthState.Healthy) {
radio.sendValue("infect"
, patientZero.id);
basic.pause(100
);
}
// all ready
state = GameState.Running;
serial.writeLine(
`game started
${players.length}
players`
);
// show startup
basic.showIcon(GameIcons.Dead);
}
// end game
else
if
(state == GameState.Running) {
gameOver();
}
})
radio.setGroup(42
);
radio.setTransmitSerialNumber(true
)
radio.onDataPacketReceived(({ time, receivedNumber, receivedString, signal, serial: id }) => {if
(master) {
if
(receivedString ==
"pair"
) {
// register player
let
n = players.length;
let
p = player(id);
// show player number if changed
if
(n != players.length) {
led.stopAnimation();
basic.showNumber(players.length);
}
}else
if
(receivedString ==
"health"
) {
let
p = player(id);
p.health = receivedNumber;// check if all infected
if
(allDead())
gameOver();
}
} else
{
if
(receivedString ==
"state"
) {
// update game state
state = receivedNumber as GameState;
}
else
if
(infectedBy <
0
&&
receivedString == "infect"
&& receivedNumber == control.deviceSerialNumber()) {
// infected by master
infectedBy =
0
;
// infected my master
infectedTime = input.runningTime();
health = HealthState.Incubating;
serial.writeLine(
`infected
${control.deviceSerialNumber()}
`
);
}if
(receivedString ==
"h"
+ control.deviceSerialNumber().toString() &&
health < receivedNumber) {
health = receivedNumber;
}switch
(state) {
case
GameState.Pairing:
// medium range in pairing mode
if
(!paired &&
receivedString == "paired"
&& receivedNumber == control.deviceSerialNumber()) {
// paired!
serial.writeLine(
`player paired ==>
${control.deviceSerialNumber()}
`
)
paired = true
;
return
;
}else
if
(paired && receivedString ==
"i"
+ control.deviceSerialNumber().toString()) {
playerIcon = receivedNumber;
}break
;
case
GameState.Running:
// broadcast infection status
if
(health == HealthState.Healthy && receivedString ==
"transmit"
) {
serial.writeLine(`signal:
${signal}
`
);
if
(signal > RSSI &&
Math
.random(
100
) > TRANSMISSIONPROB) {
infectedBy = receivedNumber;
infectedTime = input.runningTime();
health = HealthState.Incubating;
}
} else
if
(health != HealthState.Dead
&& receivedString == "health"
&& signal > RSSI) {
game.addScore(1
);
}break
;
}
}
})
// main game loop
basic.forever(() => {
if
(master) {
switch
(state) {
case
GameState.Pairing:
// tell each player they are registered
for
(
const
p of players) {
radio.sendValue("paired"
, p.id);
radio.sendValue("i"
+ p.id, p.icon);
}
serial.writeLine(`pairing
${players.length}
players`
);
basic.pause(500
);
break
;
case
GameState.Running:
for
(
const
p of players) {
radio.sendValue("h"
+ p.id, p.health);
}break
;
case
GameState.Over:
if
(patientZero)
patientZero.show();break
;
}
radio.sendValue("state"
, state);
// keep broadcasting the game state
}
else
{
// player loop
switch
(state) {
case
GameState.Pairing:
// broadcast player id
if
(playerIcon <
0
)
radio.sendValue("pair"
, control.deviceSerialNumber());
else
if
(infectedBy >
-1
)
radio.sendValue("health"
, health);
break
;
case
GameState.Running:
// update health status
if
(health != HealthState.Healthy && input.runningTime() - infectedTime > DEATH)
health = HealthState.Dead;else
if
(health != HealthState.Healthy && input.runningTime() - infectedTime > INCUBATION)
health = HealthState.Sick;// transmit disease
if
(health == HealthState.Incubating || health == HealthState.Sick)
radio.sendValue("transmit"
, playerIcon);
radio.sendValue("health"
, health);
break
;
}// show current animation
gameFace();
}
})
basic.showIcon(GameIcons.Pairing)