Tengo un mosaico que usa mosaicos de 32x32:

Lo pinto en un lienzo para representar un mapa de mosaicos de 32x32. Sin embargo, parece que las matemáticas no son correctas. ¿Por qué el lienzo pinta los mosaicos que claramente no están dentro de los límites de 32x32 de un mosaico?
Por ejemplo:
Como puede ver, la parte superior izquierda de la cuadrícula de 32x32 del lienzo debe ser UN mosaico... sin embargo, está cortado:
const appDiv = document.getElementById('app'); const tileSize = 32; const canvasSize = 480; // 32 (tiles) * 15 (columns) = 480 pixels const tilesAcross = canvasSize / tileSize; // (Size of Canvas [480] / Tile size [32]) = 15 columns appDiv.innerHTML = `<h2>Canvas</h2><canvas id="map" width="${canvasSize}" height="${canvasSize}">`; function randomIntFromInterval(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } resizeCanvas(); // Regenerate map on resize window.onresize = resizeCanvas; function resizeCanvas() { const ctx = document.getElementById('map').getContext('2d'); const image = new Image(); image.src = 'https://i.postimg.cc/k4KBLBJh/terrain.png'; // Tileset image.onload = () => { for (let column = 0; column < tilesAcross; column++) { for (let row = 0; row < tilesAcross; row++) { ctx.drawImage( image, // Image elemnt randomIntFromInterval(0, 5) * 32, // sx - The x-axis of top left corner of the rect of the image to draw into context. randomIntFromInterval(0, 5) * 32, // sy - The y-axis of top left corner of the rect of the image to draw into context. 32, // sWidth - The width of the rect of the image to draw into context. 32, // sHeight - The height of the rect of the image to draw into the destination context. row * 32, // dx - The x-axis coordinate in the canvas at which to place the top-left corner of the image. column * 32, // dy - The y-axis coordinate in the canvas at which to place the top-left corner of the image. 32, // dWidth - The width to draw the image in the canvas. This allows scaling of the drawn image. 32 // dHeight- The width to draw the image in the canvas. This allows scaling of the drawn image. ); } } }; } canvas { background: black; } <div id="app"></div> <style src="./style.css"></style>Los mosaicos en su imagen no son de 32x32px , sino de 28.56px .
Creo que necesitas volver a renderizar la hoja de sprites. No estará contento con este porque siempre tendrá líneas en los bordes donde para una fila/columna se han interpolado los píxeles de dos mosaicos.
Y si los estira, se volverán borrosos.
const appDiv = document.getElementById('app'); const tileSize = 32; const canvasSize = 480; // 32 (tiles) * 15 (columns) = 480 pixels const tilesAcross = canvasSize / tileSize; // (Size of Canvas [480] / Tile size [32]) = 15 columns appDiv.innerHTML = `<h2>Canvas</h2><canvas id="map" width="${canvasSize}" height="${canvasSize}">`; function randomIntFromInterval(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } resizeCanvas(); // Regenerate map on resize window.onresize = resizeCanvas; function resizeCanvas() { const ctx = document.getElementById('map').getContext('2d'); const image = new Image(); image.src = 'https://i.postimg.cc/k4KBLBJh/terrain.png'; // Tileset image.onload = () => { const {naturalWidth, naturalHeight} = image; const tileWidth = image.naturalWidth / 9; const tileHeight = image.naturalHeight / 28; console.log({ tileWidth, tileHeight, naturalWidth, naturalHeight, }) for (let column = 0; column < tilesAcross; column++) { for (let row = 0; row < tilesAcross; row++) { ctx.drawImage( image, // Image elemnt randomIntFromInterval(0, 5) * tileWidth, // sx - The x-axis of top left corner of the rect of the image to draw into context. randomIntFromInterval(0, 5) * tileHeight, // sy - The y-axis of top left corner of the rect of the image to draw into context. tileWidth, // sWidth - The width of the rect of the image to draw into context. tileHeight, // sHeight - The height of the rect of the image to draw into the destination context. row * 32, // dx - The x-axis coordinate in the canvas at which to place the top-left corner of the image. column * 32, // dy - The y-axis coordinate in the canvas at which to place the top-left corner of the image. 32, // dWidth - The width to draw the image in the canvas. This allows scaling of the drawn image. 32 // dHeight- The width to draw the image in the canvas. This allows scaling of the drawn image. ); } } }; } canvas { background: black; } <div id="app"></div> <style src="./style.css"></style>