00 — Blocks Example
The same PetBot as the extension version, but rebuilt entirely out of standard MakeCode blocks. Open it in MakeCode and click “Blocks” to see how every behavior is assembled — the wellbeing system, the face, the idle loop, and all the activities.
Use it to invent your own behaviors: copy a function, swap the icons, sounds, and robot moves, then wire it to a button.
Try It
Press Edit to open in MakeCode, or Run to try it in the simulator right here:
What the Code Does
Wellbeing system: The pet has a wellbeing score (0–100) that starts at 50. It slowly drops by 1 every 2 seconds in the idle loop. Each activity changes it — some boost wellbeing, others drain it.
The face: The idle loop picks an icon based on the current wellbeing:
| Wellbeing | Face |
|---|---|
| 75–100 | Fabulous |
| 50–74 | Slight smile |
| 20–49 | Sad |
| 0–19 | Angry |
| Sleeping | Asleep |
Button map:
| Input | Button | Function | Wellbeing Effect |
|---|---|---|---|
| Forward (P13) | ⬆️ | goRun() — hearts, chase music, random driving |
+10 |
| Reverse (P14) | ⬇️ | goSleep() — lullaby, asleep face |
+20 |
| Right turn (P15) | ↪️ | textFriend() — says hello, little dance, heart |
+15 |
| Stop (P9) | ⏹️ | scrollSocialMedia() — flashing text, noisy |
-15 |
| Left turn (P16) | ↩️ | playGame() — dodge the wall, A/B to move |
+1 per wave, -10 on game over |
| Play (P8) | ▶️ | seekFriend() — radio hello to nearby pets |
+5 |
| Menu (P5) | ⚪ | showStats() — shows wellbeing as a number |
— |
| Screen face-down | — | Wake up animation | — |
| Radio received | — | Giggle + react to a friend’s hello | +20 |
Code
function showStats () {
busy = true
basic.showNumber(wellbeing)
basic.pause(3000)
basic.clearScreen()
busy = false
}
function goRun () {
busy = true
for (let index = 0; index < 2; index++) {
basic.showIcon(IconNames.Heart)
basic.pause(500)
basic.showIcon(IconNames.SmallHeart)
basic.pause(500)
}
music.play(music.builtInPlayableMelody(Melodies.Chase), music.PlaybackMode.InBackground)
for (let index = 0; index < 4; index++) {
roversa.driveForwards(randint(500, 1500))
if (Math.randomBoolean()) {
roversa.right()
} else {
roversa.left()
}
}
music.stopAllSounds()
changeWellbeing(10)
busy = false
}
function scrollSocialMedia () {
busy = true
texts = [
"Like!",
"50% OFF",
"Follow!",
"Share!",
"LOL",
"OMG",
"VIRAL!"
]
for (let index = 0; index < 2; index++) {
music.play(music.builtInPlayableMelody(Melodies.BaDing), music.PlaybackMode.UntilDone)
basic.showString("" + (texts[randint(0, texts.length - 1)]))
}
basic.clearScreen()
changeWellbeing(-15)
busy = false
}
input.onButtonPressed(Button.A, function () {
if (gameRunning && birdX > 0) {
birdX += -1
}
})
roversa.onEvent(RoversaPin.P16, RoversaEvent.Click, function () {
playGame()
})
roversa.onEvent(RoversaPin.P9, RoversaEvent.Click, function () {
scrollSocialMedia()
})
function changeWellbeing (amount: number) {
wellbeing = Math.constrain(wellbeing + amount, 0, 100)
}
function goSleep (sleeping: boolean) {
busy = true
for (let index = 0; index < 2; index++) {
basic.showLeds(`
. . . . .
. # . # .
. . . . .
. # # # .
. . . . .
`)
basic.pause(400)
basic.showIcon(IconNames.Asleep)
basic.pause(400)
}
music.play(music.builtInPlayableMelody(Melodies.Blues), music.PlaybackMode.InBackground)
changeWellbeing(20)
basic.showIcon(IconNames.Asleep)
basic.pause(5000)
busy = false
}
function seekFriend () {
busy = true
for (let index = 0; index < 3; index++) {
basic.showIcon(IconNames.Heart)
basic.pause(300)
basic.showIcon(IconNames.QuarterNote)
basic.pause(300)
}
radio.sendString("hey!")
basic.showIcon(IconNames.Target)
basic.pause(1000)
basic.clearScreen()
changeWellbeing(5)
busy = false
}
roversa.onEvent(RoversaPin.P13, RoversaEvent.Click, function () {
goRun()
})
function playGame () {
busy = true
gameRunning = true
birdX = 2
obstacleY = 4
gapX = randint(0, 4)
while (gameRunning) {
basic.clearScreen()
led.plot(birdX, 0)
for (let x = 0; x <= 4; x++) {
if (x != gapX) {
led.plot(x, obstacleY)
}
}
basic.pause(700)
obstacleY += -1
if (obstacleY == 0) {
if (birdX != gapX) {
gameRunning = false
basic.clearScreen()
basic.showString("GAME OVER")
changeWellbeing(-10)
} else {
changeWellbeing(1)
obstacleY = 4
gapX = randint(0, 4)
}
}
}
basic.clearScreen()
busy = false
}
function textFriend () {
busy = true
basic.showString("Hello!")
roversa.turnRight(45)
roversa.backward()
roversa.turnLeft(45)
basic.showString(". . .")
music.play(music.builtInPlayableMelody(Melodies.Ringtone), music.PlaybackMode.InBackground)
basic.showIcon(IconNames.Heart)
basic.pause(2000)
music.stopAllSounds()
changeWellbeing(15)
busy = false
}
input.onGesture(Gesture.ScreenDown, function () {
for (let index = 0; index < 2; index++) {
basic.showLeds(`
. . . . .
. # . # .
. . . . .
. # # # .
. . . . .
`)
basic.pause(400)
basic.showIcon(IconNames.Asleep)
basic.pause(400)
}
sleeping = false
})
radio.onReceivedString(function (receivedString) {
if (!(busy)) {
busy = true
music.play(music.builtinPlayableSoundEffect(soundExpression.giggle), music.PlaybackMode.UntilDone)
basic.showIcon(IconNames.Rabbit)
changeWellbeing(20)
basic.pause(2000)
basic.clearScreen()
busy = false
}
})
input.onButtonPressed(Button.B, function () {
if (gameRunning && birdX < 4) {
birdX += 1
}
})
roversa.onEvent(RoversaPin.P14, RoversaEvent.Click, function () {
sleeping = true
goSleep(sleeping)
})
roversa.onEvent(RoversaPin.P8, RoversaEvent.Click, function () {
if (gameRunning == false) {
seekFriend()
}
})
roversa.onEvent(RoversaPin.P5, RoversaEvent.Click, function () {
showStats()
})
roversa.onEvent(RoversaPin.P15, RoversaEvent.Click, function () {
textFriend()
})
function showFace () {
if (sleeping) {
basic.showIcon(IconNames.Asleep)
} else {
if (wellbeing < 20) {
basic.showIcon(IconNames.Angry)
} else if (wellbeing < 50) {
basic.showIcon(IconNames.Sad)
} else if (wellbeing < 75) {
basic.showLeds(`
. . . . .
. # . # .
. . . . .
. . . . #
. # # # .
`)
} else {
basic.showIcon(IconNames.Fabulous)
}
}
}
let sleeping = false
let gapX = 0
let gameRunning = false
let texts: string[] = []
let busy = false
let obstacleY = 0
let birdX = 0
let wellbeing = 0
wellbeing = 50
birdX = 2
obstacleY = 4
radio.setGroup(1)
wellbeing = 50
showFace()
basic.forever(function () {
if (!(busy)) {
showFace()
changeWellbeing(-1)
}
basic.pause(2000)
})
Learning Goals
- See how a virtual pet is built from standard MakeCode blocks — no hidden extension code
- Understand the wellbeing system: how activities change the score and how the face reflects it
- Modify and extend behaviors: copy a function, change the icons/sounds/moves, wire it to a button
- Learn event-driven programming, state management, and the idle loop pattern
Concepts Covered
- Variables and state (
wellbeing,busy,sleeping,gameRunning) - Functions for organizing behaviors
- Event handlers (button presses, gestures, radio)
- Conditional logic (face thresholds, game collision)
- Radio communication between micro:bits
- Constrained values (
Math.constrainfor 0–100 range)