temple-run/ ├── index.html # complete game (canvas + logic + style) └── README.md # this file
1. Create a new repo: `temple-run` 2. Upload `index.html` and `README.md` 3. Enable **GitHub Pages** in Settings → Pages → branch `main` → Save 4. Play online at: `https://yourusername.github.io/temple-run/` temple run github
// ----- GAME STATE ----- let gameRunning = true; let score = 0; let highScore = localStorage.getItem('templeHigh') ? parseInt(localStorage.getItem('templeHigh')) : 0; document.getElementById('highScoreValue').innerText = highScore; // ----- PLAYER ----- const LANE_COUNT = 3; const LANE_WIDTH = 120; const PLAYER_WIDTH = 48; const PLAYER_HEIGHT = 52; // lane positions (center X) const laneXs = [220, 400, 580]; let currentLane = 1; // 0=left,1=middle,2=right let playerY = canvas.height - 100; // ground Y let isJumping = false; let jumpVelocity = 0; const GRAVITY = 0.8; const JUMP_POWER = -12; let groundY = canvas.height - 100; // ----- OBSTACLES ----- let obstacles = []; let obstacleTimer = 0; const OBSTACLE_BASE_INTERVAL = 70; // frames const OBSTACLE_WIDTH = 40; const OBSTACLE_HEIGHT = 48; // ----- COINS ----- let coins = []; let coinTimer = 0; const COIN_BASE_INTERVAL = 45; const COIN_WIDTH = 28; const COIN_HEIGHT = 28; // ----- VISUALS / FX ----- let frame = 0; let cameraShake = 0; // ----- helper functions ----- function updateUI() document.getElementById('scoreValue').innerText = Math.floor(score); if(score > highScore) highScore = Math.floor(score); localStorage.setItem('templeHigh', highScore); document.getElementById('highScoreValue').innerText = highScore; function resetGame() gameRunning = true; score = 0; obstacles = []; coins = []; currentLane = 1; isJumping = false; jumpVelocity = 0; playerY = groundY; obstacleTimer = 15; // small delay after reset coinTimer = 8; cameraShake = 0; updateUI(); function addObstacle() let lane = Math.floor(Math.random() * LANE_COUNT); obstacles.push( x: laneXs[lane] - OBSTACLE_WIDTH/2, y: groundY + 8, // slightly above ground to look like standing width: OBSTACLE_WIDTH, height: OBSTACLE_HEIGHT, lane: lane, active: true ); function addCoin() let lane = Math.floor(Math.random() * LANE_COUNT); // avoid overlapping exactly with fresh obstacle? not critical, fun chaos coins.push( x: laneXs[lane] - COIN_WIDTH/2, y: groundY - 10, width: COIN_WIDTH, height: COIN_HEIGHT, lane: lane, collected: false ); function updateMovement() if(!gameRunning) return; // jump physics if(isJumping) playerY += jumpVelocity; jumpVelocity += GRAVITY; if(playerY >= groundY) playerY = groundY; isJumping = false; jumpVelocity = 0; // move obstacles + collision + score gain on pass for(let i=0; i<obstacles.length; i++) let obs = obstacles[i]; obs.x -= 5; // scroll speed // collision detection (only if not jumping over? simple version: if touching and not jumping) let playerRect = x: laneXs[currentLane] - PLAYER_WIDTH/2, y: playerY, w: PLAYER_WIDTH, h: PLAYER_HEIGHT ; let obsRect = x: obs.x, y: obs.y, w: obs.width, h: obs.height ; if(!isJumping && playerRect.x < obsRect.x+obsRect.w && playerRect.x+playerRect.w > obsRect.x && playerRect.y < obsRect.y+obsRect.h && playerRect.y+playerRect.h > obsRect.y) gameRunning = false; cameraShake = 12; // remove if offscreen if(obs.x + obs.width < 0) obstacles.splice(i,1); i--; // coins collection + scoring for(let i=0; i<coins.length; i++) let coin = coins[i]; coin.x -= 5; let playerRect = x: laneXs[currentLane] - PLAYER_WIDTH/2, y: playerY, w: PLAYER_WIDTH, h: PLAYER_HEIGHT ; let coinRect = x: coin.x, y: coin.y, w: COIN_WIDTH, h: COIN_HEIGHT ; if(playerRect.x < coinRect.x+coinRect.w && playerRect.x+playerRect.w > coinRect.x && playerRect.y < coinRect.y+coinRect.h && playerRect.y+playerRect.h > coinRect.y) // collect coin score += 10; updateUI(); coins.splice(i,1); i--; else if(coin.x + COIN_WIDTH < 0) coins.splice(i,1); i--; // dynamic spawn if(gameRunning) obstacleTimer--; if(obstacleTimer <= 0) let interval = Math.max(35, OBSTACLE_BASE_INTERVAL - Math.floor(score/500)); addObstacle(); obstacleTimer = interval; coinTimer--; if(coinTimer <= 0) let coinInterval = Math.max(25, COIN_BASE_INTERVAL - Math.floor(score/700)); addCoin(); coinTimer = coinInterval; // increase score over time (distance) score += 0.35; updateUI(); // camera shake fade if(cameraShake > 0) cameraShake -= 0.6; else cameraShake = 0; // ----- DRAW EVERYTHING ----- function draw() ctx.clearRect(0,0,canvas.width,canvas.height); // apply camera shake let shakeX = (Math.random() * cameraShake) - (cameraShake/2); let shakeY = (Math.random() * cameraShake*0.6) - (cameraShake*0.3); ctx.save(); ctx.translate(shakeX, shakeY); // ---- FLOOR & TEMPLE ATMOSPHERE ---- // stone floor pattern ctx.fillStyle = "#4a3728"; ctx.fillRect(0, groundY+20, canvas.width, canvas.height-groundY-10); ctx.fillStyle = "#6b4c3b"; for(let i=0;i<20;i++) ctx.fillRect(i*70, groundY+18, 35, 8); // background: temple wall ctx.fillStyle = "#2c2118"; ctx.fillRect(0,0,canvas.width, groundY-20); // torches for(let i=0;i<6;i++) ctx.fillStyle = "#c97e3a"; ctx.fillRect(50+i*150, groundY-70, 12, 60); ctx.fillStyle = "#ffaa44"; ctx.beginPath(); ctx.arc(56+i*150, groundY-76, 10, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = "#ff6600"; ctx.beginPath(); ctx.arc(56+i*150, groundY-78, 5, 0, Math.PI*2); ctx.fill(); // ---- LANE MARKERS ---- ctx.strokeStyle = "#e8c468"; ctx.lineWidth = 3; for(let i=0; i<=LANE_COUNT; i++) let x = (i * LANE_WIDTH) + 100; ctx.beginPath(); ctx.setLineDash([12, 20]); ctx.moveTo(x, groundY-10); ctx.lineTo(x, groundY+35); ctx.stroke(); ctx.setLineDash([]); // ---- OBSTACLES (idols / pillars) ---- for(let obs of obstacles) // shadow ctx.fillStyle = "#2f241b"; ctx.fillRect(obs.x+4, obs.y+6, obs.width, obs.height); ctx.fillStyle = "#8b5a2b"; ctx.fillRect(obs.x, obs.y, obs.width, obs.height); ctx.fillStyle = "#b87c4f"; ctx.fillRect(obs.x+6, obs.y-8, obs.width-12, 12); ctx.fillStyle = "#d9a13b"; ctx.beginPath(); ctx.ellipse(obs.x+obs.width/2, obs.y-4, 12, 6, 0, 0, Math.PI*2); ctx.fill(); // scary eyes ctx.fillStyle = "#ff2200"; ctx.fillRect(obs.x+8, obs.y+15, 8, 8); ctx.fillRect(obs.x+obs.width-16, obs.y+15, 8, 8); // ---- COINS ---- for(let coin of coins) ctx.fillStyle = "#f5d742"; ctx.shadowBlur = 8; ctx.shadowColor = "#ffbf00"; ctx.beginPath(); ctx.ellipse(coin.x+COIN_WIDTH/2, coin.y+COIN_HEIGHT/2, COIN_WIDTH/2, COIN_HEIGHT/2, 0, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = "#f5a623"; ctx.beginPath(); ctx.ellipse(coin.x+COIN_WIDTH/2, coin.y+COIN_HEIGHT/2, COIN_WIDTH/3, COIN_HEIGHT/3, 0, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = "#ffffffcc"; ctx.font = "bold 18 monospace"; ctx.fillText("★", coin.x+6, coin.y+22); ctx.shadowBlur = 0; // ---- PLAYER (RUNNER) ---- let playerX = laneXs[currentLane] - PLAYER_WIDTH/2; let bobOffset = isJumping ? 0 : Math.sin(frame * 0.2) * 2; ctx.fillStyle = "#2c5f2d"; ctx.shadowBlur = 0; ctx.fillRect(playerX, playerY + bobOffset, PLAYER_WIDTH, PLAYER_HEIGHT); ctx.fillStyle = "#b87333"; ctx.fillRect(playerX+8, playerY+10 + bobOffset, 8, 16); ctx.fillRect(playerX+PLAYER_WIDTH-16, playerY+10 + bobOffset, 8, 16); ctx.fillStyle = "#f4c542"; ctx.beginPath(); ctx.arc(playerX+PLAYER_WIDTH/2, playerY-5 + bobOffset, 14, 0, Math.PI*2); ctx.fill(); ctx.fillStyle = "#000"; ctx.fillRect(playerX+12, playerY-2 + bobOffset, 6, 6); ctx.fillRect(playerX+PLAYER_WIDTH-18, playerY-2 + bobOffset, 6, 6); // scarf ctx.fillStyle = "#e34234"; ctx.fillRect(playerX+12, playerY+28+bobOffset, PLAYER_WIDTH-24, 8); // ---- GAME OVER MESSAGE ---- if(!gameRunning) ctx.font = "bold 42 'Courier New'"; ctx.shadowBlur = 0; ctx.fillStyle = "#ffbb66"; ctx.shadowColor = "black"; ctx.fillText("GAME OVER", canvas.width/2-130, 120); ctx.font = "24px monospace"; ctx.fillStyle = "#fadfaa"; ctx.fillText("tap RUN AGAIN", canvas.width/2-90, 190); // ---- SCORE ON CANVAS ---- ctx.font = "bold 24 'Courier New'"; ctx.fillStyle = "#ffeaac"; ctx.shadowBlur = 2; ctx.fillText("🏃 " + Math.floor(score), 25, 60); ctx.restore(); // end shake frame++; // ----- CONTROLS (keyboard)----- function handleKey(e) key === 'r') if(!gameRunning) return; e.preventDefault(); if(key === 'ArrowLeft' // ----- ANIMATION LOOP ----- function gameLoop() updateMovement(); draw(); requestAnimationFrame(gameLoop); // event listeners window.addEventListener('keydown', handleKey); document.getElementById('resetBtn').addEventListener('click', () => resetGame(); ); // mobile friendly (simple touch for lane change) canvas.addEventListener('click', (e) => if(!gameRunning) return; let rect = canvas.getBoundingClientRect(); let clickX = (e.clientX - rect.left) * (canvas.width/rect.width); if(clickX < canvas.width/3) currentLane = Math.max(0, currentLane-1); else if(clickX > 2*canvas.width/3) currentLane = Math.min(LANE_COUNT-1, currentLane+1); else if(!isJumping) isJumping = true; jumpVelocity = JUMP_POWER; ); // init resetGame(); gameLoop(); )(); </script> </body> </html> # 🏃 Temple Run: Endless Chase A browser-based infinite runner inspired by the classic Temple Run. Dodge ancient obstacles, grab golden coins, and survive as long as you can! temple-run/ ├── index
> **Temple Run** – an endless runner game in pure HTML/CSS/JS. Dodge obstacles, collect coins, survive the ancient temple. Works on desktop & mobile. No dependencies. Enable **GitHub Pages** in Settings → Pages →
The game includes: - 3-lane dodging - Jump mechanic - Coins + score - Persistent high score - Increasing difficulty - Camera shake on collision - Touch & keyboard support
index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> <title>Temple Run - GitHub Game</title> <style> * margin: 0; padding: 0; box-sizing: border-box; user-select: none; body background: linear-gradient(145deg, #0a2f1f 0%, #05180e 100%); min-height: 100vh; display: flex; justify-content: center; align-items: center; font-family: 'Courier New', 'Monaco', monospace; .game-container padding: 20px; border-radius: 28px; background: rgba(0,0,0,0.3); box-shadow: 0 20px 35px rgba(0,0,0,0.5); canvas display: block; margin: 0 auto; border-radius: 16px; box-shadow: 0 0 0 4px #d4af37, 0 0 0 8px #3e2a1f; cursor: pointer; .info-panel display: flex; justify-content: space-between; align-items: center; margin-top: 20px; padding: 12px 24px; background: #1e1a0c; border-radius: 60px; color: #f7e05e; text-shadow: 0 2px 0 #5a3e1a; font-weight: bold; font-size: 1.4rem; gap: 30px; flex-wrap: wrap; justify-content: center; .score-box, .high-box background: #000000aa; backdrop-filter: blur(4px); padding: 8px 20px; border-radius: 40px; letter-spacing: 1px; button background: #e25822; border: none; font-family: inherit; font-weight: bold; font-size: 1.2rem; padding: 8px 24px; border-radius: 60px; color: white; text-shadow: 0 1px 0 #7a2e0a; cursor: pointer; transition: 0.1s linear; box-shadow: 0 5px 0 #752e0a; button:active transform: translateY(2px); box-shadow: 0 2px 0 #752e0a; .controls display: flex; gap: 15px; background: #2d2418aa; padding: 8px 20px; border-radius: 60px; font-size: 0.9rem; .controls span background: #0f0f0fcc; padding: 5px 12px; border-radius: 40px; color: #ffd966; @media (max-width: 780px) .info-panel flex-direction: column; align-items: stretch; gap: 12px; .controls justify-content: center; .score-box, .high-box text-align: center; </style> </head> <body> <div> <div class="game-container"> <canvas id="gameCanvas" width="800" height="500"></canvas> <div class="info-panel"> <div class="score-box">🏆 SCORE: <span id="scoreValue">0</span></div> <div class="high-box">👑 BEST: <span id="highScoreValue">0</span></div> <button id="resetBtn">🔄 RUN AGAIN</button> <div class="controls"> <span>⬅️ A / ←</span> <span>➡️ D / →</span> <span>⬆️ W / ↑ (jump)</span> </div> </div> </div> <p style="text-align:center; margin-top:16px; color:#d4c9a3;">🏃♂️ Dodge obstacles | Collect coins | Survive the temple!</p> </div> <script> (function() // ----- CANVAS ----- const canvas = document.getElementById('gameCanvas'); const ctx = canvas.getContext('2d');
Let me know if you'd like me to add **power-ups**, **mobile swipe controls**, or a **start screen**! </code></pre>