feat: GPU particles implementation (#3212)
GPU Particle Implementation! Added GPU particle implementation for MANY MANY particles in the simulation, similar to the existing CPU particle implementation. Note `maxParticles` is new for GPU particles.
var particles = new ex.GpuParticleEmitter({
pos: ex.vec(300, 500),
maxParticles: 10_000,
emitRate: 1000,
radius: 100,
emitterType: ex.EmitterType.Circle,
particle: {
beginColor: ex.Color.Orange,
endColor: ex.Color.Purple,
focus: ex.vec(0, -400),
focusAccel: 1000,
startSize: 100,
endSize: 0,
life: 3000,
minSpeed: -100,
maxSpeed: 100,
angularVelocity: 2,
randomRotation: true,
transform: ex.ParticleTransform.Local
}
});
feat: Add ex.BezierCurve and CurveBy/CurveTo actions (#3282)
https://github.com/user-attachments/assets/e2bdff59-7551-4652-a4ba-7ce78d7eeaf8
This PR implements new CurveTo/CurveBy action for moving actors in a Bezier curve
```typescript
const curve = new ex.BezierCurve({
controlPoints: [ex.vec(0, 700), ex.vec(100, -300), ex.vec(150, 800), ex.vec(500, 100)],
quality: 10
});
actor.actions.repeatForever((ctx) => {
ctx.curveTo({
controlPoints: [ex.vec(100, -300), ex.vec(150, 800), ex.vec(500, 100)],
durationMs: 6000
});
ctx.curveBy({
controlPoints: [ex.vec(100, 0), ex.vec(-100, 0), ex.vec(0, 300)],
durationMs: 1000
});
ctx.curveTo({
controlPoints: [ex.vec(150, 800), ex.vec(100, -300), ex.vec(0, 700)],
durationMs: 6000
});
});
```
change: GraphicsGroup no longer centers with anchors (#2966)
`useAnchor: false` The graphics members are positioned from the top left
```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),
},
],
});
```

`useAnchor: true` The graphics members' total combined bounds are centered by the actor's anchor (.5, .5) by default
```typescript
const graphicGroup = new ex.GraphicsGroup({
useAnchor: true,
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),
},
],
});
```

feat: Nine-slice Graphic (#3241)
- Added a new `ex.NineSlice` `Graphic` for creating arbitrarily resizable rectangular regions, useful for creating UI, backgrounds, and other resizable elements.
```typescript
var nineSlice = new ex.NineSlice({
width: 300,
height: 100,
source: inputTile,
sourceConfig: {
width: 64,
height: 64,
topMargin: 5,
leftMargin: 7,
bottomMargin: 5,
rightMargin: 7
},
destinationConfig: {
drawCenter: true,
horizontalStretch: ex.NineSliceStretch.Stretch,
verticalStretch: ex.NineSliceStretch.Stretch
}
});
actor.graphics.add(nineSlice);
```