Skip to content

Instantly share code, notes, and snippets.

@straker
Last active December 13, 2024 17:10
Show Gist options
  • Save straker/ff00b4b49669ad3dec890306d348adc4 to your computer and use it in GitHub Desktop.
Save straker/ff00b4b49669ad3dec890306d348adc4 to your computer and use it in GitHub Desktop.
Basic Snake HTML and JavaScript Game

Basic Snake HTML and JavaScript Game

Snake is a fun game to make as it doesn't require a lot of code (less than 100 lines with all comments removed). This is a basic implementation of the snake game, but it's missing a few things intentionally and they're left as further exploration for the reader.

Further Exploration

  • Score
    • When the snake eats an apple, the score should increase by one. Use context.fillText() to display the score to the screen
  • Mobile and touchscreen support
  • Better apple spawning
    • Currently the apple spawns in any random grid in the game, even if the snake is already on that spot. Improve it so it only spawns in empty grid locations

Important note: I will answer questions about the code but will not add more features or answer questions about adding more features. This series is meant to give a basic outline of the game but nothing more.

License

(CC0 1.0 Universal) You're free to use this game and code in any project, personal or commercial. There's no need to ask permission before using these. Giving attribution is not required, but appreciated.

Other Basic Games

Support

Basic HTML Games are made possible by users like you. When you become a Patron, you get access to behind the scenes development logs, the ability to vote on which games I work on next, and early access to the next Basic HTML Game.

Top Patrons

  • Karar Al-Remahy
  • UnbrandedTech
  • Innkeeper Games
  • Nezteb
<!DOCTYPE html>
<html>
<head>
<title>Basic Snake HTML Game</title>
<meta charset="UTF-8">
<style>
html, body {
height: 100%;
margin: 0;
}
body {
background: black;
display: flex;
align-items: center;
justify-content: center;
}
canvas {
border: 1px solid white;
}
</style>
</head>
<body>
<canvas width="400" height="400" id="game"></canvas>
<script>
var canvas = document.getElementById('game');
var context = canvas.getContext('2d');
// the canvas width & height, snake x & y, and the apple x & y, all need to be a multiples of the grid size in order for collision detection to work
// (e.g. 16 * 25 = 400)
var grid = 16;
var count = 0;
var snake = {
x: 160,
y: 160,
// snake velocity. moves one grid length every frame in either the x or y direction
dx: grid,
dy: 0,
// keep track of all grids the snake body occupies
cells: [],
// length of the snake. grows when eating an apple
maxCells: 4
};
var apple = {
x: 320,
y: 320
};
// get random whole numbers in a specific range
// @see https://stackoverflow.com/a/1527820/2124254
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
// game loop
function loop() {
requestAnimationFrame(loop);
// slow game loop to 15 fps instead of 60 (60/15 = 4)
if (++count < 4) {
return;
}
count = 0;
context.clearRect(0,0,canvas.width,canvas.height);
// move snake by it's velocity
snake.x += snake.dx;
snake.y += snake.dy;
// wrap snake position horizontally on edge of screen
if (snake.x < 0) {
snake.x = canvas.width - grid;
}
else if (snake.x >= canvas.width) {
snake.x = 0;
}
// wrap snake position vertically on edge of screen
if (snake.y < 0) {
snake.y = canvas.height - grid;
}
else if (snake.y >= canvas.height) {
snake.y = 0;
}
// keep track of where snake has been. front of the array is always the head
snake.cells.unshift({x: snake.x, y: snake.y});
// remove cells as we move away from them
if (snake.cells.length > snake.maxCells) {
snake.cells.pop();
}
// draw apple
context.fillStyle = 'red';
context.fillRect(apple.x, apple.y, grid-1, grid-1);
// draw snake one cell at a time
context.fillStyle = 'green';
snake.cells.forEach(function(cell, index) {
// drawing 1 px smaller than the grid creates a grid effect in the snake body so you can see how long it is
context.fillRect(cell.x, cell.y, grid-1, grid-1);
// snake ate apple
if (cell.x === apple.x && cell.y === apple.y) {
snake.maxCells++;
// canvas is 400x400 which is 25x25 grids
apple.x = getRandomInt(0, 25) * grid;
apple.y = getRandomInt(0, 25) * grid;
}
// check collision with all cells after this one (modified bubble sort)
for (var i = index + 1; i < snake.cells.length; i++) {
// snake occupies same space as a body part. reset game
if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y) {
snake.x = 160;
snake.y = 160;
snake.cells = [];
snake.maxCells = 4;
snake.dx = grid;
snake.dy = 0;
apple.x = getRandomInt(0, 25) * grid;
apple.y = getRandomInt(0, 25) * grid;
}
}
});
}
// listen to keyboard events to move the snake
document.addEventListener('keydown', function(e) {
// prevent snake from backtracking on itself by checking that it's
// not already moving on the same axis (pressing left while moving
// left won't do anything, and pressing right while moving left
// shouldn't let you collide with your own body)
// left arrow key
if (e.which === 37 && snake.dx === 0) {
snake.dx = -grid;
snake.dy = 0;
}
// up arrow key
else if (e.which === 38 && snake.dy === 0) {
snake.dy = -grid;
snake.dx = 0;
}
// right arrow key
else if (e.which === 39 && snake.dx === 0) {
snake.dx = grid;
snake.dy = 0;
}
// down arrow key
else if (e.which === 40 && snake.dy === 0) {
snake.dy = grid;
snake.dx = 0;
}
});
// start the game
requestAnimationFrame(loop);
</script>
</body>
</html>
@maddyapk
Copy link

