Así que tengo una imagen de 600x2400 que estoy tratando de hacer que se desplace hacia arriba (el personaje se ejecutará automáticamente hacia abajo en la pantalla) y repita. Tengo el desplazamiento, pero no la repetición. Mi pregunta es, ¿cómo hago que la imagen se vuelva a dibujar para una segunda instancia desde arriba y continúe cuando llegue al final de esta? hasta ahora, cuando el código llega al final de la imagen, solo obtengo una repetición escalonada de la sección inferior del desplazamiento de primera instancia.
JS
let canvas; let context; let secondsPassed; let oldTimeStamp; let fps; let map = new Image(); let roadMovement = 0; let increment = 2; 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 = "map.png"; } function gameLoop(timeStamp) { secondsPassed = (timeStamp - oldTimeStamp) / 1000; oldTimeStamp = timeStamp; fps = Math.round(1 / secondsPassed); roadMovement += increment; map.onload = function () { context.drawImage(map, 0, roadMovement, 600, 600, 0, 0, canvas.width, canvas.height); }; draw(); 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>Editado let agregado para el valor de incremento para que se pueda cambiar la velocidad de desplazamiento automático.
¿Qué hay de colocar la imagen como fondo de la página directamente en CSS?
Prueba esto:
body{ position: absolute; width:100vw; height:1000vh; margin:0; padding:0; display: flex; justify-content: center; align-items: center; background-image: url('./map.png'); background-repeat: repeat; background-size: 100%; /*scale the image at 100% of the page width*/ }Puede dibujar la imagen del mapa dos veces y restablecer el movimiento de la roadMovement cada vez que sea más grande que la altura de la imagen. Ahí es cuando sabes que toda la imagen está fuera de la vista del lienzo.
Técnicamente, solo necesita dibujar la segunda imagen cuando imageHeight - roadMovement < canvasHeight , pero puede que no valga la pena optimizarlo.
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>