handler-playable-sdk 0.3.1 → 0.3.2

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.
@@ -1,4 +1,6 @@
1
+ import * as PixiJS from 'pixi.js';
1
2
  import { Application, Container, Texture, Sprite, Text, Graphics, Point } from 'pixi.js';
3
+ import { O as ObjectCentricConfig$1 } from '../loader-object-centric-C1QteFfG.js';
2
4
 
3
5
  /**
4
6
  * Handler SDK - PixiJS Base Context
@@ -255,104 +257,12 @@ declare function registerFont(fontId: string, definition: FontDefinition): void;
255
257
  declare function getRegisteredFontIds(): string[];
256
258
 
257
259
  /**
258
- * Handler SDK - Type Definitions for PixiJS Integration
260
+ * Object-centric configuration
259
261
  *
260
- * DO NOT EDIT - Handler SDK Core
261
- */
262
- /**
263
- * Object configuration from JSON files
262
+ * Single source of truth is the config loader type.
263
+ * Pixi systems/engine should never diverge from that shape.
264
264
  */
265
- interface ObjectConfig {
266
- object_config?: string;
267
- transform?: {
268
- position?: {
269
- x: number;
270
- y: number;
271
- };
272
- scale?: number;
273
- rotation?: number;
274
- offset?: {
275
- x?: number;
276
- y?: number;
277
- };
278
- };
279
- render?: {
280
- z_index?: number;
281
- alpha?: number;
282
- visible?: boolean;
283
- tint?: number | string | null;
284
- background_color?: string;
285
- background_alpha?: number;
286
- border_color?: string;
287
- anchor?: {
288
- x: number;
289
- y: number;
290
- };
291
- };
292
- gameplay?: {
293
- rules?: Record<string, unknown>;
294
- tuning?: Record<string, unknown>;
295
- };
296
- ui?: {
297
- text?: string;
298
- font?: string;
299
- fontSize?: number;
300
- letterSpacing?: number;
301
- align?: string;
302
- };
303
- effects?: Record<string, unknown>;
304
- audio?: Record<string, unknown>;
305
- physics?: Record<string, unknown>;
306
- interaction?: Record<string, unknown>;
307
- identity?: Record<string, unknown>;
308
- visibility?: Record<string, unknown>;
309
- }
310
- /**
311
- * Engine configuration
312
- */
313
- interface EngineConfig {
314
- assets?: Record<string, string>;
315
- runtime?: {
316
- ui?: Record<string, unknown>;
317
- theme?: Record<string, unknown>;
318
- ui_styles?: Record<string, unknown>;
319
- timeline?: Record<string, number>;
320
- };
321
- }
322
- /**
323
- * Theme configuration
324
- */
325
- interface ThemeConfig {
326
- background_color?: string;
327
- text_color?: string;
328
- square_color?: string;
329
- cta_background?: string;
330
- cta_text?: string;
331
- melt_color?: string;
332
- danger_color?: string;
333
- brush_color?: string;
334
- success_color?: string;
335
- }
336
- /**
337
- * Gameplay configuration
338
- */
339
- interface GameplayConfig {
340
- [key: string]: unknown;
341
- }
342
- /**
343
- * Object-centric configuration
344
- * This is the main config type that students work with
345
- */
346
- interface ObjectCentricConfig {
347
- /** Map of object instance IDs to their configurations */
348
- objects: Map<string, ObjectConfig>;
349
- /** Engine configuration (assets, runtime settings) */
350
- engine: EngineConfig;
351
- /** Theme configuration */
352
- theme: ThemeConfig;
353
- /** Gameplay configuration */
354
- gameplay: GameplayConfig;
355
- }
265
+ type ObjectCentricConfig = ObjectCentricConfig$1;
356
266
 
357
267
  /**
358
268
  * Handler SDK - EndGame UI Panel
@@ -387,6 +297,69 @@ declare function animatePanelEntrance(elements: EndGamePanelElements, config: Ob
387
297
  */
388
298
  declare function animateHandClick(hand: Sprite, ctaButton: Graphics, config: ObjectCentricConfig, onClick: () => void): void;
389
299
 
