Click and hold on the blue box to raise the stick



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="myCanvaswidth="600height="500style='position:absoluteleft: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 = 6size = 40;
let angle = -Math.PI / 2;
let xyframecurrentStonemoderunoffsetstickLengthstones;
 
function reset() {
    currentStone = 0;
    x = 100;
    y = 360;
    frame = 0;
    stones = [];
    stickLength = 0;
    offset = 0;
    run = 0;
    for (let i = 0i < maxStonesi++) {
        stones[i] = {
            xi * 300 + Math.floor(Math.random() * 80),
            width50 + Math.floor(Math.random() * 50)
        };
    }
    stones[0].x = 80;
    mode = 'wait';
}
 
function animate() {
    context.clearRect(00canvas.widthcanvas.height);
    context.fillText('Distance remaining: ' + (maxStones - currentStone - 1), 250100);
    stones.forEach((stone)=>{
        context.fillRect(stone.x - offset398stone.width600);
    }
    );
 
    context.drawImage(imageMath.floor(frame) * size0sizesizex + size / 2ysizesize);
    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(currentStoneindex);
                    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 overClick to restart', 2060);
        } else
            context.fillText('You winClick to restart', 2060);
    }
    let x2 = x + (stickLength - run) * Math.cos(angle);
    let y2 = y + (stickLength - run) * Math.sin(angle);
    context.beginPath();
    context.moveTo(x + size - runy + 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




GitHub repo
All the code is provided under the MIT license