make canvas image repeat scrolling upwards *solved*

Issue

So I’ve got a 600×2400 image I’m trying to make scroll upwards (character will be autorunning down the screen) and repeat. I’ve got the scrolling, but not the repeat. My question is, how do I make the image redraw for a second instance from the top and continue when I get to the end of this one? so far when the code gets to the end of the image, I just get a staggered repeat of the bottom section of the first instance scrolling.

JS

let canvas;
let context;
let secondsPassed;
let oldTimeStamp;
let fps;
let map = new Image();
let roadMovement = 0;
let increment = 2;
let screenx = window.innerWidth;
let screeny = window.innerHeight;
let run = true;
let bumper = 0;


window.onload = init;

function init() {
    canvas = document.getElementById('gameCanvas');
    context = canvas.getContext('2d');


    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;


    window.requestAnimationFrame(gameLoop);
}

function draw() {
    map.src = "downMap.png";

}


function gameLoop(timeStamp) {
    secondsPassed = (timeStamp - oldTimeStamp) / 1000;
    oldTimeStamp = timeStamp;
    fps = Math.round(1 / secondsPassed);



    roadMovement += increment;
    console.log(roadMovement);
    map.onload = function () {
        if (bumper < canvas.height) {
            context.drawImage(map, 0, roadMovement, 600, screeny, 0, 0, screenx, screeny);
        }
        if (roadMovement >= map.height - canvas.height && bumper < canvas.height) {

            bumper += increment;
            context.drawImage(map, 0, 0, 600, screeny, 0, screeny - bumper, screenx, screeny);
        }
        if (bumper >= canvas.height) {
            bumper = 0;
            roadMovement -= map.height;
        }
    };

    // Perform the drawing operation
    draw();

    if (run) {
        window.requestAnimationFrame(gameLoop);
    }
}

CSS

body{
    position: absolute;
    width:100vw;
    height:100vh;
    margin:0;
    padding:0;
    display: flex;
    justify-content: center;
    align-items: center;
}

#gameCanvas{
    position: relative;
    left:0;
    top:0;
    margin:0;
    padding:0;
}

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></title>
    <link rel="stylesheet" href="style.css">
    <script src="jquery-3.6.0.min.js"></script>
</head>
<body>
    <canvas id="gameCanvas">
    </canvas>

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

Edited added let for increment value so autoscroll speed can be changed.

Edited final Working continues rolling background ^_^ Thank you!! Code above for anyone who needs it!

Solution

You could draw the map image twice and reset the roadMovement any time it gets larger than the image height. That’s when you know the whole image is outside of the canvas view.

Technically, you only need to draw the second image when imageHeight - roadMovement < canvasHeight, but it might not be worth it to optimize.

let canvas;
let context;
let secondsPassed;
let oldTimeStamp;
let fps;
let map = new Image(600, 600);
map.onload = init;
map.src = "http://www.secretdoors.com/playit/resources/chessboard.gif";

let roadMovement = 0;
let increment = 2;

function init() {
    canvas = document.getElementById('gameCanvas');
    context = canvas.getContext('2d');
    canvas.width = 150;
    canvas.height = 150;
    window.requestAnimationFrame(gameLoop);
}


function gameLoop(timeStamp) {
    secondsPassed = (timeStamp - oldTimeStamp) / 1000;
    oldTimeStamp = timeStamp;
    fps = Math.round(1 / secondsPassed);

    roadMovement += increment;
    roadMovement %= map.naturalHeight;
    
    const y1 = roadMovement;
    const y2 = y1 - map.naturalHeight;

    context.clearRect(0, 0, 600, 600);

    context.drawImage(
      map,
      0, y1, map.naturalWidth, map.naturalHeight
    );
    
    context.drawImage(
      map,
      0, y2, map.naturalWidth, map.naturalHeight
    );
    
    window.requestAnimationFrame(gameLoop);
}
#gameCanvas{
  width: 150px;
  height: 150px;
  border: 1px solid red;
}
<canvas id="gameCanvas">
</canvas>

Answered By – user3297291

Answer Checked By – Cary Denson (AngularFixing Admin)

Leave a Reply

Your email address will not be published.