@unboxy/phaser-sdk 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SDK-GUIDE.md +35 -0
- package/dist/core/Unboxy.js +1 -1
- package/dist/core/UnboxyGame.d.ts +2 -0
- package/dist/core/UnboxyGame.js +1 -0
- package/package.json +1 -1
package/SDK-GUIDE.md
CHANGED
|
@@ -286,6 +286,40 @@ Rules of thumb:
|
|
|
286
286
|
- **Do not implement position sync via messages.** You will reinvent delta compression badly and spend more bandwidth. Use `room.player.set('pos', {x,y})`.
|
|
287
287
|
- **Server is authoritative but permissive** — it doesn't validate what you put in `data`. Treat inbound values from other players as untrusted (don't eval, validate shape before reading).
|
|
288
288
|
|
|
289
|
+
#### Making remote motion feel smooth
|
|
290
|
+
|
|
291
|
+
State updates arrive at roughly 20 Hz (every ~50 ms). If you re-render remote entities by snapping directly to `room.player.get(sid, 'pos')` each frame, their movement will visibly step. Pick a smoothing technique that fits the game:
|
|
292
|
+
|
|
293
|
+
**Interpolation** — good for continuous motion (platformer, shooter, racer). Keep a `target` on each remote sprite, update it from state, lerp toward it each frame.
|
|
294
|
+
|
|
295
|
+
```ts
|
|
296
|
+
// On state change, just update the target
|
|
297
|
+
room.onStateChange(() => {
|
|
298
|
+
room.state.players.forEach((_p, sid) => {
|
|
299
|
+
if (sid === room.sessionId) return;
|
|
300
|
+
const pos = room.player.get<{x:number;y:number}>(sid, 'pos');
|
|
301
|
+
if (pos) remoteSprites.get(sid)!.target = pos;
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
// In your scene's update() loop
|
|
306
|
+
remoteSprites.forEach((s) => {
|
|
307
|
+
s.sprite.x = Phaser.Math.Linear(s.sprite.x, s.target.x, 0.2);
|
|
308
|
+
s.sprite.y = Phaser.Math.Linear(s.sprite.y, s.target.y, 0.2);
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Pair this with **client-side prediction for the LOCAL player**: render your own sprite from a locally-predicted position (updated by input every frame) so input feels instant, not gated on the round trip. Publish the predicted position to state at ~10–20 Hz with `room.player.set('pos', predicted)`. You rarely need to reconcile in casual games; trust the local prediction.
|
|
313
|
+
|
|
314
|
+
**Extrapolation** — good for projectiles and other predictable trajectories. Send `{ x, y, vx, vy, t }` once on spawn, let each client simulate locally with `x += vx * dt`. Only re-sync on events that change the trajectory (hit, bounce, destroy). Uses far less bandwidth than per-frame position sync.
|
|
315
|
+
|
|
316
|
+
**Snap** — the right choice for:
|
|
317
|
+
- Infrequent updates: score, hp, current turn, chat messages, lobby ready flags.
|
|
318
|
+
- Turn-based games: pieces jumping to their next square shouldn't glide.
|
|
319
|
+
- Discrete grids: same reason.
|
|
320
|
+
|
|
321
|
+
Don't blindly apply interpolation to everything. It's wrong for a chess piece and wasteful on a hp bar.
|
|
322
|
+
|
|
289
323
|
#### Availability
|
|
290
324
|
|
|
291
325
|
- Requires sign-in. Anonymous players get `RpcError('UNAUTHENTICATED')`.
|
|
@@ -314,6 +348,7 @@ Rules of thumb:
|
|
|
314
348
|
|
|
315
349
|
## Changelog
|
|
316
350
|
|
|
351
|
+
- **0.2.8** — docs: added "Making remote motion feel smooth" section to the multiplayer chapter with concrete examples for interpolation (continuous motion), extrapolation (projectiles), and snap (discrete/turn-based/infrequent). No code changes — version bumped so existing workspaces pick up the new guidance via `npm update @unboxy/phaser-sdk`.
|
|
317
352
|
- **0.2.7** — fixed handshake race on slow-mounting hosts. `PostMessageTransport.connect` now retries `unboxy:hello` every 200 ms until `unboxy:init` arrives (previously one-shot → lost on Android/mobile where React mounted after the iframe first fired hello). Default handshake timeout bumped from 2 s → 5 s.
|
|
318
353
|
- **0.2.6** — redesigned `unboxy.rooms` around two generic primitives: delta-synced KV state (`room.player.set/get/delete`, `room.data.set/get/delete`) + transient relay (`room.send` / `room.on`). Server no longer bakes in game-specific fields like x/y/color/ready or a `move` handler — games define their own shapes via opaque JSON values, same contract as `gameData` / `saves`.
|
|
319
354
|
- **0.2.5** — added `unboxy.rooms` module (server-authoritative multiplayer rooms backed by Colyseus on unboxy-realtime-service). Requires sign-in. Host must advertise `realtime` capability. Colyseus client loaded lazily — single-player games do not pay for the dependency.
|
package/dist/core/Unboxy.js
CHANGED
|
@@ -4,7 +4,7 @@ import { SavesModule } from '../saves/SavesModule.js';
|
|
|
4
4
|
import { GameDataModule } from '../gamedata/GameDataModule.js';
|
|
5
5
|
import { RealtimeModule } from '../realtime/RealtimeModule.js';
|
|
6
6
|
// Kept in sync with package.json on each publish.
|
|
7
|
-
const SDK_VERSION = '0.2.
|
|
7
|
+
const SDK_VERSION = '0.2.8';
|
|
8
8
|
/**
|
|
9
9
|
* Unboxy platform services bound to the current (game, user).
|
|
10
10
|
*
|
|
@@ -12,6 +12,8 @@ export interface UnboxyGameOptions {
|
|
|
12
12
|
pixelArt?: boolean;
|
|
13
13
|
/** Custom physics config (default: arcade with no gravity) */
|
|
14
14
|
physics?: Phaser.Types.Core.PhysicsConfig;
|
|
15
|
+
/** Phaser plugin registrations (e.g. `phaser3-rex-plugins` virtual joystick) */
|
|
16
|
+
plugins?: Phaser.Types.Core.PluginObject;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
17
19
|
* Create an Unboxy-enhanced Phaser game instance.
|
package/dist/core/UnboxyGame.js
CHANGED