Moving Background Homework
Categories: LessonsReview of JavaScript concepts through creating a moving background
Part 1: JavaScript Core Concepts (Basics)
%%js
// Activity 1: Variable Fixing
// This code has mistakes. Fix them so it works correctly.
var name = "Mario";
let score; // declare score but don't assign yet
const lives = 3;
score = 100;
console.log("Player:", name);
console.log("Score:", score);
console.log("Lives:", lives);
// TODO: Change `score` so it increases by 50 and log the new value.
<IPython.core.display.Javascript object>
%%js
// Activity 2: Function Completion
// Finish the function so it multiplies two numbers instead of adding.
function multiply(a, b) {
// TODO: Replace return statement so it multiplies
return a + b;
}
console.log("Expected 20:", multiply(4, 5));
<IPython.core.display.Javascript object>
Part 2: Canvas Activities
%%js
// Activity 3: Draw Your Own Shape
// The following draws a blue rectangle. Change it to draw a green square.
let canvas = document.createElement("canvas");
document.body.appendChild(canvas);
let ctx = canvas.getContext("2d");
canvas.width = 400;
canvas.height = 300;
canvas.style.border = "1px solid black";
ctx.fillStyle = "blue";
ctx.fillRect(50, 50, 200, 100);
// TODO: Change the color and dimensions to make it a green square.
<IPython.core.display.Javascript object>
%%js
// Activity 4: Move a Rectangle
// This code draws a rectangle. Modify it so it moves 2px to the right each frame.
let canvas2 = document.createElement("canvas");
document.body.appendChild(canvas2);
let ctx2 = canvas2.getContext("2d");
canvas2.width = 400;
canvas2.height = 200;
canvas2.style.border = "1px solid black";
let x = 20;
function animateRect() {
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
ctx2.fillStyle = "purple";
ctx2.fillRect(x, 50, 50, 50);
// TODO: increase `x` so the square moves right
requestAnimationFrame(animateRect);
}
animateRect();
<IPython.core.display.Javascript object>
Part 3: Moving Background Activities
%%js
// Activity 5: Background Image Setup
// The code is missing parts. Fill in the missing lines.
let canvas3 = document.createElement("canvas");
document.body.appendChild(canvas3);
let ctx3 = canvas3.getContext("2d");
canvas3.width = 600;
canvas3.height = 200;
canvas3.style.border = "1px solid black";
// TODO: Declare background and sprite as images
// const background = ...
// const sprite = ...
// TODO: Set `background.src` and `sprite.src` to image URLs
<IPython.core.display.Javascript object>
%%js
// Activity 6: Animate the Background
// The background should move left, but part of the code is missing.
// Complete the TODOs.
let canvas4 = document.createElement("canvas");
document.body.appendChild(canvas4);
let ctx4 = canvas4.getContext("2d");
canvas4.width = 600;
canvas4.height = 200;
canvas4.style.border = "1px solid black";
const background2 = new Image();
background2.src = "https://i.imgur.com/3e5pRfj.jpeg";
let bgX = 0;
function animateBackground() {
ctx4.clearRect(0, 0, canvas4.width, canvas4.height);
ctx4.drawImage(background2, bgX, 0, canvas4.width, canvas4.height);
ctx4.drawImage(background2, bgX + canvas4.width, 0, canvas4.width, canvas4.height);
// TODO: decrease bgX so it moves left
// TODO: reset bgX when it reaches -canvas4.width
requestAnimationFrame(animateBackground);
}
background2.onload = animateBackground;
%%js
// Activity 7 (Challenge): Floating Sprite!
// Modify this so the sprite "bobs" up and down while the background moves.
let canvas5 = document.createElement("canvas");
document.body.appendChild(canvas5);
let ctx5 = canvas5.getContext("2d");
canvas5.width = 600;
canvas5.height = 200;
canvas5.style.border = "1px solid black";
const bg = new Image();
bg.src = "https://i.imgur.com/3e5pRfj.jpeg";
const sprite = new Image();
sprite.src = "https://i.imgur.com/Qbl1bLZ.png";
let bgX2 = 0;
let frame = 0;
function animateScene() {
ctx5.clearRect(0, 0, canvas5.width, canvas5.height);
ctx5.drawImage(bg, bgX2, 0, canvas5.width, canvas5.height);
ctx5.drawImage(bg, bgX2 + canvas5.width, 0, canvas5.width, canvas5.height);
let spriteX = canvas5.width / 2 - 50;
let spriteY = canvas5.height / 2 - 50;
// TODO: add vertical floating effect using Math.sin() and frame
ctx5.drawImage(sprite, spriteX, spriteY, 100, 100);
bgX2 -= 2;
if (bgX2 <= -canvas5.width) {
bgX2 = 0;
}
frame++;
requestAnimationFrame(animateScene);
}
bg.onload = animateScene;
<IPython.core.display.Javascript object>
Extra Practice Questions
- Why does
requestAnimationFrame
work better thansetInterval
for animations? - What happens if you forget to call
ctx.clearRect()
inside an animation loop? - How would you modify the background speed so it moves faster?
- (Challenge) Make the sprite move left and right with the arrow keys.
Homework: Moving Background with JavaScript and Canvas
In this lesson, we learned how to make a background move continuously while keeping a sprite centered.
We will now practice by filling in missing pieces of code and editing snippets.
Part 1: Understanding the Core
The moving background is achieved by:
- Updating the
x
position of the background each frame. - Drawing two images side by side to create a seamless loop.
- Using
requestAnimationFrame
for smooth animation.
Activity 1: Fill in the Code
Below is the Background
class with missing code.
Fill in the blanks (???
) to complete it.
class Background extends GameObject {
update() {
// Shift the background left
this.x = (this.x - ???) % ???;
}
draw(ctx) {
// Draw two images side by side
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
ctx.drawImage(this.image, this.x + ???, this.y, this.width, this.height);
}
}
# Activity 2: Edit the Code
Right now, the background always scrolls to the left.
Task: Modify the update() method so the background can also scroll right when this.speed is negative.
Hint: You’ll need to adjust the math inside update() so the % this.width logic works both ways.
# Activity 3 - Speed Control
Currently in the game the speed is fixed:
```python
var gameSpeed = 5;
Task:
Add keyboard controls so that:
Pressing the Arrow Up increases gameSpeed.
Pressing the Arrow Down decreases gameSpeed.
Starter Code (fill in the blanks):
window.addEventListener('keydown', function(event) {
if (event.key === "ArrowUp") {
gameSpeed += ???;
} else if (event.key === "ArrowDown") {
gameSpeed = Math.max(1, gameSpeed - ???);
}
});
Activity 4: Add a Second Background Layer
Parallax scrolling makes games look more realistic. You can add two background objects moving at different speeds.
Task: Duplicate the backgroundObj creation code, but use a different speedRatio. Then, draw both layers in the animate() loop.
Starter Code:
// Background layers
const backgroundObj1 = new Background(backgroundImg, canvasWidth, canvasHeight, 0, 0, 0.1);
const backgroundObj2 = new Background(backgroundImg, canvasWidth, canvasHeight, 0, 0, ???); // slower speed
function animate() {
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
backgroundObj1.update();
backgroundObj1.draw(ctx);
backgroundObj2.update();
backgroundObj2.draw(ctx);
spriteObj.draw(ctx);
requestAnimationFrame(animate);
}
Activity 5: Complexity Question
Each frame, the program:
Updates background position(s).
Draws background(s).
Draws the sprite.
Question:
If there are n background layers, what is the time complexity of each frame’s animate() call?
What about memory complexity?
Basic Instructions:
1) Create a file called something like background.md
just as long as it ends with .md
(Strongly recommend placing it in a folder named hacks)
2) In your new file, after creating your heading, make sure to create an ID for your image, something like <canvas id="world"></canvas>
, you can copy this ID and change ‘world’ to whatever you want.
3) Still in the same file, under the ID, open your script for code by typing <script>
, and under that, create your code for your moving image using code displayed from lesson/popcorn hacks
4) Finish your script (code for background) by adding </script>
, this should be the last line of the file.
Grading (May be modified in class)
-
.55 - No work done, no effort shown by group or student
-
.75 - Student shows they put in effort, but didn’t complete any assigned tasks
-
.8 - Background shows, but isn’t animated
-
.85 - Background shows, isn’t animated, but there is a second background object
-
.89 - Background shows and IS ANIMATED, but work is submitted late and Complexity Questions are unanswered. (There may be some exeptions for late work if students were not present for the lesson)
-
.90 - Background shows and IS ANIMATED, complexity questions are not done or answered incorrectly
-
.91 - Background is shown and animated, one complexity question is answered AND CORRECT
-
.92 - Background is shown and animated, both complexity questions are answered correctly