Week 11: Canvas Games & APIs with fetch()

To Do This Week

Explore Canvas game techniques and APIs with fetch(). Add to your running list of combination ideas for the Front-End Module Projects. Each project combines at least two front-end modules:

Use AI freely to research and test ideas. If you use AI to build logic steps and syntax, use JS Mentor, and document what it contributed and how you changed and extended it.


Monday: Canvas Games

A game is an animation loop plus state (score, lives, level, game over) plus input (keys, mouse, touch). Each frame the loop clears the canvas, reads input, updates every object, checks for collisions, and redraws.

HTML5 Games

Explore the W3Schools HTML5 Games Demo to see how JavaScript builds a game on the Canvas element.

Here is the example refactored for ES6: Dodging Obstacles Game. Look at how objects are generated and then animated with speed and gravity properties. Experiment with values.


New Syntax: Classes

A class is a blueprint. Write it once, then make as many objects from it as you need: one player, fifty obstacles, a hundred falling stars.

class Ball {
  constructor(x, y, speed) {   // runs when a new Ball is made
    this.x = x;                 // "this" = the ball being made
    this.y = y;
    this.speed = speed;
    this.radius = 15;
  }

  update() {                    // a method: what the ball does each frame
    this.y += this.speed;
  }

  draw() {                      // a method: how the ball looks
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
    ctx.fill();
  }
}

const balls = [];                              // many objects in an array
balls.push(new Ball(100, 0, 3));
balls.push(new Ball(250, 0, 5));

Arrow Functions (=>)

An arrow function is a shorter way to write a function. If you see =>, it means “this is a function.”

// Arrow function
balls.forEach(ball => {
  ball.update();
  ball.draw();
});

// Same thing as a regular function
balls.forEach(function(ball) {
  ball.update();
  ball.draw();
});

Keyboard Input

Store which keys are held down as booleans, then check them inside the game loop. This gives smooth movement instead of one jump per key press.

const keys = {};

document.addEventListener('keydown', e => keys[e.key] = true);
document.addEventListener('keyup',   e => keys[e.key] = false);

// inside the game loop
if (keys['ArrowLeft'])  player.x -= player.speed;
if (keys['ArrowRight']) player.x += player.speed;

Collision Detection (Rectangles)

function hits(a, b) {
  return a.x < b.x + b.width &&
         a.x + a.width > b.x &&
         a.y < b.y + b.height &&
         a.y + a.height > b.y;
}

if (hits(player, enemy)) {
  gameOver = true;
}

The Game Loop

function updateGame() {
  ctx.clearRect(0, 0, canvas.width, canvas.height); // 1. clear
  player.update();                                   // 2. update
  balls.forEach(ball => ball.update());
  balls.forEach(ball => {                            // 3. check collisions
    if (hits(player, ball)) score++;
  });
  player.draw();                                     // 4. draw
  balls.forEach(ball => ball.draw());
  ctx.fillText('Score: ' + score, 20, 30);
  if (!gameOver) requestAnimationFrame(updateGame);  // 5. repeat
}

Adding Images and Sound Effects

To add images, load the image into an Image() object, then draw it with drawImage() in place of a shape.

const playerImg = new Image();
playerImg.src = 'player.png';

// inside the player's draw() method
ctx.drawImage(playerImg, this.x, this.y, this.width, this.height);

To add sound effects, load the audio file into an Audio() object and call play() when something happens in the game.

const shootSound = new Audio('shoot.wav');

// when the player shoots
shootSound.currentTime = 0; // rewind so it can retrigger quickly
shootSound.play();

The game with images | Download ZIP


Demos

Writing Logic Steps First: Pong

Before coding a game, describe it in plain language. Here is Pong:

  1. Set up the canvas: Get the canvas element and its drawing context so we can draw paddles and the ball.
  2. Create a Paddle class: Each paddle has a position (x, y), size (width, height), and speed. It responds to player input (W/S, arrow keys) and draws itself each frame.
  3. Create a Ball class: The ball has a position, size, and speed in both X and Y directions. It moves, bounces, detects paddle collisions, and resets after a score.
  4. Track game state: Keep score, listen for key presses, and use booleans to store which keys are held down.
  5. Game loop (updateGame): Clear the canvas, update positions, check for collisions, draw everything, and use requestAnimationFrame() to repeat.

