diff --git a/src/assets/asset.ts b/src/assets/asset.ts index 2057131b..91f82981 100644 --- a/src/assets/asset.ts +++ b/src/assets/asset.ts @@ -214,7 +214,7 @@ export function load(prom: Promise): Asset { // create assets export type AssetsCtx = ReturnType; -export const initAssets = (ggl: GfxCtx) => { +export const initAssets = (ggl: GfxCtx, spriteAtlasPadding: number) => { const assets = { urlPrefix: "", // asset holders @@ -225,7 +225,12 @@ export const initAssets = (ggl: GfxCtx) => { shaders: new AssetBucket(), custom: new AssetBucket(), music: {} as Record, - packer: new TexPacker(ggl, SPRITE_ATLAS_WIDTH, SPRITE_ATLAS_HEIGHT), + packer: new TexPacker( + ggl, + SPRITE_ATLAS_WIDTH, + SPRITE_ATLAS_HEIGHT, + spriteAtlasPadding, + ), // if we finished initially loading all assets loaded: false, }; diff --git a/src/gfx/classes/TexPacker.ts b/src/gfx/classes/TexPacker.ts index 6af9ba49..8addbd30 100644 --- a/src/gfx/classes/TexPacker.ts +++ b/src/gfx/classes/TexPacker.ts @@ -17,14 +17,16 @@ export default class TexPacker { private y: number = 0; private curHeight: number = 0; private gfx: GfxCtx; + private padding: number; - constructor(gfx: GfxCtx, w: number, h: number) { + constructor(gfx: GfxCtx, w: number, h: number, padding: number) { this.gfx = gfx; this.canvas = document.createElement("canvas"); this.canvas.width = w; this.canvas.height = h; this.textures = [Texture.fromImage(gfx, this.canvas)]; this.bigTextures = []; + this.padding = padding; const context2D = this.canvas.getContext("2d"); if (!context2D) throw new Error("Failed to get 2d context"); @@ -33,21 +35,26 @@ export default class TexPacker { } add(img: ImageSource): [Texture, Quad, number] { - if (img.width > this.canvas.width || img.height > this.canvas.height) { + const paddedWidth = img.width + this.padding * 2; + const paddedHeight = img.height + this.padding * 2; + + if ( + paddedWidth > this.canvas.width || paddedHeight > this.canvas.height + ) { const tex = Texture.fromImage(this.gfx, img); this.bigTextures.push(tex); return [tex, new Quad(0, 0, 1, 1), 0]; } // next row - if (this.x + img.width > this.canvas.width) { + if (this.x + paddedWidth > this.canvas.width) { this.x = 0; this.y += this.curHeight; this.curHeight = 0; } // next texture - if (this.y + img.height > this.canvas.height) { + if (this.y + paddedHeight > this.canvas.height) { this.c2d.clearRect(0, 0, this.canvas.width, this.canvas.height); this.textures.push(Texture.fromImage(this.gfx, this.canvas)); this.x = 0; @@ -56,14 +63,12 @@ export default class TexPacker { } const curTex = this.textures[this.textures.length - 1]; - const pos = new Vec2(this.x, this.y); - const differenceWidth = this.canvas.width - this.x; - const differenceHeight = this.canvas.height - this.y; + const pos = new Vec2(this.x + this.padding, this.y + this.padding); - this.x += img.width; + this.x += paddedWidth; - if (img.height > this.curHeight) { - this.curHeight = img.height; + if (paddedHeight > this.curHeight) { + this.curHeight = paddedHeight; } if (img instanceof ImageData) { diff --git a/src/kaplay.ts b/src/kaplay.ts index ba356517..34db2687 100644 --- a/src/kaplay.ts +++ b/src/kaplay.ts @@ -484,7 +484,7 @@ const kaplay = < _k.gfx = gfx; const audio = initAudio(); _k.audio = audio; - const assets = initAssets(ggl); + const assets = initAssets(ggl, gopt.spriteAtlasPadding ?? 0); _k.assets = assets; const game = initGame(); _k.game = game; diff --git a/src/types.ts b/src/types.ts index f0af3b2f..b5c0f787 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5963,6 +5963,11 @@ export interface KAPLAYOpt< * @experimental This feature is in experimental phase, it will be fully released in v3001.1.0 */ tagsAsComponents?: boolean; + /** + * Padding used when adding sprites to texture atlas. + * @default 0 + */ + spriteAtlasPadding?: number; } /**