{"id":238,"date":"2026-03-09T01:55:00","date_gmt":"2026-03-08T20:25:00","guid":{"rendered":"https:\/\/toolorama.in\/?p=238"},"modified":"2026-03-09T01:55:11","modified_gmt":"2026-03-08T20:25:11","slug":"bird-game","status":"publish","type":"post","link":"https:\/\/toolorama.in\/index.php\/2026\/03\/09\/bird-game\/","title":{"rendered":"Bird Game"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>sky glide \u00b7 bird game<\/title>\n    <style>\n        * {\n            margin: 0;\n            padding: 0;\n            box-sizing: border-box;\n            user-select: none;\n        }\n        body {\n            background: linear-gradient(145deg, #0b3b3f 0%, #1c5a6a 100%);\n            min-height: 100vh;\n            display: flex;\n            justify-content: center;\n            align-items: center;\n            font-family: 'Segoe UI', system-ui, sans-serif;\n        }\n        .game-wrapper {\n            background: #1f4d5e;\n            border-radius: 3rem 3rem 2rem 2rem;\n            padding: 1.5rem 2rem 2rem 2rem;\n            box-shadow: 0 30px 30px -10px rgba(0,0,0,0.6), inset 0 2px 5px #b3e9f0;\n        }\n        canvas {\n            display: block;\n            width: 600px;\n            height: 400px;\n            border-radius: 24px;\n            background: radial-gradient(circle at 40% 30%, #a5e3f0, #2d7b8f);\n            box-shadow: 0 0 0 3px #9bc7d3, 0 15px 20px #041e24;\n            cursor: pointer;\n            transition: transform 0.1s ease;\n        }\n        canvas:active {\n            transform: scale(0.99);\n        }\n        .panel {\n            display: flex;\n            justify-content: space-between;\n            align-items: center;\n            margin: 1.2rem 0.3rem 0.3rem 0.3rem;\n            color: #e6f7ff;\n            text-shadow: 2px 2px 0 #0a363f;\n            font-weight: bold;\n        }\n        .score-box {\n            background: #0f404b;\n            padding: 0.6rem 2rem;\n            border-radius: 60px;\n            font-size: 2rem;\n            letter-spacing: 2px;\n            box-shadow: inset 0 -4px 0 #05262e, 0 6px 10px black;\n            color: #fee7a0;\n            font-family: 'Courier New', monospace;\n            font-weight: 700;\n        }\n        .hint {\n            background: #ceb25e;\n            color: #1f3f45;\n            padding: 0.6rem 1.6rem;\n            border-radius: 40px;\n            font-size: 1.3rem;\n            font-weight: 600;\n            box-shadow: 0 5px 0 #6f4f1f, 0 8px 12px #041e24;\n            transition: 0.07s;\n        }\n        .hint:active {\n            transform: translateY(5px);\n            box-shadow: 0 2px 0 #6f4f1f, 0 8px 12px #041e24;\n        }\n        .footer {\n            text-align: center;\n            color: #bee3ea;\n            margin-top: 0.5rem;\n            font-size: 1rem;\n            text-shadow: 1px 1px 0 #1c404b;\n        }\n        .footer span {\n            background: #0d3b44;\n            padding: 0.2rem 1.2rem;\n            border-radius: 30px;\n            display: inline-block;\n        }\n    <\/style>\n<\/head>\n<body>\n<div class=\"game-wrapper\">\n    <canvas id=\"birdCanvas\" width=\"600\" height=\"400\"><\/canvas>\n    <div class=\"panel\">\n        <div class=\"score-box\" id=\"scoreDisplay\">0<\/div>\n        <div class=\"hint\" id=\"restartBtn\">\u21bb start<\/div>\n    <\/div>\n    <div class=\"footer\">\n        <span>\u2423  space \/ click  \u00b7  fly little bird<\/span>\n    <\/div>\n<\/div>\n\n<script>\n    (function() {\n        \/\/ ----- canvas & context -----\n        const canvas = document.getElementById('birdCanvas');\n        const ctx = canvas.getContext('2d');\n        const scoreSpan = document.getElementById('scoreDisplay');\n\n        \/\/ ----- fixed dimensions -----\n        const W = 600, H = 400;\n\n        \/\/ ----- bird constants -----\n        const BIRD_RADIUS = 16;           \/\/ circle bird (easy collisions)\n        const GRAVITY = 0.2;\n        const JUMP_FORCE = -5.5;\n        const MAX_FALL_SPEED = 8;\n\n        \/\/ ----- pipe settings -----\n        const PIPE_WIDTH = 60;\n        const GAP_HEIGHT = 120;            \/\/ space between upper and lower pipe\n        const PIPE_SPACING = 280;           \/\/ distance between pipe pairs\n        const PIPE_SPEED = 2.5;\n\n        \/\/ ----- game state -----\n        let gameActive = false;              \/\/ true = playing, false = frozen (start or game over)\n        let score = 0;\n\n        \/\/ bird\n        let bird = {\n            x: 120,                          \/\/ fixed horizontal position\n            y: H \/ 2,\n            vy: 0\n        };\n\n        \/\/ pipes array\n        let pipes = [];\n\n        \/\/ ----- helper: generate a new pipe pair (x starts off screen right) -----\n        function createPipePair(xPos = W) {\n            \/\/ ensure gap is fully inside canvas (top pipe min 40, bottom pipe max H-40)\n            const minTop = 35;\n            const maxTop = H - GAP_HEIGHT - 35;\n            const topHeight = Math.floor(Math.random() * (maxTop - minTop + 1)) + minTop;\n\n            return {\n                x: xPos,\n                top: topHeight,               \/\/ height (length) of upper pipe (drawn from ceiling)\n                bottom: H - (topHeight + GAP_HEIGHT),  \/\/ height of lower pipe (from floor)\n                passed: false                  \/\/ whether score already counted for this pair\n            };\n        }\n\n        \/\/ ----- reset everything to fresh game -----\n        function fullReset() {\n            gameActive = true;\n            score = 0;\n            updateScoreDisplay();\n            bird.y = H \/ 2;\n            bird.vy = 0;\n\n            \/\/ start with two pipes: one at 600, next one further\n            pipes = [];\n            pipes.push(createPipePair(W));                \/\/ first pipe at right edge\n            pipes.push(createPipePair(W + PIPE_SPACING)); \/\/ second pipe already waiting\n        }\n\n        \/\/ ----- collision test (bird circle vs pipes) -----\n        function collidesWithPipe() {\n            \/\/ bird edges\n            const birdLeft = bird.x - BIRD_RADIUS;\n            const birdRight = bird.x + BIRD_RADIUS;\n            const birdTop = bird.y - BIRD_RADIUS;\n            const birdBottom = bird.y + BIRD_RADIUS;\n\n            for (let p of pipes) {\n                const pipeLeft = p.x;\n                const pipeRight = p.x + PIPE_WIDTH;\n\n                \/\/ if bird is horizontally overlapping pipe column\n                if (birdRight > pipeLeft && birdLeft < pipeRight) {\n                    \/\/ upper pipe collision (from y=0 to p.top)\n                    if (birdTop < p.top) return true;\n                    \/\/ lower pipe collision (from H - p.bottom to H)\n                    if (birdBottom > H - p.bottom) return true;\n                }\n                \/\/ also check if bird is beyond left edge (fail safe)\n                if (birdLeft < 0) return true;   \/\/ hit left wall (but pipe collision covers left side, still fine)\n            }\n            \/\/ ground \/ ceiling (strict)\n            if (birdTop < 0 || birdBottom > H) return true;\n            return false;\n        }\n\n        \/\/ ----- update score, check pipe passing -----\n        function updateScoreAndPipePass() {\n            for (let p of pipes) {\n                \/\/ if pipe not yet passed and bird has passed the right edge of pipe (with its left side)\n                if (!p.passed && bird.x - BIRD_RADIUS > p.x + PIPE_WIDTH) {\n                    p.passed = true;\n                    score++;\n                    updateScoreDisplay();\n                }\n            }\n        }\n\n        \/\/ ----- update pipes (move left, generate new, remove off-screen) -----\n        function movePipesAndAdd() {\n            \/\/ move all pipes left\n            for (let p of pipes) {\n                p.x -= PIPE_SPEED;\n            }\n\n            \/\/ remove pipes that are completely off screen (x + width < 0)\n            pipes = pipes.filter(p => p.x + PIPE_WIDTH > 0);\n\n            \/\/ add new pipe if the last pipe is far enough to the right\n            if (pipes.length === 0 || pipes[pipes.length - 1].x <= W - PIPE_SPACING) {\n                pipes.push(createPipePair(W));\n            }\n        }\n\n        \/\/ ----- main game update (called every frame) -----\n        function gameUpdate() {\n            if (!gameActive) return;\n\n            \/\/ 1. bird physics\n            bird.vy += GRAVITY;\n            if (bird.vy > MAX_FALL_SPEED) bird.vy = MAX_FALL_SPEED;\n            bird.y += bird.vy;\n\n            \/\/ 2. move pipes & manage generation\n            movePipesAndAdd();\n\n            \/\/ 3. scoring (check before collision to allow exact pass)\n            updateScoreAndPipePass();\n\n            \/\/ 4. collision detection (if collision -> game over)\n            if (collidesWithPipe()) {\n                gameActive = false;   \/\/ game over, stop updates\n            }\n\n            \/\/ 5. optional: if bird goes too far below (already handled in collision)\n        }\n\n        \/\/ ----- draw everything -----\n        function draw() {\n            ctx.clearRect(0, 0, W, H);\n\n            \/\/ ---- sky details ----\n            ctx.fillStyle = '#c1e7f0';\n            ctx.globalAlpha = 0.3;\n            for (let i = 0; i < 8; i++) {\n                ctx.beginPath();\n                ctx.arc(70 + i * 60, 60 + i * 10, 25, 0, Math.PI * 2);\n                ctx.fillStyle = '#f9fbc6';\n                ctx.fill();\n            }\n            ctx.globalAlpha = 1.0;\n\n            \/\/ ---- draw pipes ----\n            pipes.forEach(p => {\n                const pipeTopHeight = p.top;\n                const pipeBottomHeight = p.bottom;\n\n                \/\/ upper pipe (with gradient)\n                const grdTop = ctx.createLinearGradient(p.x, 0, p.x + PIPE_WIDTH, 0);\n                grdTop.addColorStop(0, '#3c8d5e');\n                grdTop.addColorStop(0.7, '#1f5f3a');\n                ctx.fillStyle = grdTop;\n                ctx.fillRect(p.x, 0, PIPE_WIDTH, pipeTopHeight);\n                \/\/ rim \/ detail\n                ctx.fillStyle = '#7eaa64';\n                ctx.fillRect(p.x - 5, pipeTopHeight - 20, PIPE_WIDTH + 10, 16);\n                ctx.fillStyle = '#b2d48b';\n                ctx.fillRect(p.x - 3, pipeTopHeight - 18, PIPE_WIDTH + 6, 12);\n\n                \/\/ lower pipe (from bottom)\n                const bottomY = H - pipeBottomHeight;\n                const grdBottom = ctx.createLinearGradient(p.x, H, p.x + PIPE_WIDTH, H);\n                grdBottom.addColorStop(0, '#3c8d5e');\n                grdBottom.addColorStop(0.7, '#1f5f3a');\n                ctx.fillStyle = grdBottom;\n                ctx.fillRect(p.x, bottomY, PIPE_WIDTH, pipeBottomHeight);\n                \/\/ rim\n                ctx.fillStyle = '#7eaa64';\n                ctx.fillRect(p.x - 5, bottomY, PIPE_WIDTH + 10, 16);\n                ctx.fillStyle = '#b2d48b';\n                ctx.fillRect(p.x - 3, bottomY + 2, PIPE_WIDTH + 6, 12);\n            });\n\n            \/\/ ---- bird (glowing circle) ----\n            \/\/ outer glow\n            ctx.shadowColor = '#f5e56b';\n            ctx.shadowBlur = 22;\n            ctx.beginPath();\n            ctx.arc(bird.x, bird.y, BIRD_RADIUS + 2, 0, 2 * Math.PI);\n            ctx.fillStyle = '#fcd462';\n            ctx.fill();\n            ctx.shadowBlur = 10;\n            \/\/ main body\n            ctx.beginPath();\n            ctx.arc(bird.x, bird.y, BIRD_RADIUS, 0, 2 * Math.PI);\n            ctx.fillStyle = '#ffc164';\n            ctx.fill();\n            \/\/ eye\n            ctx.shadowBlur = 0;\n            ctx.beginPath();\n            ctx.arc(bird.x - 4, bird.y - 5, 4, 0, 2 * Math.PI);\n            ctx.fillStyle = 'white';\n            ctx.fill();\n            ctx.beginPath();\n            ctx.arc(bird.x - 5, bird.y - 6, 2, 0, 2 * Math.PI);\n            ctx.fillStyle = '#0b1f24';\n            ctx.fill();\n            \/\/ beak\n            ctx.beginPath();\n            ctx.moveTo(bird.x + 8, bird.y - 6);\n            ctx.lineTo(bird.x + 18, bird.y - 2);\n            ctx.lineTo(bird.x + 8, bird.y + 2);\n            ctx.fillStyle = '#f79b4b';\n            ctx.fill();\n\n            \/\/ ---- game over overlay if inactive ----\n            if (!gameActive && pipes.length > 0) {   \/\/ either start or game over\n                ctx.globalAlpha = 0.7;\n                ctx.fillStyle = '#08222b';\n                ctx.fillRect(0, 0, W, H);\n                ctx.globalAlpha = 1;\n                ctx.font = 'bold 38px \"Segoe UI\", \"Courier New\", monospace';\n                ctx.fillStyle = '#fadf8a';\n                ctx.shadowBlur = 18;\n                ctx.shadowColor = '#000';\n                ctx.fillText('\ud83d\udca5', 240, 170);\n                ctx.font = 'bold 30px \"Segoe UI\", sans-serif';\n                ctx.fillText('click \/ space', 170, 260);\n                ctx.shadowBlur = 0;\n            } else if (!gameActive && pipes.length === 0) {\n                \/\/ extremely rare, but fallback\n            }\n\n            \/\/ reset shadow\n            ctx.shadowBlur = 0;\n            ctx.shadowColor = 'transparent';\n        }\n\n        \/\/ ----- animation loop -----\n        function animate() {\n            if (gameActive) {\n                gameUpdate();\n            }\n            draw();\n            requestAnimationFrame(animate);\n        }\n\n        \/\/ ----- helper to update score display -----\n        function updateScoreDisplay() {\n            scoreSpan.textContent = score;\n        }\n\n        \/\/ ----- jump action (space, click, restart) -----\n        function handleJump(e) {\n            \/\/ prevent space from scrolling \/ click double actions\n            if (e.type === 'keydown') {\n                if (e.code === 'Space') {\n                    e.preventDefault();\n                } else {\n                    return;  \/\/ only space triggers jump\n                }\n            }\n\n            if (!gameActive) {\n                \/\/ if game over, restart fresh on any jump-like action (space\/click)\n                fullReset();\n                return;\n            }\n\n            \/\/ game active: apply jump (only if gameActive true)\n            bird.vy = JUMP_FORCE;\n\n            \/\/ tiny wing flap effect (no logic change, just fun)\n            \/\/ you could add a small animation tweak but it's fine.\n        }\n\n        \/\/ ----- restart via button (explicit restart) -----\n        function restartGame() {\n            fullReset();\n        }\n\n        \/\/ ----- initial setup: draw welcome screen (game not active) -----\n        function setupWelcome() {\n            gameActive = false;         \/\/ not playing, show overlay\n            bird.y = H \/ 2;\n            bird.vy = 0;\n            \/\/ create two static pipes for preview (not moving)\n            pipes = [];\n            pipes.push({ x: 320, top: 120, bottom: H - (120 + GAP_HEIGHT), passed: false });\n            pipes.push({ x: 600, top: 180, bottom: H - (180 + GAP_HEIGHT), passed: false });\n            score = 0;\n            updateScoreDisplay();\n            draw();  \/\/ immediate draw\n        }\n\n        \/\/ ----- event listeners -----\n        window.addEventListener('keydown', handleJump);\n        canvas.addEventListener('click', handleJump);\n        document.getElementById('restartBtn').addEventListener('click', (e) => {\n            e.stopPropagation();   \/\/ avoid button click triggering canvas jump\n            restartGame();\n        });\n\n        \/\/ also prevent context menu on canvas (avoid disturbance)\n        canvas.addEventListener('contextmenu', (e) => e.preventDefault());\n\n        \/\/ start animation, but game not active (welcome screen)\n        setupWelcome();\n        animate();\n\n        \/\/ extra safety: ensure space doesn't cause any page scroll (also in global)\n        window.addEventListener('keyup', (e) => { if (e.code === 'Space') e.preventDefault(); });\n    })();\n<\/script>\n<\/body>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>sky glide \u00b7 bird game 0 \u21bb start \u2423 space \/ click \u00b7 fly little bird<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-238","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/toolorama.in\/index.php\/wp-json\/wp\/v2\/posts\/238","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/toolorama.in\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/toolorama.in\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/toolorama.in\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/toolorama.in\/index.php\/wp-json\/wp\/v2\/comments?post=238"}],"version-history":[{"count":1,"href":"https:\/\/toolorama.in\/index.php\/wp-json\/wp\/v2\/posts\/238\/revisions"}],"predecessor-version":[{"id":239,"href":"https:\/\/toolorama.in\/index.php\/wp-json\/wp\/v2\/posts\/238\/revisions\/239"}],"wp:attachment":[{"href":"https:\/\/toolorama.in\/index.php\/wp-json\/wp\/v2\/media?parent=238"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/toolorama.in\/index.php\/wp-json\/wp\/v2\/categories?post=238"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/toolorama.in\/index.php\/wp-json\/wp\/v2\/tags?post=238"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}