@maccesar/titools 4.15.0 → 4.16.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.
- package/README.md +7 -1
- package/package.json +1 -1
- package/skills/ti-game/SKILL.md +88 -197
- package/skills/ti-game/references/api.md +45 -13
- package/skills/ti-game/references/debugging-performance.md +103 -0
- package/skills/ti-game/references/examples.md +54 -0
- package/skills/ti-game/references/patterns.md +699 -0
- package/skills/ti-game/references/project-setup.md +15 -6
- package/skills/ti-game/references/recipes-action.md +633 -0
- package/skills/ti-game/references/recipes-adventure-effects.md +340 -0
- package/skills/ti-game/references/roadmap.md +44 -65
- package/skills/ti-game/references/tilemaps.md +125 -0
- package/skills/ti-game/references/recipes.md +0 -1679
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Debugging and performance telemetry
|
|
2
|
+
|
|
3
|
+
Verified against `ti.game@d587081`: both `GameViewProxy` implementations, `DebugHud`, `FrameStats`, both scene renderers, `example/camera.js`, `example/particles.js`, and `example/tilemap.js`.
|
|
4
|
+
|
|
5
|
+
## The two debug aids
|
|
6
|
+
|
|
7
|
+
`GameView.debug` accepts a legacy boolean or an object:
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
const gameView = Game.createGameView({
|
|
11
|
+
debug: {
|
|
12
|
+
hitbox: true,
|
|
13
|
+
hud: 'topRight'
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
| Form | Meaning |
|
|
19
|
+
| --- | --- |
|
|
20
|
+
| `debug: true` | Global collision shapes only; shorthand for `{ hitbox: true }` |
|
|
21
|
+
| `{ hitbox: true }` | Global sprite and tile-cell collision visualization |
|
|
22
|
+
| `{ hud: true }` | Performance HUD in `topLeft` |
|
|
23
|
+
| `{ hud: 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight' }` | HUD in an explicit corner |
|
|
24
|
+
| `{ hud: true, hudFont: font }` | HUD drawn with a `Game.createFont()` bitmap font |
|
|
25
|
+
|
|
26
|
+
Writing the object replaces both modes: omit `hitbox` and it becomes false; omit `hud` and the HUD turns off. Reading `gameView.debug` returns `{ hitbox: boolean, hud: false | corner }`; `hudFont` is configuration, not part of the readback. Sprite-level `sprite.debug` remains a boolean.
|
|
27
|
+
|
|
28
|
+
The HUD is screen-space and is drawn after the camera effect. Camera scroll, zoom, shake, and glitch do not move or distort it. It starts compact (`FPS`, `MS`, `DC`); tapping it expands/collapses the panel, and the panel consumes its own touches.
|
|
29
|
+
|
|
30
|
+
## Hitbox colors and tuning
|
|
31
|
+
|
|
32
|
+
- Green: collision shape after `hitboxScale`, `hitboxScaleX`, and `hitboxScaleY`.
|
|
33
|
+
- Blue: full sprite/touch bounds.
|
|
34
|
+
- Orange: anchor.
|
|
35
|
+
- Tile debug: outlines fully solid cells in view.
|
|
36
|
+
|
|
37
|
+
Tune geometry in this order:
|
|
38
|
+
|
|
39
|
+
1. Put the correct shape on both mover and solid (`rect`, `circle`, or `rotatedRect`).
|
|
40
|
+
2. Set the anchor to the semantic contact point, often `anchor: 'bottom'` for feet.
|
|
41
|
+
3. Apply the global hitbox scale.
|
|
42
|
+
4. Correct one axis only when the frame padding differs by axis.
|
|
43
|
+
|
|
44
|
+
The scale properties affect collision, not the touch rectangle. `hitboxShape: 'circle'` does change the touch shape.
|
|
45
|
+
|
|
46
|
+
## Performance HUD fields
|
|
47
|
+
|
|
48
|
+
| HUD | Event key | Meaning |
|
|
49
|
+
| --- | --- | --- |
|
|
50
|
+
| `FPS` | `fps` | Frames presented in the closed one-second window |
|
|
51
|
+
| `MS` | `averageCpuMs` | Average engine CPU time per frame; the `maxFps` wait is excluded |
|
|
52
|
+
| `P95` | `p95CpuMs` | 95th percentile CPU frame time |
|
|
53
|
+
| `MAX` | `maxCpuMs` | Worst CPU frame in the window |
|
|
54
|
+
| `DROP` | `droppedFrames` | Presentation intervals longer than one target refresh |
|
|
55
|
+
| `SPRITES` | `visibleSprites` / `sprites` | Drawn sprites / sprites in the scene |
|
|
56
|
+
| `EMITTERS` | `emitters` | Emitters in the scene |
|
|
57
|
+
| `PARTICLES` | `particles` | Live particles |
|
|
58
|
+
| `DRAWCALLS` | `drawCalls` | Scene draw calls; HUD draw calls excluded |
|
|
59
|
+
| `TEXSWITCH` | `textureSwitches` | Texture switches |
|
|
60
|
+
| `UPDATE` | `averageUpdateMs` | Physics, animation, tween, and scene update time |
|
|
61
|
+
| `TEXTURE` | `averageTexturePrepareMs` | Texture preparation/upload time |
|
|
62
|
+
| `BATCH` | `averageBatchMs` | Batching and drawing time |
|
|
63
|
+
| `PRESENT` | `averagePresentMs` | iOS only: buffer presentation time |
|
|
64
|
+
| `PRESENTFAIL` | `presentFailures` | iOS only: failed presentations |
|
|
65
|
+
|
|
66
|
+
The event also includes `surfaceWidth` and `surfaceHeight`. Android omits `averagePresentMs` and `presentFailures`; do not interpret missing keys as zero.
|
|
67
|
+
|
|
68
|
+
## Programmatic telemetry
|
|
69
|
+
|
|
70
|
+
The `performance` event fires at most once per second and only while a listener exists:
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
function onPerformance({ fps, averageCpuMs, drawCalls, textureSwitches }) {
|
|
74
|
+
Ti.API.info(`${fps} fps; ${averageCpuMs.toFixed(1)} ms; ${drawCalls} calls; ${textureSwitches} switches`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
gameView.addEventListener('performance', onPerformance);
|
|
78
|
+
|
|
79
|
+
function cleanup() {
|
|
80
|
+
gameView.removeEventListener('performance', onPerformance);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Telemetry is opt-in inside the renderers. With the HUD disabled and no `performance` listener, frame-stat clock reads are disabled. Use the HUD while developing; use the event for short diagnostic sessions or a deliberate in-app performance screen, not permanent per-frame business logic.
|
|
85
|
+
|
|
86
|
+
## Reading the numbers
|
|
87
|
+
|
|
88
|
+
- High draw calls with stable sprite count: inspect texture order, blend changes, glow/flash, ropes, skid marks, and debug overlays.
|
|
89
|
+
- High texture switches: pack related art into fewer sheets and group sprites using the same sheet/blend into coherent `zIndex` bands.
|
|
90
|
+
- High update time: narrow collision groups and reduce active colliders/particles; hidden sprites are excluded from render and collision.
|
|
91
|
+
- A large `TileLayer` should keep draw calls and visible work stable while the camera moves; one sprite per tile scales with the whole scene instead.
|
|
92
|
+
- `maxFps: 60` can prevent a 120 Hz display from doubling work when the game does not need it.
|
|
93
|
+
- Judge final performance on hardware. The iOS Simulator's translated OpenGL path is intentionally rendered at 1× and remains slower than a device.
|
|
94
|
+
|
|
95
|
+
## Common diagnostic order
|
|
96
|
+
|
|
97
|
+
1. Confirm the object was added and is visible/in bounds.
|
|
98
|
+
2. Turn on the relevant sprite/layer debug shape, then the global overlay if relationships are unclear.
|
|
99
|
+
3. Verify `collisionGroup` is on the target and `solidWith`/`collidesWith` on the mover.
|
|
100
|
+
4. Inspect HUD counts and draw calls before changing code.
|
|
101
|
+
5. Compare the smallest relevant upstream demo from [examples.md](examples.md).
|
|
102
|
+
6. Disable instrumentation after the issue is understood.
|
|
103
|
+
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Upstream example catalog
|
|
2
|
+
|
|
3
|
+
Verified against all 33 self-contained demos under `ti.game@d587081:example/` plus the launcher `example/app.js`.
|
|
4
|
+
|
|
5
|
+
The demos prove that API combinations run together on the current module. They are **not** production templates: most keep state in one file, repeat launcher/back-button plumbing, and still use pre-ES6 syntax. Start from the closest demo, retain the demonstrated engine calls, then apply the focused structure and cleanup patterns in this skill.
|
|
6
|
+
|
|
7
|
+
| Demo | What it proves | Production-oriented reference |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `basic.js` | Sheets, frame animation, drag/pinch/rotate, tween completion | [Scaffolding](patterns.md#the-scaffolding) |
|
|
10
|
+
| `puzzle.js` | Multi-touch drag, press-to-lift, snapping and tween-back | [Cards and board games](recipes-adventure-effects.md#cards-and-board-games) |
|
|
11
|
+
| `flappy.js` | Gravity impulse, invisible score/death zones, wrapping parallax | [Tap-to-flap](recipes-action.md#tap-to-flap) |
|
|
12
|
+
| `platformer.js` | `solidWith`, `land`, `oneWay`, carried rider, camera follow, multi-touch controls | [Platformer](recipes-action.md#platformer) |
|
|
13
|
+
| `volley.js` | Restitution ball, `land`, collision response, coarse AI timer | [Ball sports](recipes-action.md#ball-sports--breakout-physics) |
|
|
14
|
+
| `racing.js` | `carMode`, drift, skid marks, checkpoints and lap state | [Top-down racer](recipes-action.md#top-down-racer) |
|
|
15
|
+
| `cards.js` | Dealing, fanned layout, selection tweens and idle wobble | [Cards and board games](recipes-adventure-effects.md#cards-and-board-games) |
|
|
16
|
+
| `asteroids.js` | Thrust, angular velocity, wrapping, pooling, additive bolts, effect/music audio | [Space shooter](recipes-action.md#asteroids--space-shooter) |
|
|
17
|
+
| `topdown.js` | Small string map made from sprites, `ySort`, eight-way input, decision timer | [Top-down / Zelda](recipes-action.md#top-down--zelda) |
|
|
18
|
+
| `skate.js` | Endless-runner pooling, carried/uncarried terrain, parallax, emitter and audio hooks | [Endless runner](recipes-action.md#endless-runner) |
|
|
19
|
+
| `pointclick.js` | Tap-to-walk with `findPath` → `followPath`, hotspots and `ySort` | [Point-and-click](recipes-adventure-effects.md#point--click-adventure) |
|
|
20
|
+
| `particles.js` | Continuous/burst emitters, sprite target, HUD telemetry | [Particles](recipes-adventure-effects.md#particles) and [debugging](debugging-performance.md) |
|
|
21
|
+
| `rhythm.js` | Pooled notes, native velocity, `press` pads, timing and audio feedback | [Rhythm game](recipes-action.md#rhythm-game) |
|
|
22
|
+
| `camera.js` | Two-axis follow, bounds, zoom, shake, camera effects, parallax and debug HUD | [Camera work](recipes-adventure-effects.md#camera-work) |
|
|
23
|
+
| `rope.js` | Rope pinned to a sprite, fixed head, tail weight | [Ropes and chains](recipes-adventure-effects.md#ropes-and-chains) |
|
|
24
|
+
| `flip.js` | Draw-only flips driven by direction and inverted gravity | [Visual effects](recipes-adventure-effects.md#visual-effects) |
|
|
25
|
+
| `hitbox.js` | Global/sprite debug overlays and per-axis hitbox correction | [Seeing the hitbox](patterns.md#seeing-the-hitbox--hitboxjs) |
|
|
26
|
+
| `blend.js` | Normal/add/multiply/screen modes and `flash()` | [Visual effects](recipes-adventure-effects.md#visual-effects) |
|
|
27
|
+
| `text.js` | Screen-fixed HUD, world labels, text buttons, word wrap and `attachTo` | [HUD](patterns.md#hud--textjs-flappyjs) |
|
|
28
|
+
| `swept.js` | Identical fast bullets with and without continuous sweep | [Object pooling](patterns.md#object-pooling) and [API gotchas](api.md#gotchas-the-property-tables-do-not-show) |
|
|
29
|
+
| `path.js` | Looped/smoothed paths, one-shot paths and animation chains | [Patrol routes](patterns.md#patrol-routes-and-animation-chains--pathjs) |
|
|
30
|
+
| `raycast.js` | Line of sight, ledge probes and tap-fired hitscan | [Raycast pattern](patterns.md#line-of-sight-ledge-probes-and-hitscan--raycastjs) |
|
|
31
|
+
| `zones.js` | `collision`/`collisionend`, pressure plate and removal during contact | [Zones](patterns.md#zones-you-can-be-inside-of-enter--exit--zonesjs) |
|
|
32
|
+
| `demoscene.js` | Follow-path circles, per-character scroller, glow, blend and music | [Visual effects](recipes-adventure-effects.md#visual-effects) |
|
|
33
|
+
| `maze.js` | Raw/simplified A*, re-pathing AI and path visualization | [Pathfinding](patterns.md#pathfinding-around-obstacles--mazejs-pointclickjs) |
|
|
34
|
+
| `timescale.js` | Slow/frozen scene, engine timer versus real-time interval | [Game-clock timers](patterns.md#timers-on-the-game-clock) |
|
|
35
|
+
| `circles.js` | Rect/circle/rotated-rect solids and `block` versus bilateral `push` | [Shaped solids](patterns.md#shaped-solids-ramps-round-posts-and-bodies-that-push-back--slopesjs-circlesjs-pooljs-drumjs) |
|
|
36
|
+
| `slopes.js` | Rotated-rect ramp normals and restitution supplied by a surface | [Shaped solids](patterns.md#shaped-solids-ramps-round-posts-and-bodies-that-push-back--slopesjs-circlesjs-pooljs-drumjs) |
|
|
37
|
+
| `plinko.js` | Circular pegs, swept balls and trigger slots | [Shaped solids](patterns.md#shaped-solids-ramps-round-posts-and-bodies-that-push-back--slopesjs-circlesjs-pooljs-drumjs) |
|
|
38
|
+
| `pool.js` | Bilateral circle momentum, rails, pockets and linear damping | [Shaped solids](patterns.md#shaped-solids-ramps-round-posts-and-bodies-that-push-back--slopesjs-circlesjs-pooljs-drumjs) |
|
|
39
|
+
| `drum.js` | Analytic circular containment and contact-driven impulses | [Shaped solids](patterns.md#shaped-solids-ramps-round-posts-and-bodies-that-push-back--slopesjs-circlesjs-pooljs-drumjs) |
|
|
40
|
+
| `wind.js` | `gravityX` as wind and as top-down constant acceleration | [Shaped solids](patterns.md#shaped-solids-ramps-round-posts-and-bodies-that-push-back--slopesjs-circlesjs-pooljs-drumjs) |
|
|
41
|
+
| `tilemap.js` | One 120×90 `TileLayer`, visible-cell rendering, cell collision, live edits, A* and HUD | [Tile maps](tilemaps.md) |
|
|
42
|
+
|
|
43
|
+
## Choosing the right map example
|
|
44
|
+
|
|
45
|
+
`topdown.js` deliberately creates one sprite per tile for a small 16×12 scene; that remains reasonable when individual tiles need sprite behavior. `tilemap.js` is the reference for large or mostly static grids: one native `TileLayer` avoids ticking, sorting, drawing, and collision-scanning off-screen tile sprites.
|
|
46
|
+
|
|
47
|
+
## Reading a demo safely
|
|
48
|
+
|
|
49
|
+
1. Identify the engine-owned behavior being demonstrated.
|
|
50
|
+
2. Copy the smallest connected API sequence, not the entire file.
|
|
51
|
+
3. Replace `var` and function-expression callbacks with the project's current ES6+ style.
|
|
52
|
+
4. Keep resources outside `resize`; create surface-sized scene objects inside one guarded `resize` path.
|
|
53
|
+
5. Separate reusable state from launcher UI and add explicit cleanup for app-owned listeners, timers, and sounds.
|
|
54
|
+
|