JS Background lesson
Learn javascript and simple animation building a background with flying object.
Background
A background and flying object start the brain thinking…
- Can we add keys movements?
- How about making another objects?
- How does something like Flappy Bird work?
Code Overview
Frontmatter Images
These are yml key value pairs that are used to define the images for the center object and the moving background.
sprite: /images/platformer/sprites/flying-ufo.png
background: /images/platformer/backgrounds/alien_planet1.jpg
Obtains assets for project using VSCode terminal
mkdir -p hacks
wget https://raw.githubusercontent.com/Open-Coding-Society/pages/refs/heads/main/hacks/background.md -O hacks/background.md
mkdir -p images/platformer/sprites
wget https://raw.githubusercontent.com/Open-Coding-Society/pages/refs/heads/main/images/platformer/sprites/flying-ufo.png -O images/platformer/sprites/flying-ufo.png
mkdir -p images/platformer/backgrounds
wget https://raw.githubusercontent.com/Open-Coding-Society/pages/refs/heads/main/images/platformer/backgrounds/alien_planet1.jpg -O images/platformer/backgrounds/alien_planet1.jpg
Open these files in VSCode
- hacks/background.md
- frontmatter changes
- change “opencs” to “base”
- remove forward slashes on image names
- frontmatter changes
- images/platformer/backgrounds/flying-ufo.png
- images/platformer/backgrounds/alien_planet.jpg
Canvas
In order for anything to show up on your screen in the first place, we have to create a canvas for everything to be drawn on.
We’re going to need to declare a constant variable using the keyword const
const canvas = document.getElementById("world");
// document.getElementById("world") finds the <canvas id="world"> element in the DOM.
const ctx = canvas.getContext('2d');
// every canvas has a drawing context. for example, getContext('2d') returns the 2D drawing API (methods like drawImage, fillRect, clearRect).
// canvas is the DOM element; ctx is what draws pixels
Sizing the Canvas
We need to setup the GameWorld
- The
canvasis setup things being drawn are’nt too small or too big for your window screen. Look at all thethis.canvascommands. - The
ctxis used to draw into the canvas - THe
objectsare assigned tothis.objectsthese are the the game pieces placed into the game world.
class GameWorld {
static gameSpeed = 5;
constructor(backgroundImg, spriteImg) {
this.canvas = document.getElementById("world");
this.ctx = this.canvas.getContext('2d');
this.width = window.innerWidth;
this.height = window.innerHeight;
this.canvas.width = this.width;
this.canvas.height = this.height;
this.canvas.style.width = `${this.width}px`;
this.canvas.style.height = `${this.height}px`;
this.canvas.style.position = 'absolute';
this.canvas.style.left = `0px`;
this.canvas.style.top = `${(window.innerHeight - this.height) / 2}px`;
this.objects = [
new Background(backgroundImg, this),
new Player(spriteImg, this)
];
Here are a couple of definitions
canvas.width, canvas.height: set the drawing buffer size (pixel resolution of the canvas).
canvas.style.width, canvas.style.height: set the CSS size (how big it appears on screen).
They set both equal so the drawing area matches the visible size.
Game Objects
In our game, everything that shows up on the screen (like the background or the character sprite) can be thought of as a game objects. Instead of writing separate code for each image, we create a class that acts like a blueprint.
class GameObject {
constructor(image, width, height, x = 0, y = 0, speedRatio = 0) {
this.image = image; // what picture to draw
this.width = width; // how wide to draw it
this.height = height; // how tall to draw it
this.x = x; // where it is horizontally
this.y = y; // where it is vertically
this.speedRatio = speedRatio;
this.speed = gameSpeed * this.speedRatio; // how fast it moves
}
update() {
// gets filled in by subclasses (like Background)
}
draw(ctx) {
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
}
}
Instead of hardcoding the background or sprite separately, we can now make them instances of this GameObject class. Looks for Background and Player class.
Background Object
Our background is special: it has to move sideways forever to look like we’re running. To make it seamless, we draw two copies of the background image side-by-side. As one scrolls off the screen, the other one takes its place.
class Background extends GameObject {
update() {
this.x = (this.x - this.speed) % this.width;
}
draw(ctx) {
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
ctx.drawImage(this.image, this.x + this.width, this.y, this.width, this.height);
}
}
update() moves the background a little bit every frame.
The % this.width (modulo) makes sure it “wraps around” so it never disappears.
draw() paints two backgrounds so there’s no empty gap.
The Game Loop (Animation)
The most important piece of a game is the loop that keeps running forever. This is where things get updated and redrawn, frame after frame.
gameLoop() {
this.ctx.clearRect(0, 0, this.width, this.height);
for (const obj of this.objects) {
obj.update();
obj.draw(this.ctx);
}
requestAnimationFrame(this.gameLoop.bind(this));
}
start() {
this.gameLoop();
}
clearRect wipes the screen so old frames so they don’t overlap.
for cycles through every object we defined with the GameWorld constructor.
update changes typically changes object positions.
draw puts the image onto the canvas according to recent updates.
requestAnimationFrame tells the browser: “do this again on the next frame.”
That’s what makes the background look alive — it’s being redrawn 60 times per second!
Hacks
The Player object is distinct on the canvas.
Make Player Object update
Goal. Make the player oscilate up and down during gaemLoop loop.
class Player extends GameObject {
constructor(image) {
// Sets up object specifics and calls super
}
update() {
// We need to change y value to go up a down
}
}
Make comments in the project
Commenting is key to our understanding. The code has been spaced into sections seperated by space. Make comments in every section. Open Chat to help, but Teacher will expect that you can explain and change.
Single line or end of line comment //
Multi line commets starting line /* ending line */
Make your own scene
There are backgrounds and sprites in images/platform. Locate and make a change.