Me gustaría dibujar esta imagen en un lienzo sin las partes transparentes. El principio de mi representación es que recorto imágenes pequeñas de una imagen grande usando el método createImageBitmap y las almaceno en una matriz. Luego los renderizo en el lienzo uno por uno. El problema es que también dibuja innecesariamente las partes transparentes. Entonces, si registro mi matriz, obtengo esto . Dado que mi mapa tiene mosaicos de 10x10, da como resultado 100 imágenes (de las cuales 96 son inútiles). En cambio, me gustaría guardar solo 4 imágenes.
No solo estropea mi rendimiento, sino que tengo más razones por las que me molesta. ¿Hay alguna manera de resolver este problema?
Mi código hasta ahora:
(async () => { const img = new Image(); img.src = "./img/obstacles.png"; await img.decode(); let tiles = []; let tileWidth = 32; let tileHeight = 32; for (let i = 0; i < 100; i++) { let x = i % 10; let y = Math.floor(i / 10); let bmp = await createImageBitmap(img, x * tileWidth, y * tileHeight, tileWidth, tileHeight); // index.js:13 tiles.push({ bmp, x, y }) } console.log(tiles) const canvas = document.querySelector("canvas"); canvas.width = 320; canvas.height = 320; const ctx = canvas.getContext("2d"); function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); tiles.forEach((tile) => { ctx.drawImage(tile.bmp, tile.x * tileWidth, tile.y * tileHeight); }) // requestAnimationFrame(draw) } draw(); })();Lo mejor es preparar su activo correctamente, por lo que eso significaría tener solo los 3 sprites únicos en su atlas:
Luego puede usar su bucle simple para obtener estos como objetos separados.
Sin embargo, no es raro tener sprites de diferentes tamaños en el mismo atlas, en tal caso, su ciclo simple no funcionará. En su lugar, debe preparar un diccionario de coordenadas (por ejemplo, como un archivo JSON, o incrustado directamente en su js), con todas las coordenadas de cada sprites.
La mayoría de las herramientas de generación de hojas de sprites producirán esto por ti.
Aquí hay un ejemplo en el que acabo de agregar un gran sprite al atlas:
(async () => { // If you are same-origin, it's better to fetch as a Blob // and create your ImageBitmap from the Blob // Here we aren't, so we have to go through an <img> const img = new Image(); img.src = "https://i.stack.imgur.com/h7w1C.png"; await img.decode(); document.body.append(img); // We hardcode the coords of each sprite const map = [ // [x, y, w, h] [0, 0, 32, 32], [0, 32, 32, 32], [0, 64, 32, 32], [32, 0, 96, 96], ]; const tiles = []; for (const [x, y, w, h] of map) { const bmp = await createImageBitmap(img, x, y, w, h); tiles.push({ bmp, x, y }) } console.log(tiles) const canvas = document.querySelector("canvas"); canvas.width = 320; canvas.height = 320; const ctx = canvas.getContext("2d"); let m = 0; function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); m = (m + 0.005) % 0.5; const margin = m + 1; tiles.forEach((tile) => { // we add some margin to show these are separate bitmaps ctx.drawImage(tile.bmp, tile.x * margin, tile.y * margin); }) requestAnimationFrame(draw) } draw(); })().catch(console.error); .as-console-wrapper { max-height: 100px !important } <canvas></canvas>