@fabi-play/engine 0.5.0 → 0.7.0

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.
@@ -86,6 +86,36 @@ declare namespace FabiEngine {
86
86
  /** Height, a fraction of the viewport's height. */
87
87
  h: number;
88
88
  }
89
+ /** A hand: the child's own left or right. */
90
+ export type HandSide = "left" | "right";
91
+ class AimHold {
92
+ readonly holdMs: number;
93
+ private readonly last;
94
+ constructor(holdMs?: number);
95
+ /** A number for a player's hand. */
96
+ static key(player: number, side: HandSide): number;
97
+ /** The aim to use at time t (ms) for the hand key, given what aimPoint said now (p, or null if lost). */
98
+ at(key: number, p: Point | null, t: number): Point | null;
99
+ /** Forgets every hand. */
100
+ clear(): void;
101
+ }
102
+ /**
103
+ * The parts of the game's viewport a phone's notch, rounded corners or home bar may cover, in fractions of the
104
+ * viewport (top and bottom of its height, left and right of its width; each 0–0.25). The game's frame cannot read
105
+ * env(safe-area-inset-*), so the screen sends it (init.safeArea): keep buttons, scores and targets out of it, and
106
+ * still paint the background under it. Zeros where nothing is covered (a TV, a tablet, older hosts).
107
+ */
108
+ export interface SafeArea {
109
+ top: number;
110
+ bottom: number;
111
+ left: number;
112
+ right: number;
113
+ }
114
+ /**
115
+ * A screen's orientation: 'landscape' when its width is at least its height, else 'portrait' (see orientationOf).
116
+ * GameManifest.orientations lists those a game supports; HostMessage init.orientation says the one it starts in.
117
+ */
118
+ export type Orientation = "landscape" | "portrait";
89
119
  /**
90
120
  * Small pure helpers: 2D affine matrices, colours, easing. No DOM here, so they run in Node tests.
91
121
  */
@@ -1339,11 +1369,18 @@ declare namespace FabiEngine {
1339
1369
  }[];
1340
1370
  /** A player's colour (CSS), as the TV draws them: player 1 orange, 2 blue, 3 green, 4 lilac, then again. */
1341
1371
  export const playerColor: (player: number) => "#EE6A43" | "#6FA0E0" | "#8CC9A0" | "#C49BE0";
1372
+ /** handsOf's aim: the screen's orientation and, in portrait, what keeps hands through short losses (and its clock, ms). */
1373
+ export interface HandsAim {
1374
+ orientation?: Orientation;
1375
+ hold?: AimHold;
1376
+ t?: number;
1377
+ }
1342
1378
  /**
1343
- * Every player's hands in stage units: wrists of bodyOf(frame) (null: the frame's own body), through toScreen
1344
- * (player space to screen fractions), times the stage size.
1379
+ * Every player's hands in stage units, where they aim (the protocol's aimPoint), times the stage size; bodyOf(frame)
1380
+ * is the body to read (null: the frame's own). Landscape (the default): its wrists through toScreen (player space to
1381
+ * screen fractions). Portrait (aim.orientation): the wrists stretched to the whole screen, held by aim.hold if given.
1345
1382
  */
1346
- export function handsOf(frames: readonly PlayerFrame[], toScreen: (p: Point) => Point, width: number, height: number, bodyOf?: (f: PlayerFrame) => Body | null): Hand[];
1383
+ export function handsOf(frames: readonly PlayerFrame[], toScreen: (p: Point) => Point, width: number, height: number, bodyOf?: (f: PlayerFrame) => Body | null, aim?: HandsAim): Hand[];
1347
1384
  /** What a node offers to hit tests: its world transform, size and anchor, or a radius. */
1348
1385
  export interface Hittable {
1349
1386
  /** The node's transform to the stage. */
@@ -1520,6 +1557,10 @@ declare namespace FabiEngine {
1520
1557
  readonly backdrop?: Backdrop;
1521
1558
  /** Where the camera image is on the screen, in fractions; null if unknown. */
1522
1559
  readonly view?: BackdropView | null;
1560
+ /** The screen's orientation at the start ('landscape' if unknown): in 'portrait' the hands aim (see Engine.hands). */
1561
+ readonly orientation?: Orientation;
1562
+ /** What a phone's notch and home bar cover, fractions of the viewport (see Engine.safeArea). */
1563
+ readonly safeArea?: SafeArea;
1523
1564
  /** The screen's sound is off. */
1524
1565
  readonly muted?: boolean;
1525
1566
  /** What the screen knows about the device (init.device): a starting tier and the display's rate. */
@@ -1629,6 +1670,18 @@ declare namespace FabiEngine {
1629
1670
  readonly backdrop: Backdrop;
1630
1671
  /** Where the camera image is on the screen, in fractions; null if the host didn't say. */
1631
1672
  readonly view: BackdropView | null;
1673
+ /**
1674
+ * The screen's orientation when the game started: 'landscape' (a TV, a tablet; also before the host says) or
1675
+ * 'portrait' (a phone held upright). It decides where hands() are (see there).
1676
+ */
1677
+ readonly orientation: Orientation;
1678
+ /**
1679
+ * What a phone's notch, rounded corners and home bar cover, in fractions of the viewport (top and bottom of its
1680
+ * height, left and right of its width; each 0–0.25; zeros on a TV, a tablet, and from hosts that don't say). The
1681
+ * game's frame can't read env(safe-area-inset-*): keep buttons, scores and targets out of it (in stage units, top
1682
+ * × 720, left × stage.width), still paint the background under it.
1683
+ */
1684
+ readonly safeArea: Readonly<SafeArea>;
1632
1685
  /** Paused by the host (pause, break) or by pause(): game time, tweens, particles and sound are stopped. */
1633
1686
  readonly paused: boolean;
1634
1687
  /** Sounds and tones, quiet while paused or muted. */
@@ -1715,9 +1768,16 @@ declare namespace FabiEngine {
1715
1768
  * bitmap fonts (.fnt, or a BMFont .json, + page images), sounds and fonts, by name.
1716
1769
  */
1717
1770
  load(assets: Record<string, string>): Promise<void>;
1718
- /** This frame's hands (of one player, or everyone's), stage units: in the avatar's hands, or on the real ones. */
1771
+ /**
1772
+ * This frame's hands (of one player, or everyone's), stage units, where they aim: what they touch, catch, press.
1773
+ * Landscape (a TV, a tablet): in the avatar's hands, or on the real ones over the video. Portrait (a phone held
1774
+ * upright, where the camera image is small at the bottom): the wrists stretched around the shoulders to the whole
1775
+ * stage (the protocol's aimPoint), so arms straight up reach the top (y ≈ 0.15 × 720) and arms out the sides, held
1776
+ * for 300 ms when the camera loses a wrist; the avatars are still drawn small in the view. To draw on the body
1777
+ * itself, use toScreen(wrist) of the SDK. touched() and handMarkers() use these hands.
1778
+ */
1719
1779
  hands(player?: number): Hand[];
1720
- /** The first hand (of one player, or anyone's) touching the node, or null. padding: stage units. */
1780
+ /** The first hand (of one player, or anyone's) touching the node, or null; the hands are hands()'s. padding: stage units. */
1721
1781
  touched(node: Node, player?: number, opts?: {
1722
1782
  padding?: number;
1723
1783
  }): Hand | null;