diff --git a/html/css/dino.css b/html/css/dino.css new file mode 100644 index 0000000..bd90cdc --- /dev/null +++ b/html/css/dino.css @@ -0,0 +1,42 @@ +body { + margin: 0; + padding: 0; + display: flex; + justify-content: center; + align-items: center; + min-height: 100vh; + background-color: #f7f7f7; + font-family: Arial, sans-serif; +} + +.game-container { + position: relative; +} + +#gameCanvas { + border: 2px solid #535353; + background-color: #fff; + display: block; +} + +#score { + position: absolute; + top: 10px; + right: 10px; + font-size: 20px; + font-weight: bold; + color: #535353; +} + +#gameOver { + position: absolute; + width: 100%; + text-align: center; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: 24px; + font-weight: bold; + color: #535353; + display: none; +} diff --git a/html/dino.html b/html/dino.html new file mode 100644 index 0000000..cb5f81f --- /dev/null +++ b/html/dino.html @@ -0,0 +1,19 @@ + + + + + + Dino Game + + + +
+ +
Score: 0
+
+ Game Over! Press Space to Restart +
+
+ + + diff --git a/html/index.html b/html/index.html index 6cc4b66..a07f23f 100644 --- a/html/index.html +++ b/html/index.html @@ -19,7 +19,7 @@ gap: 1rem; " > -
+
Dino
diff --git a/html/js/dino.js b/html/js/dino.js new file mode 100644 index 0000000..fba1829 --- /dev/null +++ b/html/js/dino.js @@ -0,0 +1,246 @@ +const canvas = document.getElementById("gameCanvas"); +const ctx = canvas.getContext("2d"); +const scoreElement = document.getElementById("score"); +const gameOverElement = document.getElementById("gameOver"); + +let score = 0; +let gameSpeed = 3; +let isGameOver = false; +let frameCount = 0; +let nextObstacleFrame = 10; + +const dino = { + x: 50, + y: 150, + width: 40, + height: 50, + dy: 0, + gravity: 0.3, + jumpPower: -8, + isJumping: false, + isDucking: false, + + draw() { + ctx.fillStyle = "#8aacdf"; + ctx.fillRect(this.x, this.y, this.width, this.height); + }, + + update() { + if (this.isDucking) { + this.y = 170; + this.height = 30; + } else { + this.height = 50; + } + + if (this.isJumping) { + this.dy += this.gravity; + this.y += this.dy; + + if (this.y >= 150) { + this.y = 150; + this.isJumping = false; + this.dy = 0; + } + } + }, + + duck() { + if (!this.isJumping && !isGameOver) { + this.isDucking = true; + } else if (this.isJumping && !isGameOver) { + this.dy += this.gravity * 10; + this.y += this.dy; + } + }, + + jump() { + if (!this.isJumping && !isGameOver) { + this.isJumping = true; + this.dy = this.jumpPower; + } + }, +}; + +const obstacles = []; + +class Obstacle { + constructor() { + this.x = canvas.width; + const type = Math.random(); + if (type < 0.5) { + this.width = 20; + this.height = 40; + this.y = 160; + } else if (type < 0.8) { + this.width = 20; + this.height = 25; + this.y = 175; + } else { + this.width = 40; + this.height = 32; + this.y = 168; + } + } + + draw() { + ctx.fillStyle = "#40a02b"; + ctx.fillRect(this.x, this.y, this.width, this.height); + } + + update() { + this.x -= gameSpeed; + } +} + +class BirdObstacle { + constructor() { + this.x = canvas.width; + this.width = 30; + this.height = 20; + const heightType = Math.floor(Math.random() * 3); + if (heightType === 0) { + this.y = 170; + } else if (heightType === 1) { + this.y = 150; + } else { + this.y = 130; + } + } + + draw() { + ctx.fillStyle = "#dd7878"; + ctx.fillRect(this.x, this.y, this.width, this.height); + } + + update() { + this.x -= gameSpeed; + } +} + +function checkCollision(dino, obstacle) { + return ( + dino.x < obstacle.x + obstacle.width && + dino.x + dino.width > obstacle.x && + dino.y < obstacle.y + obstacle.height && + dino.y + dino.height > obstacle.y + ); +} + +function spawnObstacle() { + if (frameCount >= nextObstacleFrame) { + const type = Math.random(); + if (type < 0.9) { + obstacles.push(new Obstacle()); + } else { + obstacles.push(new BirdObstacle()); + } + + const baseMin = 80; + const baseMax = 140; + + const speedFactor = 3 / gameSpeed; + + const minInterval = Math.floor(baseMin * speedFactor); + const maxInterval = Math.floor(baseMax * speedFactor); + nextObstacleFrame = + frameCount + + Math.floor(Math.random() * (maxInterval - minInterval) + minInterval); + } +} + +function updateScore() { + if (!isGameOver) { + score++; + scoreElement.textContent = `Score: ${Math.floor(score / 10)}`; + + // Increase difficulty + if (score % 500 === 0) { + gameSpeed += 0.5; + } + } +} + +function gameLoop() { + if (isGameOver) return; + + ctx.clearRect(0, 0, canvas.width, canvas.height); + + ctx.strokeStyle = "#535353"; + ctx.beginPath(); + ctx.moveTo(0, 200); + ctx.lineTo(canvas.width, 200); + ctx.stroke(); + + dino.update(); + dino.draw(); + + spawnObstacle(); + + for (let i = obstacles.length - 1; i >= 0; i--) { + obstacles[i].update(); + obstacles[i].draw(); + + if (checkCollision(dino, obstacles[i])) { + isGameOver = true; + gameOverElement.style.display = "block"; + } + + if (obstacles[i].x + obstacles[i].width < 0) { + obstacles.splice(i, 1); + } + } + + updateScore(); + frameCount++; + + requestAnimationFrame(gameLoop); +} + +function resetGame() { + score = 0; + gameSpeed = 3; + isGameOver = false; + frameCount = 0; + obstacles.length = 0; + dino.y = 150; + dino.dy = 0; + dino.isJumping = false; + gameOverElement.style.display = "none"; + nextObstacleFrame = 10; + gameLoop(); +} + +document.addEventListener("keydown", (e) => { + e.preventDefault(); + switch (e.code) { + case "ArrowUp": + case "Space": { + if (isGameOver) { + resetGame(); + } else { + dino.jump(); + } + break; + } + case "ArrowDown": { + dino.duck(); + break; + } + default: + } +}); + +document.addEventListener("keyup", (e) => { + switch (e.code) { + case "ArrowDown": { + e.preventDefault(); + dino.isDucking = false; + if (!dino.isJumping) { + dino.y = 150; + } + } + } +}); + +gameLoop(); diff --git a/html/js/script.js b/html/js/script.js index 1834c7a..46ab4bb 100644 --- a/html/js/script.js +++ b/html/js/script.js @@ -1,4 +1,6 @@ -const projects = {}; +const projects = { + dino: "dino.html", +}; const openProject = (project) => { if (Object.keys(projects).includes(project)) {