He estado programando un juego usando el lienzo de HTML5 y JavaScript, y cuando trato de rotar una imagen, muestra una pequeña porción de la imagen adyacente de la hoja de sprites. Sé que podría separar las imágenes en la hoja de sprites, pero estoy tratando de encontrar otra forma de resolver el problema, como cambiar una configuración.
No es un gran problema, pero es extraño que se agarre una parte de una imagen adyacente cuando no se especificó. Los sprites son de 16 por 16 píxeles.
La línea de código que dibuja el sprite de la mano es la segunda imagen dibujada y estoy usando un índice para capturar las imágenes. Aquí, el resultado es 208, que es donde está el cuadrado verde en la imagen.
c.save(); c.translate(canvas.width/2, canvas.height/2); if(mouseAngle >= 90 || mouseAngle <= -90) { c.scale(-1, 1); c.rotate(Math.PI / 180 * (180 + -mouseAngle)); } else { c.rotate(Math.PI / 180 * (mouseAngle)); }; c.drawImage(Images.items, itemID[this.heldItem] * 16, 0, 16, 16, scale, -12 * scale, 16 * scale, 16 * scale); c.drawImage(Images.player, this.handFramePath[this.dmgIndex] * 16, 0, 16, 16, scale, -12 * scale, 16 * scale, 16 * scale); c.restore();Sí, las texturas sangran por el recorte de drawImage .
Por lo general, podemos intentar evitar eso asegurándonos de que las transformaciones de nuestro contexto estén en coordenadas enteras, para evitar cualquier suavizado, pero para la rotación... eso es más complejo.
Entonces, lo mejor en su caso (con o sin sangrado en realidad), es extraer cada sprite de la hoja de sprite en su propio objeto ImageBitmap .
De esta manera, el recorte se realizará sin que se produzca ninguna transformación, y tendrá la ventaja adicional de permitir que el navegador optimice los sprites que se usan con más frecuencia (en lugar de mover toda la hoja de sprites cada vez).
(async() => { const spritesheet = document.querySelector("img"); await spritesheet.decode(); const canvas = document.querySelector("canvas"); const ctx = canvas.getContext("2d"); // apply some transforms ctx.translate(50, 50); ctx.rotate(Math.PI/32); ctx.translate(-50, -50); // draw only the gray rectangle // cropped from the full spritesheet on the left // (bleeds in all directions on Chrome) ctx.drawImage(spritesheet, 8, 8, 8, 8, 50, 50, 50, 50 ); // single sprite on the right const sprite = await createImageBitmap(spritesheet, 8, 8, 8, 8); ctx.drawImage(sprite, 150, 50, 50, 50 ); })().catch(console.error); <p>The original sprite-sheet:<img src="https://i.stack.imgur.com/I1xPN.png"></p> <canvas></canvas> createImageBitmap ahora es compatible con todos los navegadores actualizados, pero para los más antiguos (por ejemplo, Safari lo expuso hace solo unas semanas), hice un polyfill que puede encontrar aquí .