Back to Freecodecamp

Step 41

curriculum/challenges/english/blocks/learn-intermediate-oop-by-building-a-platformer-game/64ab178206f3237eafcc0ef4.md

latest4.8 KB
Original Source

--description--

The <dfn>requestAnimationFrame()</dfn> web API, takes in a callback and is used to update the animation on the screen. The animate function will be responsible for updating the player's position and continually drawing it on the canvas.

Inside the animate function, call the requestAnimationFrame() API and pass animate as the argument.

--hints--

You should call the requestAnimationFrame() API and pass in animate for the argument.

js
assert.match(code, /\s*requestAnimationFrame\s*\(\s*animate\s*\)\s*;?/);

--seed--

--seed-contents--

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Learn Intermediate OOP by Building a Platformer Game</title>
    <link rel="stylesheet" href="./styles.css" />
  </head>
  <body>
    <div class="start-screen">
      <h1 class="main-title">freeCodeCamp Code Warrior</h1>
      <p class="instructions">
        Help the main player navigate to the yellow checkpoints.
      </p>
      <p class="instructions">
        Use the keyboard arrows to move the player around.
      </p>
      <p class="instructions">You can also use the spacebar to jump.</p>

      <div class="btn-container">
        <button class="btn" id="start-btn">Start Game</button>
      </div>
    </div>

    <div class="checkpoint-screen">
      <h2>Congrats!</h2>
      <p>You reached the last checkpoint.</p>
    </div>

    <canvas id="canvas"></canvas>

    <script src="./script.js"></script>
  </body>
</html>

css
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

:root {
  --main-bg-color: #0a0a23;
  --section-bg-color: #ffffff;
  --golden-yellow: #feac32;
}

body {
  background-color: var(--main-bg-color);
}

.start-screen {
  background-color: var(--section-bg-color);
  width: 100%;
  position: absolute;
  top: 50%;
  left: 50%;
  margin-right: -50%;
  transform: translate(-50%, -50%);
  border-radius: 30px;
  padding: 20px;
  padding-bottom: 5px;
}

.main-title {
  text-align: center;
}

.instructions {
  text-align: center;
  font-size: 1.2rem;
  margin: 15px;
  line-height: 2rem;
}

.btn {
  cursor: pointer;
  width: 100px;
  margin: 10px;
  color: #0a0a23;
  font-size: 18px;
  background-color: var(--golden-yellow);
  background-image: linear-gradient(#fecc4c, #ffac33);
  border-color: var(--golden-yellow);
  border-width: 3px;
}

.btn:hover {
  background-image: linear-gradient(#ffcc4c, #f89808);
}

.btn-container {
  display: flex;
  align-items: center;
  justify-content: center;
}

.checkpoint-screen {
  position: absolute;
  left: 0;
  right: 0;
  margin-left: auto;
  margin-right: auto;
  width: 100%;
  text-align: center;
  background-color: var(--section-bg-color);
  border-radius: 20px;
  padding: 10px;
  display: none;
}

#canvas {
  display: none;
}

@media (min-width: 768px) {
  .start-screen {
    width: 60%;
    max-width: 700px;
  }

  .checkpoint-screen {
    max-width: 300px;
  }
}

js
const startBtn = document.getElementById("start-btn");
const canvas = document.getElementById("canvas");
const startScreen = document.querySelector(".start-screen");
const checkpointScreen = document.querySelector(".checkpoint-screen");
const checkpointMessage = document.querySelector(".checkpoint-screen > p");
const ctx = canvas.getContext("2d");
canvas.width = innerWidth;
canvas.height = innerHeight;
const gravity = 0.5;
let isCheckpointCollisionDetectionActive = true;

const proportionalSize = (size) => {
  return innerHeight < 500 ? Math.ceil((size / 500) * innerHeight) : size;
}

class Player {
  constructor() {
    this.position = {
      x: proportionalSize(10),
      y: proportionalSize(400),
    };
    this.velocity = {
      x: 0,
      y: 0,
    };
    this.width = proportionalSize(40);
    this.height = proportionalSize(40);
  }
  draw() {
    ctx.fillStyle = "#99c9ff";
    ctx.fillRect(this.position.x, this.position.y, this.width, this.height);
  }
  
  update() {
    this.draw();
    this.position.x += this.velocity.x;
    this.position.y += this.velocity.y;

    if (this.position.y + this.height + this.velocity.y <= canvas.height) {
      if (this.position.y < 0) {
        this.position.y = 0;
        this.velocity.y = gravity;
      }
      this.velocity.y += gravity;
    } else {
      this.velocity.y = 0;
    }

    if (this.position.x < this.width) {
      this.position.x = this.width;
    }

    if (this.position.x >= canvas.width - this.width * 2) {
      this.position.x = canvas.width - this.width * 2;
    }
  }
}

const player = new Player();

--fcc-editable-region--

const animate = () => {

}

--fcc-editable-region--

const startGame = () => {
  canvas.style.display = "block";
  startScreen.style.display = "none";
  player.draw();
}

startBtn.addEventListener("click", startGame);