littlejsengine 1.18.22 → 1.18.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5841,13 +5841,15 @@ declare module "littlejsengine" {
5841
5841
  * @param {Vector2} imageSize - Size of the source image in pixels
5842
5842
  * @param {Vector2} [frameSize] - Size of each frame, or the whole image if not passed
5843
5843
  * @param {number} [padding] - How many pixels padding around each frame
5844
+ * @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image
5844
5845
  * @return {TileInfo} Tile for the packed image, or undefined if the sheet is full */
5845
- tryAdd(imageSize: Vector2, frameSize?: Vector2, padding?: number): TileInfo;
5846
+ tryAdd(imageSize: Vector2, frameSize?: Vector2, padding?: number, sourcePadding?: number | Vector2): TileInfo;
5846
5847
  /** Draw an image into this sheet at a tile returned by tryAdd
5847
5848
  * @param {HTMLImageElement} image - Source image to copy from
5848
5849
  * @param {TileInfo} tileInfo - Where to put it, from tryAdd
5849
- * @param {boolean} [update] - Upload to webgl now, pass false when batching */
5850
- drawImage(image: HTMLImageElement, tileInfo: TileInfo, update?: boolean): void;
5850
+ * @param {boolean} [update] - Upload to webgl now, pass false when batching
5851
+ * @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image */
5852
+ drawImage(image: HTMLImageElement, tileInfo: TileInfo, update?: boolean, sourcePadding?: number | Vector2): void;
5851
5853
  /** Upload the canvas to webgl if it has changed since the last upload
5852
5854
  * Only needed after batching, drawImage uploads automatically by default */
5853
5855
  updateTexture(): void;
@@ -5857,15 +5859,17 @@ declare module "littlejsengine" {
5857
5859
  * - Nothing is visible until it loads, use spritesReady to wait for it
5858
5860
  * - Pass frameSize for animations, then step through them with TileInfo.frame
5859
5861
  * - Grid images keep their layout and frames wrap down to the next row
5862
+ * - Pass sourcePadding if the source image has padding baked in around frames
5860
5863
  * @param {string} src - Image source path
5861
5864
  * @param {Vector2|number} [frameSize] - Size of each animation frame in pixels
5862
5865
  * @param {number} [padding] - How many pixels padding around each frame
5866
+ * @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image
5863
5867
  * @return {TileInfo}
5864
5868
  * @example
5865
5869
  * const playerTile = loadSprite('player.png'); // a single sprite
5866
5870
  * const runTile = loadSprite('run.png', vec2(16)); // a 16x16 frame animation
5867
5871
  * @memberof TextureSheets */
5868
- export function loadSprite(src: string, frameSize?: Vector2 | number, padding?: number): TileInfo;
5872
+ export function loadSprite(src: string, frameSize?: Vector2 | number, padding?: number, sourcePadding?: number | Vector2): TileInfo;
5869
5873
  /** Load a pre-packed texture atlas and repack it onto texture sheets
5870
5874
  * - Supports TexturePacker json (hash and array) and Aseprite json
5871
5875
  * - Returns an empty object which is filled with TileInfos when loaded
@@ -35,7 +35,7 @@ const engineName = 'LittleJS';
35
35
  * @type {string}
36
36
  * @default
37
37
  * @memberof Engine */
38
- const engineVersion = '1.18.22';
38
+ const engineVersion = '1.18.24';
39
39
 
40
40
  /** Frames per second to update
41
41
  * @type {number}
@@ -14998,13 +14998,23 @@ class TextureSheet
14998
14998
  * @param {Vector2} imageSize - Size of the source image in pixels
14999
14999
  * @param {Vector2} [frameSize] - Size of each frame, or the whole image if not passed
15000
15000
  * @param {number} [padding] - How many pixels padding around each frame
15001
+ * @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image
15001
15002
  * @return {TileInfo} Tile for the packed image, or undefined if the sheet is full */
15002
- tryAdd(imageSize, frameSize=imageSize, padding=textureSheetPadding)
15003
+ tryAdd(imageSize, frameSize=imageSize, padding=textureSheetPadding, sourcePadding=0)
15003
15004
  {
15004
15005
  ASSERT(isVector2(imageSize) && isVector2(frameSize), 'sizes must be vec2');
15005
15006
  ASSERT(frameSize.x > 0 && frameSize.y > 0, 'frame size must be positive');
15006
- ASSERT(imageSize.x % frameSize.x === 0 && imageSize.y % frameSize.y === 0,
15007
- 'image size must be a multiple of the frame size');
15007
+
15008
+ if (isNumber(sourcePadding))
15009
+ sourcePadding = vec2(sourcePadding);
15010
+ ASSERT(isVector2(sourcePadding) && sourcePadding.x >= 0 && sourcePadding.y >= 0,
15011
+ 'sourcePadding must be a number or vec2 >= 0');
15012
+
15013
+ // the source may have its own padding baked in around each frame
15014
+ const sourceCellWidth = frameSize.x + sourcePadding.x*2;
15015
+ const sourceCellHeight = frameSize.y + sourcePadding.y*2;
15016
+ ASSERT(imageSize.x % sourceCellWidth === 0 && imageSize.y % sourceCellHeight === 0,
15017
+ 'image size must be a multiple of the padded frame size');
15008
15018
 
15009
15019
  const cellWidth = frameSize.x + padding*2;
15010
15020
  const cellHeight = frameSize.y + padding*2;
@@ -15013,8 +15023,8 @@ class TextureSheet
15013
15023
 
15014
15024
  // keep the layout of the source image, but narrow it if a row is too wide
15015
15025
  // frames wrap down to the next row, which TileInfo.frame handles via columns
15016
- const sourceColumns = imageSize.x / frameSize.x;
15017
- const frameCount = sourceColumns * (imageSize.y / frameSize.y);
15026
+ const sourceColumns = imageSize.x / sourceCellWidth;
15027
+ const frameCount = sourceColumns * (imageSize.y / sourceCellHeight);
15018
15028
  const columns = min(sourceColumns, maxColumns);
15019
15029
  const blockWidth = columns * cellWidth;
15020
15030
  const blockHeight = ceil(frameCount / columns) * cellHeight;
@@ -15043,23 +15053,29 @@ class TextureSheet
15043
15053
  /** Draw an image into this sheet at a tile returned by tryAdd
15044
15054
  * @param {HTMLImageElement} image - Source image to copy from
15045
15055
  * @param {TileInfo} tileInfo - Where to put it, from tryAdd
15046
- * @param {boolean} [update] - Upload to webgl now, pass false when batching */
15047
- drawImage(image, tileInfo, update=true)
15056
+ * @param {boolean} [update] - Upload to webgl now, pass false when batching
15057
+ * @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image */
15058
+ drawImage(image, tileInfo, update=true, sourcePadding=0)
15048
15059
  {
15049
15060
  ASSERT(!!this.context, 'texture sheet has no canvas');
15050
15061
 
15062
+ if (isNumber(sourcePadding))
15063
+ sourcePadding = vec2(sourcePadding);
15064
+
15051
15065
  // copy frames in order, reading the source left to right, top to bottom
15052
15066
  // the destination wraps at tileInfo.columns which may be narrower than the source
15053
15067
  const frameSize = tileInfo.size;
15054
- const sourceColumns = image.width / frameSize.x;
15055
- const frameCount = sourceColumns * (image.height / frameSize.y);
15068
+ const sourceCellWidth = frameSize.x + sourcePadding.x*2;
15069
+ const sourceCellHeight = frameSize.y + sourcePadding.y*2;
15070
+ const sourceColumns = image.width / sourceCellWidth;
15071
+ const frameCount = sourceColumns * (image.height / sourceCellHeight);
15056
15072
  const columns = tileInfo.columns || frameCount;
15057
15073
  const cellWidth = frameSize.x + tileInfo.padding*2;
15058
15074
  const cellHeight = frameSize.y + tileInfo.padding*2;
15059
15075
  for (let i = frameCount; i--;)
15060
15076
  {
15061
- const sourceX = (i % sourceColumns) * frameSize.x;
15062
- const sourceY = (i / sourceColumns | 0) * frameSize.y;
15077
+ const sourceX = (i % sourceColumns) * sourceCellWidth + sourcePadding.x;
15078
+ const sourceY = (i / sourceColumns | 0) * sourceCellHeight + sourcePadding.y;
15063
15079
  this.context.drawImage(image,
15064
15080
  sourceX, sourceY, frameSize.x, frameSize.y,
15065
15081
  tileInfo.pos.x + (i % columns) * cellWidth,
@@ -15089,19 +15105,22 @@ class TextureSheet
15089
15105
  * - Nothing is visible until it loads, use spritesReady to wait for it
15090
15106
  * - Pass frameSize for animations, then step through them with TileInfo.frame
15091
15107
  * - Grid images keep their layout and frames wrap down to the next row
15108
+ * - Pass sourcePadding if the source image has padding baked in around frames
15092
15109
  * @param {string} src - Image source path
15093
15110
  * @param {Vector2|number} [frameSize] - Size of each animation frame in pixels
15094
15111
  * @param {number} [padding] - How many pixels padding around each frame
15112
+ * @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image
15095
15113
  * @return {TileInfo}
15096
15114
  * @example
15097
15115
  * const playerTile = loadSprite('player.png'); // a single sprite
15098
15116
  * const runTile = loadSprite('run.png', vec2(16)); // a 16x16 frame animation
15099
15117
  * @memberof TextureSheets */
15100
- function loadSprite(src, frameSize, padding=textureSheetPadding)
15118
+ function loadSprite(src, frameSize, padding=textureSheetPadding, sourcePadding=0)
15101
15119
  {
15102
15120
  ASSERT(isStringLike(src), 'image src must be a string');
15103
15121
  ASSERT(!frameSize || isVector2(frameSize) || isNumber(frameSize), 'frameSize must be a vec2 or number');
15104
15122
  ASSERT(isNumber(padding), 'padding must be a number');
15123
+ ASSERT(isNumber(sourcePadding) || isVector2(sourcePadding), 'sourcePadding must be a number or vec2');
15105
15124
 
15106
15125
  if (isNumber(frameSize))
15107
15126
  frameSize = vec2(frameSize);
@@ -15132,9 +15151,9 @@ function loadSprite(src, frameSize, padding=textureSheetPadding)
15132
15151
  // pack onto a sheet, then fill in the tile that was already handed out,
15133
15152
  // copying every field so nothing is missed if TileInfo gains more of them
15134
15153
  const imageSize = vec2(image.width, image.height);
15135
- const {sheet, tile} = textureSheetAdd(imageSize, frameSize, padding);
15154
+ const {sheet, tile} = textureSheetAdd(imageSize, frameSize, padding, sourcePadding);
15136
15155
  Object.assign(tileInfo, tile);
15137
- sheet.drawImage(image, tileInfo, false); // upload once per batch below
15156
+ sheet.drawImage(image, tileInfo, false, sourcePadding); // upload once per batch below
15138
15157
  }
15139
15158
  else
15140
15159
  {
@@ -15335,16 +15354,16 @@ function textureSheetCreate()
15335
15354
  }
15336
15355
 
15337
15356
  // use the first sheet with enough space, or make a new one
15338
- function textureSheetAdd(imageSize, frameSize, padding)
15357
+ function textureSheetAdd(imageSize, frameSize, padding, sourcePadding)
15339
15358
  {
15340
15359
  let sheet, tile;
15341
15360
  for (sheet of textureSheets)
15342
- if (tile = sheet.tryAdd(imageSize, frameSize, padding))
15361
+ if (tile = sheet.tryAdd(imageSize, frameSize, padding, sourcePadding))
15343
15362
  break;
15344
15363
  if (!tile)
15345
15364
  {
15346
15365
  sheet = textureSheetCreate();
15347
- tile = sheet.tryAdd(imageSize, frameSize, padding);
15366
+ tile = sheet.tryAdd(imageSize, frameSize, padding, sourcePadding);
15348
15367
  ASSERT(!!tile, 'image is too large to fit on a texture sheet');
15349
15368
  }
15350
15369
  return {sheet, tile};