- Difficulty
- Advanced
- Build time
- 120-180 min
- Estimated cost
- $0
- Age range
- 12-18
- Workspace
- A computer or tablet workspace
The finish line
What you will build
The game loads one original tilemap, supports walking and grounded jumps, collects coins once, handles hazards, and reaches a win state.
Learning goals
- Identify how left, right, and jump button events produces player motion, score, lives, and level completion.
- Construct and explain a digital input-to-velocity-based sprite motion system.
- Measure how jump velocity changes performance.
- Diagnose losses caused by frame-rate assumptions and double jumps.
Before you build
Materials, tools, and safety
Reuse-material cost: $0-$3 with reused materials. Supervision: Adult help recommended for sharp or heated tools.
Tools
- Computer or tablet
- Web browser or offline editor
- Notebook for test results
Low-cost swaps
- Use the platform's offline editor when internet access is limited.
- Storyboard the logic with cards and arrows before opening the coding tool.
- Use the MakeCode Arcade offline app and keyboard-only controls.
Project-specific safety
- Use a teacher, parent, or guardian account where the platform requires an adult.
- Do not publish student names, locations, or personal contact details inside a project.
- Use approved accounts, do not include personal information, and take screen and hand breaks during longer coding sessions.
Orient the build
Treat the screen origin and stage edges as fixed references. The control that creates left, right, and jump button events is the input side; the sprite, score, or display that produces player motion, score, lives, and level completion is the output side.
Build it
Step-by-step instructions
Step 1
Plan the level
Draw start, platforms, five coins, two hazards, and goal on grid paper.
Ensure every required jump is possible.
Step 2
Create player physics
Make the sprite, set horizontal controller movement, and apply downward acceleration.
Keep speed values in named constants.
Step 3
Build the tilemap
Draw original solid ground, empty space, hazard, and goal tiles.
Place player at the start marker.
Builder checkpoint: After build the tilemap, the first subassembly should stay aligned when handled gently.
Step 4
Add grounded jumping
On jump press, change vertical velocity only when the player hits a wall below.
Prevent air jumps.
Watch for: If this stage binds or drifts, inspect duplicate overlap events before adding more parts.
Step 5
Program coins
Create coin sprites at marked tiles and destroy each on overlap after scoring.
Use one event handler.
Step 6
Handle hazards
On hazard overlap, reduce life, move to checkpoint, and briefly protect from repeat damage.
End at zero lives.
Builder checkpoint: After handle hazards, operate the build slowly and confirm that player motion, score, lives, and level completion begins without binding.
Step 7
Add the goal
Require all five coins before the goal wins; otherwise show remaining count.
Stop movement after win.
Step 8
Test edge cases
Try jumping under platforms, touching a hazard continuously, revisiting coins, and restarting.
Fix one state bug at a time.
Builder checkpoint: At the final checkpoint, The game loads one original tilemap, supports walking and grounded jumps, collects coins once, handles hazards, and reaches a win state.
See the engineering
Why it works
- Input
- left, right, and jump button events
- Output
- player motion, score, lives, and level completion
- Motion
- digital input-to-velocity-based sprite motion
- Energy losses
- frame-rate assumptions, double jumps, tile-edge collisions, duplicate overlap events
Why this works
Discrete game physics
The engine updates velocity and position each frame, then resolves collisions with solid tiles. A grounded test allows jumps only when the player is standing on a floor tile.
Look for: Display vertical velocity while jumping and note where it crosses zero at the top of the arc.
Where the energy goes
Efficiency and losses
The ideal model leaves out frame-rate assumptions, double jumps, tile-edge collisions, duplicate overlap events. These effects turn some input energy into heat, sound, vibration, or unwanted motion, so measured performance will be lower than an ideal calculation.
Look for: Run the build slowly and locate the first place where frame-rate assumptions becomes visible or audible.
Math bite
Estimate jump time
Formula: time to peak = initial upward speed / gravity
- Upward speed magnitude = 150 px/s
- Gravity = 400 px/s²
Substitute: time = 150 / 400 = 0.375 s
Result: The player reaches the ideal jump peak after about 0.38 seconds.
Total airtime is roughly twice that when landing at the same height.
The tile engine resolves motion in discrete frames and collisions alter the path.makecode_platformer.ts
A complete MakeCode Arcade TypeScript project using built-in tilemaps and sprite events; replace the sample tilemap literals with original editor-created tiles at the same named locations.
namespace SpriteKind { export const Coin = SpriteKind.create() }
const MOVE_SPEED=90, JUMP_SPEED=-150, GRAVITY=400, TOTAL_COINS=5
let collected=0, invulnerable=false
const player=sprites.create(img` . . . . 8 8 8 8 . . . . . . . .
. . 8 8 9 9 9 9 8 8 . . . . . .
. . 8 9 9 8 8 9 9 8 . . . . . .
. . 8 9 9 9 9 9 9 8 . . . . . .
. . . 8 9 9 9 9 8 . . . . . . .
. . 8 8 8 8 8 8 8 8 . . . . . .
. 8 8 . 8 8 8 8 . 8 8 . . . . .
. . . . 8 . . 8 . . . . . . . .`,SpriteKind.Player)
controller.moveSprite(player,MOVE_SPEED,0); player.ay=GRAVITY; scene.cameraFollowSprite(player); info.setLife(3)
tiles.setCurrentTilemap(tilemap`level1`); tiles.placeOnRandomTile(player,assets.tile`start`); tiles.setTileAt(player.tilemapLocation(),assets.tile`transparent`)
for(let i=0;i<TOTAL_COINS;i++){ const coin=sprites.create(img` . 5 5 . / 5 4 4 5 / 5 4 4 5 / . 5 5 .`,SpriteKind.Coin); tiles.placeOnRandomTile(coin,assets.tile`coinSpot`) }
controller.A.onEvent(ControllerButtonEvent.Pressed,()=>{ if(player.isHittingTile(CollisionDirection.Bottom)) player.vy=JUMP_SPEED })
sprites.onOverlap(SpriteKind.Player,SpriteKind.Coin,(hero,coin)=>{ coin.destroy(effects.spray,100); collected++; info.changeScoreBy(1) })
scene.onOverlapTile(SpriteKind.Player,assets.tile`hazard`,sprite=>{ if(invulnerable)return; invulnerable=true; info.changeLifeBy(-1); tiles.placeOnRandomTile(sprite,assets.tile`checkpoint`); timer.after(1000,()=>invulnerable=false) })
scene.onOverlapTile(SpriteKind.Player,assets.tile`goal`,()=>{ if(collected>=TOTAL_COINS) game.over(true,effects.confetti); else player.sayText((TOTAL_COINS-collected)+" coins left",700) })
Make it behave
Test, troubleshoot, and tune
Controlled test
Start here: Verify walking and one grounded jump in an empty test room before loading the full level.
Success looks like: The complete level supports all required events and restarts with score and lives reset.
Measure: Jump success, duplicate coin events, hazard repeats, completion state, and restart state.
Change: jump velocity
Keep constant: tilemap, gravity, horizontal speed, controls, coin count, and test route
- lower jump
- baseline jump
- higher safe jump
| Symptom | Likely cause | Confirm it | Fix |
|---|---|---|---|
| Player can double jump | Grounded condition is missing or always true | Press jump repeatedly in air | Check collision below before setting velocity |
| Coins score twice | Sprite is not destroyed immediately | Pause on one overlap | Destroy before any delayed effect |
| Hazard removes all lives | Overlap repeats every frame | Stand on hazard during test | Move to checkpoint and add invulnerability time |
| Goal wins early | Coin requirement is not checked | Reach goal with zero coins | Compare score with total before game over win |
Choose your tradeoff
Tune gravity and jump velocity together. A higher jump reaches more tiles but can reduce control and make ceilings or hazards easier to bypass.
Keep experimenting
Try another version
Practice level
Remove hazards and require three coins.
Time trial
Add a timer without changing physics.
Moving platforms
Create controlled platform motion and safe rider behavior.
Build together
Classroom and access options
Classroom version
Teams can compare jump velocity while keeping tilemap, gravity, horizontal speed, controls, coin count, and test route. Assign builder, tester, recorder, and explainer roles; have each team predict the result before collecting three trials.
Access adaptations
- Use keyboard-accessible controls and high-contrast sprites or interface elements.
- Pair a navigator who reads instructions with a driver who enters blocks or code.
- Use high-contrast tiles, remappable controls, forgiving jump speed, and an optional no-hazard practice mode.
Reflect on the design
- How did jump velocity change the measured result?
- Where did frame-rate assumptions affect the build most strongly?
- What evidence shows that discrete game physics explains the motion?
- Which change would improve player motion, score, lives, and level completion without creating a new problem?
Glossary
- Discrete game physics
- The engine updates velocity and position each frame, then resolves collisions with solid tiles.
- Input
- The action or energy supplied to a system; here it is left, right, and jump button events.
- Output
- The useful response produced by a system; here it is player motion, score, lives, and level completion.
- Efficiency
- The fraction of input energy that becomes useful output instead of friction, sound, heat, or unwanted motion.
Build your dreams
One build can start the next.
Share what you learned, change one variable, and help another builder understand what worked.
Explore more guidesSources and build notes
A platform-appropriate educational coding project with original logic and instruction.
- Programming project basis: A platform-appropriate educational project with complete logic, setup instructions, debugging, and original examples.
Written and edited by BrickLabClips. Published 2026-07-22; updated 2026-07-22.

