Stick champ game
Here's the code of our little game where our champ uses a stick to jump over stones (detailed explanation below):
| <html> |
| <body> |
| <canvas id="myCanvas" width="600" height="500" style='position:absolute; left:0;'></canvas> |
| <script> |
| let canvas = document.getElementById("myCanvas"); |
| let context = canvas.getContext("2d"); |
| context.font = 'bold 30px sans-serif'; |
| context.lineWidth = 4; |
| let image = new Image(); |
| image.src = "sprite.png"; |
| const maxStones = 6, size = 40; |
| let angle = -Math.PI / 2; |
| let x, y, frame, currentStone, mode, run, offset, stickLength, stones; |
| |
| function reset() { |
| currentStone = 0; |
| x = 100; |
| y = 360; |
| frame = 0; |
| stones = []; |
| stickLength = 0; |
| offset = 0; |
| run = 0; |
| for (let i = 0; i < maxStones; i++) { |
| stones[i] = { |
| x: i * 300 + Math.floor(Math.random() * 80), |
| width: 50 + Math.floor(Math.random() * 50) |
| }; |
| } |
| stones[0].x = 80; |
| mode = 'wait'; |
| } |
| |
| function animate() { |
| context.clearRect(0, 0, canvas.width, canvas.height); |
| context.fillText('Distance remaining: ' + (maxStones - currentStone - 1), 250, 100); |
| stones.forEach((stone)=>{ |
| context.fillRect(stone.x - offset, 398, stone.width, 600); |
| } |
| ); |
| |
| context.drawImage(image, Math.floor(frame) * size, 0, size, size, x + size / 2, y, size, size); |
| switch (mode) { |
| case 'pointerdown': |
| stickLength++; |
| break; |
| case 'stickFall': |
| angle = angle + Math.PI / 64; |
| if (angle >= 0) |
| mode = 'run'; |
| break; |
| case 'run': |
| offset++; |
| run++; |
| frame = frame + .5; |
| if (frame == 20) |
| frame = 0; |
| if (stickLength == run) { |
| mode = 'wait'; |
| angle = -Math.PI / 2; |
| stickLength = 0; |
| run = 0; |
| let gameOver = true; |
| stones.forEach((stone,index)=>{ |
| if (offset + x + size > stone.x && offset + x < stone.x + stone.width - size) { |
| gameOver = false; |
| currentStone = Math.max(currentStone, index); |
| if (currentStone == maxStones - 1) { |
| mode = 'gameOver'; |
| frame = 21; |
| } |
| } |
| } |
| ); |
| if (gameOver) { |
| mode = 'gameOver'; |
| frame = 20; |
| } |
| } |
| break; |
| case 'gameOver': |
| if (currentStone < maxStones - 1) { |
| y++; |
| context.fillText('Game over. Click to restart', 20, 60); |
| } else |
| context.fillText('You win! Click to restart', 20, 60); |
| } |
| let x2 = x + (stickLength - run) * Math.cos(angle); |
| let y2 = y + (stickLength - run) * Math.sin(angle); |
| context.beginPath(); |
| context.moveTo(x + size - run, y + size); |
| context.lineTo(x2 + size, y2 + size); |
| context.stroke(); |
| window.requestAnimationFrame(animate); |
| } |
| |
| window.onpointerdown = function() { |
| switch (mode) { |
| case 'wait': |
| mode = 'pointerdown'; |
| break; |
| case 'gameOver': |
| mode = 'wait'; |
| reset(); |
| } |
| }; |
| |
| window.onpointerup = function() { |
| if (mode == 'pointerdown') |
| mode = 'stickFall'; |
| }; |
| reset(); |
| animate(); |
| </script> |
| </body> |
| </html> |
Lines [1-8] set up the HTML5 Canvas and the 2d context
[9-10] invisible image that holds the spritesheet (20 frames of run sequence, 1 fall, 1 celebration):

[11-13] Declare game variables and constants:
[11] maximum number of stones (=distance to be covered), size of the sprite (40x40 pixels)
[12] initial angle of the stick - it goes straight up
[13] x - x coordinate of the champ
y - y coordinate of the top of the stick
frame - current animation frame
currentStone - how many stones have been reached
mode - game mode (wait/pointerdown/stickFall/gameOver)
run - the length of the current run
offset - the horizontal scroll offset of screen
stickLength - the current extension of the stick
stones - array of stone objects
[15-32] reset all variables to initial values
[24-29] randomize stone positions and widths
[34-96] main game loop:
[35] clear the frame
[36] show the remaining distance on the screen
[37-40] draw the stones (even if they don't fit on the screen - to keep things simple)
[42] draw the current animation frame of the sprite
If you need details about
how drawImage works, click here
[44-46] if the pointer (mouse/touch) is pressed, increase the stick length
[47-51] if the stick is falling, increase the angle.
[49-50] if it fell all the way down, change game mode to "run"
[52-80] if we're in the 'run' mode:
[53-54] increase the offset and the length of the run
[55] sprite frame changes every 2 animation frames
[56-57] if we reached the end of the animation sequence in the spritesheet, go back to the beginning
[58-62] if the length of the run equals the end of the stick, reset the stick length, angle, run and switch to 'wait' mode
[63-74] check if we landed on the stone:
[63] assume we landed on an empty space
[64-65] compare the champ coordinates with each stone
[66] if the champ landed on a stone, correct the pessimistic assumption from [63]
[67] calculate the currentStone
[68-71] if the last stone was reached, you win!
[75-78] if the champ landed on an empty space, switch mode to gameOver and show the falling pose
[81-87] in the 'gameOver' mode:
[82-84] if you lost, you fall
[85-86] if you won, you won.
[88-89] calculate the coords of the end of the stick
[90-93] draw the stick
[94] trigger the next animation frame
[97-107] if the screen is clicked/touched:
[98-101] if we were waiting, we switch to the 'pointerdown' mode
[102-105] if we were in the 'gameOver' mode, the game is restarted
[108-111] if the pointer is released and we were in the 'pointerdown' mode, we switch to the 'stickFall' mode
[112] initiate the game
[113] start the animation
Enjoy the game!
Check out these programming tutorials:
JavaScript:
Goldmine - idle game (~200 lines)
Tunnel run game (~170 lines)
Tower game (84 lines)
Optical illusion (18 lines)
Spinning squares - visual effect (25 lines)
Oldschool fire effect (20 lines)
Fireworks (60 lines)
Animated fractal (32 lines)
Physics engine for beginners
Physics engine - interactive sandbox
Physics engine - silly contraption
Starfield (21 lines)
Yin Yang with a twist (4 circles and 20 lines)
Tile map editor (70 lines)
Sine scroller (30 lines)
Interactive animated sprites
Image transition effect (16 lines)
Your first program in JavaScript: you need 5 minutes and a notepad
Fractals in Excel
Python in Blender 3d:
Domino effect (10 lines)
Wrecking ball effect (14 lines)
3d fractal in Blender Python