diff --git a/index.html b/index.html index d80d77c..13a29c3 100644 --- a/index.html +++ b/index.html @@ -19,10 +19,24 @@
-
+

Stats

-

Score: 0

-

Lives: 3

+
+
Score:
+ 0 +
+
+
Lives:
+ 0 +
+
+
speed X:
+ 0 +
+
+
Speed Y:
+ 0 +
@@ -37,6 +51,9 @@

Game Over

+ + + diff --git a/js/component.js b/js/component.js new file mode 100644 index 0000000..bff0f4b --- /dev/null +++ b/js/component.js @@ -0,0 +1,25 @@ +class Component { + constructor(gameScreen, x, y, width, height, imgSrc, speed) { + this.gameScreen = gameScreen; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + this.directionX = 0; + this.directionY = 0; + this.element = document.createElement("img"); + this.element.src = imgSrc; + this.element.style.position = "absolute"; + this.element.style.width = this.width + "px"; + this.element.style.height = this.height + "px"; + this.element.style.left = this.x + "px"; + this.element.style.top = this.y + "px"; + this.gameScreen.appendChild(this.element); + this.speed = speed; + } + + updatePosition() { + this.element.style.left = this.x + "px"; + this.element.style.top = this.y + "px"; + } +} \ No newline at end of file diff --git a/js/game.js b/js/game.js index af4789c..5e28a88 100644 --- a/js/game.js +++ b/js/game.js @@ -1,3 +1,149 @@ class Game { - // code to be added + constructor() { + this.startScreen = document.getElementById("game-intro"); + this.gameScreen = document.getElementById("game-screen"); + this.endScreen = document.getElementById("game-end"); + this.livesLabel = document.getElementById("lives"); + this.scoreLabel = document.getElementById("score"); + this.speedXLabel = document.getElementById("speed-x"); + this.speedYLabel = document.getElementById("speed-y"); + this.player = null; + this.height = 600; + this.width = 500; + this.obstacles = []; + this.score = 0; + this.lives = 3; + this.gameIsOver = false; + this.gameIntervalId; + this.gameLoopFrecuency = 1000 / 60; + } + + start() { + this.player = new Player(this.gameScreen, 200, 500, 100, 150, "./images/car.png", 2); + this.gameScreen.style.width = this.width + "px"; + this.gameScreen.style.height = this.height + "px"; + this.startScreen.style.display = "none"; + this.gameScreen.style.display = "block"; + this.gameIntervalId = setInterval(this.gameLoop.bind(this), this.gameLoopFrecuency); + } + + endGame() { + this.player.element.remove(); + this.obstacles.forEach((obstacle) => obstacle.element.remove()); + + this.gameIsOver = true; + + this.gameScreen.style.display = "none"; + this.endScreen.style.display = "block"; + } + + update() { + this.player.move(); + + if (this.spawnObstacleCheck()) { + let speed = 3; + this.generateObstacle(speed); + } + + this.collissionCheck(); + + this.setLabels(); + + const drag = 0.01; + this.player.directionX -= drag * Math.sign(this.player.directionX); + this.player.directionY -= drag * Math.sign(this.player.directionY); + + if (this.lives == 0) { + this.endGame(); + } + } + + gameLoop() { + this.update(); + if (this.gameIsOver) { + clearInterval(this.gameIntervalId); + } + } + + spawnObstacleCheck() { + if (this.obstacles.length > 1) { + return false; + } + return Math.random() < 0.05; + } + + generateObstacle(speed) { + const width = 100; + const height = 150; + const x = Math.random() * this.width - width * 0.5; + const y = -height; + const obstacle = new Obstacle(this.gameScreen, x, y, width, height, "./images/redCar.png", speed); + this.obstacles.push(obstacle); + } + + collissionCheck() { + for (let i = this.obstacles.length - 1; i >= 0; i--) { + const obstacle = this.obstacles[i]; + + obstacle.move() + let deleteObstacle = false; + if (this.player.didCollide(obstacle)) { + this.lives--; + deleteObstacle = true; + } + else if (obstacle.y > this.height + obstacle.height) { + this.score++; + deleteObstacle = true; + } + if (deleteObstacle) { + obstacle.element.remove(); + this.obstacles.splice(i, 1); + } + } + } + + setLabels() { + this.livesLabel.innerText = this.lives; + this.scoreLabel.innerText = this.score; + this.speedXLabel.innerText = this.player.directionX.toFixed(2); + this.speedYLabel.innerText = this.player.directionY.toFixed(2); + } + + handleKeydown(e) { + if (this.gameIsOver) { + return; + } + + const key = e.key; + const possibleKeys = [ + "ArrowLeft", + "ArrowUp", + "ArrowRight", + "ArrowDown", + "w", "a", "s", "d", + ]; + + if (possibleKeys.includes(key)) { + e.preventDefault(); + + switch (key) { + case "ArrowLeft": + case "a": + this.player.directionX = -1; + break; + case "ArrowRight": + case "d": + this.player.directionX = 1; + break; + case "ArrowUp": + case "w": + this.player.directionY = -1; + break; + case "ArrowDown": + case "s": + this.player.directionY = 1; + break; + } + } + } } \ No newline at end of file diff --git a/js/obstacle.js b/js/obstacle.js new file mode 100644 index 0000000..2552fc1 --- /dev/null +++ b/js/obstacle.js @@ -0,0 +1,11 @@ +class Obstacle extends Component { + constructor(gameScreen, x, y, width, height, imgSrc, speed) { + super(gameScreen, x, y, width, height, imgSrc, speed); + + } + + move() { + this.y += this.speed; + this.updatePosition(); + } +} \ No newline at end of file diff --git a/js/player.js b/js/player.js new file mode 100644 index 0000000..5a611d5 --- /dev/null +++ b/js/player.js @@ -0,0 +1,27 @@ +class Player extends Component { + constructor(gameScreen, x, y, width, height, imgSrc, speed) { + super(gameScreen, x, y, width, height, imgSrc, speed); + } + + move() { + this.x += this.directionX * this.speed; + this.y += this.directionY * this.speed; + this.x = clamp(this.x, 10, this.gameScreen.offsetWidth - this.width - 10); + this.y = clamp(this.y, 10, this.gameScreen.offsetHeight - this.height - 10); + this.updatePosition(); + } + + didCollide(obstacle) { + const playerRect = this.element.getBoundingClientRect(); + const obstacleRect = obstacle.element.getBoundingClientRect(); + + if (playerRect.left < obstacleRect.right && + playerRect.right > obstacleRect.left && + playerRect.top < obstacleRect.bottom && + playerRect.bottom > obstacleRect.top + ) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/js/script.js b/js/script.js index 95e544f..815baf5 100644 --- a/js/script.js +++ b/js/script.js @@ -1,12 +1,20 @@ window.onload = function () { - const startButton = document.getElementById("start-button"); - const restartButton = document.getElementById("restart-button"); + const startButton = document.getElementById("start-button"); + const restartButton = document.getElementById("restart-button"); - startButton.addEventListener("click", function () { - startGame(); - }); + startButton.addEventListener("click", function () { + startGame(); + }); + restartButton.addEventListener("click", () => location.reload()); - function startGame() { - console.log("start game"); - } + function startGame() { + console.log("start game"); + const game = new Game(); + window.addEventListener("keydown", (e) => game.handleKeydown(e)); + game.start(); + } }; + +function clamp(number, min, max) { + return Math.max(min, Math.min(number, max)); +} diff --git a/styles/style.css b/styles/style.css index cf0cff3..1318582 100644 --- a/styles/style.css +++ b/styles/style.css @@ -14,6 +14,22 @@ body { justify-content: center; } +#game-stats +{ + font-family: Consolas, monaco, monospace; + padding-right: 50px; + width: 200px; + text-align: left; +} + +.speed +{ + display: flex; + flex-direction: row; + justify-content: space-between; + width: 150px; +} + #game-screen { display: none; align-content: center;