Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

My lab Solution #173

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 22 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

# LAB | DOM Race Car


![Island Racer Logo](images/logo.png)

<details>
Expand Down Expand Up @@ -79,7 +78,7 @@ The start screen is already displayed on the page, as shown below.

![island racer game start screen](https://education-team-2020.s3.eu-west-1.amazonaws.com/web-dev/m1/lab-dom-race-car/lab-dom-race-car-start-screen.png)

Upon clicking the **Start Game** button, the player should transition from the _start screen_ to the _game screen_, initiating the game.
Upon clicking the **Start Game** button, the player should transition from the _start screen_ to the _game screen_, initiating the game.

In the next iteration, we will create the `Game` class and implement the functionality required to **start** the game.

Expand Down Expand Up @@ -173,7 +172,7 @@ class Game {
this.lives = 3;
this.gameIsOver = false;
this.gameIntervalId;
this.gameLoopFrequency = Math.round(1000/60); // 60fps
this.gameLoopFrequency = Math.round(1000 / 60); // 60fps
}

start() {
Expand All @@ -183,24 +182,24 @@ class Game {

// Hide the start screen
this.startScreen.style.display = "none";

// Show the game screen
this.gameScreen.style.display = "block";

// Runs the gameLoop on a fequency of 60 times per second. Also stores the ID of the interval.
this.gameIntervalId = setInterval(() => {
this.gameLoop()
}, this.gameLoopFrequency)
this.gameLoop();
}, this.gameLoopFrequency);
}

gameLoop() {
console.log("in the game loop");

this.update();

// If "gameIsOver" is set to "true" clear the interval to stop the loop
if (this.gameIsOver) {
clearInterval(this.gameIntervalId)
clearInterval(this.gameIntervalId);
}
}

Expand Down Expand Up @@ -281,11 +280,12 @@ In this iteration, we will create the `Player` class, representing the player's
- `1`: moving horizontally to the right
- `-1`: moving horizontally to the left
- `directionY` - initially set to 0. It is used to specify the **vertical** movement direction and can have the following values:

- `0`: not moving vertically
- `1`: moving vertically down
- `-1`: moving vertically up

- `element` - the **image** element representing the car. This image element should be created in the constructor using the *provided image source (image url) passed as an argument* to the constructor.
- `element` - the **image** element representing the car. This image element should be created in the constructor using the _provided image source (image url) passed as an argument_ to the constructor.

<br>

Expand Down Expand Up @@ -404,8 +404,6 @@ class Player {
return false;
}
}


}
```

Expand All @@ -417,7 +415,7 @@ class Player {

## Iteration 4: Add the Player to the Game

1. As a reminder, we have already defined the `player` property of the `Game` class and set it to `null`. Now let's instantiate a new `Player` object and store it in the `player` property of the `Game`.
1. As a reminder, we have already defined the `player` property of the `Game` class and set it to `null`. Now let's instantiate a new `Player` object and store it in the `player` property of the `Game`.

<details>
<summary>See the code</summary>
Expand Down Expand Up @@ -472,19 +470,15 @@ class Game {

<br>



![island racer game - player car showing](https://education-team-2020.s3.eu-west-1.amazonaws.com/web-dev/m1/lab-dom-race-car/lab-dom-race-car-player.png)



<br>

## Iteration 5: Handle Keyboard Input

The goal of this iteration is to allow the player to control the car using the keyboard.

To do this, we will add an event listener in the `js/script.js` file, which will update the player's car `directionX` and `directionY` properties based on the keys that the user presses on the keyboard.
To do this, we will add an event listener in the `js/script.js` file, which will update the player's car `directionX` and `directionY` properties based on the keys that the user presses on the keyboard.
This function listens for the `keydown` event using `document.onkeydown` and checks if the pressed key matches any of the allowed keystrokes (arrow keys).

<details>
Expand Down Expand Up @@ -580,7 +574,7 @@ In this iteration, we will create the `Obstacle` class, which will be used to cr
<details>
<summary> <code><b>move()</b></code> </summary>

- Move the obstacle down by 3px by continuously updating its `top` property.
- Move the obstacle down by 3px by continuously updating its `top` property.

- Update the obstacle's position on the screen by calling the `updatePosition()` method.

Expand Down Expand Up @@ -666,16 +660,15 @@ This method is responsible for updating the game state during each loop iteratio

- Check if the player has run out of lives, and end the game if so. Create a new method (`endGame`) responsible for ending the game.


</details>

<details>
<summary> <code><b>endGame()</b></code> </summary>

- Remove a player and all the obstacles from the DOM.
- Set the `gameIsOver` flag to `true`.
- Hide the game screen.
- Show the end game screen.
- Remove a player and all the obstacles from the DOM.
- Set the `gameIsOver` flag to `true`.
- Hide the game screen.
- Show the end game screen.

</details>

Expand Down Expand Up @@ -740,7 +733,7 @@ class Game {
// Create a new method responsible for ending the game
endGame() {
this.player.element.remove();
this.obstacles.forEach(obstacle => obstacle.element.remove());
this.obstacles.forEach((obstacle) => obstacle.element.remove());

this.gameIsOver = true;

Expand All @@ -760,14 +753,10 @@ class Game {

<br>



<img src="https://education-team-2020.s3.eu-west-1.amazonaws.com/web-dev/m1/lab-dom-race-car/lab-dom-race-car-start-game-obstacles.gif" width="600" style="display: block; margin: 0 auto" />

<br>



## Iteration 8: End Game Screen

In this final iteration, we will implement the end game screen, shown to the user when the game is over.
Expand Down Expand Up @@ -796,9 +785,10 @@ window.onload = function () {
});

// The function that reloads the page to start a new game
function restartGame() {
location.reload();
}
restartButton.addEventListener("click", function () {
// Call the restartGame function when the button is clicked
restartGame();
});
};
```

