From 3976b32951aaf72f6785b3be0324deee97dbc6eb Mon Sep 17 00:00:00 2001 From: Justin Young <62815737+jyoung4242@users.noreply.github.com> Date: Sun, 2 Feb 2025 21:48:50 -0500 Subject: [PATCH] fix: Spritesheet Spacing Options, allowing Vectors (#3350) ### SpriteSheet.ts - modified SpriteSheetSpacingDimensions originOffset and margin to accept optional Vectors - modified fromImageSource to test for instance of Vector and handle it properly, while maintaining backward compatibility ### SpriteSheetSpec.ts - added test: `can be created from with spacing using vectors` ### Updated docs entry on Spritesheets to note that Vectors are now allowed Ran locally and verified functionality using both vec() and new Vector --------- Co-authored-by: Erik Onarheim --- CHANGELOG.md | 1 + site/docs/04-graphics/04.1-spritesheets.mdx | 4 +-- src/engine/Graphics/SpriteSheet.ts | 28 ++++++++++++++++--- src/spec/SpriteSheetSpec.ts | 31 +++++++++++++++++++++ 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45246a6c7..a3900860d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- Added ability to use `ex.Vector` to specify offset and margin in `SpriteSheet.fromImageSource({..})` - New PostProcessor.onDraw() hook to handle uploading textures - Adds contact solve bias to RealisticSolver, this allows customization on which direction contacts are solved first. By default there is no bias set to 'none'. diff --git a/site/docs/04-graphics/04.1-spritesheets.mdx b/site/docs/04-graphics/04.1-spritesheets.mdx index b1dc504a8..d364ba521 100644 --- a/site/docs/04-graphics/04.1-spritesheets.mdx +++ b/site/docs/04-graphics/04.1-spritesheets.mdx @@ -35,9 +35,9 @@ const spriteSheet = ex.SpriteSheet.fromImageSource({ }, spacing: { // Optionally specify the offset from the top left of sheet to start parsing - originOffset: { x: 11, y: 2 }, + originOffset: { x: 11, y: 2 }, // you can now also use a Vector here i.e. vec(11,2), or new Vector(11,2), // Optionally specify the margin between each sprite - margin: { x: 23, y: 5} + margin: { x: 23, y: 5} // you can now also use a Vector here i.e. vec(23,5), or new Vector(23,5), } }); ``` diff --git a/src/engine/Graphics/SpriteSheet.ts b/src/engine/Graphics/SpriteSheet.ts index 59946bc8d..0d2bde7c9 100644 --- a/src/engine/Graphics/SpriteSheet.ts +++ b/src/engine/Graphics/SpriteSheet.ts @@ -2,6 +2,7 @@ import { ImageSource } from './ImageSource'; import { SourceView, Sprite } from './Sprite'; import { GraphicOptions } from './Graphic'; import { TiledSprite, TiledSpriteOptions } from './TiledSprite'; +import { Vector } from '../Math/vector'; /** * Specify sprite sheet spacing options, useful if your sprites are not tightly packed @@ -12,13 +13,13 @@ export interface SpriteSheetSpacingDimensions { * The starting point to offset and start slicing the sprite sheet from the top left of the image. * Default is (0, 0) */ - originOffset?: { x?: number; y?: number }; + originOffset?: { x?: number; y?: number } | Vector; /** * The margin between sprites. * Default is (0, 0) */ - margin?: { x?: number; y?: number }; + margin?: { x?: number; y?: number } | Vector; } /** @@ -227,8 +228,27 @@ export class SpriteSheet { grid: { rows, columns: cols, spriteWidth, spriteHeight }, spacing: { originOffset, margin } } = options; - const offsetDefaults = { x: 0, y: 0, ...originOffset }; - const marginDefaults = { x: 0, y: 0, ...margin }; + let newmargin: { x: number; y: number } | undefined; + let neworiginOffset: { x: number; y: number } | undefined; + + if (originOffset instanceof Vector) { + neworiginOffset = { x: originOffset.x, y: originOffset.y }; + } else { + if (originOffset) { + neworiginOffset = { x: originOffset.x as number, y: originOffset.y as number }; + } + } + + if (margin instanceof Vector) { + newmargin = { x: margin.x, y: margin.y }; + } else { + if (margin) { + newmargin = { x: margin.x as number, y: margin.y as number }; + } + } + + const offsetDefaults = { x: 0, y: 0, ...neworiginOffset }; + const marginDefaults = { x: 0, y: 0, ...newmargin }; for (let x = 0; x < cols; x++) { for (let y = 0; y < rows; y++) { sprites[x + y * cols] = new Sprite({ diff --git a/src/spec/SpriteSheetSpec.ts b/src/spec/SpriteSheetSpec.ts index 3aa9fbcb2..5796d560e 100644 --- a/src/spec/SpriteSheetSpec.ts +++ b/src/spec/SpriteSheetSpec.ts @@ -100,6 +100,37 @@ describe('A SpriteSheet for Graphics', () => { await expectAsync(canvasElement).toEqualImage('src/spec/images/SpriteSheetSpec/NewSpriteSpacing.png'); }); + it('can be created from with spacing using vectors', async () => { + const image = new ex.ImageSource('src/spec/images/SpriteSheetSpec/kenny-cards.png'); + + await image.load(); + + const ss = ex.SpriteSheet.fromImageSource({ + image, + grid: { + rows: 4, + columns: 14, + spriteWidth: 42, + spriteHeight: 60 + }, + spacing: { + originOffset: ex.vec(11, 2), + margin: ex.vec(23, 5) + } + }); + + ctx.clear(); + + ss.sprites[12].draw(ctx, 0, 0); + ss.sprites[24].draw(ctx, 60, 0); + ss.sprites[36].draw(ctx, 0, 60); + ss.sprites[48].draw(ctx, 60, 60); + + expect(ss.sprites.length).toBe(4 * 14); + + await expectAsync(canvasElement).toEqualImage('src/spec/images/SpriteSheetSpec/NewSpriteSpacing.png'); + }); + it('can retrieve a sprite by x,y', async () => { const image = new ex.ImageSource('src/spec/images/SpriteSheetSpec/kenny-cards.png');