6. gyakorlat - Platformjáték canvasen MI ágenssel
In class you watched a pixel-art platformer get built on a <canvas>, first by hand and then by directing a coding agent. Now build it yourself. Type the game loop in a by hand. From b onward, an agent writes the code and you decide what it builds: write the prompt, read the plan before approving it, run the result, and read the diff. The slides are at /en/slides/canvas-platformer.
Any coding agent works: Antigravity (used in class), GitHub Copilot, Claude Code, or similar. The starter’s AGENTS.md holds the rules the agent must follow, and assets/ASSETS.md lists every sprite index, so the agent does not have to guess coordinates. Open a fresh agent conversation in the starter folder so it reads AGENTS.md.
Open index.html with Live Server and keep the browser Console open. Have Python 3 installed too: agents use it for their own helper scripts. Put the folder under Git and commit after every checkpoint, so you can roll back when the agent breaks something. Canvas is not exam material; the point is to learn the game loop and practise directing an agent.
Kezdőcsomag
A feladatleírás és a kezdőfájlok helyi munkához előkészítve.
Tartalmazott fájlok: AGENTS.mdassets/ASSETS.mdassets/tilemap_packed.pngassets/tilemap-backgrounds_packed.pngassets/tilemap-characters_packed.pngindex.htmlscript.js
Feladatok
Do this one without the agent. script.js already selects the canvas and its 2D context. Add a state object with a box, an update(dt) that moves the box right and wraps it back to the left edge, a draw() that clears the canvas and fills the box, and a gameLoop() that measures dt with performance.now(), calls update(dt) and draw(), and schedules itself with requestAnimationFrame.
Hint: Store the speed in px/ms and move by vx * dt, not by a fixed number per frame. Put if (dt > 100) return; at the top of update so a hidden tab does not make the box jump. Leave out clearRect once and watch what happens.
Checkpoint: The box crosses the screen and wraps around. Without clearRect it smears into a bar; with it, it is a clean box. Its speed does not depend on the monitor’s refresh rate.
Ask the agent to replace the box with a 36×48 rectangle player on a flat floor. The arrow keys move it, Space or Up jumps, and gravity pulls it down. Pressed keys go in a keys object updated by keydown/keyup and read inside update(dt).
Prompt idea: Replace the moving box with a player: a 36x48 rectangle on a flat floor. Left/right arrows move it, Space or Up jumps, gravity pulls it down. Track pressed keys in a keys object and read it in update(dt). Only allow jumping on the ground.
Checkpoint: Holding an arrow moves the player smoothly. Jumping only works on the ground, so holding Space in the air does nothing. Space does not scroll the page. If the jump feels floaty, change the gravity and jump constants yourself.
Design a level as an array of strings: # for solid ground, . for empty, P for the player’s start. Add at least one platform, one wall and one pit. Ask the agent to draw solid tiles as rectangles (54×54 on screen) and to make the player collide with them on every side.
Hint: Ask for horizontal and vertical movement to be resolved separately. Otherwise, moving diagonally into a corner gives no way to tell a wall from a floor. Math.floor(x / TILE) turns a pixel position into a column of level[row]. That is the same grid idea as the Pixel Art Editor’s pixels.
Checkpoint: The player lands on platforms, bumps its head on ceilings, and stops at walls. Holding right against a wall in mid-air does not stick to it. Falling into a pit does not crash the game. If you find a bug, report it to the agent precisely: what you did, what you expected, what happened.
Ask the agent to replace the rectangles with sprites from assets/, using the file names, frame sizes and indices in assets/ASSETS.md. Pixel art is drawn at 3× scale: 18×18 tiles become 54×54 and 24×24 character frames become 72×72. The walk cycle animates while the player moves.
Hint: Use the 9-argument drawImage (source rectangle, then destination rectangle). Images load asynchronously, so start the loop only after every image has loaded. All characters face left: mirror the sprite with ctx.save(), ctx.scale(-1, 1) and ctx.restore() when the player moves right. Time the walk frames with dt, not once per frame.
Checkpoint: The art is crisp, not blurry (ctx.imageSmoothingEnabled = false). The player faces the way it walks, the walk cycle runs at the same speed on any monitor, and the sprite’s feet touch the ground.
Make the level about three screens wide and ask for a camera that follows the player horizontally. It is drawn with ctx.translate inside save/restore in draw().
Hint: The player’s x stays a world coordinate; only the drawing shifts. Clamp the camera so it never shows past the level’s edges, and skip tiles that are off screen.
Checkpoint: Walking right scrolls the level smoothly. At either end of the level the camera stops and the player walks toward the screen’s edge. Collision still works everywhere.
Add coins as c characters in the level strings, drawn with the coin sprite. When the player overlaps a coin, it disappears and state.score grows by 1. The score is drawn with fillText in the top-left corner.
Hint: Overlap is a rectangle test on both axes (AABB). Ask yourself first whether the score must be drawn inside or outside the camera’s save/restore.
Checkpoint: Each coin counts once. The score stays fixed in the corner while the level scrolls.
Add an enemy as e in the level strings, drawn with the crawler frames from ASSETS.md. It walks back and forth and turns around at walls and at platform edges. Touching it from the side restarts the level; landing on its head removes it and bounces the player up.
Hint: Before you send the prompt, try a vague one (add enemies) and read the plan without approving it. Count every decision the agent had to guess, then cancel it and write a precise prompt instead.
Checkpoint: The enemy never walks off a platform or into a wall. A stomp removes it and bounces the player; a side hit restarts the level with every coin back.
Követelmények
- Vanilla JavaScript, HTML and CSS only: no libraries, game engines, npm or ES modules. Keep the 960×540 canvas size set in HTML.
- Follow
AGENTS.md: all game data in onestateobject, logic inupdate(dt), drawing indraw(), the loop ingameLoop()withrequestAnimationFrame, and tunable numbers asUPPER_CASEconstants. - All movement and animation use
dt. Pixel art is drawn at 3× with image smoothing off. - Use only the sprites in
assets/, with indices fromassets/ASSETS.md. - Commit after each checkpoint. You must be able to explain every line the agent wrote; ask it to explain anything you cannot.
- The game should run without Console errors.