Expand Down Expand Up @@ -910,7 +900,6 @@ class Player extends Component {
}
}
}

```

<br>
Expand All @@ -936,17 +925,13 @@ class Obstacle extends Component {
// Update the obstacle's position on the screen
this.updatePosition();
}

}

```

<br>

</details>



<br>

## BONUS - Iteration 10: Points, points, points
Expand All @@ -959,7 +944,7 @@ To make the game more competitive, add elements to shows the player's score and

## Lab Solution

You can find the complete solution code for the lab at: [dom-race-car](https://github.com/ironhack-labs/lesson-code-dom-race-car).
You can find the complete solution code for the lab at: [dom-race-car](https://github.com/ironhack-labs/lesson-code-dom-race-car).

To clone the solution repository, run the following commands:

Expand All @@ -971,8 +956,6 @@ git clone https://github.com/ironhack-labs/lesson-code-dom-race-car.git
cd lesson-code-dom-race-car
```



<br>

**Happy coding!** :heart:
3 changes: 3 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,8 @@ <h1>Game Over</h1>

<script type="text/javascript" src="js/game.js"></script>
<script type="text/javascript" src="js/script.js"></script>
<script type="text/javascript" src="js/player.js"></script>
<script type="text/javascript" src="js/obstacle.js"></script>
<script type="text/javascript" src="js/components.js"></script>
</body>
</html>
24 changes: 24 additions & 0 deletions js/components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class Component {
constructor(gameScreen, left, top, width, height, imgSrc) {
this.gameScreen = gameScreen;
this.left = left;
this.top = top;
this.width = width;
this.height = height;
this.element = document.createElement("img");

this.element.src = imgSrc;
this.element.style.position = "absolute";
this.element.style.width = `${width}px`;
this.element.style.height = `${height}px`;
this.element.style.left = `${left}px`;
this.element.style.top = `${top}px`;

this.gameScreen.appendChild(this.element);
}

updatePosition() {
this.element.style.left = `${this.left}px`;
this.element.style.top = `${this.top}px`;
}
}
107 changes: 105 additions & 2 deletions js/game.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,106 @@
class Game {
// code to be added
}
constructor() {
this.startScreen = document.getElementById("game-intro");
this.gameScreen = document.getElementById("game-screen");
this.gameEndScreen = document.getElementById("game-end");
this.player = new Player(
this.gameScreen,
200,
500,
100,
150,
"./images/car.png"
);
this.height = 600;
this.width = 500;
this.obstacles = [];
this.score = 0;
this.lives = 3;
this.gameIsOver = false;
this.gameIntervalId;
this.gameLoopFrequency = Math.round(1000 / 60); // 60fps
}

start() {
// Set the height and width of the game screen
this.gameScreen.style.height = `${this.height}px`;
this.gameScreen.style.width = `${this.width}px`;

// Hide the start screen
this.startScreen.style.display = "none";
// Show the game screen
this.gameScreen.style.display = "block";

// Executes the gameLoop on a fequency of 60 times per second. Also stores the ID of the interval.
this.gameIntervalId = setInterval(() => {
this.gameLoop();
}, this.gameLoopFrequency);
}

gameLoop() {
console.log("in the game loop");

this.update();

if (this.gameIsOver) {
clearInterval(this.gameIntervalId);
}
}

update() {
this.player.move();

// Check for collision and if an obstacle is still on the screen
for (let i = 0; i < this.obstacles.length; i++) {
const obstacle = this.obstacles[i];
obstacle.move();

// If the player's car collides with an obstacle
if (this.player.didCollide(obstacle)) {
// Remove the obstacle element from the DOM
obstacle.element.remove();
// Remove obstacle object from the array
this.obstacles.splice(i, 1);
// Reduce player's lives by 1
this.lives--;
// Update the counter variable to account for the removed obstacle
i--;
} // If the obstacle is off the screen (at the bottom)
else if (obstacle.top > this.height) {
// Increase the score by 1
this.score++;
// Remove the obstacle from the DOM
obstacle.element.remove();
// Remove obstacle object from the array
this.obstacles.splice(i, 1);
// Update the counter variable to account for the removed obstacle
i--;
}
}

// If the lives are 0, end the game
if (this.lives === 0) {
this.endGame();
}

// Create a new obstacle based on a random probability
// when there is no other obstacles on the screen
if (Math.random() > 0.98 && this.obstacles.length < 1) {
this.obstacles.push(new Obstacle(this.gameScreen));
}
}

// Create a new method responsible for ending the game
endGame() {
this.player.element.remove();
this.obstacles.forEach(function (obstacle) {
obstacle.element.remove();
});

this.gameIsOver = true;
// Hide game screen
this.gameScreen.style.display = "none";
// Show end game screen
this.gameEndScreen.style.display = "block";
}
}
Loading