maddyapk commented Mar 2, 2024

So I kinda migrated it to a nextjs typescript project and added a touch screen support , also added a score function.. just basic level modifications

// app/components/SnakeGame.tsx
import React, { useEffect, useRef, useState } from 'react';

interface SnakeGameProps {
    onValueChange: (newValue: number) => void;
}

const SnakeGame: React.FC<SnakeGameProps> = ({ onValueChange }) => {
    let gameOver = false;
    const [go, setGo] = useState(false);
    const scoreRef = useRef(0);
    const grid = 20;
    let count = 0;

    function getRandomInt(min: number, max: number): number {
        return Math.floor(Math.random() * (max - min)) + min;
    }

    useEffect(() => {
        interface Snake {
            x: number;
            y: number;
            dx: number;
            dy: number;
            cells: Array<{ x: number; y: number }>;
            maxCells: number;
        }

        const snake: Snake = {
            x: 160,
            y: 160,
            dx: grid,
            dy: 0,
            cells: [],
            maxCells: 4,
        };
        const apple = {
            x: 60,
            y: 60,
        };

        function loop() {
            requestAnimationFrame(loop);
            if (!go) {
                if (++count < 20) {
                    return;
                }

                gameOver = false;
                count = 0;
                const canvas = document.getElementById('game') as HTMLCanvasElement;
                const context = canvas.getContext('2d') as CanvasRenderingContext2D;

                context.clearRect(0, 0, canvas.width, canvas.height);

                snake.x += snake.dx;
                snake.y += snake.dy;

                if (snake.x < 0) {
                    snake.x = canvas.width - grid;
                } else if (snake.x >= canvas.width) {
                    snake.x = 0;
                }

                if (snake.y < 0) {
                    snake.y = canvas.height - grid;
                } else if (snake.y >= canvas.height) {
                    snake.y = 0;
                }

                snake.cells.unshift({ x: snake.x, y: snake.y });

                if (snake.cells.length > snake.maxCells) {
                    snake.cells.pop();
                }

                context.fillStyle = 'red';
                context.fillRect(apple.x, apple.y, grid - 1, grid - 1);

                context.fillStyle = 'black';
                snake.cells.forEach(function (cell, index) {
                    context.fillRect(cell.x, cell.y, grid - 1, grid - 1);

                    if (cell.x === apple.x && cell.y === apple.y) {
                        snake.maxCells++;
                        scoreRef.current = scoreRef.current + 1;
                        onValueChange(scoreRef.current);
                        console.log(scoreRef.current);
                        apple.x = getRandomInt(0, 25) * grid;
                        apple.y = getRandomInt(0, 25) * grid;
                    }

                    for (var i = index + 1; i < snake.cells.length; i++) {
                        if (cell.x === snake.cells[i].x && cell.y === snake.cells[i].y) {
                            console.log('Game Over');
                            snake.x = 160;
                            snake.y = 160;
                            snake.cells = [];
                            snake.maxCells = 4;
                            snake.dx = grid;
                            snake.dy = 0;

                            apple.x = getRandomInt(0, 25) * grid;
                            apple.y = getRandomInt(0, 25) * grid;
                            gameOver = true;
                        }
                    }

                    if (gameOver) {
                        setGo(true);
                    }
                });
            }
        }

        const handleKeyDown = (e: KeyboardEvent) => {
            if (e.which === 37 && snake.dx === 0) {
                snake.dx = -grid;
                snake.dy = 0;
            } else if (e.which === 38 && snake.dy === 0) {
                snake.dy = -grid;
                snake.dx = 0;
            } else if (e.which === 39 && snake.dx === 0) {
                snake.dx = grid;
                snake.dy = 0;
            } else if (e.which === 40 && snake.dy === 0) {
                snake.dy = grid;
                snake.dx = 0;
            }
        };

        const handleTouchStart = (e: TouchEvent) => {
            const { clientX, clientY } = e.touches[0];
            const deltaX = clientX - snake.x;
            const deltaY = clientY - snake.y;

            if (Math.abs(deltaX) > Math.abs(deltaY)) {
                // Horizontal swipe
                if (deltaX > 0 && snake.dx === 0) {
                    snake.dx = grid;
                    snake.dy = 0;
                } else if (deltaX < 0 && snake.dx === 0) {
                    snake.dx = -grid;
                    snake.dy = 0;
                }
            } else {
                // Vertical swipe
                if (deltaY > 0 && snake.dy === 0) {
                    snake.dy = grid;
                    snake.dx = 0;
                } else if (deltaY < 0 && snake.dy === 0) {
                    snake.dy = -grid;
                    snake.dx = 0;
                }
            }
        };

        const handleTouchEnd = () => {
            // Handle touch end if needed
        };
        const handleResize = () => {
            const canvas = document.getElementById('game') as HTMLCanvasElement;
            canvas.width = canvas.offsetWidth;
            canvas.height = canvas.offsetHeight;
        };
    
        // Call handleResize once to set initial dimensions
        handleResize();
    
        // Add event listener for window resize
        window.addEventListener('resize', handleResize);

        document.addEventListener('keydown', handleKeyDown);
        document.addEventListener('touchstart', handleTouchStart);
        document.addEventListener('touchend', handleTouchEnd);
        https://progamestuff.com/
        requestAnimationFrame(loop);

        return () => {
            document.removeEventListener('keydown', handleKeyDown);
            document.removeEventListener('touchstart', handleTouchStart);
            document.removeEventListener('touchend', handleTouchEnd);
            window.removeEventListener('resize', handleResize);
        };
    }, [gameOver]);

    const handleRestart = () => {
        setGo(false);
        
        scoreRef.current = 0;
        onValueChange(scoreRef.current);
        localStorage.setItem('score', '0');
    };

    return (
        <div className="flex w-full justify-center items-center bg-white">
            <canvas id="game" width="1000" height="700" className={`bg-[#f8f8f8] ${go ? 'hidden' : ''} `}></canvas>
            {go && (
                <div className={`flex flex-col items-center justify-center w-full h-full text-black text-6xl   ${!go ? 'hidden' : ''}`}>
                    <div className='p-5'>Game Over. </div>
                    <button onClick={handleRestart} className='bg-black rounded-md p-2 text-3xl text-white'>Restart</button>
                </div>
            )}
        </div>
    );
};

