CMU Coding Bootcamp

feat(html): dino

thecoded.prof 0997b9b6 e973da63

verified
+311 -2
+42
html/css/dino.css
··· 1 + body { 2 + margin: 0; 3 + padding: 0; 4 + display: flex; 5 + justify-content: center; 6 + align-items: center; 7 + min-height: 100vh; 8 + background-color: #f7f7f7; 9 + font-family: Arial, sans-serif; 10 + } 11 + 12 + .game-container { 13 + position: relative; 14 + } 15 + 16 + #gameCanvas { 17 + border: 2px solid #535353; 18 + background-color: #fff; 19 + display: block; 20 + } 21 + 22 + #score { 23 + position: absolute; 24 + top: 10px; 25 + right: 10px; 26 + font-size: 20px; 27 + font-weight: bold; 28 + color: #535353; 29 + } 30 + 31 + #gameOver { 32 + position: absolute; 33 + width: 100%; 34 + text-align: center; 35 + top: 50%; 36 + left: 50%; 37 + transform: translate(-50%, -50%); 38 + font-size: 24px; 39 + font-weight: bold; 40 + color: #535353; 41 + display: none; 42 + }
+19
html/dino.html
··· 1 + <!doctype html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8" /> 5 + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 + <title>Dino Game</title> 7 + <link rel="stylesheet" href="css/dino.css" /> 8 + </head> 9 + <body> 10 + <div class="game-container"> 11 + <canvas id="gameCanvas" width="800" height="600"></canvas> 12 + <div id="score">Score: 0</div> 13 + <div id="gameOver"> 14 + Game Over! Press <kbd>Space</kbd> to Restart 15 + </div> 16 + </div> 17 + <script src="js/dino.js"></script> 18 + </body> 19 + </html>
+1 -1
html/index.html
··· 19 19 gap: 1rem; 20 20 " 21 21 > 22 - <div class="card" onclick="openProject('temp')"></div> 22 + <div class="card" onclick="openProject('dino')">Dino</div> 23 23 <div class="card" onclick="openProject('temp')"></div> 24 24 <div class="card" onclick="openProject('temp')"></div> 25 25 </div>
+246
html/js/dino.js
··· 1 + const canvas = document.getElementById("gameCanvas"); 2 + const ctx = canvas.getContext("2d"); 3 + const scoreElement = document.getElementById("score"); 4 + const gameOverElement = document.getElementById("gameOver"); 5 + 6 + let score = 0; 7 + let gameSpeed = 3; 8 + let isGameOver = false; 9 + let frameCount = 0; 10 + let nextObstacleFrame = 10; 11 + 12 + const dino = { 13 + x: 50, 14 + y: 150, 15 + width: 40, 16 + height: 50, 17 + dy: 0, 18 + gravity: 0.3, 19 + jumpPower: -8, 20 + isJumping: false, 21 + isDucking: false, 22 + 23 + draw() { 24 + ctx.fillStyle = "#8aacdf"; 25 + ctx.fillRect(this.x, this.y, this.width, this.height); 26 + }, 27 + 28 + update() { 29 + if (this.isDucking) { 30 + this.y = 170; 31 + this.height = 30; 32 + } else { 33 + this.height = 50; 34 + } 35 + 36 + if (this.isJumping) { 37 + this.dy += this.gravity; 38 + this.y += this.dy; 39 + 40 + if (this.y >= 150) { 41 + this.y = 150; 42 + this.isJumping = false; 43 + this.dy = 0; 44 + } 45 + } 46 + }, 47 + 48 + duck() { 49 + if (!this.isJumping && !isGameOver) { 50 + this.isDucking = true; 51 + } else if (this.isJumping && !isGameOver) { 52 + this.dy += this.gravity * 10; 53 + this.y += this.dy; 54 + } 55 + }, 56 + 57 + jump() { 58 + if (!this.isJumping && !isGameOver) { 59 + this.isJumping = true; 60 + this.dy = this.jumpPower; 61 + } 62 + }, 63 + }; 64 + 65 + const obstacles = []; 66 + 67 + class Obstacle { 68 + constructor() { 69 + this.x = canvas.width; 70 + const type = Math.random(); 71 + if (type < 0.5) { 72 + this.width = 20; 73 + this.height = 40; 74 + this.y = 160; 75 + } else if (type < 0.8) { 76 + this.width = 20; 77 + this.height = 25; 78 + this.y = 175; 79 + } else { 80 + this.width = 40; 81 + this.height = 32; 82 + this.y = 168; 83 + } 84 + } 85 + 86 + draw() { 87 + ctx.fillStyle = "#40a02b"; 88 + ctx.fillRect(this.x, this.y, this.width, this.height); 89 + } 90 + 91 + update() { 92 + this.x -= gameSpeed; 93 + } 94 + } 95 + 96 + class BirdObstacle { 97 + constructor() { 98 + this.x = canvas.width; 99 + this.width = 30; 100 + this.height = 20; 101 + const heightType = Math.floor(Math.random() * 3); 102 + if (heightType === 0) { 103 + this.y = 170; 104 + } else if (heightType === 1) { 105 + this.y = 150; 106 + } else { 107 + this.y = 130; 108 + } 109 + } 110 + 111 + draw() { 112 + ctx.fillStyle = "#dd7878"; 113 + ctx.fillRect(this.x, this.y, this.width, this.height); 114 + } 115 + 116 + update() { 117 + this.x -= gameSpeed; 118 + } 119 + } 120 + 121 + function checkCollision(dino, obstacle) { 122 + return ( 123 + dino.x < obstacle.x + obstacle.width && 124 + dino.x + dino.width > obstacle.x && 125 + dino.y < obstacle.y + obstacle.height && 126 + dino.y + dino.height > obstacle.y 127 + ); 128 + } 129 + 130 + function spawnObstacle() { 131 + if (frameCount >= nextObstacleFrame) { 132 + const type = Math.random(); 133 + if (type < 0.9) { 134 + obstacles.push(new Obstacle()); 135 + } else { 136 + obstacles.push(new BirdObstacle()); 137 + } 138 + 139 + const baseMin = 80; 140 + const baseMax = 140; 141 + 142 + const speedFactor = 3 / gameSpeed; 143 + 144 + const minInterval = Math.floor(baseMin * speedFactor); 145 + const maxInterval = Math.floor(baseMax * speedFactor); 146 + nextObstacleFrame = 147 + frameCount + 148 + Math.floor(Math.random() * (maxInterval - minInterval) + minInterval); 149 + } 150 + } 151 + 152 + function updateScore() { 153 + if (!isGameOver) { 154 + score++; 155 + scoreElement.textContent = `Score: ${Math.floor(score / 10)}`; 156 + 157 + // Increase difficulty 158 + if (score % 500 === 0) { 159 + gameSpeed += 0.5; 160 + } 161 + } 162 + } 163 + 164 + function gameLoop() { 165 + if (isGameOver) return; 166 + 167 + ctx.clearRect(0, 0, canvas.width, canvas.height); 168 + 169 + ctx.strokeStyle = "#535353"; 170 + ctx.beginPath(); 171 + ctx.moveTo(0, 200); 172 + ctx.lineTo(canvas.width, 200); 173 + ctx.stroke(); 174 + 175 + dino.update(); 176 + dino.draw(); 177 + 178 + spawnObstacle(); 179 + 180 + for (let i = obstacles.length - 1; i >= 0; i--) { 181 + obstacles[i].update(); 182 + obstacles[i].draw(); 183 + 184 + if (checkCollision(dino, obstacles[i])) { 185 + isGameOver = true; 186 + gameOverElement.style.display = "block"; 187 + } 188 + 189 + if (obstacles[i].x + obstacles[i].width < 0) { 190 + obstacles.splice(i, 1); 191 + } 192 + } 193 + 194 + updateScore(); 195 + frameCount++; 196 + 197 + requestAnimationFrame(gameLoop); 198 + } 199 + 200 + function resetGame() { 201 + score = 0; 202 + gameSpeed = 3; 203 + isGameOver = false; 204 + frameCount = 0; 205 + obstacles.length = 0; 206 + dino.y = 150; 207 + dino.dy = 0; 208 + dino.isJumping = false; 209 + gameOverElement.style.display = "none"; 210 + nextObstacleFrame = 10; 211 + gameLoop(); 212 + } 213 + 214 + document.addEventListener("keydown", (e) => { 215 + e.preventDefault(); 216 + switch (e.code) { 217 + case "ArrowUp": 218 + case "Space": { 219 + if (isGameOver) { 220 + resetGame(); 221 + } else { 222 + dino.jump(); 223 + } 224 + break; 225 + } 226 + case "ArrowDown": { 227 + dino.duck(); 228 + break; 229 + } 230 + default: 231 + } 232 + }); 233 + 234 + document.addEventListener("keyup", (e) => { 235 + switch (e.code) { 236 + case "ArrowDown": { 237 + e.preventDefault(); 238 + dino.isDucking = false; 239 + if (!dino.isJumping) { 240 + dino.y = 150; 241 + } 242 + } 243 + } 244 + }); 245 + 246 + gameLoop();
+3 -1
html/js/script.js
··· 1 - const projects = {}; 1 + const projects = { 2 + dino: "dino.html", 3 + }; 2 4 3 5 const openProject = (project) => { 4 6 if (Object.keys(projects).includes(project)) {