300
+ interface SplashScreenConfig {
301
+ enabled: boolean;
302
+ show_on_start: boolean;
303
+ background_color: string;
304
+ background_alpha: number;
305
+ title: string;
306
+ subtitle: string;
307
+ button_label: string;
308
+ title_color: string;
309
+ subtitle_color: string;
310
+ button_bg: string;
311
+ button_text: string;
312
+ button_width: number;
313
+ button_height: number;
314
+ button_radius: number;
315
+ loading_blur: boolean;
316
+ loading_blur_strength: number;
317
+ loading_overlay_alpha: number;
318
+ font_family: string;
319
+ title_size: number;
320
+ subtitle_size: number;
321
+ loading_text: string;
322
+ loading_text_scale: number;
323
+ }
324
+ declare class SplashScreen {
325
+ private app;
326
+ private stage;
327
+ private activeConfig;
328
+ private splashConfig;
329
+ private splashEnabled;
330
+ private loadingBlurEnabled;
331
+ private loadingBlurStrength;
332
+ private loadingOverlayAlpha;
333
+ private splashLayer;
334
+ private splashBg;
335
+ private splashTitle;
336
+ private splashSubtitle;
337
+ private splashButton;
338
+ private splashButtonText;
339
+ private loadingLayer;
340
+ private loadingBg;
341
+ private loadingText;
342
+ private loadingTime;
343
+ private tickLoadingHandler;
344
+ constructor(app: Application, stage: Container, activeConfig: ObjectCentricConfig);
345
+ private resolveLoadingTextStyle;
346
+ syncConfig(next?: any): void;
347
+ updateLayout(width: number, height: number): void;
348
+ private updateSplashLayout;
349
+ private updateLoadingLayout;
350
+ show(): void;
351
+ hide(): void;
352
+ startLoadingAnimation(): void;
353
+ stopLoadingAnimation(): void;
354
+ destroyLoadingLayer(): void;
355
+ applyLoadingBlur(background: Sprite | Graphics): any[] | null;
356
+ removeLoadingBlur(background: Sprite | Graphics, prevFilters: any[] | null): void;
357
+ setupWindowGlobals(): void;
358
+ getSplashButton(): Graphics;
359
+ shouldShowOnStart(): boolean;
360
+ destroy(): void;
361
+ }
362
+
390
363
  /**
391
364
  * Handler SDK - Tutorial UI Components
392
365
  *
@@ -562,4 +535,322 @@ declare class ObjectFactory {
562
535
  private static applyTransform;
563
536
  }
564
537
 
565
- export { AssetCache, type AssetDefinition, AssetLoader, type EndGamePanelElements, GameObject, GameObjectManager, type ObjectCentricConfig, ObjectFactory, type PixiBaseContext, type PixiTheme, Renderer, Transform, animateHandClick, animatePanelEntrance, createEndGamePanel, createHandTutorial, createPixiBase, createTutorialLabel, getRegisteredFontIds, playLottieOverlay, registerFont, registerType, resolveFont, resolveFontWeight, setLottieInstance, updateHandAnimation };
538
+ /**
539
+ * Base context provided to all systems
540
+ */
541
+ interface SystemContext {
542
+ app: Application;
543
+ stage: Container;
544
+ config: ObjectCentricConfig$1;
545
+ gameObjectManager: GameObjectManager;
546
+ destinationUrl: string;
547
+ root: HTMLElement;
548
+ engine: GameEngine;
549
+ }
550
+ /**
551
+ * Base class for all game systems
552
+ */
553
+ declare abstract class BaseSystem {
554
+ protected context: SystemContext;
555
+ /**
556
+ * Internal initialization by GameEngine
557
+ */
558
+ setContext(context: SystemContext): void;
559
+ /**
560
+ * Called once during engine initialization
561
+ */
562
+ init?(): void | Promise<void>;
563
+ /**
564
+ * Called after all systems are initialized
565
+ */
566
+ onStart?(): void | Promise<void>;
567
+ /**
568
+ * Called every frame
569
+ * @param deltaTime normalized time since last frame
570
+ * @param totalTime total time elapsed since start
571
+ */
572
+ update?(deltaTime: number, totalTime: number): void;
573
+ /**
574
+ * Called when the screen is resized
575
+ */
576
+ onResize?(width: number, height: number): void;
577
+ /**
578
+ * Called when config changes (hot-reload)
579
+ */
580
+ onConfigUpdate?(newConfig: ObjectCentricConfig$1): void;
581
+ /**
582
+ * Cleanup system
583
+ */
584
+ onDestroy?(): void;
585
+ }
586
+
587
+ declare class GameEngine {
588
+ private app;
589
+ private stage;
590
+ private gameObjectManager;
591
+ private systems;
592
+ private totalTime;
593
+ private config;
594
+ private destinationUrl;
595
+ private root;
596
+ constructor(root: HTMLElement, config: ObjectCentricConfig$1, destinationUrl: string);
597
+ /**
598
+ * Initialize PIXI and systems
599
+ */
600
+ init(theme: any): Promise<{
601
+ app: Application;
602
+ gameObjectManager: GameObjectManager;
603
+ }>;
604
+ /**
605
+ * Register systems before starting
606
+ */
607
+ registerSystems(systems: BaseSystem[]): void;
608
+ /**
609
+ * Start the game loop
610
+ */
611
+ start(): Promise<void>;
612
+ /**
613
+ * Central update loop
614
+ */
615
+ private update;
616
+ /**
617
+ * Propagate resize
618
+ */
619
+ resize(width: number, height: number): void;
620
+ /**
621
+ * Handle hot-reload
622
+ */
623
+ updateConfig(newConfig: ObjectCentricConfig$1): void;
624
+ /**
625
+ * Destroy engine and systems
626
+ */
627
+ destroy(): void;
628
+ getApp(): Application;
629
+ getGameObjectManager(): GameObjectManager;
630
+ getTotalTime(): number;
631
+ /**
632
+ * Find a registered system by its class
633
+ */
634
+ getSystem<T extends BaseSystem>(type: new (...args: any[]) => T): T;
635
+ }
636
+
637
+ /**
638
+ * Runtime Object Registry
639
+ *
640
+ * Passive config registry that reads object configs from loaded ObjectCentricConfig.
641
+ * Hot-reload friendly - config passed at runtime.
642
+ *
643
+ * DO NOT EDIT - Base Layer
644
+ */
645
+
646
+ /**
647
+ * Runtime object registry - provides access to object configs
648
+ */
649
+ declare class RuntimeObjectRegistry {
650
+ private config;
651
+ /**
652
+ * Initialize registry with config
653
+ */
654
+ init(config: ObjectCentricConfig$1): void;
655
+ /**
656
+ * Get object config by instance ID
657
+ */
658
+ get(instanceId: string): any;
659
+ /**
660
+ * Get all object instance IDs
661
+ */
662
+ getAllIds(): string[];
663
+ /**
664
+ * Check if object exists
665
+ */
666
+ has(instanceId: string): boolean;
667
+ }
668
+
669
+ /**
670
+ * Base Layer - PixiJS Instance
671
+ *
672
+ * Provides isolated pixi.js instance for base layer.
673
+ * Prevents conflicts with student layer's pixi instance.
674
+ *
675
+ * DO NOT EDIT - Base Layer
676
+ */
677
+
678
+ declare const basePixi: typeof PixiJS;
679
+
680
+ /**
681
+ * Assets Proxy - Student-Facing API
682
+ *
683
+ * Provides simple API: Assets.ready() then Assets.xxx
684
+ *
685
+ * RULES:
686
+ * - Singleton instances by default
687
+ * - Assets.ready() resolves when all objects preloaded and Assets.xxx accesses are sync/safe
688
+ * - resetScene() clears instance cache only (NOT asset cache)
689
+ * - reloadObject(id) explicitly recreates single object
690
+ * - Separate asset cache (global) and instance cache (scene-scoped, strong references)
691
+ *
692
+ * DO NOT EDIT - Base Layer
693
+ */
694
+
695
+ /**
696
+ * Assets core implementation
697
+ */
698
+ declare class AssetsCore {
699
+ private registry;
700
+ private instanceCache;
701
+ private readyPromise;
702
+ private app;
703
+ constructor();
704
+ /**
705
+ * Initialize with config and app
706
+ */
707
+ init(config: ObjectCentricConfig$1, app: any): void;
708
+ /**
709
+ * Update config (for hot-reload)
710
+ * Re-initializes registry and clears instance cache
711
+ */
712
+ updateConfig(config: ObjectCentricConfig$1): void;
713
+ /**
714
+ * Preload all objects
715
+ * RULE: Resolves when all objects are preloaded and Assets.xxx accesses are sync/safe
716
+ * RULE: Idempotent - subsequent calls only reload changed objects
717
+ */
718
+ ready(): Promise<void>;
719
+ /**
720
+ * Reset scene - clears instance cache but NOT asset cache
721
+ * RULE: Strong references, cleared ONLY by resetScene()
722
+ */
723
+ resetScene(): void;
724
+ /**
725
+ * Reload a single object explicitly
726
+ */
727
+ reloadObject(id: string): Promise<void>;
728
+ /**
729
+ * Get object instance by ID
730
+ */
731
+ get(id: string): any;
732
+ }
733
+ declare const Assets: AssetsCore & {
734
+ [key: string]: any;
735
+ };
736
+ /**
737
+ * Initialize Assets with config and app
738
+ * Must be called before Assets.ready()
739
+ */
740
+ declare function initAssets(config: ObjectCentricConfig$1, app: any): void;
741
+
742
+ declare class AssetSystem extends BaseSystem {
743
+ private splashScreen;
744
+ init(): Promise<void>;
745
+ onStart(): Promise<void>;
746
+ onConfigUpdate(): void;
747
+ }
748
+
749
+ declare let globalResponsiveMultipliers: {
750
+ scale: number;
751
+ position: number;
752
+ };
753
+ declare function clearResponsiveElements(): void;
754
+ declare function updateScreenState(width: number, height: number): void;
755
+ type AnchorSpec = string | {
756
+ x: number;
757
+ y: number;
758
+ } | [number, number] | null | undefined;
759
+ type RatioSpec = {
760
+ x: number;
761
+ y: number;
762
+ } | [number, number] | null | undefined;
763
+ type ScreenInset = {
764
+ top?: number;
765
+ right?: number;
766
+ bottom?: number;
767
+ left?: number;
768
+ };
769
+ declare function resolveAnchorVec2(anchor: AnchorSpec, fallback?: {
770
+ x: number;
771
+ y: number;
772
+ }): {
773
+ x: number;
774
+ y: number;
775
+ };
776
+ declare function resolveScreenAnchorPoint(screenWidth: number, screenHeight: number, anchor: AnchorSpec, opts?: {
777
+ inset?: ScreenInset;
778
+ padding?: {
779
+ x: number;
780
+ y: number;
781
+ };
782
+ }): {
783
+ x: number;
784
+ y: number;
785
+ };
786
+ declare function resolveScreenRatioPoint(screenWidth: number, screenHeight: number, ratio: RatioSpec, opts?: {
787
+ inset?: ScreenInset;
788
+ padding?: {
789
+ x: number;
790
+ y: number;
791
+ };
792
+ }): {
793
+ x: number;
794
+ y: number;
795
+ };
796
+ declare function applyScreenAnchor(element: any, screenWidth: number, screenHeight: number, options?: {
797
+ anchor?: AnchorSpec;
798
+ positionRatio?: RatioSpec;
799
+ offset?: {
800
+ x: number;
801
+ y: number;
802
+ };
803
+ inset?: ScreenInset;
804
+ screenPadding?: {
805
+ x: number;
806
+ y: number;
807
+ };
808
+ renderAnchor?: {
809
+ x: number;
810
+ y: number;
811
+ };
812
+ scale?: number;
813
+ scaleMultiplier?: number;
814
+ }): void;
815
+ /**
816
+ * Layout Manager
817
+ * Strategy: ADAPTIVE ANCHOR
818
+ * - Tall Screens: Show full rope (Anchor Top).
819
+ * - Short Screens: Prioritize Character (Anchor Character Position).
820
+ */
821
+ interface LayoutScreen {
822
+ width: number;
823
+ height: number;
824
+ }
825
+ interface LayoutElements {
826
+ mainContainer: any;
827
+ label: any;
828
+ background: any;
829
+ backgroundTexture: any;
830
+ app: any;
831
+ }
832
+ declare function layout(elements: LayoutElements, config: ObjectCentricConfig, time: number, screen: LayoutScreen, gameObjectManager?: any, options?: {
833
+ skipInstanceIds?: string[];
834
+ enableDebugLogs?: boolean;
835
+ skipMainContainerTransform?: boolean;
836
+ }): void;
837
+
838
+ interface InitSequenceStates<State = unknown> {
839
+ showHook: State;
840
+ waitInput: State;
841
+ }
842
+ interface InitSequenceOptions<State = unknown> {
843
+ setState: (state: State) => void;
844
+ updateLabelAlpha: (alpha: number) => void;
845
+ updateHandAlpha: (alpha: number) => void;
846
+ config: ObjectCentricConfig;
847
+ states: InitSequenceStates<State>;
848
+ }
849
+ /**
850
+ * Shared, config-driven init sequence.
851
+ *
852
+ * Keeps the SDK generic by letting the caller pass game-specific state values.
853
+ */
854
+ declare function runInitSequence<State = unknown>(options: InitSequenceOptions<State>): void;
855
+
856
+ export { AssetCache, type AssetDefinition, AssetLoader, AssetSystem, Assets, BaseSystem, type EndGamePanelElements, GameEngine, GameObject, GameObjectManager, type ObjectCentricConfig, ObjectFactory, type PixiBaseContext, type PixiTheme, Renderer, RuntimeObjectRegistry, SplashScreen, type SplashScreenConfig, type SystemContext, Transform, animateHandClick, animatePanelEntrance, applyScreenAnchor, basePixi, clearResponsiveElements, createEndGamePanel, createHandTutorial, createPixiBase, createTutorialLabel, getRegisteredFontIds, globalResponsiveMultipliers, initAssets, layout, playLottieOverlay, registerFont, registerType, resolveAnchorVec2, resolveFont, resolveFontWeight, resolveScreenAnchorPoint, resolveScreenRatioPoint, runInitSequence, setLottieInstance, updateHandAnimation, updateScreenState };