export default SnakeGame;

@NothingButTyler
Copy link

Great job @straker!

@surahmulk
Copy link

Thank you for sharing this information, I'm also this in my website and it's work.

@ValodokaGames
Copy link

Great job @straker!

@Musaddik41
Copy link

// Game constants
const CANVAS_WIDTH = 800;
const CANVAS_HEIGHT = 400;
const GRAVITY = 0.5;
const JUMP_FORCE = -10;

// Game class
class ScootyRacingGame {
constructor() {
this.canvas = document.getElementById('gameCanvas');
this.ctx = this.canvas.getContext('2d');
this.canvas.width = CANVAS_WIDTH;
this.canvas.height = CANVAS_HEIGHT;

    this.player = new Player(50, CANVAS_HEIGHT - 50, 30, 50);
    this.level = 1;
    this.distance = 0;
    this.petrol = 100;
    this.coins = 0;
    this.score = 0;
    
    this.obstacles = [];
    this.powerUps = [];
    
    this.keys = {};
    
    this.setupEventListeners();
}

setupEventListeners() {
    document.addEventListener('keydown', (e) => this.keys[e.code] = true);
    document.addEventListener('keyup', (e) => this.keys[e.code] = false);
}

update() {
    this.player.update(this.keys);
    this.updateObstacles();
    this.updatePowerUps();
    this.checkCollisions();
    this.updateGameState();
}

draw() {
    this.ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    this.player.draw(this.ctx);
    this.drawObstacles();
    this.drawPowerUps();
    this.drawUI();
}

updateObstacles() {
    // Add logic to update obstacles
}

updatePowerUps() {
    // Add logic to update power-ups
}

checkCollisions() {
    // Add collision detection logic
}

updateGameState() {
    this.distance += this.player.speed;
    this.petrol -= 0.1;
    this.score = this.distance + this.coins * 10;
    
    if (this.petrol <= 0) {
        this.gameOver();
    }
    
    if (this.distance >= this.getLevelDistance()) {
        this.levelUp();
    }
}

drawObstacles() {
    // Add logic to draw obstacles
}

drawPowerUps() {
    // Add logic to draw power-ups
}

drawUI() {
    this.ctx.fillStyle = 'black';
    this.ctx.font = '16px Arial';
    this.ctx.fillText(`Level: ${this.level}`, 10, 20);
    this.ctx.fillText(`Distance: ${Math.floor(this.distance)}m`, 10, 40);
    this.ctx.fillText(`Petrol: ${Math.floor(this.petrol)}%`, 10, 60);
    this.ctx.fillText(`Coins: ${this.coins}`, 10, 80);
    this.ctx.fillText(`Score: ${this.score}`, 10, 100);
}

gameOver() {
    console.log('Game Over');
    // Add game over logic
}

levelUp() {
    this.level++;
    console.log(`Level up! Now on level ${this.level}`);
    // Add level up logic
}

getLevelDistance() {
    return this.level * 500; // 500m, 1000m, 1500m, etc.
}

gameLoop() {
    this.update();
    this.draw();
    requestAnimationFrame(() => this.gameLoop());
}

start() {
    this.gameLoop();
}

}

