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.
- package/dist/littlejs.d.ts +8 -4
- package/dist/littlejs.esm.js +37 -18
- package/dist/littlejs.esm.min.js +1 -1
- package/dist/littlejs.js +37 -18
- package/dist/littlejs.min.js +1 -1
- package/dist/littlejs.release.js +37 -18
- package/package.json +1 -1
- package/plugins/textureSheet.js +36 -17
- package/src/engine.js +1 -1
package/dist/littlejs.release.js
CHANGED
|
@@ -35,7 +35,7 @@ const engineName = 'LittleJS';
|
|
|
35
35
|
* @type {string}
|
|
36
36
|
* @default
|
|
37
37
|
* @memberof Engine */
|
|
38
|
-
const engineVersion = '1.18.
|
|
38
|
+
const engineVersion = '1.18.24';
|
|
39
39
|
|
|
40
40
|
/** Frames per second to update
|
|
41
41
|
* @type {number}
|
|
@@ -14307,13 +14307,23 @@ class TextureSheet
|
|
|
14307
14307
|
* @param {Vector2} imageSize - Size of the source image in pixels
|
|
14308
14308
|
* @param {Vector2} [frameSize] - Size of each frame, or the whole image if not passed
|
|
14309
14309
|
* @param {number} [padding] - How many pixels padding around each frame
|
|
14310
|
+
* @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image
|
|
14310
14311
|
* @return {TileInfo} Tile for the packed image, or undefined if the sheet is full */
|
|
14311
|
-
tryAdd(imageSize, frameSize=imageSize, padding=textureSheetPadding)
|
|
14312
|
+
tryAdd(imageSize, frameSize=imageSize, padding=textureSheetPadding, sourcePadding=0)
|
|
14312
14313
|
{
|
|
14313
14314
|
ASSERT(isVector2(imageSize) && isVector2(frameSize), 'sizes must be vec2');
|
|
14314
14315
|
ASSERT(frameSize.x > 0 && frameSize.y > 0, 'frame size must be positive');
|
|
14315
|
-
|
|
14316
|
-
|
|
14316
|
+
|
|
14317
|
+
if (isNumber(sourcePadding))
|
|
14318
|
+
sourcePadding = vec2(sourcePadding);
|
|
14319
|
+
ASSERT(isVector2(sourcePadding) && sourcePadding.x >= 0 && sourcePadding.y >= 0,
|
|
14320
|
+
'sourcePadding must be a number or vec2 >= 0');
|
|
14321
|
+
|
|
14322
|
+
// the source may have its own padding baked in around each frame
|
|
14323
|
+
const sourceCellWidth = frameSize.x + sourcePadding.x*2;
|
|
14324
|
+
const sourceCellHeight = frameSize.y + sourcePadding.y*2;
|
|
14325
|
+
ASSERT(imageSize.x % sourceCellWidth === 0 && imageSize.y % sourceCellHeight === 0,
|
|
14326
|
+
'image size must be a multiple of the padded frame size');
|
|
14317
14327
|
|
|
14318
14328
|
const cellWidth = frameSize.x + padding*2;
|
|
14319
14329
|
const cellHeight = frameSize.y + padding*2;
|
|
@@ -14322,8 +14332,8 @@ class TextureSheet
|
|
|
14322
14332
|
|
|
14323
14333
|
// keep the layout of the source image, but narrow it if a row is too wide
|
|
14324
14334
|
// frames wrap down to the next row, which TileInfo.frame handles via columns
|
|
14325
|
-
const sourceColumns = imageSize.x /
|
|
14326
|
-
const frameCount = sourceColumns * (imageSize.y /
|
|
14335
|
+
const sourceColumns = imageSize.x / sourceCellWidth;
|
|
14336
|
+
const frameCount = sourceColumns * (imageSize.y / sourceCellHeight);
|
|
14327
14337
|
const columns = min(sourceColumns, maxColumns);
|
|
14328
14338
|
const blockWidth = columns * cellWidth;
|
|
14329
14339
|
const blockHeight = ceil(frameCount / columns) * cellHeight;
|
|
@@ -14352,23 +14362,29 @@ class TextureSheet
|
|
|
14352
14362
|
/** Draw an image into this sheet at a tile returned by tryAdd
|
|
14353
14363
|
* @param {HTMLImageElement} image - Source image to copy from
|
|
14354
14364
|
* @param {TileInfo} tileInfo - Where to put it, from tryAdd
|
|
14355
|
-
* @param {boolean} [update] - Upload to webgl now, pass false when batching
|
|
14356
|
-
|
|
14365
|
+
* @param {boolean} [update] - Upload to webgl now, pass false when batching
|
|
14366
|
+
* @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image */
|
|
14367
|
+
drawImage(image, tileInfo, update=true, sourcePadding=0)
|
|
14357
14368
|
{
|
|
14358
14369
|
ASSERT(!!this.context, 'texture sheet has no canvas');
|
|
14359
14370
|
|
|
14371
|
+
if (isNumber(sourcePadding))
|
|
14372
|
+
sourcePadding = vec2(sourcePadding);
|
|
14373
|
+
|
|
14360
14374
|
// copy frames in order, reading the source left to right, top to bottom
|
|
14361
14375
|
// the destination wraps at tileInfo.columns which may be narrower than the source
|
|
14362
14376
|
const frameSize = tileInfo.size;
|
|
14363
|
-
const
|
|
14364
|
-
const
|
|
14377
|
+
const sourceCellWidth = frameSize.x + sourcePadding.x*2;
|
|
14378
|
+
const sourceCellHeight = frameSize.y + sourcePadding.y*2;
|
|
14379
|
+
const sourceColumns = image.width / sourceCellWidth;
|
|
14380
|
+
const frameCount = sourceColumns * (image.height / sourceCellHeight);
|
|
14365
14381
|
const columns = tileInfo.columns || frameCount;
|
|
14366
14382
|
const cellWidth = frameSize.x + tileInfo.padding*2;
|
|
14367
14383
|
const cellHeight = frameSize.y + tileInfo.padding*2;
|
|
14368
14384
|
for (let i = frameCount; i--;)
|
|
14369
14385
|
{
|
|
14370
|
-
const sourceX = (i % sourceColumns) *
|
|
14371
|
-
const sourceY = (i / sourceColumns | 0) *
|
|
14386
|
+
const sourceX = (i % sourceColumns) * sourceCellWidth + sourcePadding.x;
|
|
14387
|
+
const sourceY = (i / sourceColumns | 0) * sourceCellHeight + sourcePadding.y;
|
|
14372
14388
|
this.context.drawImage(image,
|
|
14373
14389
|
sourceX, sourceY, frameSize.x, frameSize.y,
|
|
14374
14390
|
tileInfo.pos.x + (i % columns) * cellWidth,
|
|
@@ -14398,19 +14414,22 @@ class TextureSheet
|
|
|
14398
14414
|
* - Nothing is visible until it loads, use spritesReady to wait for it
|
|
14399
14415
|
* - Pass frameSize for animations, then step through them with TileInfo.frame
|
|
14400
14416
|
* - Grid images keep their layout and frames wrap down to the next row
|
|
14417
|
+
* - Pass sourcePadding if the source image has padding baked in around frames
|
|
14401
14418
|
* @param {string} src - Image source path
|
|
14402
14419
|
* @param {Vector2|number} [frameSize] - Size of each animation frame in pixels
|
|
14403
14420
|
* @param {number} [padding] - How many pixels padding around each frame
|
|
14421
|
+
* @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image
|
|
14404
14422
|
* @return {TileInfo}
|
|
14405
14423
|
* @example
|
|
14406
14424
|
* const playerTile = loadSprite('player.png'); // a single sprite
|
|
14407
14425
|
* const runTile = loadSprite('run.png', vec2(16)); // a 16x16 frame animation
|
|
14408
14426
|
* @memberof TextureSheets */
|
|
14409
|
-
function loadSprite(src, frameSize, padding=textureSheetPadding)
|
|
14427
|
+
function loadSprite(src, frameSize, padding=textureSheetPadding, sourcePadding=0)
|
|
14410
14428
|
{
|
|
14411
14429
|
ASSERT(isStringLike(src), 'image src must be a string');
|
|
14412
14430
|
ASSERT(!frameSize || isVector2(frameSize) || isNumber(frameSize), 'frameSize must be a vec2 or number');
|
|
14413
14431
|
ASSERT(isNumber(padding), 'padding must be a number');
|
|
14432
|
+
ASSERT(isNumber(sourcePadding) || isVector2(sourcePadding), 'sourcePadding must be a number or vec2');
|
|
14414
14433
|
|
|
14415
14434
|
if (isNumber(frameSize))
|
|
14416
14435
|
frameSize = vec2(frameSize);
|
|
@@ -14441,9 +14460,9 @@ function loadSprite(src, frameSize, padding=textureSheetPadding)
|
|
|
14441
14460
|
// pack onto a sheet, then fill in the tile that was already handed out,
|
|
14442
14461
|
// copying every field so nothing is missed if TileInfo gains more of them
|
|
14443
14462
|
const imageSize = vec2(image.width, image.height);
|
|
14444
|
-
const {sheet, tile} = textureSheetAdd(imageSize, frameSize, padding);
|
|
14463
|
+
const {sheet, tile} = textureSheetAdd(imageSize, frameSize, padding, sourcePadding);
|
|
14445
14464
|
Object.assign(tileInfo, tile);
|
|
14446
|
-
sheet.drawImage(image, tileInfo, false); // upload once per batch below
|
|
14465
|
+
sheet.drawImage(image, tileInfo, false, sourcePadding); // upload once per batch below
|
|
14447
14466
|
}
|
|
14448
14467
|
else
|
|
14449
14468
|
{
|
|
@@ -14644,16 +14663,16 @@ function textureSheetCreate()
|
|
|
14644
14663
|
}
|
|
14645
14664
|
|
|
14646
14665
|
// use the first sheet with enough space, or make a new one
|
|
14647
|
-
function textureSheetAdd(imageSize, frameSize, padding)
|
|
14666
|
+
function textureSheetAdd(imageSize, frameSize, padding, sourcePadding)
|
|
14648
14667
|
{
|
|
14649
14668
|
let sheet, tile;
|
|
14650
14669
|
for (sheet of textureSheets)
|
|
14651
|
-
if (tile = sheet.tryAdd(imageSize, frameSize, padding))
|
|
14670
|
+
if (tile = sheet.tryAdd(imageSize, frameSize, padding, sourcePadding))
|
|
14652
14671
|
break;
|
|
14653
14672
|
if (!tile)
|
|
14654
14673
|
{
|
|
14655
14674
|
sheet = textureSheetCreate();
|
|
14656
|
-
tile = sheet.tryAdd(imageSize, frameSize, padding);
|
|
14675
|
+
tile = sheet.tryAdd(imageSize, frameSize, padding, sourcePadding);
|
|
14657
14676
|
ASSERT(!!tile, 'image is too large to fit on a texture sheet');
|
|
14658
14677
|
}
|
|
14659
14678
|
return {sheet, tile};
|
package/package.json
CHANGED
package/plugins/textureSheet.js
CHANGED
|
@@ -73,13 +73,23 @@ class TextureSheet
|
|
|
73
73
|
* @param {Vector2} imageSize - Size of the source image in pixels
|
|
74
74
|
* @param {Vector2} [frameSize] - Size of each frame, or the whole image if not passed
|
|
75
75
|
* @param {number} [padding] - How many pixels padding around each frame
|
|
76
|
+
* @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image
|
|
76
77
|
* @return {TileInfo} Tile for the packed image, or undefined if the sheet is full */
|
|
77
|
-
tryAdd(imageSize, frameSize=imageSize, padding=textureSheetPadding)
|
|
78
|
+
tryAdd(imageSize, frameSize=imageSize, padding=textureSheetPadding, sourcePadding=0)
|
|
78
79
|
{
|
|
79
80
|
ASSERT(isVector2(imageSize) && isVector2(frameSize), 'sizes must be vec2');
|
|
80
81
|
ASSERT(frameSize.x > 0 && frameSize.y > 0, 'frame size must be positive');
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
|
|
83
|
+
if (isNumber(sourcePadding))
|
|
84
|
+
sourcePadding = vec2(sourcePadding);
|
|
85
|
+
ASSERT(isVector2(sourcePadding) && sourcePadding.x >= 0 && sourcePadding.y >= 0,
|
|
86
|
+
'sourcePadding must be a number or vec2 >= 0');
|
|
87
|
+
|
|
88
|
+
// the source may have its own padding baked in around each frame
|
|
89
|
+
const sourceCellWidth = frameSize.x + sourcePadding.x*2;
|
|
90
|
+
const sourceCellHeight = frameSize.y + sourcePadding.y*2;
|
|
91
|
+
ASSERT(imageSize.x % sourceCellWidth === 0 && imageSize.y % sourceCellHeight === 0,
|
|
92
|
+
'image size must be a multiple of the padded frame size');
|
|
83
93
|
|
|
84
94
|
const cellWidth = frameSize.x + padding*2;
|
|
85
95
|
const cellHeight = frameSize.y + padding*2;
|
|
@@ -88,8 +98,8 @@ class TextureSheet
|
|
|
88
98
|
|
|
89
99
|
// keep the layout of the source image, but narrow it if a row is too wide
|
|
90
100
|
// frames wrap down to the next row, which TileInfo.frame handles via columns
|
|
91
|
-
const sourceColumns = imageSize.x /
|
|
92
|
-
const frameCount = sourceColumns * (imageSize.y /
|
|
101
|
+
const sourceColumns = imageSize.x / sourceCellWidth;
|
|
102
|
+
const frameCount = sourceColumns * (imageSize.y / sourceCellHeight);
|
|
93
103
|
const columns = min(sourceColumns, maxColumns);
|
|
94
104
|
const blockWidth = columns * cellWidth;
|
|
95
105
|
const blockHeight = ceil(frameCount / columns) * cellHeight;
|
|
@@ -118,23 +128,29 @@ class TextureSheet
|
|
|
118
128
|
/** Draw an image into this sheet at a tile returned by tryAdd
|
|
119
129
|
* @param {HTMLImageElement} image - Source image to copy from
|
|
120
130
|
* @param {TileInfo} tileInfo - Where to put it, from tryAdd
|
|
121
|
-
* @param {boolean} [update] - Upload to webgl now, pass false when batching
|
|
122
|
-
|
|
131
|
+
* @param {boolean} [update] - Upload to webgl now, pass false when batching
|
|
132
|
+
* @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image */
|
|
133
|
+
drawImage(image, tileInfo, update=true, sourcePadding=0)
|
|
123
134
|
{
|
|
124
135
|
ASSERT(!!this.context, 'texture sheet has no canvas');
|
|
125
136
|
|
|
137
|
+
if (isNumber(sourcePadding))
|
|
138
|
+
sourcePadding = vec2(sourcePadding);
|
|
139
|
+
|
|
126
140
|
// copy frames in order, reading the source left to right, top to bottom
|
|
127
141
|
// the destination wraps at tileInfo.columns which may be narrower than the source
|
|
128
142
|
const frameSize = tileInfo.size;
|
|
129
|
-
const
|
|
130
|
-
const
|
|
143
|
+
const sourceCellWidth = frameSize.x + sourcePadding.x*2;
|
|
144
|
+
const sourceCellHeight = frameSize.y + sourcePadding.y*2;
|
|
145
|
+
const sourceColumns = image.width / sourceCellWidth;
|
|
146
|
+
const frameCount = sourceColumns * (image.height / sourceCellHeight);
|
|
131
147
|
const columns = tileInfo.columns || frameCount;
|
|
132
148
|
const cellWidth = frameSize.x + tileInfo.padding*2;
|
|
133
149
|
const cellHeight = frameSize.y + tileInfo.padding*2;
|
|
134
150
|
for (let i = frameCount; i--;)
|
|
135
151
|
{
|
|
136
|
-
const sourceX = (i % sourceColumns) *
|
|
137
|
-
const sourceY = (i / sourceColumns | 0) *
|
|
152
|
+
const sourceX = (i % sourceColumns) * sourceCellWidth + sourcePadding.x;
|
|
153
|
+
const sourceY = (i / sourceColumns | 0) * sourceCellHeight + sourcePadding.y;
|
|
138
154
|
this.context.drawImage(image,
|
|
139
155
|
sourceX, sourceY, frameSize.x, frameSize.y,
|
|
140
156
|
tileInfo.pos.x + (i % columns) * cellWidth,
|
|
@@ -164,19 +180,22 @@ class TextureSheet
|
|
|
164
180
|
* - Nothing is visible until it loads, use spritesReady to wait for it
|
|
165
181
|
* - Pass frameSize for animations, then step through them with TileInfo.frame
|
|
166
182
|
* - Grid images keep their layout and frames wrap down to the next row
|
|
183
|
+
* - Pass sourcePadding if the source image has padding baked in around frames
|
|
167
184
|
* @param {string} src - Image source path
|
|
168
185
|
* @param {Vector2|number} [frameSize] - Size of each animation frame in pixels
|
|
169
186
|
* @param {number} [padding] - How many pixels padding around each frame
|
|
187
|
+
* @param {number|Vector2} [sourcePadding] - How many pixels padding around each frame in the source image
|
|
170
188
|
* @return {TileInfo}
|
|
171
189
|
* @example
|
|
172
190
|
* const playerTile = loadSprite('player.png'); // a single sprite
|
|
173
191
|
* const runTile = loadSprite('run.png', vec2(16)); // a 16x16 frame animation
|
|
174
192
|
* @memberof TextureSheets */
|
|
175
|
-
function loadSprite(src, frameSize, padding=textureSheetPadding)
|
|
193
|
+
function loadSprite(src, frameSize, padding=textureSheetPadding, sourcePadding=0)
|
|
176
194
|
{
|
|
177
195
|
ASSERT(isStringLike(src), 'image src must be a string');
|
|
178
196
|
ASSERT(!frameSize || isVector2(frameSize) || isNumber(frameSize), 'frameSize must be a vec2 or number');
|
|
179
197
|
ASSERT(isNumber(padding), 'padding must be a number');
|
|
198
|
+
ASSERT(isNumber(sourcePadding) || isVector2(sourcePadding), 'sourcePadding must be a number or vec2');
|
|
180
199
|
|
|
181
200
|
if (isNumber(frameSize))
|
|
182
201
|
frameSize = vec2(frameSize);
|
|
@@ -207,9 +226,9 @@ function loadSprite(src, frameSize, padding=textureSheetPadding)
|
|
|
207
226
|
// pack onto a sheet, then fill in the tile that was already handed out,
|
|
208
227
|
// copying every field so nothing is missed if TileInfo gains more of them
|
|
209
228
|
const imageSize = vec2(image.width, image.height);
|
|
210
|
-
const {sheet, tile} = textureSheetAdd(imageSize, frameSize, padding);
|
|
229
|
+
const {sheet, tile} = textureSheetAdd(imageSize, frameSize, padding, sourcePadding);
|
|
211
230
|
Object.assign(tileInfo, tile);
|
|
212
|
-
sheet.drawImage(image, tileInfo, false); // upload once per batch below
|
|
231
|
+
sheet.drawImage(image, tileInfo, false, sourcePadding); // upload once per batch below
|
|
213
232
|
}
|
|
214
233
|
else
|
|
215
234
|
{
|
|
@@ -410,16 +429,16 @@ function textureSheetCreate()
|
|
|
410
429
|
}
|
|
411
430
|
|
|
412
431
|
// use the first sheet with enough space, or make a new one
|
|
413
|
-
function textureSheetAdd(imageSize, frameSize, padding)
|
|
432
|
+
function textureSheetAdd(imageSize, frameSize, padding, sourcePadding)
|
|
414
433
|
{
|
|
415
434
|
let sheet, tile;
|
|
416
435
|
for (sheet of textureSheets)
|
|
417
|
-
if (tile = sheet.tryAdd(imageSize, frameSize, padding))
|
|
436
|
+
if (tile = sheet.tryAdd(imageSize, frameSize, padding, sourcePadding))
|
|
418
437
|
break;
|
|
419
438
|
if (!tile)
|
|
420
439
|
{
|
|
421
440
|
sheet = textureSheetCreate();
|
|
422
|
-
tile = sheet.tryAdd(imageSize, frameSize, padding);
|
|
441
|
+
tile = sheet.tryAdd(imageSize, frameSize, padding, sourcePadding);
|
|
423
442
|
ASSERT(!!tile, 'image is too large to fit on a texture sheet');
|
|
424
443
|
}
|
|
425
444
|
return {sheet, tile};
|