Imgflip Logo Icon

my hand hurts fr

my hand hurts fr | <!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>gd</title>
    <meta name="description" content="yuh">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        body {
            margin: 0;
            background: #111;
            overflow: hidden;
        }

        canvas {
            display: block;
            margin: auto;
            background: #000099;
        }
    </style>
</head>

<body>
    <canvas id="game"></canvas>

    <script>
        /* Canvas Setup */
        const canvas = document.getElementById("game");
        const ctx = canvas.getContext("2d");
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        window.addEventListener("resize", () => {
            canvas.width = window.innerWidth;
            canvas.height = window.innerHeight;
        });

        /* Global Variables */
        const TILE_SIZE = 40;
        const SPIKE_HITBOX_SIZE = TILE_SIZE / 2;

        let cameraX = 0;

        let paused = false;
        let input = { pressed: false };
        let wasPressed = false;
        let jumpBuffered = false;
        let activatedPads = new Set();
        let activatedOrbs = new Set();
        let activatedPortals = new Set();
        let levelCompleted = false;

        let player = {
            x: 0,
            y: 0,
            prevX: 0,
            width: TILE_SIZE,
            height: TILE_SIZE,
            velY: 0,
            gravity: 0.6,
            gravityState: 1, // 1 = normal, -1 = inverted
            jumpForce: -10.5,
            grounded: false,
            speed: 5.5,
            rotation: 0,
            rotationSpeed: Math.PI / 30,
            gamemode: "cube"
        };

        /* Level Data */
        const TILE_TYPES = {
            "#": { solid: true },

            "A": { hazard: true },
            "^": { hazard: true },
            "V": { hazard: true },
            "v": { hazard: true },
            "X": { hazard: true },

            "y": { orb: true },
            "m": { orb: true },
            "r": { orb: true },
            "b": { orb: true },

            "Y": { pad: true },
            "M": { pad: true },
            "R": { pad: true },
            "B": { pad: true },

            ")": { portal: true, gravity: -1 },
            "(": { portal: true, gravity: 1 },
            "]": { portal: true, gamemode: "cube" },
            "[": { portal: true, gamemode: "ship" },
            "}": { portal: true, gamemode: "ball" },
            "{": { portal: true, gamemode: "ufo" },

            "E": { levelEnd: true }
        };

        const levelData = {
            level1: [
                "..............................#...........#.................#..........#........#...................",
                "..............................#...........#.................#..........#........#...................",
                "..............................#...........#.................#..........#........#...................",
                "..............................#...........#.................#..........#........#...................",
                "..............................#...........#.................#..........#........#...................",
                "..............................#...........#.................#..........#........#...................",
                "..............................#...........#.................#..........#........#...................",
                "..............................#...........#.................#..........#........#...................",
                "..............................#...........#.................#..........#........#...................",
                "..............................#...........#.................#..........#........#...................",
                "..............................#...........#.................#..........#............................",
                "..............................#...........#............................#............................",
                "..............................#############............................#............................",
                "................................................................................#...................",
                "........................}...........................{.......#...................#...................",
                "......................#...........^.......y....y.....Y......#...................#...................",
                "..................#...#..##########..................#......#..........#........#...................",
                "*......^A.....#...#...#..#........#AAAAAAAAAAAAAAAAAA#......#..........#........#...................",
                "###############XXX#XXX##############################################################################",
                "####################################################################################################"
            ]
        };

        const music = new Audio("SuperUltraMDK.mp3");
        music.loop = true;
        music.volume = 0.5;

        /* Level Helpers */
        function getTile(col, row) {
            if (
                row < 0 ||
                row >= levelData.level1.length ||
                col < 0 ||
                col >= levelData.level1[0].length
            ) return null;

            return levelData.level1[row][col];
        }

        function tileKey(col, row) {
            return col + "," + row;
        }

        function findStart() {
            for (let row = 0; row < levelData.level1.length; row++) {
                for (let col = 0; col < levelData.level1[row].length; col++) {
                    if (levelData.level1[row][col] === "*") {
                        player.x = col * TILE_SIZE;
                        player.y = row * TILE_SIZE;
                    }
                }
            }
        }

        function isSolid(tile) {
            return TILE_TYPES[tile]?.solid;
        }

        function isHazard(tile) {
            return TILE_TYPES[tile]?.hazard;
        }

        function isOrb(tile) {
            return TILE_TYPES[tile]?.orb;
        }

        function isPad(tile) {
            return TILE_TYPES[tile]?.pad;
        }

        function isPortal(tile) {
            return TILE_TYPES[tile]?.portal;
        }

        function isLevelEnd(tile) {
            return TILE_TYPES[tile]?.levelEnd;
        }

        /* Input Handling */
        function setupInput() {
            window.addEventListener("keydown", (e) => {
                if (e.code === "Space" || e.code === "ArrowUp") {
                    input.pressed = true;
                }
            });

            window.addEventListener("keyup", (e) => {
                if (e.code === "Space" || e.code === "ArrowUp") {
                    input.pressed = false;
                }
            });

            window.addEventListener("mousedown", () => input.pressed = true);
            window.addEventListener("mouseup", () => input.pressed = false);

            window.addEventListener("touchstart", (e) => {
                e.preventDefault();
                input.pressed = true;
            }, { passive: false });

            window.addEventListener("touchend", () => input.pressed = false);

            window.addEventListener("keydown", (e) => {

                if (e.code === "KeyP" || e.code === "Escape") {
                    togglePause();
                }

                if (e.code === "Space" || e.code === "ArrowUp") {
                    input.pressed = true;
                    music.play().catch(() => { });
                }
            });
        }

        /* Physics and Movement */
        function applyPhysics() {
            const justPressed = input.pressed && !wasPressed;
            wasPressed = input.pressed;

            if (justPressed && !player.grounded) {
                jumpBuffered = true;
            }

            if (player.gamemode === "cube") {
                if (player.grounded && input.pressed) {
                    player.velY = player.jumpForce * player.gravityState;
                    jumpBuffered = false;
                }
            } else if (player.gamemode === "ball") {
                if (justPressed && player.grounded) {
                    player.gravityState *= -1;
                    player.velY = 0;
                }
            } else if (player.gamemode === "ufo") {
                if (justPressed) {
                    player.velY = player.jumpForce * player.gravityState;
                    jumpBuffered = false;
                    player.grounded = false;
                }
            }

            player.prevX = player.x;
            player.x += player.speed;

            player.velY += player.gravity * player.gravityState;
            player.y += player.velY;

            player.grounded = false;

            if (player.gamemode === "cube") {
                if (!player.grounded) {
                    player.rotation += player.rotationSpeed * player.gravityState;
                }
            } else if (player.gamemode === "ball") {
                player.rotation += (player.speed / TILE_SIZE) * 2 * Math.PI * player.gravityState;
            } else if (player.gamemode === "ufo") {
                player.rotation = 0;
            }
        }

        /* Collision Handling */
        function handleCollisions() {

            const leftCol = Math.floor(player.x / TILE_SIZE);
            const rightCol = Math.floor((player.x + player.width - 1) / TILE_SIZE);
            const topRow = Math.floor(player.y / TILE_SIZE);
            const bottomRow = Math.floor((player.y + player.height) / TILE_SIZE);

            for (let row = topRow; row <= bottomRow; row++) {
                for (let col = leftCol; col <= rightCol; col++) {

                    const tile = getTile(col, row);
                    if (!tile) continue;

                    const tileX = col * TILE_SIZE;
                    const tileY = row * TILE_SIZE;

                    if (isSolid(tile)) {

                        if (player.gravityState === 1) {

                            // landing on floor
                            if (player.velY > 0 && player.y + player.height > tileY && player.y < tileY) {
                                player.y = tileY - player.height;
                                player.velY = 0;
                                player.grounded = true;

                                if (player.gamemode === "cube") {
                                    player.rotation = Math.round(player.rotation / (Math.PI / 2)) * (Math.PI / 2);
                                }
                            }

                            // hitting ceiling
                            else if (player.velY < 0 && player.y < tileY + TILE_SIZE) {
                                player.y = tileY + TILE_SIZE;
                                player.velY = 0;
                            }

                        } else {

                            // landing on ceiling
                            if (player.velY < 0 && player.y < tileY + TILE_SIZE && player.y + player.height > tileY + TILE_SIZE) {
                                player.y = tileY + TILE_SIZE;
                                player.velY = 0;
                                player.grounded = true;

                                if (player.gamemode === "cube") {
                                    player.rotation = Math.round(player.rotation / (Math.PI / 2)) * (Math.PI / 2);
                                }
                            }

                            // hitting floor
                            else if (player.velY > 0 && player.y + player.height > tileY) {
                                player.y = tileY - player.height;
                                player.velY = 0;
                            }
                        }
                    }

                    if (isHazard(tile) && checkSpikeCollision(tileX, tileY)) {
                        resetPlayer();
                        console.log("Hit hazard at (" + col + ", " + row + ")");
                    }

                    if (isPad(tile)) {

                        const key = tileKey(col, row);

                        const padHeight = TILE_SIZE / 3;
                        const padX = tileX;
                        const padY = tileY + TILE_SIZE - padHeight;

                        const touching =
                            player.x < padX + TILE_SIZE &&
                            player.x + player.width > padX &&
                            player.y + player.height > padY &&
                            player.y < padY + padHeight;

                        if (touching && !activatedPads.has(key)) {

                            activatedPads.add(key);

                            if (tile === "Y") {
                                player.velY = -15 * player.gravityState;
                            } else if (tile === "M") {
                                player.velY = -10 * player.gravityState;
                            } else if (tile === "R") {
                                player.velY = -20 * player.gravityState;
                            } else if (tile === "B") {
                                player.velY = -5 * player.gravityState;
                                player.gravityState *= -1;
                            }

                            player.grounded = false;
                            return;
                        }

                        if (!touching) {
                            activatedPads.delete(key);
                        }
                    }

                    if (isOrb(tile)) {

                        const key = tileKey(col, row);

                        if (isCollidingWithTile(tileX, tileY, TILE_SIZE)) {

                            if ((input.pressed || jumpBuffered) && !activatedOrbs.has(key)) {

                                activatedOrbs.add(key);

                                if (tile === "y") {
                                    player.velY = player.jumpForce * player.gravityState;
                                } else if (tile === "m") {
                                    player.velY = player.jumpForce * player.gravityState + 5;
                                } else if (tile === "r") {
                                    player.velY = player.jumpForce * player.gravityState - 5;
                                } else if (tile === "b") {
                                    player.velY = -5 * player.gravityState;
                                    player.gravityState *= -1;
                                }

                                jumpBuffered = false;
                            }
                        } else {
                            activatedOrbs.delete(key);
                        }
                    }

                    if (isPortal(tile)) {
                        const key = tileKey(col, row);

                        if (isCollidingWithTile(tileX, tileY, TILE_SIZE)) {
                            if (!activatedPortals.has(key)) {
                                activatedPortals.add(key);
                                const portal = TILE_TYPES[tile];

                                if (portal.gravity !== undefined) {
                                    player.gravityState = portal.gravity;
                                }

                                if (portal.gamemode) {
                                    player.gamemode = portal.gamemode;
                                }
                            }
                        } else {
                            activatedPortals.delete(key);
                        }
                    }

                    if (isLevelEnd(tile)) {
                        const key = tileKey(col, row);

                        if (isCollidingWithTile(tileX, tileY, TILE_SIZE)) {

                            if ((input.pressed || jumpBuffered) && !activatedOrbs.has(key)) {
                                jumpBuffered = false;
                                completeLevel();
                            }
                        } else {
                            activatedOrbs.delete(key);
                        }
                    }
                }
            }
        }

        function checkSpikeCollision(tileX, tileY) {
            const hitboxX = tileX + (TILE_SIZE - SPIKE_HITBOX_SIZE) / 2;
            const hitboxY = tileY + (TILE_SIZE - SPIKE_HITBOX_SIZE) / 2;

            return player.x < hitboxX + SPIKE_HITBOX_SIZE &&
                player.x + player.width > hitboxX &&
                player.y < hitboxY + SPIKE_HITBOX_SIZE &&
                player.y + player.height > hitboxY;
        }

        function isCollidingWithTile(tileX, tileY, tileSize) {
            return player.x < tileX + tileSize &&
                player.x + player.width > tileX &&
                player.y < tileY + tileSize &&
                player.y + player.height > tileY;
        }

        function checkBlockCrush() {

            const col = Math.floor((player.x + player.width / 2) / TILE_SIZE);
            const row = Math.floor((player.y + player.height / 2) / TILE_SIZE);

            const tile = getTile(col, row);

            if (isSolid(tile)) {
                resetPlayer();
                console.log("Crushed inside block at (" + col + ", " + row + ")");
            }
        }

        /* Camera, Progress Bar, & Rendering*/
        function updateCamera() {
            const targetX = player.x - canvas.width / 4;
            if (targetX > cameraX) {
                cameraX += (targetX - cameraX) * 0.1;
            }
        }

        function getProgress() {
            const levelWidth = levelData.level1[0].length * TILE_SIZE;
            return Math.min(player.x / levelWidth, 1);
        }

        function drawProgressBar() {
            const progress = getProgress();

            const barWidth = canvas.width * 0.6;
            const barHeight = 10;

            const x = (canvas.width - barWidth) / 2;
            const y = 20;

            // Background
            ctx.fillStyle = "rgba(255,255,255,0.2)";
            ctx.fillRect(x, y, barWidth, barHeight);

            // Fill
            ctx.fillStyle = "lime";
            ctx.fillRect(x, y, barWidth * progress, barHeight);

            // Outline
            ctx.strokeStyle = "white";
            ctx.lineWidth = 2;
            ctx.strokeRect(x, y, barWidth, barHeight);

            ctx.fillStyle = "white";
            ctx.font = "16px Arial";
            ctx.textAlign = "center";
            ctx.fillText(Math.floor(progress * 100) + "%", canvas.width / 2, y + 25);
        }

        function render() {
            ctx.clearRect(0, 0, canvas.width, canvas.height);

            drawProgressBar();
            drawLevel();
            drawPlayer();

            if (levelCompleted) {
                ctx.fillStyle = "rgba(0,0,0,0.5)";
                ctx.fillRect(0, 0, canvas.width, canvas.height);

                ctx.fillStyle = "lime";
                ctx.font = "60px Arial";
                ctx.textAlign = "center";

                ctx.fillText("Level Complete!", canvas.width / 2, canvas.height / 2);
            }

            if (paused && !levelCompleted) {

                ctx.fillStyle = "rgba(0,0,0,0.5)";
                ctx.fillRect(0, 0, canvas.width, canvas.height);

                ctx.fillStyle = "white";
                ctx.font = "48px Arial";
                ctx.textAlign = "center";

                ctx.fillText("Game Paused", canvas.width / 2, canvas.height / 2);
            }
        }

        /* Drawing Functions */
        function drawLevel() {

            const startCol = Math.floor(cameraX / TILE_SIZE);
            const endCol = startCol + Math.ceil(canvas.width / TILE_SIZE) + 1;

            for (let row = 0; row < levelData.level1.length; row++) {

                for (let col = startCol; col < endCol; col++) {

                    const tile = getTile(col, row);
                    if (!tile) continue;

                    const x = col * TILE_SIZE - cameraX;
                    const y = row * TILE_SIZE;

                    if (isSolid(tile)) {
                        drawSolid(tile, x, y);
                    }

                    if (isHazard(tile)) {
                        drawHazard(tile, x, y);
                    }

                    if (isOrb(tile)) {
                        drawOrb(tile, x, y);
                    }

                    if (isPad(tile)) {
                        drawPad(tile, x, y);
                    }

                    if (isPortal(tile)) {
                        drawPortal(tile, x, y);
                    }

                    if (isLevelEnd(tile)) {
                        drawEnd(tile, x, y);
                    }
                }
            }
        }

        function drawPlayer() {
            const drawX = player.x - cameraX + player.width / 2;
            const drawY = player.y + player.height / 2;

            ctx.save();
            ctx.translate(drawX, drawY);
            if (player.gamemode === "cube") {
                ctx.rotate(player.rotation);

                ctx.fillStyle = "lime";
                ctx.fillRect(-player.width / 2, -player.height / 2, player.width, player.height);
            } else if (player.gamemode === "ball") {
                ctx.rotate(player.rotation);

                ctx.fillStyle = "red";
                ctx.beginPath();
                const size = TILE_SIZE / 2;
                ctx.moveTo(0, size);
                ctx.lineTo(0, size / 2);
                ctx.lineTo(size / 1.5, size / 1.5);
                ctx.lineTo(size / 3, size / 3);
                ctx.lineTo(size, 0);
                ctx.lineTo(size / 2, 0);
                ctx.lineTo(size / 1.5, -size / 1.5);
                ctx.lineTo(size / 3, -size / 3);
                ctx.lineTo(0, -size);
                ctx.lineTo(0, -size / 2);
                ctx.lineTo(-size / 1.5, -size / 1.5);
                ctx.lineTo(-size / 3, -size / 3);
                ctx.lineTo(-size, 0);
                ctx.lineTo(-size / 2, 0);
                ctx.lineTo(-size / 1.5, size / 1.5);
                ctx.lineTo(-size / 3, size / 3);
                ctx.closePath();
                ctx.fill();
            } else if (player.gamemode === "ufo") {
                ctx.fillStyle = "orange";

                // simple UFO shape
                ctx.beginPath();
                ctx.ellipse(0, 0, TILE_SIZE / 2, TILE_SIZE / 3, 0, 0, Math.PI * 2);
                ctx.fill();

                ctx.fillStyle = "white";
                ctx.beginPath();
                ctx.arc(0, -TILE_SIZE / 6, TILE_SIZE / 6, 0, Math.PI * 2);
                ctx.fill();
            }

            ctx.restore();
        }

        function drawSolid(tile, x, y) {
            ctx.save();
            ctx.fillStyle = "grey";
            ctx.strokeStyle = "black";
            ctx.lineWidth = 3;
            ctx.fillRect(x, y, TILE_SIZE, TILE_SIZE);
            ctx.strokeRect(x, y, TILE_SIZE, TILE_SIZE);
            ctx.restore();
        }

        function drawHazard(tile, x, y) {
            ctx.save();
            ctx.fillStyle = "red";
            ctx.beginPath();

            if (tile === "A") {
                // Full spike pointing up
                ctx.moveTo(x, y + TILE_SIZE);
                ctx.lineTo(x + TILE_SIZE / 2, y);
                ctx.lineTo(x + TILE_SIZE, y + TILE_SIZE);
            } else if (tile === "^") {
                // Half spike pointing up
                ctx.moveTo(x, y + TILE_SIZE);
                ctx.lineTo(x + TILE_SIZE / 2, y + TILE_SIZE / 2);
                ctx.lineTo(x + TILE_SIZE, y + TILE_SIZE);
            } else if (tile === "V") {
                // Full spike pointing down
                ctx.moveTo(x, y);
                ctx.lineTo(x + TILE_SIZE / 2, y + TILE_SIZE);
                ctx.lineTo(x + TILE_SIZE, y);
            } else if (tile === "v") {
                // Half spike pointing down
                ctx.moveTo(x, y);
                ctx.lineTo(x + TILE_SIZE / 2, y + TILE_SIZE / 2);
                ctx.lineTo(x + TILE_SIZE, y);
            } else if (tile === "X") {
                ctx.moveTo(x, y + TILE_SIZE);
                ctx.lineTo(x + TILE_SIZE, y + TILE_SIZE);
                ctx.lineTo(x + TILE_SIZE, y);
                ctx.lineTo(x, y);
            }

            ctx.fill();
            ctx.restore();
        }

        function drawOrb(tile, x, y) {
            ctx.save();
            if (tile === "y") {
                ctx.fillStyle = "yellow";
            } else if (tile === "m") {
                ctx.fillStyle = "magenta";
            } else if (tile === "r") {
                ctx.fillStyle = "red";
            } else if (tile === "b") {
                ctx.fillStyle = "cyan"
            }
            ctx.beginPath();
            ctx.arc(x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE / 3, 0, 2 * Math.PI);
            ctx.fill();

            ctx.beginPath();
            ctx.strokeStyle = "white";
            ctx.lineWidth = 3;
            ctx.arc(x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE / 2, 0, 2 * Math.PI);
            ctx.stroke();
            ctx.restore();
        }

        function drawPad(tile, x, y) {
            ctx.save();
            if (tile === "Y") {
                ctx.fillStyle = "yellow"
            } else if (tile === "M") {
                ctx.fillStyle = "magenta"
            } else if (tile === "R") {
                ctx.fillStyle = "red"
            } else if (tile === "B") {
                ctx.fillStyle = "cyan"
            }
            const padHeight = TILE_SIZE / 3;
            ctx.fillRect(x, y + TILE_SIZE - padHeight, TILE_SIZE, padHeight);
            ctx.restore();
        }

        function drawPortal(tile, x, y) {
            ctx.save();

            let color = "";
            if (tile === ")") {
                color = "yellow";
            } else if (tile === "(") {
                color = "blue";
            } else if (tile === "]") {
                color = "lime";
            } else if (tile === "[") {
                color = "magenta";
            } else if (tile === "}") {
                color = "red";
            } else if (tile === "{") {
                color = "orange";
            }

            // Glow
            const gradient = ctx.createRadialGradient(
                x + TILE_SIZE / 2,
                y,
                5,
                x + TILE_SIZE / 2,
                y,
                TILE_SIZE
            );

            gradient.addColorStop(0, color);
            gradient.addColorStop(1, "transparent");

            ctx.fillStyle = gradient;
            ctx.fillRect(x - TILE_SIZE / 2, y - TILE_SIZE, TILE_SIZE * 2, TILE_SIZE * 3);

            // Core
            ctx.fillStyle = color;
            ctx.fillRect(x, y - TILE_SIZE / 2, TILE_SIZE, TILE_SIZE * 2);

            ctx.restore();
        }

        function drawEnd(tile, x, y) {
            ctx.save();
            // Glow
            const gradient = ctx.createRadialGradient(
                x + TILE_SIZE / 2,
                y + TILE_SIZE / 2,
                5,
                x + TILE_SIZE / 2,
                y + TILE_SIZE / 2,
                TILE_SIZE
            );

            gradient.addColorStop(0, "orange");
            gradient.addColorStop(1, "transparent");

            ctx.fillStyle = gradient;
            ctx.beginPath();
            ctx.arc(x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE, 0, 2 * Math.PI);
            ctx.fill();

            // Core circle
            ctx.fillStyle = "orange";
            ctx.beginPath();
            ctx.arc(x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE / 3, 0, 2 * Math.PI);
            ctx.fill();

            // Ring
            ctx.strokeStyle = "white";
            ctx.lineWidth = 3;
            ctx.beginPath();
            ctx.arc(x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE / 2, 0, 2 * Math.PI);
            ctx.stroke();

            ctx.restore();
        }

        function update() {
            if (paused) return;

            applyPhysics();
            handleCollisions();
            checkBlockCrush();
            updateCamera();
            checkLevelComplete();
        }

        /* Reset, Loop, Check for Complete, Pause, Init */
        function resetPlayer() {
            player.gamemode = "cube";
            levelCompleted = false;
            findStart();
            music.currentTime = 0;
            cameraX = 0;
            player.velY = 0;
            player.gravityState = 1;
            jumpBuffered = false;

            activatedPads.clear();
            activatedOrbs.clear();
            activatedPortals.clear();

            console.log("Player reset");
        }

        function gameLoop() {
            update();
            render();
            requestAnimationFrame(gameLoop);
        }

        function checkLevelComplete() {
            const levelWidth = levelData.level1[0].length * TILE_SIZE;

            if (player.x > levelWidth - TILE_SIZE / 2) {
                completeLevel();
            }
        }

        function completeLevel() {
            if (levelCompleted) return;

            levelCompleted = true;
            paused = true;

            music.pause();

            console.log("Level Complete!");
        }

        function togglePause() {

            paused = !paused;

            if (paused) {
                music.pause();
                console.log("Game paused");
            } else {
                music.play().catch(() => { });
                console.log("Game unpaused");
            }

        }

        function init() {
            setupInput();
            findStart();
            gameLoop();
            music.play().catch(() => { });
            console.log("Game initialized");
        }

        init();
    </script>