Asteroids Logic Steps

  1. Set up the canvas: Same as Pong.
  2. Create a Ship class: Position, direction, and thrust; moves with physics, rotates, shoots, and wraps around the screen.
  3. Create a Bullet class: Starts at the ship’s position, moves in its direction, and disappears after a while.
  4. Create an Asteroid class: Random positions and velocities; moves, wraps around, and detects bullet hits.
  5. Create a Game class: Manages the ship, asteroids, and input; runs the update/draw loop.

Previous Student Canvas Games

Knight Runner: How a Larger Game Is Organized

Larger games split each class into its own file. Look at how Knight Runner is organized:

Its assets: UI elements from OwlishMedia, background layers from Edermunizz, and sprites from Dumbmanex, Craftpix, OpenGameArt, and Freepik.

HTML5 Game Elements

Game Resources

Game Assets + AI Tools

Check the license for every asset you use and credit it in your project.


Monday In-Class Sandbox

Start from Falling Balls or Dodging Obstacles and make it your own.

  1. Play it, then experiment with values: speed, gravity, spawn rate, player size and controls.
  2. Write three to five numbered logic steps for one real change to how the game plays (a new rule, a new object, a win condition). Use JS Mentor to work out the syntax.
  3. Replace at least one shape with an image using drawImage().
  4. Add a sound effect for one game event: a catch, a hit, or game over.

What would I combine this with? Add one sentence to your list.


Wednesday: APIs with fetch()

An API (Application Programming Interface) lets your page request data from another service: weather, art collections, space images, poems. The data usually comes back as JSON, which JavaScript reads as an object. Live data can then drive what your page shows, how an animation moves, or how a game behaves.

Server Requests

The Fetch API is a built-in browser feature: a set of methods that make network requests like GET (grab data), POST (send data), and PUT / DELETE (update or remove data). For most front-end projects you only need GET.


New Syntax: fetch()

const apiKey = 'YOUR_API_KEY';

async function getWeather(city) {
  const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=imperial&appid=${apiKey}`;

  try {
    const response = await fetch(url);       // 1. send the request, wait for a reply
    if (!response.ok) {                      // 2. check it worked (404 = city not found)
      throw new Error('City not found');
    }
    const data = await response.json();      // 3. turn the reply into a JS object
    showWeather(data);                       // 4. use the data
  } catch (error) {
    message.textContent = error.message;     // 5. tell the user what went wrong
  }
}

JSON Methods

Reading Nested JSON

Use dot notation to reach into the object, and square brackets for arrays. Open the JSON Weather Data and trace each path:

data.name                      // "Vancouver"
data.main.temp                 // 54.3
data.main.humidity             // 81
data.wind.speed                // 6.9
data.clouds.all                // 75   (cloud cover %)
data.weather[0].main           // "Rain"
data.weather[0].description    // "light rain"
data.sys.sunrise / data.sys.sunset / data.dt   // times, for day vs. night

Use includes() to search a description for a word:

if (data.weather[0].description.includes('clouds')) {
  // Do something
}

Demo: Weather App

Use the OpenWeather API to get current weather by city with fetch().

Getting an API Key

  1. Go to the sign-up page for the free version.
  2. Your key will be emailed to you. It can take a little while to activate.
  3. Replace the placeholder key in the template with your own.

For a US city with a state, use the format Vancouver,WA,US.

Weather App Resources

Other APIs to Explore


Wednesday In-Class Sandbox: Weather + Canvas Animation

Turn live weather into motion. Start from a weather app template and add a canvas that animates according to the data.

  1. Get the template working with your own API key. Test a few cities.
  2. Pick two or three data points to drive the animation.
  3. Add a canvas and an animation loop. You can start from a rain or snow animation demo, or a p5.js sketch.
  4. Connect each data point to something visual. Ideas:
    • data.wind.speed → how fast or sideways particles move
    • data.clouds.all → how many clouds, or how gray the sky is
    • data.main.temp → color palette, warm to cool
    • data.weather[0].main → which animation runs: rain, snow, sun, fog
    • data.dt compared to sunrise and sunset → day or night sky
  5. Add a loading message and an error message for a city that isn’t found.
// Example: wind speed (0–30 mph) controls drift, temperature controls color
let drift = (data.wind.speed / 30) * 5;           // 0 to 5 pixels per frame
let warm  = Math.min(Math.max((data.main.temp - 20) / 80, 0), 1); // 0 = cold, 1 = hot
ctx.fillStyle = `rgb(${warm * 255}, 120, ${(1 - warm) * 255})`;

Think about mood, not just accuracy. A weather app can be calm, eerie, playful, or poetic. Other directions: a game that gets harder in bad weather, a soundscape that shifts with conditions, or another API from the list above.

What would I combine this with? Add one sentence to your list.