// Player class
class Player {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.speed = 0;
this.maxSpeed = 5;
this.acceleration = 0.1;
this.deceleration = 0.05;
this.isJumping = false;
this.jumpVelocity = 0;
}

update(keys) {
    if (keys['ArrowRight']) {
        this.speed = Math.min(this.speed + this.acceleration, this.maxSpeed);
    } else if (keys['ArrowLeft']) {
        this.speed = Math.max(this.speed - this.acceleration, 0);
    } else {
        this.speed = Math.max(this.speed - this.deceleration, 0);
    }
    
    if (keys['Space'] && !this.isJumping) {
        this.jump();
    }
    
    this.x += this.speed;
    
    if (this.isJumping) {
        this.y += this.jumpVelocity;
        this.jumpVelocity += GRAVITY;
        
        if (this.y >= CANVAS_HEIGHT - this.height) {
            this.y = CANVAS_HEIGHT - this.height;
            this.isJumping = false;
            this.jumpVelocity = 0;
        }
    }
}

jump() {
    this.isJumping = true;
    this.jumpVelocity = JUMP_FORCE;
}

draw(ctx) {
    ctx.fillStyle = 'blue';
    ctx.fillRect(this.x, this.y, this.width, this.height);
}

}

// Initialize and start the game
const game = new ScootyRacingGame();
game.start();

@Musaddik41
Copy link

// Game constants
const CANVAS_WIDTH = 800;
const CANVAS_HEIGHT = 400;
const GRAVITY = 0.5;
const JUMP_FORCE = -10;

