Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change: GraphicsGroup no longer centers with anchors #2966

Merged
merged 6 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Added

- Added `useAnchor` parameter to `ex.GraphicsGroup` to allow users to opt out of anchor based positioning, if set to false all graphics members
will be positioned with the top left of the graphic at the actor's position.
```typescript
const graphicGroup = new ex.GraphicsGroup({
useAnchor: false,
members: [
{
graphic: heartImage.toSprite(),
offset: ex.vec(0, 0),
},
{
graphic: heartImage.toSprite(),
offset: ex.vec(0, 16),
},
{
graphic: heartImage.toSprite(),
offset: ex.vec(16, 16),
},
{
graphic: heartImage.toSprite(),
offset: ex.vec(16, 0),
},
],
});
```
- Added simplified `ex.coroutine` overloads, you need not pass engine as long as you are in an Excalibur lifecycle
```typescript
const result = ex.coroutine(function* () {...});
Expand Down
35 changes: 20 additions & 15 deletions sandbox/tests/graphics-group/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
var game = new ex.Engine({
width: 1000,
height: 1000,
pixelArt: true
});
game.toggleDebug();
game.debug.graphics.showBounds = true;
game.debug.transform.showPosition = true;

var heartImage = new ex.ImageSource('./heart.png');

Expand All @@ -19,28 +23,27 @@ class MyActor2 extends ex.Actor {
this.graphics.add(
"interactive",
new ex.GraphicsGroup({
useAnchor: false,
members: [
{
graphic: undefined,
offset: ex.vec(8, 8),
graphic: heartImage.toSprite(),
offset: ex.vec(0, 0),
},
{
graphic: heartImage.toSprite(),
offset: ex.vec(0, 16),
},
{
graphic: heartImage.toSprite(),
offset: ex.vec(8, -16),
offset: ex.vec(16, 16),
},
{
graphic: heartImage.toSprite(),
offset: ex.vec(16, 0),
},
],
}),
{
anchor: ex.vec(0, 0),
}
})
);
this.graphics.add(
"noninteractive",
heartImage.toSprite(),
{
anchor: ex.vec(8, 8),
}
)
}

onPreUpdate(engine: ex.Engine<any>, delta: number): void {
Expand All @@ -50,4 +53,6 @@ class MyActor2 extends ex.Actor {

game.add(new MyActor2());

game.start(loader)
game.start(loader)
game.currentScene.camera.pos = ex.vec(200, 200);
game.currentScene.camera.zoom = 3;
7 changes: 6 additions & 1 deletion src/engine/Graphics/GraphicsComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Material } from './Context/material';
import { Logger } from '../Util/Log';
import { WatchVector } from '../Math/watch-vector';
import { TransformComponent } from '../EntityComponentSystem';
import { GraphicsGroup } from '../Graphics/GraphicsGroup';

/**
* Type guard for checking if a Graphic HasTick (used for graphics that change over time like animations)
Expand Down Expand Up @@ -359,7 +360,11 @@ export class GraphicsComponent extends Component {
const bounds = graphic.localBounds;
const offsetX = -bounds.width * anchor.x + offset.x;
const offsetY = -bounds.height * anchor.y + offset.y;
bb = graphic?.localBounds.translate(vec(offsetX, offsetY)).combine(bb);
if (graphic instanceof GraphicsGroup && !graphic.useAnchor) {
bb = graphic?.localBounds.combine(bb);
} else {
bb = graphic?.localBounds.translate(vec(offsetX, offsetY)).combine(bb);
}
this._localBounds = bb;
}

Expand Down
11 changes: 10 additions & 1 deletion src/engine/Graphics/GraphicsGroup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ import { Logger } from '../Util/Log';

export interface GraphicsGroupingOptions {
members: (GraphicsGrouping | Graphic)[];
/**
* Default true, GraphicsGroup will use the anchor to position all the graphics based on their combined bounds
*
* Setting to false will ignore anchoring and position the top left of all graphics at the actor's position,
* positioning graphics in the group is done with the `offset` property.
*/
useAnchor?: boolean;
}

export interface GraphicsGrouping {
Expand All @@ -24,11 +31,13 @@ export interface GraphicsGrouping {

export class GraphicsGroup extends Graphic implements HasTick {
private _logger = Logger.getInstance();
public useAnchor: boolean = true;
public members: (GraphicsGrouping | Graphic)[] = [];

constructor(options: GraphicsGroupingOptions & GraphicOptions) {
super(options);
this.members = options.members;
this.useAnchor = options.useAnchor ?? this.useAnchor;
this._updateDimensions();
}

Expand Down Expand Up @@ -100,7 +109,7 @@ export class GraphicsGroup extends Graphic implements HasTick {

protected _preDraw(ex: ExcaliburGraphicsContext, x: number, y: number) {
this._updateDimensions();
super._preDraw(ex, x, y);
super._preDraw(ex, this.useAnchor ? x : 0, this.useAnchor ? y : 0);
}

protected _drawImage(ex: ExcaliburGraphicsContext, x: number, y: number) {
Expand Down
7 changes: 6 additions & 1 deletion src/engine/Graphics/GraphicsSystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,12 @@ export class GraphicsSystem extends System {
g = member.graphic;
pos = member.offset;
}
g?.localBounds.translate(offset.add(pos)).draw(this._graphicsContext, this._engine.debug.graphics.boundsColor);

if (graphic.useAnchor) {
g?.localBounds.translate(offset.add(pos)).draw(this._graphicsContext, this._engine.debug.graphics.boundsColor);
} else {
g?.localBounds.translate(pos).draw(this._graphicsContext, this._engine.debug.graphics.boundsColor);
}
}
} else {
/* istanbul ignore next */
Expand Down
37 changes: 37 additions & 0 deletions src/spec/GraphicsGroupSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,43 @@ describe('A Graphics Group', () => {
await expectAsync(canvasElement).toEqualImage('src/spec/images/GraphicsGroupSpec/graphics-group.png');
});

it('can be created and drawn without anchor', async () => {
const rect1 = new ex.Rectangle({
width: 25,
height: 25,
color: ex.Color.Blue
});

const rect2 = new ex.Rectangle({
width: 25,
height: 25,
color: ex.Color.Yellow
});

const group = new ex.GraphicsGroup({
useAnchor: false,
members: [
{ offset: ex.vec(0, 0), graphic: rect1 },
{ offset: ex.vec(25, 25), graphic: rect2 }
]
});

expect(group.width).toBe(50);
expect(group.height).toBe(50);
expect(group.localBounds.width).toBe(50);
expect(group.localBounds.height).toBe(50);

const canvasElement = document.createElement('canvas');
canvasElement.width = 100;
canvasElement.height = 100;
const ctx = new ex.ExcaliburGraphicsContext2DCanvas({ canvasElement });

ctx.clear();
group.draw(ctx, 100, 100);

await expectAsync(canvasElement).toEqualImage('src/spec/images/GraphicsGroupSpec/graphics-group-without-anchor.png');
});

it('can be cloned', () => {
const animation = new ex.Animation({
frames: []
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.