</body>

</html> | image tagged in my hand hurts fr | made w/ Imgflip meme maker
51 views 1 upvote Made by Cheze 2 weeks ago in MS_memer_group
my hand hurts fr memeCaption this Meme
my hand hurts fr memeCaption this Meme
Created with the Imgflip Meme Generator
IMAGE DESCRIPTION:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>gd</title> <meta name="description" content="yuh"> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> body { margin: 0; background: #111; overflow: hidden; } canvas { display: block; margin: auto; background: #000099; } </style> </head> <body> <canvas id="game"></canvas> <script> /* Canvas Setup */ const canvas = document.getElementById("game"); const ctx = canvas.getContext("2d"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; window.addEventListener("resize", () => { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }); /* Global Variables */ const TILE_SIZE = 40; const SPIKE_HITBOX_SIZE = TILE_SIZE / 2; let cameraX = 0; let paused = false; let input = { pressed: false }; let wasPressed = false; let jumpBuffered = false; let activatedPads = new Set(); let activatedOrbs = new Set(); let activatedPortals = new Set(); let levelCompleted = false; let player = { x: 0, y: 0, prevX: 0, width: TILE_SIZE, height: TILE_SIZE, velY: 0, gravity: 0.6, gravityState: 1, // 1 = normal, -1 = inverted jumpForce: -10.5, grounded: false, speed: 5.5, rotation: 0, rotationSpeed: Math.PI / 30, gamemode: "cube" }; /* Level Data */ const TILE_TYPES = { "#": { solid: true }, "A": { hazard: true }, "^": { hazard: true }, "V": { hazard: true }, "v": { hazard: true }, "X": { hazard: true }, "y": { orb: true }, "m": { orb: true }, "r": { orb: true }, "b": { orb: true }, "Y": { pad: true }, "M": { pad: true }, "R": { pad: true }, "B": { pad: true }, ")": { portal: true, gravity: -1 }, "(": { portal: true, gravity: 1 }, "]": { portal: true, gamemode: "cube" }, "[": { portal: true, gamemode: "ship" }, "}": { portal: true, gamemode: "ball" }, "{": { portal: true, gamemode: "ufo" }, "E": { levelEnd: true } }; const levelData = { level1: [ "..............................#...........#.................#..........#........#...................", "..............................#...........#.................#..........#........#...................", "..............................#...........#.................#..........#........#...................", "..............................#...........#.................#..........#........#...................", "..............................#...........#.................#..........#........#...................", "..............................#...........#.................#..........#........#...................", "..............................#...........#.................#..........#........#...................", "..............................#...........#.................#..........#........#...................", "..............................#...........#.................#..........#........#...................", "..............................#...........#.................#..........#........#...................", "..............................#...........#.................#..........#............................", "..............................#...........#............................#............................", "..............................#############............................#............................", "................................................................................#...................", "........................}...........................{.......#...................#...................", "......................#...........^.......y....y.....Y......#...................#...................", "..................#...#..##########..................#......#..........#........#...................", "*......^A.....#...#...#..#........#AAAAAAAAAAAAAAAAAA#......#..........#........#...................", "###############XXX#XXX##############################################################################", "####################################################################################################" ] }; const music = new Audio("SuperUltraMDK.mp3"); music.loop = true; music.volume = 0.5; /* Level Helpers */ function getTile(col, row) { if ( row < 0 || row >= levelData.level1.length || col < 0 || col >= levelData.level1[0].length ) return null; return levelData.level1[row][col]; } function tileKey(col, row) { return col + "," + row; } function findStart() { for (let row = 0; row < levelData.level1.length; row++) { for (let col = 0; col < levelData.level1[row].length; col++) { if (levelData.level1[row][col] === "*") { player.x = col * TILE_SIZE; player.y = row * TILE_SIZE; } } } } function isSolid(tile) { return TILE_TYPES[tile]?.solid; } function isHazard(tile) { return TILE_TYPES[tile]?.hazard; } function isOrb(tile) { return TILE_TYPES[tile]?.orb; } function isPad(tile) { return TILE_TYPES[tile]?.pad; } function isPortal(tile) { return TILE_TYPES[tile]?.portal; } function isLevelEnd(tile) { return TILE_TYPES[tile]?.levelEnd; } /* Input Handling */ function setupInput() { window.addEventListener("keydown", (e) => { if (e.code === "Space" || e.code === "ArrowUp") { input.pressed = true; } }); window.addEventListener("keyup", (e) => { if (e.code === "Space" || e.code === "ArrowUp") { input.pressed = false; } }); window.addEventListener("mousedown", () => input.pressed = true); window.addEventListener("mouseup", () => input.pressed = false); window.addEventListener("touchstart", (e) => { e.preventDefault(); input.pressed = true; }, { passive: false }); window.addEventListener("touchend", () => input.pressed = false); window.addEventListener("keydown", (e) => { if (e.code === "KeyP" || e.code === "Escape") { togglePause(); } if (e.code === "Space" || e.code === "ArrowUp") { input.pressed = true; music.play().catch(() => { }); } }); } /* Physics and Movement */ function applyPhysics() { const justPressed = input.pressed && !wasPressed; wasPressed = input.pressed; if (justPressed && !player.grounded) { jumpBuffered = true; } if (player.gamemode === "cube") { if (player.grounded && input.pressed) { player.velY = player.jumpForce * player.gravityState; jumpBuffered = false; } } else if (player.gamemode === "ball") { if (justPressed && player.grounded) { player.gravityState *= -1; player.velY = 0; } } else if (player.gamemode === "ufo") { if (justPressed) { player.velY = player.jumpForce * player.gravityState; jumpBuffered = false; player.grounded = false; } } player.prevX = player.x; player.x += player.speed; player.velY += player.gravity * player.gravityState; player.y += player.velY; player.grounded = false; if (player.gamemode === "cube") { if (!player.grounded) { player.rotation += player.rotationSpeed * player.gravityState; } } else if (player.gamemode === "ball") { player.rotation += (player.speed / TILE_SIZE) * 2 * Math.PI * player.gravityState; } else if (player.gamemode === "ufo") { player.rotation = 0; } } /* Collision Handling */ function handleCollisions() { const leftCol = Math.floor(player.x / TILE_SIZE); const rightCol = Math.floor((player.x + player.width - 1) / TILE_SIZE); const topRow = Math.floor(player.y / TILE_SIZE); const bottomRow = Math.floor((player.y + player.height) / TILE_SIZE); for (let row = topRow; row <= bottomRow; row++) { for (let col = leftCol; col <= rightCol; col++) { const tile = getTile(col, row); if (!tile) continue; const tileX = col * TILE_SIZE; const tileY = row * TILE_SIZE; if (isSolid(tile)) { if (player.gravityState === 1) { // landing on floor if (player.velY > 0 && player.y + player.height > tileY && player.y < tileY) { player.y = tileY - player.height; player.velY = 0; player.grounded = true; if (player.gamemode === "cube") { player.rotation = Math.round(player.rotation / (Math.PI / 2)) * (Math.PI / 2); } } // hitting ceiling else if (player.velY < 0 && player.y < tileY + TILE_SIZE) { player.y = tileY + TILE_SIZE; player.velY = 0; } } else { // landing on ceiling if (player.velY < 0 && player.y < tileY + TILE_SIZE && player.y + player.height > tileY + TILE_SIZE) { player.y = tileY + TILE_SIZE; player.velY = 0; player.grounded = true; if (player.gamemode === "cube") { player.rotation = Math.round(player.rotation / (Math.PI / 2)) * (Math.PI / 2); } } // hitting floor else if (player.velY > 0 && player.y + player.height > tileY) { player.y = tileY - player.height; player.velY = 0; } } } if (isHazard(tile) && checkSpikeCollision(tileX, tileY)) { resetPlayer(); console.log("Hit hazard at (" + col + ", " + row + ")"); } if (isPad(tile)) { const key = tileKey(col, row); const padHeight = TILE_SIZE / 3; const padX = tileX; const padY = tileY + TILE_SIZE - padHeight; const touching = player.x < padX + TILE_SIZE && player.x + player.width > padX && player.y + player.height > padY && player.y < padY + padHeight; if (touching && !activatedPads.has(key)) { activatedPads.add(key); if (tile === "Y") { player.velY = -15 * player.gravityState; } else if (tile === "M") { player.velY = -10 * player.gravityState; } else if (tile === "R") { player.velY = -20 * player.gravityState; } else if (tile === "B") { player.velY = -5 * player.gravityState; player.gravityState *= -1; } player.grounded = false; return; } if (!touching) { activatedPads.delete(key); } } if (isOrb(tile)) { const key = tileKey(col, row); if (isCollidingWithTile(tileX, tileY, TILE_SIZE)) { if ((input.pressed || jumpBuffered) && !activatedOrbs.has(key)) { activatedOrbs.add(key); if (tile === "y") { player.velY = player.jumpForce * player.gravityState; } else if (tile === "m") { player.velY = player.jumpForce * player.gravityState + 5; } else if (tile === "r") { player.velY = player.jumpForce * player.gravityState - 5; } else if (tile === "b") { player.velY = -5 * player.gravityState; player.gravityState *= -1; } jumpBuffered = false; } } else { activatedOrbs.delete(key); } } if (isPortal(tile)) { const key = tileKey(col, row); if (isCollidingWithTile(tileX, tileY, TILE_SIZE)) { if (!activatedPortals.has(key)) { activatedPortals.add(key); const portal = TILE_TYPES[tile]; if (portal.gravity !== undefined) { player.gravityState = portal.gravity; } if (portal.gamemode) { player.gamemode = portal.gamemode; } } } else { activatedPortals.delete(key); } } if (isLevelEnd(tile)) { const key = tileKey(col, row); if (isCollidingWithTile(tileX, tileY, TILE_SIZE)) { if ((input.pressed || jumpBuffered) && !activatedOrbs.has(key)) { jumpBuffered = false; completeLevel(); } } else { activatedOrbs.delete(key); } } } } } function checkSpikeCollision(tileX, tileY) { const hitboxX = tileX + (TILE_SIZE - SPIKE_HITBOX_SIZE) / 2; const hitboxY = tileY + (TILE_SIZE - SPIKE_HITBOX_SIZE) / 2; return player.x < hitboxX + SPIKE_HITBOX_SIZE && player.x + player.width > hitboxX && player.y < hitboxY + SPIKE_HITBOX_SIZE && player.y + player.height > hitboxY; } function isCollidingWithTile(tileX, tileY, tileSize) { return player.x < tileX + tileSize && player.x + player.width > tileX && player.y < tileY + tileSize && player.y + player.height > tileY; } function checkBlockCrush() { const col = Math.floor((player.x + player.width / 2) / TILE_SIZE); const row = Math.floor((player.y + player.height / 2) / TILE_SIZE); const tile = getTile(col, row); if (isSolid(tile)) { resetPlayer(); console.log("Crushed inside block at (" + col + ", " + row + ")"); } } /* Camera, Progress Bar, & Rendering*/ function updateCamera() { const targetX = player.x - canvas.width / 4; if (targetX > cameraX) { cameraX += (targetX - cameraX) * 0.1; } } function getProgress() { const levelWidth = levelData.level1[0].length * TILE_SIZE; return Math.min(player.x / levelWidth, 1); } function drawProgressBar() { const progress = getProgress(); const barWidth = canvas.width * 0.6; const barHeight = 10; const x = (canvas.width - barWidth) / 2; const y = 20; // Background ctx.fillStyle = "rgba(255,255,255,0.2)"; ctx.fillRect(x, y, barWidth, barHeight); // Fill ctx.fillStyle = "lime"; ctx.fillRect(x, y, barWidth * progress, barHeight); // Outline ctx.strokeStyle = "white"; ctx.lineWidth = 2; ctx.strokeRect(x, y, barWidth, barHeight); ctx.fillStyle = "white"; ctx.font = "16px Arial"; ctx.textAlign = "center"; ctx.fillText(Math.floor(progress * 100) + "%", canvas.width / 2, y + 25); } function render() { ctx.clearRect(0, 0, canvas.width, canvas.height); drawProgressBar(); drawLevel(); drawPlayer(); if (levelCompleted) { ctx.fillStyle = "rgba(0,0,0,0.5)"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "lime"; ctx.font = "60px Arial"; ctx.textAlign = "center"; ctx.fillText("Level Complete!", canvas.width / 2, canvas.height / 2); } if (paused && !levelCompleted) { ctx.fillStyle = "rgba(0,0,0,0.5)"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "white"; ctx.font = "48px Arial"; ctx.textAlign = "center"; ctx.fillText("Game Paused", canvas.width / 2, canvas.height / 2); } } /* Drawing Functions */ function drawLevel() { const startCol = Math.floor(cameraX / TILE_SIZE); const endCol = startCol + Math.ceil(canvas.width / TILE_SIZE) + 1; for (let row = 0; row < levelData.level1.length; row++) { for (let col = startCol; col < endCol; col++) { const tile = getTile(col, row); if (!tile) continue; const x = col * TILE_SIZE - cameraX; const y = row * TILE_SIZE; if (isSolid(tile)) { drawSolid(tile, x, y); } if (isHazard(tile)) { drawHazard(tile, x, y); } if (isOrb(tile)) { drawOrb(tile, x, y); } if (isPad(tile)) { drawPad(tile, x, y); } if (isPortal(tile)) { drawPortal(tile, x, y); } if (isLevelEnd(tile)) { drawEnd(tile, x, y); } } } } function drawPlayer() { const drawX = player.x - cameraX + player.width / 2; const drawY = player.y + player.height / 2; ctx.save(); ctx.translate(drawX, drawY); if (player.gamemode === "cube") { ctx.rotate(player.rotation); ctx.fillStyle = "lime"; ctx.fillRect(-player.width / 2, -player.height / 2, player.width, player.height); } else if (player.gamemode === "ball") { ctx.rotate(player.rotation); ctx.fillStyle = "red"; ctx.beginPath(); const size = TILE_SIZE / 2; ctx.moveTo(0, size); ctx.lineTo(0, size / 2); ctx.lineTo(size / 1.5, size / 1.5); ctx.lineTo(size / 3, size / 3); ctx.lineTo(size, 0); ctx.lineTo(size / 2, 0); ctx.lineTo(size / 1.5, -size / 1.5); ctx.lineTo(size / 3, -size / 3); ctx.lineTo(0, -size); ctx.lineTo(0, -size / 2); ctx.lineTo(-size / 1.5, -size / 1.5); ctx.lineTo(-size / 3, -size / 3); ctx.lineTo(-size, 0); ctx.lineTo(-size / 2, 0); ctx.lineTo(-size / 1.5, size / 1.5); ctx.lineTo(-size / 3, size / 3); ctx.closePath(); ctx.fill(); } else if (player.gamemode === "ufo") { ctx.fillStyle = "orange"; // simple UFO shape ctx.beginPath(); ctx.ellipse(0, 0, TILE_SIZE / 2, TILE_SIZE / 3, 0, 0, Math.PI * 2); ctx.fill(); ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(0, -TILE_SIZE / 6, TILE_SIZE / 6, 0, Math.PI * 2); ctx.fill(); } ctx.restore(); } function drawSolid(tile, x, y) { ctx.save(); ctx.fillStyle = "grey"; ctx.strokeStyle = "black"; ctx.lineWidth = 3; ctx.fillRect(x, y, TILE_SIZE, TILE_SIZE); ctx.strokeRect(x, y, TILE_SIZE, TILE_SIZE); ctx.restore(); } function drawHazard(tile, x, y) { ctx.save(); ctx.fillStyle = "red"; ctx.beginPath(); if (tile === "A") { // Full spike pointing up ctx.moveTo(x, y + TILE_SIZE); ctx.lineTo(x + TILE_SIZE / 2, y); ctx.lineTo(x + TILE_SIZE, y + TILE_SIZE); } else if (tile === "^") { // Half spike pointing up ctx.moveTo(x, y + TILE_SIZE); ctx.lineTo(x + TILE_SIZE / 2, y + TILE_SIZE / 2); ctx.lineTo(x + TILE_SIZE, y + TILE_SIZE); } else if (tile === "V") { // Full spike pointing down ctx.moveTo(x, y); ctx.lineTo(x + TILE_SIZE / 2, y + TILE_SIZE); ctx.lineTo(x + TILE_SIZE, y); } else if (tile === "v") { // Half spike pointing down ctx.moveTo(x, y); ctx.lineTo(x + TILE_SIZE / 2, y + TILE_SIZE / 2); ctx.lineTo(x + TILE_SIZE, y); } else if (tile === "X") { ctx.moveTo(x, y + TILE_SIZE); ctx.lineTo(x + TILE_SIZE, y + TILE_SIZE); ctx.lineTo(x + TILE_SIZE, y); ctx.lineTo(x, y); } ctx.fill(); ctx.restore(); } function drawOrb(tile, x, y) { ctx.save(); if (tile === "y") { ctx.fillStyle = "yellow"; } else if (tile === "m") { ctx.fillStyle = "magenta"; } else if (tile === "r") { ctx.fillStyle = "red"; } else if (tile === "b") { ctx.fillStyle = "cyan" } ctx.beginPath(); ctx.arc(x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE / 3, 0, 2 * Math.PI); ctx.fill(); ctx.beginPath(); ctx.strokeStyle = "white"; ctx.lineWidth = 3; ctx.arc(x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE / 2, 0, 2 * Math.PI); ctx.stroke(); ctx.restore(); } function drawPad(tile, x, y) { ctx.save(); if (tile === "Y") { ctx.fillStyle = "yellow" } else if (tile === "M") { ctx.fillStyle = "magenta" } else if (tile === "R") { ctx.fillStyle = "red" } else if (tile === "B") { ctx.fillStyle = "cyan" } const padHeight = TILE_SIZE / 3; ctx.fillRect(x, y + TILE_SIZE - padHeight, TILE_SIZE, padHeight); ctx.restore(); } function drawPortal(tile, x, y) { ctx.save(); let color = ""; if (tile === ")") { color = "yellow"; } else if (tile === "(") { color = "blue"; } else if (tile === "]") { color = "lime"; } else if (tile === "[") { color = "magenta"; } else if (tile === "}") { color = "red"; } else if (tile === "{") { color = "orange"; } // Glow const gradient = ctx.createRadialGradient( x + TILE_SIZE / 2, y, 5, x + TILE_SIZE / 2, y, TILE_SIZE ); gradient.addColorStop(0, color); gradient.addColorStop(1, "transparent"); ctx.fillStyle = gradient; ctx.fillRect(x - TILE_SIZE / 2, y - TILE_SIZE, TILE_SIZE * 2, TILE_SIZE * 3); // Core ctx.fillStyle = color; ctx.fillRect(x, y - TILE_SIZE / 2, TILE_SIZE, TILE_SIZE * 2); ctx.restore(); } function drawEnd(tile, x, y) { ctx.save(); // Glow const gradient = ctx.createRadialGradient( x + TILE_SIZE / 2, y + TILE_SIZE / 2, 5, x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE ); gradient.addColorStop(0, "orange"); gradient.addColorStop(1, "transparent"); ctx.fillStyle = gradient; ctx.beginPath(); ctx.arc(x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE, 0, 2 * Math.PI); ctx.fill(); // Core circle ctx.fillStyle = "orange"; ctx.beginPath(); ctx.arc(x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE / 3, 0, 2 * Math.PI); ctx.fill(); // Ring ctx.strokeStyle = "white"; ctx.lineWidth = 3; ctx.beginPath(); ctx.arc(x + TILE_SIZE / 2, y + TILE_SIZE / 2, TILE_SIZE / 2, 0, 2 * Math.PI); ctx.stroke(); ctx.restore(); } function update() { if (paused) return; applyPhysics(); handleCollisions(); checkBlockCrush(); updateCamera(); checkLevelComplete(); } /* Reset, Loop, Check for Complete, Pause, Init */ function resetPlayer() { player.gamemode = "cube"; levelCompleted = false; findStart(); music.currentTime = 0; cameraX = 0; player.velY = 0; player.gravityState = 1; jumpBuffered = false; activatedPads.clear(); activatedOrbs.clear(); activatedPortals.clear(); console.log("Player reset"); } function gameLoop() { update(); render(); requestAnimationFrame(gameLoop); } function checkLevelComplete() { const levelWidth = levelData.level1[0].length * TILE_SIZE; if (player.x > levelWidth - TILE_SIZE / 2) { completeLevel(); } } function completeLevel() { if (levelCompleted) return; levelCompleted = true; paused = true; music.pause(); console.log("Level Complete!"); } function togglePause() { paused = !paused; if (paused) { music.pause(); console.log("Game paused"); } else { music.play().catch(() => { }); console.log("Game unpaused"); } } function init() { setupInput(); findStart(); gameLoop(); music.play().catch(() => { }); console.log("Game initialized"); } init(); </script> </body> </html>