phaser3-rex-plugins
Version:
311 lines (226 loc) • 7.44 kB
Markdown
# RexCustomShapes (Source Traced README)
This document describes how to use `CustomShapes` by tracing source files:
- `plugins/gameobjects/shape/customshapes/CustomShapes.js`
- `plugins/gameobjects/shape/customshapes/ShapesUpdateMethods.js`
- `plugins/gameobjects/shape/shapes/BaseShapes.js`
It is intended for practical use and code generation.
## 1. Core API
### A) Add via factory
```js
const customShapes = scene.add.rexCustomShapes(x, y, width, height, {
type, // optional, default: 'rexCustomShapes'
create, // object | array | function
update // function
});
```
### B) Add via config object
```js
const customShapes = scene.add.rexCustomShapes({
x, y, width, height,
type, create, update
});
```
### C) Use class directly
```js
import CustomShapes from 'phaser3-rex-plugins/plugins/customshapes.js';
const customShapes = new CustomShapes(scene, x, y, width, height, config);
scene.add.existing(customShapes);
```
Or:
```js
const customShapes = new CustomShapes(scene, {
x, y, width, height, type, create, update
});
scene.add.existing(customShapes);
```
## 2. Config Fields
- `x`, `y`: object position. Default `0, 0`.
- `width`, `height`: object size. Default `2, 2`.
- `type`: custom game object type string. Default `'rexCustomShapes'`.
- `create`: shape creation spec. Supported formats are in section 3.
- `update`: callback executed when this object refreshes shape geometry/style.
If `update` is omitted, a default callback clears style on all shapes each refresh:
```js
shape.lineStyle().fillStyle();
```
## 3. `create` Supported Formats
`create` supports 3 formats.
### A) Plain object
```js
create: {
line: 4, // create 4 unnamed lines
lines: ['border', 'fill'], // create named lines
circle: 'dot' // create one named circle
}
```
`shapeType` keys supported at runtime:
- `arc`
- `circle`
- `curve`
- `ellipse`
- `line`
- `lines`
- `rectangle`
- `roundRectangle`
- `triangle`
Value types:
- `number`: create N unnamed shapes.
- `string`: create 1 named shape.
- `string[]`: create named shapes.
### B) Array
```js
create: [
{ type: 'line', name: 'l0' },
{ type: 'line', name: 'l1' },
{ type: 'lines', name: 'path' }
]
```
### C) Callback
```js
create: function () {
const box = this.createShape('rectangle', 'box');
const check = this.createShape('lines', 'check');
this.addShape(box).addShape(check);
}
```
Inside callback, `this` is the `CustomShapes` instance.
## 4. `update` Callback Context
Inside `update: function () { ... }`, `this` is the `CustomShapes` instance.
Useful properties:
- `this.width`, `this.height`
- `this.centerX`, `this.centerY` (read-only getters)
- `this.isSizeChanged`
- `this.fillColor`, `this.fillAlpha`
- `this.lineWidth`, `this.strokeColor`, `this.strokeAlpha`
Shape access:
- `this.getShapes()`
- `this.getShape(name)`
Shape management:
- `this.createShape(type, name)`
- `this.addShape(shape)`
- `this.deleteShape(name)`
- `this.clear()`
Dirty/redraw:
- `this.setDirty()` / `this.setDirty(true)`
- `this.setUpdateShapesCallback(callback)`
## 5. Size, Style, Refresh
### Size
```js
customShapes.setSize(width, height);
customShapes.resize(width, height);
customShapes.width = width;
customShapes.height = height;
```
These operations mark object dirty and trigger rebuild on next render/update.
### Fill and stroke style
```js
customShapes.setFillStyle(color, alpha);
customShapes.setStrokeStyle(lineWidth, color, alpha);
customShapes.fillColor = color;
customShapes.fillAlpha = alpha;
customShapes.lineWidth = lineWidth;
customShapes.strokeColor = color;
customShapes.strokeAlpha = alpha;
```
These are object-level style values, commonly consumed in `update`.
### Force refresh
```js
customShapes.setDirty();
customShapes.updateData(); // immediately rebuild shape data now
```
## 6. `worldToLocalXY`
Convert world position to this object's local coordinates:
```js
const localXY = customShapes.worldToLocalXY(worldX, worldY);
// -> { x, y }
```
With camera and output object:
```js
const out = customShapes.worldToLocalXY(worldX, worldY, camera, outObj);
```
With reusable internal temp object:
```js
const out = customShapes.worldToLocalXY(worldX, worldY, true);
```
This is useful when building dynamic paths (for example, speech bubble pointer).
## 7. Common Shape API
All shape instances support:
- `shape.fillStyle(color?, alpha?)`
- `shape.lineStyle(lineWidth?, color?, alpha?)`
- `shape.setVisible(visible?)`
- `shape.visible`
- `shape.name`
- `shape.setData(key, value)` or `shape.setData(object)`
- `shape.getData(key, defaultValue?)`
- `shape.incData(key, inc, defaultValue?)`
- `shape.mulData(key, mul, defaultValue?)`
- `shape.clearData()`
Style clearing:
- `fillStyle()` with no args clears fill.
- `lineStyle()` with no args clears stroke.
## 8. Shape Specific API Quick Reference
### Line
- `setP0(x, y)`
- `setP1(x, y)`
### Lines
- Path build: `start()`, `startAt(x,y)`, `lineTo(x,y,relative?)`, `verticalLineTo(x,relative?)`, `horizontalLineTo(y,relative?)`
- Curves: `arc(...)`, `ellipticalArc(...)`, `quadraticBezierTo(...)`, `cubicBezierTo(...)`, `catmullRomTo(...)`
- End path: `close()`, `end()`
- Path segment: `copyPathFrom(...)`, `appendPathFrom(...)`, `setDisplayPathSegment(...)`
- Transform: `rotateAround(cx, cy, angleDeg)`, `offset(x, y)`
- Hit area helper: `toPolygon()`
### Arc / Circle / Ellipse
- `setCenterPosition(x, y)`
- `setRadius(rx, ry?)`
- `setAngle(startDeg, endDeg, anticlockwise?)` (Arc)
- `setPie(pie?)` (Arc)
### Rectangle / RoundRectangle
- `setTopLeftPosition(x, y)`
- `setCenterPosition(x, y)`
- `setSize(width, height)`
- `setRadius(radius)` (RoundRectangle)
### Triangle
- `setP0(x, y)`
- `setP1(x, y)`
- `setP2(x, y)`
### Curve
- `setCurve(phaserCurve)`
- `setIterations(n)`
## 9. Minimal Example
```js
const checkbox = scene.add.rexCustomShapes({
create: [
{ name: 'box', type: 'rectangle' },
{ name: 'check', type: 'lines' }
],
update: function () {
const r = Math.min(this.centerX, this.centerY);
const x = this.centerX - r;
const y = this.centerY - r;
const w = r * 2;
const step = w / 4;
if (this.isSizeChanged) {
this.getShape('box')
.setTopLeftPosition(x + 2, y + 2)
.setSize(w - 4, w - 4);
this.getShape('check')
.startAt(x + step, y + step * 2)
.lineTo(x + step * 2, y + step * 3)
.lineTo(x + step * 3, y + step)
.end();
}
this.getShape('box')
.fillStyle(this.fillColor, 1)
.lineStyle(2, this.fillColor, 1);
this.getShape('check')
.lineStyle(3, 0xffffff, 1);
}
});
```
## 10. Implementation Rules For Stable Results
1. Use `create` only to allocate shapes and names.
2. Put per-frame geometry/style logic inside `update`.
3. In `update`, explicitly apply or clear styles to avoid stale state.
4. Rebuild expensive path geometry only when `this.isSizeChanged` is `true`.
5. Call `setDirty()` when external state changes and you need a refresh.
6. Use `worldToLocalXY` when mixing pointer/world coords with local shape drawing.