// Game class
class ScootyRacingGame {
constructor() {
this.canvas = document.getElementById('gameCanvas');
this.ctx = this.canvas.getContext('2d');
this.canvas.width = CANVAS_WIDTH;
this.canvas.height = CANVAS_HEIGHT;

    this.player = new Player(50, CANVAS_HEIGHT - 50, 30, 50);
    this.level = 1;
    this.distance = 0;
    this.petrol = 100;
    this.coins = 0;
    this.score = 0;
    
    this.obstacles = [];
    this.powerUps = [];
    
    this.keys = {};
    
    this.setupEventListeners();
}

setupEventListeners() {
    document.addEventListener('keydown', (e) => this.keys[e.code] = true);
    document.addEventListener('keyup', (e) => this.keys[e.code] = false);
}

update() {
    this.player.update(this.keys);
    this.updateObstacles();
    this.updatePowerUps();
    this.checkCollisions();
    this.updateGameState();
}

draw() {
    this.ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    this.player.draw(this.ctx);
    this.drawObstacles();
    this.drawPowerUps();
    this.drawUI();
}

updateObstacles() {
    // Add logic to update obstacles
}

updatePowerUps() {
    // Add logic to update power-ups
}

checkCollisions() {
    // Add collision detection logic
}

updateGameState() {
    this.distance += this.player.speed;
    this.petrol -= 0.1;
    this.score = this.distance + this.coins * 10;
    
    if (this.petrol <= 0) {
        this.gameOver();
    }
    
    if (this.distance >= this.getLevelDistance()) {
        this.levelUp();
    }
}

drawObstacles() {
    // Add logic to draw obstacles
}

drawPowerUps() {
    // Add logic to draw power-ups
}

drawUI() {
    this.ctx.fillStyle = 'black';
    this.ctx.font = '16px Arial';
    this.ctx.fillText(`Level: ${this.level}`, 10, 20);
    this.ctx.fillText(`Distance: ${Math.floor(this.distance)}m`, 10, 40);
    this.ctx.fillText(`Petrol: ${Math.floor(this.petrol)}%`, 10, 60);
    this.ctx.fillText(`Coins: ${this.coins}`, 10, 80);
    this.ctx.fillText(`Score: ${this.score}`, 10, 100);
}

gameOver() {
    console.log('Game Over');
    // Add game over logic
}

levelUp() {
    this.level++;
    console.log(`Level up! Now on level ${this.level}`);
    // Add level up logic
}

getLevelDistance() {
    return this.level * 500; // 500m, 1000m, 1500m, etc.
}

gameLoop() {
    this.update();
    this.draw();
    requestAnimationFrame(() => this.gameLoop());
}

start() {
    this.gameLoop();
}

}

// Player class
class Player {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.speed = 0;
this.maxSpeed = 5;
this.acceleration = 0.1;
this.deceleration = 0.05;
this.isJumping = false;
this.jumpVelocity = 0;
}

update(keys) {
    if (keys['ArrowRight']) {
        this.speed = Math.min(this.speed + this.acceleration, this.maxSpeed);
    } else if (keys['ArrowLeft']) {
        this.speed = Math.max(this.speed - this.acceleration, 0);
    } else {
        this.speed = Math.max(this.speed - this.deceleration, 0);
    }
    
    if (keys['Space'] && !this.isJumping) {
        this.jump();
    }
    
    this.x += this.speed;
    
    if (this.isJumping) {
        this.y += this.jumpVelocity;
        this.jumpVelocity += GRAVITY;
        
        if (this.y >= CANVAS_HEIGHT - this.height) {
            this.y = CANVAS_HEIGHT - this.height;
            this.isJumping = false;
            this.jumpVelocity = 0;
        }
    }
}

jump() {
    this.isJumping = true;
    this.jumpVelocity = JUMP_FORCE;
}

draw(ctx) {
    ctx.fillStyle = 'blue';
    ctx.fillRect(this.x, this.y, this.width, this.height);
}

}

// Initialize and start the game
const game = new ScootyRacingGame();
game.start();

@Musaddik41
Copy link

// Game constants
const CANVAS_WIDTH = 800;
const CANVAS_HEIGHT = 400;
const GRAVITY = 0.5;
const JUMP_FORCE = -10;

