curves-and-paths
Use this skill when working with curves and paths in Phaser 4. Covers splines, bezier curves, lines, ellipses, path followers, and mathematical curve types. Triggers on: curve, path, spline, bezier, path follower.
What this skill does
# Curves and Paths
> Creating paths from curves, getting points along them, drawing them with Graphics, and making sprites follow paths automatically using PathFollower in Phaser 4.
**Key source paths:** `src/curves/`, `src/curves/path/`, `src/gameobjects/pathfollower/`, `src/gameobjects/components/PathFollower.js`
**Related skills:** ../sprites-and-images/SKILL.md, ../graphics-and-shapes/SKILL.md, ../tweens/SKILL.md
## Quick Start
```js
// In a Scene's create() method:
// 1. Create a Path starting at (50, 300)
const path = this.add.path(50, 300);
// 2. Add curves to the path
path.lineTo(200, 100);
path.splineTo([ new Phaser.Math.Vector2(300, 400), new Phaser.Math.Vector2(500, 200) ]);
path.lineTo(700, 300);
// 3. Draw the path using Graphics
const graphics = this.add.graphics();
graphics.lineStyle(2, 0xffffff, 1);
path.draw(graphics, 64);
// 4. Create a PathFollower sprite that moves along the path
const follower = this.add.follower(path, 50, 300, 'ship');
follower.startFollow({
duration: 5000,
rotateToPath: true,
repeat: -1,
yoyo: true
});
```
## Core Concepts
### Path
A `Phaser.Curves.Path` is a container that combines multiple Curves into one continuous compound curve. Curves in a Path do not need to be connected end-to-end. Only the order of curves affects point calculations along the path.
Created via factory: `this.add.path(x, y)` where x/y is the starting point.
Key properties:
- `curves` -- array of `Phaser.Curves.Curve` objects in the Path
- `startPoint` -- `Vector2`, the defined starting position
- `autoClose` -- boolean, if true `getPoints()` appends the first point at the end
- `defaultDivisions` -- number (default: 12), divisions per curve when calling `getPoints()`
- `name` -- string, empty by default, for developer use
### Curves
All curve types extend `Phaser.Curves.Curve` (the base class). Every curve supports:
- `getPoint(t, out)` -- get a point at position t (0-1) based on curve parameterization
- `getPointAt(u, out)` -- get a point at position u (0-1) based on arc length (evenly spaced)
- `getPoints(divisions, stepRate, out)` -- array of points along the curve
- `getSpacedPoints(divisions, stepRate, out)` -- array of equidistant points by arc length
- `getDistancePoints(distance)` -- points spaced by pixel distance
- `getLength()` -- total arc length in pixels
- `getBounds(out, accuracy)` -- bounding Rectangle
- `getTangent(t, out)` / `getTangentAt(u, out)` -- unit tangent vector
- `getStartPoint(out)` / `getEndPoint(out)` -- first/last points
- `getRandomPoint(out)` -- random point on the curve
- `draw(graphics, pointsTotal)` -- render the curve onto a Graphics object
- `active` -- boolean, when false the parent Path skips this curve
### PathFollower
A `Phaser.GameObjects.PathFollower` is a Sprite with the `Components.PathFollower` mixin. It uses an internal Tween (a number counter from 0 to 1) to advance along a Path each frame.
Created via factory: `this.add.follower(path, x, y, texture, frame)`
The PathFollower component provides:
- `path` -- the `Phaser.Curves.Path` being followed
- `pathTween` -- the internal Tween driving movement
- `pathOffset` -- `Vector2`, offset added to path coordinates
- `pathVector` -- `Vector2`, current position on the path
- `pathDelta` -- `Vector2`, distance traveled since last frame
- `rotateToPath` -- boolean, auto-rotate to face path direction
- `pathRotationOffset` -- number (degrees), added to auto-rotation
## Common Patterns
### Creating Paths with Chained Curves
Path has convenience methods that create curves starting from the previous end point:
```js
const path = this.add.path(100, 500);
path.lineTo(300, 100); // straight line
path.cubicBezierTo(500, 100, 350, 50, 450, 50); // cubic bezier (endX, endY, cp1X, cp1Y, cp2X, cp2Y)
path.quadraticBezierTo(700, 400, 600, 100); // quadratic bezier (endX, endY, cpX, cpY)
path.splineTo([ // spline through points
new Phaser.Math.Vector2(750, 300),
new Phaser.Math.Vector2(600, 500)
]);
path.ellipseTo(50, 80, 0, 270, false, 0); // ellipse arc (xRadius, yRadius, startAngle, endAngle, clockwise, rotation)
path.circleTo(40); // shortcut for ellipseTo with equal radii and 0-360
// Jump to a new position without drawing (creates a gap)
path.moveTo(400, 400);
path.lineTo(500, 400);
// Close the path by connecting end to start
path.closePath();
```
### Adding Standalone Curve Objects
```js
const path = new Phaser.Curves.Path(0, 0);
// Add pre-constructed curve objects
const line = new Phaser.Curves.Line(new Phaser.Math.Vector2(0, 0), new Phaser.Math.Vector2(200, 200));
path.add(line);
const spline = new Phaser.Curves.Spline([ 200, 200, 300, 100, 400, 300 ]);
path.add(spline);
const ellipse = new Phaser.Curves.Ellipse(400, 300, 100, 60, 0, 360, false, 0);
path.add(ellipse);
```
### Getting Points Along a Path
```js
// Array of points (uses defaultDivisions per curve)
const points = path.getPoints();
// With explicit divisions per curve
const detailed = path.getPoints(32);
// Equally spaced points along the entire path
const spaced = path.getSpacedPoints(100);
// Single point at normalized position (0-1)
const midpoint = path.getPoint(0.5);
// Tangent vector at a position
const tangent = path.getTangent(0.5);
// Total path length in pixels
const length = path.getLength();
// Bounding rectangle
const bounds = path.getBounds();
```
### Drawing Paths with Graphics
```js
const graphics = this.add.graphics();
// Draw entire path
graphics.lineStyle(2, 0x00ff00, 1);
path.draw(graphics, 64); // 64 = points per curve for smoothness
// Draw individual curves
graphics.lineStyle(1, 0xff0000, 1);
path.curves[0].draw(graphics, 32);
// Draw debug points
const points = path.getSpacedPoints(50);
points.forEach(p => {
graphics.fillStyle(0xffff00, 1);
graphics.fillCircle(p.x, p.y, 3);
});
```
### PathFollower Sprite
```js
const path = this.add.path(100, 200);
path.lineTo(400, 400);
path.lineTo(700, 200);
// Create follower
const enemy = this.add.follower(path, 100, 200, 'enemy');
// Start following with config
enemy.startFollow({
duration: 3000, // ms to traverse path
positionOnPath: true, // snap to path start position
rotateToPath: true, // auto-rotate to face direction
rotationOffset: 90, // offset added to auto-rotation (degrees)
repeat: -1, // -1 = infinite repeat
yoyo: true, // reverse on each repeat
from: 0, // start position on path (0-1)
to: 1, // end position on path (0-1)
startAt: 0, // initial seek position
ease: 'Sine.easeInOut' // any valid Phaser ease
});
// Control during playback
enemy.pauseFollow();
enemy.resumeFollow();
enemy.stopFollow();
enemy.isFollowing(); // returns boolean
// Change path at runtime
enemy.setPath(newPath);
enemy.setPath(newPath, { duration: 2000 }); // auto-starts
// Set rotation independently
enemy.setRotateToPath(true, 90); // (value, offsetDegrees)
```
### PathFollower with Simple Duration
```js
// Shorthand: pass just a duration number
enemy.startFollow(5000);
// Equivalent to:
enemy.startFollow({ duration: 5000 });
```
## All Curve Types
| Curve | Class | Constructor Params | Description |
|---|---|---|---|
| Line | `Phaser.Curves.Line` | `(p0, p1)` Vector2 endpoints, or `([x0,y0,x1,y1])` | Straight line segment between two points |
| Spline | `Phaser.Curves.Spline` | `(points)` array of Vector2, flat numbers, or nested arrays | Catmull-Rom spline through control points |
| CubicBezier | `Phaser.Curves.CubicBezier` | `(p0, p1, p2, p3)` or `([x0,y0,...x3,y3])` | Cubic Bezier with start, 2 control points, end |
| QuadraticBezier | `Phaser.Curves.QuadraticBezier` | `(p0, p1, p2)` or `([x0,y0,...x2,y2])` | Quadratic Bezier with start, 1 control point, end |
| Ellipse | `Phaser.Curves.Ellipse` | `(x, y, xRadius, yRadius, startAngle, endAngle, clockRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.