// Game class
class ScootyRacingGame {
constructor() {
this.canvas = document.getElementById('gameCanvas');
this.ctx = this.canvas.getContext('2d');
this.canvas.width = CANVAS_WIDTH;
this.canvas.height = CANVAS_HEIGHT;

    this.player = new Player(50, CANVAS_HEIGHT - 50, 30, 50);
    this.level = 1;
    this.distance = 0;
    this.petrol = 100;
    this.coins = 0;
    this.score = 0;
    
    this.obstacles = [];
    this.powerUps = [];
    
    this.keys = {};
    
    this.setupEventListeners();
}

setupEventListeners() {
    document.addEventListener('keydown', (e) => this.keys[e.code] = true);
    document.addEventListener('keyup', (e) => this.keys[e.code] = false);
}

update() {
    this.player.update(this.keys);
    this.updateObstacles();
    this.updatePowerUps();
    this.checkCollisions();
    this.updateGameState();
}

draw() {
    this.ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    this.player.draw(this.ctx);
    this.drawObstacles();
    this.drawPowerUps();
    this.drawUI();
}

updateObstacles() {
    // Add logic to update obstacles
}

updatePowerUps() {
    // Add logic to update power-ups
}

checkCollisions() {
    // Add collision detection logic
}

updateGameState() {
    this.distance += this.player.speed;
    this.petrol -= 0.1;
    this.score = this.distance + this.coins * 10;
    
    if (this.petrol <= 0) {
        this.gameOver();
    }
    
    if (this.distance >= this.getLevelDistance()) {
        this.levelUp();
    }
}

drawObstacles() {
    // Add logic to draw obstacles
}

drawPowerUps() {
    // Add logic to draw power-ups
}

drawUI() {
    this.ctx.fillStyle = 'black';
    this.ctx.font = '16px Arial';
    this.ctx.fillText(`Level: ${this.level}`, 10, 20);
    this.ctx.fillText(`Distance: ${Math.floor(this.distance)}m`, 10, 40);
    this.ctx.fillText(`Petrol: ${Math.floor(this.petrol)}%`, 10, 60);
    this.ctx.fillText(`Coins: ${this.coins}`, 10, 80);
    this.ctx.fillText(`Score: ${this.score}`, 10, 100);
}

gameOver() {
    console.log('Game Over');
    // Add game over logic
}

levelUp() {
    this.level++;
    console.log(`Level up! Now on level ${this.level}`);
    // Add level up logic
}

getLevelDistance() {
    return this.level * 500; // 500m, 1000m, 1500m, etc.
}

gameLoop() {
    this.update();
    this.draw();
    requestAnimationFrame(() => this.gameLoop());
}

start() {
    this.gameLoop();
}

}

// Player class
class Player {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.speed = 0;
this.maxSpeed = 5;
this.acceleration = 0.1;
this.deceleration = 0.05;
this.isJumping = false;
this.jumpVelocity = 0;
}

update(keys) {
    if (keys['ArrowRight']) {
        this.speed = Math.min(this.speed + this.acceleration, this.maxSpeed);
    } else if (keys['ArrowLeft']) {
        this.speed = Math.max(this.speed - this.acceleration, 0);
    } else {
        this.speed = Math.max(this.speed - this.deceleration, 0);
    }
    
    if (keys['Space'] && !this.isJumping) {
        this.jump();
    }
    
    this.x += this.speed;
    
    if (this.isJumping) {
        this.y += this.jumpVelocity;
        this.jumpVelocity += GRAVITY;
        
        if (this.y >= CANVAS_HEIGHT - this.height) {
            this.y = CANVAS_HEIGHT - this.height;
            this.isJumping = false;
            this.jumpVelocity = 0;
        }
    }
}

jump() {
    this.isJumping = true;
    this.jumpVelocity = JUMP_FORCE;
}

draw(ctx) {
    ctx.fillStyle = 'blue';
    ctx.fillRect(this.x, this.y, this.width, this.height);
}

}

// Initialize and start the game
const game = new ScootyRacingGame();
game.start();
Uploading Screenshot_2024_0902_110713.jpg…

@yt1d
Copy link

yt1d commented Sep 23, 2024

Thank you for sharing this information, I'm also this in my website and it's work.

Thank you for sharing this. This website, yt1d.online, is also using this script.

@Hudamuneeb
Copy link

Hudamuneeb commented Oct 1, 2024

Thank you for sharing this, I am also using it on my website and its work.

@NothingButTyler
Copy link

I found it just to change the 4. function loop() { requestAnimationFrame(loop); // slow game loop to 15 fps instead of 60 (60/15 = 4) if (++count < 4) { return; }

Thats funny...that was on my birthday 😅.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment