dino-ge 1.0.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.
Files changed (66) hide show
  1. package/dist/Camera.d.ts +37 -0
  2. package/dist/Camera.js +44 -0
  3. package/dist/Camera.js.map +1 -0
  4. package/dist/Canvas.d.ts +12 -0
  5. package/dist/Canvas.js +21 -0
  6. package/dist/Canvas.js.map +1 -0
  7. package/dist/Circle.d.ts +39 -0
  8. package/dist/Circle.js +51 -0
  9. package/dist/Circle.js.map +1 -0
  10. package/dist/Engine.d.ts +114 -0
  11. package/dist/Engine.js +321 -0
  12. package/dist/Engine.js.map +1 -0
  13. package/dist/GameObject.d.ts +41 -0
  14. package/dist/GameObject.js +35 -0
  15. package/dist/GameObject.js.map +1 -0
  16. package/dist/Input.d.ts +27 -0
  17. package/dist/Input.js +99 -0
  18. package/dist/Input.js.map +1 -0
  19. package/dist/Line.d.ts +41 -0
  20. package/dist/Line.js +40 -0
  21. package/dist/Line.js.map +1 -0
  22. package/dist/Loader.d.ts +26 -0
  23. package/dist/Loader.js +76 -0
  24. package/dist/Loader.js.map +1 -0
  25. package/dist/Physics.d.ts +16 -0
  26. package/dist/Physics.js +77 -0
  27. package/dist/Physics.js.map +1 -0
  28. package/dist/Rectangle.d.ts +41 -0
  29. package/dist/Rectangle.js +44 -0
  30. package/dist/Rectangle.js.map +1 -0
  31. package/dist/Scene.d.ts +19 -0
  32. package/dist/Scene.js +27 -0
  33. package/dist/Scene.js.map +1 -0
  34. package/dist/Sprite.d.ts +76 -0
  35. package/dist/Sprite.js +129 -0
  36. package/dist/Sprite.js.map +1 -0
  37. package/dist/Text.d.ts +80 -0
  38. package/dist/Text.js +110 -0
  39. package/dist/Text.js.map +1 -0
  40. package/dist/Tilemap.d.ts +46 -0
  41. package/dist/Tilemap.js +48 -0
  42. package/dist/Tilemap.js.map +1 -0
  43. package/dist/Vector2.d.ts +26 -0
  44. package/dist/Vector2.js +21 -0
  45. package/dist/Vector2.js.map +1 -0
  46. package/dist/index.d.ts +15 -0
  47. package/dist/index.js +16 -0
  48. package/dist/index.js.map +1 -0
  49. package/package.json +18 -0
  50. package/src/Camera.ts +47 -0
  51. package/src/Canvas.ts +24 -0
  52. package/src/Circle.ts +88 -0
  53. package/src/Engine.ts +407 -0
  54. package/src/GameObject.ts +56 -0
  55. package/src/Input.ts +117 -0
  56. package/src/Line.ts +75 -0
  57. package/src/Loader.ts +66 -0
  58. package/src/Physics.ts +77 -0
  59. package/src/Rectangle.ts +83 -0
  60. package/src/Scene.ts +30 -0
  61. package/src/Sprite.ts +194 -0
  62. package/src/Text.ts +187 -0
  63. package/src/Tilemap.ts +95 -0
  64. package/src/Vector2.ts +36 -0
  65. package/src/index.ts +15 -0
  66. package/tsconfig.json +16 -0
@@ -0,0 +1,37 @@
1
+ import Vector2 from './Vector2.js';
2
+ /**
3
+ * Manages the viewport and transformation of the game world.
4
+ */
5
+ export default class Camera {
6
+ /** Current camera position in world space. */
7
+ position: Vector2;
8
+ /** Zoom level of the camera. */
9
+ zoom: number;
10
+ constructor();
11
+ /**
12
+ * Center the camera on a target object.
13
+ * @param target The object to follow.
14
+ * @param viewportWidth Width of the viewport.
15
+ * @param viewportHeight Height of the viewport.
16
+ */
17
+ follow(target: {
18
+ position: Vector2;
19
+ width: number;
20
+ height: number;
21
+ }, viewportWidth: number, viewportHeight: number): void;
22
+ /**
23
+ * Returns the current viewport bounds in world space.
24
+ * @param width Width of the viewport.
25
+ * @param height Height of the viewport.
26
+ */
27
+ getViewportBounds(width: number, height: number): {
28
+ x: number;
29
+ y: number;
30
+ width: number;
31
+ height: number;
32
+ };
33
+ /**
34
+ * Reset camera position to origin and zoom to 1.
35
+ */
36
+ reset(): void;
37
+ }
package/dist/Camera.js ADDED
@@ -0,0 +1,44 @@
1
+ import Vector2 from './Vector2.js';
2
+ /**
3
+ * Manages the viewport and transformation of the game world.
4
+ */
5
+ export default class Camera {
6
+ constructor() {
7
+ /** Current camera position in world space. */
8
+ this.position = new Vector2(0, 0);
9
+ /** Zoom level of the camera. */
10
+ this.zoom = 1;
11
+ }
12
+ /**
13
+ * Center the camera on a target object.
14
+ * @param target The object to follow.
15
+ * @param viewportWidth Width of the viewport.
16
+ * @param viewportHeight Height of the viewport.
17
+ */
18
+ follow(target, viewportWidth, viewportHeight) {
19
+ this.position.x = (target.position.x + target.width / 2) - (viewportWidth / 2) / this.zoom;
20
+ this.position.y = (target.position.y + target.height / 2) - (viewportHeight / 2) / this.zoom;
21
+ }
22
+ /**
23
+ * Returns the current viewport bounds in world space.
24
+ * @param width Width of the viewport.
25
+ * @param height Height of the viewport.
26
+ */
27
+ getViewportBounds(width, height) {
28
+ return {
29
+ x: this.position.x,
30
+ y: this.position.y,
31
+ width: width / this.zoom,
32
+ height: height / this.zoom
33
+ };
34
+ }
35
+ /**
36
+ * Reset camera position to origin and zoom to 1.
37
+ */
38
+ reset() {
39
+ this.position.x = 0;
40
+ this.position.y = 0;
41
+ this.zoom = 1;
42
+ }
43
+ }
44
+ //# sourceMappingURL=Camera.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Camera.js","sourceRoot":"","sources":["../src/Camera.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,MAAM;IAMzB;QALA,8CAA8C;QACvC,aAAQ,GAAY,IAAI,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7C,gCAAgC;QACzB,SAAI,GAAW,CAAC,CAAC;IAET,CAAC;IAEhB;;;;;OAKG;IACH,MAAM,CAAC,MAA4D,EAAE,aAAqB,EAAE,cAAsB;QAChH,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;QAC3F,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;IAC/F,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CAAC,KAAa,EAAE,MAAc;QAC7C,OAAO;YACL,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClB,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC,IAAI;YACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,IAAI;SAC3B,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Simple wrapper for creating and managing a full-screen canvas element.
3
+ */
4
+ export default class Canvas {
5
+ /** The underlying HTMLCanvasElement. */
6
+ canvas: HTMLCanvasElement;
7
+ constructor();
8
+ /**
9
+ * Resizes the canvas to match the window dimensions.
10
+ */
11
+ resize(): void;
12
+ }
package/dist/Canvas.js ADDED
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Simple wrapper for creating and managing a full-screen canvas element.
3
+ */
4
+ export default class Canvas {
5
+ constructor() {
6
+ this.canvas = document.createElement('canvas');
7
+ this.canvas.id = 'canvas';
8
+ this.canvas.width = window.innerWidth;
9
+ this.canvas.height = window.innerHeight;
10
+ this.canvas.style.zIndex = '0';
11
+ this.canvas.style.position = 'fixed';
12
+ }
13
+ /**
14
+ * Resizes the canvas to match the window dimensions.
15
+ */
16
+ resize() {
17
+ this.canvas.width = window.innerWidth;
18
+ this.canvas.height = window.innerHeight;
19
+ }
20
+ }
21
+ //# sourceMappingURL=Canvas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Canvas.js","sourceRoot":"","sources":["../src/Canvas.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,MAAM;IAIzB;QACE,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC;IAC1C,CAAC;CACF"}
@@ -0,0 +1,39 @@
1
+ import Vector2 from './Vector2.js';
2
+ import GameObject from './GameObject.js';
3
+ /**
4
+ * Configuration for creating a Circle object.
5
+ */
6
+ export interface CircleProps {
7
+ /** Unique tag for identification. */
8
+ tag: string;
9
+ /** Initial position of the circle. */
10
+ position: Vector2;
11
+ /** Radius of the circle. */
12
+ radius: number;
13
+ /** Fill colour. */
14
+ colour: string;
15
+ /** Render order (lower is background). */
16
+ zIndex: number;
17
+ }
18
+ /**
19
+ * A basic circle shape that can be drawn to the screen.
20
+ */
21
+ export default class Circle extends GameObject {
22
+ private _position;
23
+ /** Radius of the circle. */
24
+ radius: number;
25
+ /** Fill colour. */
26
+ colour: string;
27
+ /** Gets or sets the position of the circle. */
28
+ get position(): Vector2;
29
+ set position(val: Vector2);
30
+ /** Width of the circle (radius * 2). */
31
+ get width(): number;
32
+ /** Height of the circle (radius * 2). */
33
+ get height(): number;
34
+ /** Center point of the circle. */
35
+ get center(): Vector2;
36
+ constructor(props: CircleProps);
37
+ /** Draws the circle onto the provided rendering context. */
38
+ draw(ctx: CanvasRenderingContext2D): void;
39
+ }
package/dist/Circle.js ADDED
@@ -0,0 +1,51 @@
1
+ import Vector2 from './Vector2.js';
2
+ import GameObject from './GameObject.js';
3
+ const defaultProps = {
4
+ tag: 'circle',
5
+ colour: 'black',
6
+ zIndex: 0,
7
+ };
8
+ /**
9
+ * A basic circle shape that can be drawn to the screen.
10
+ */
11
+ export default class Circle extends GameObject {
12
+ /** Gets or sets the position of the circle. */
13
+ get position() { return this._position; }
14
+ set position(val) { this._position = val; }
15
+ /** Width of the circle (radius * 2). */
16
+ get width() { return this.radius * 2; }
17
+ /** Height of the circle (radius * 2). */
18
+ get height() { return this.radius * 2; }
19
+ /** Center point of the circle. */
20
+ get center() {
21
+ return new Vector2(this.position.x + this.radius, this.position.y + this.radius);
22
+ }
23
+ constructor(props) {
24
+ super(props.tag || defaultProps.tag, props.zIndex || defaultProps.zIndex);
25
+ const defaultedProps = Object.assign(Object.assign({}, defaultProps), props);
26
+ if (!(defaultedProps.position instanceof Vector2)) {
27
+ throw new Error('"position" must be a Vector2!');
28
+ }
29
+ if (!defaultedProps.radius) {
30
+ throw new Error('You must provide a radius for Circle');
31
+ }
32
+ this.tag = defaultedProps.tag;
33
+ this._position = defaultedProps.position;
34
+ this.radius = defaultedProps.radius;
35
+ this.colour = defaultedProps.colour;
36
+ this.zIndex = defaultedProps.zIndex;
37
+ this.registerSelf();
38
+ }
39
+ /** Draws the circle onto the provided rendering context. */
40
+ draw(ctx) {
41
+ if (!this.visible)
42
+ return;
43
+ ctx.beginPath();
44
+ ctx.fillStyle = this.colour;
45
+ const center = this.center;
46
+ ctx.arc(center.x, center.y, this.radius, 0, Math.PI * 2);
47
+ ctx.fill();
48
+ ctx.closePath();
49
+ }
50
+ }
51
+ //# sourceMappingURL=Circle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Circle.js","sourceRoot":"","sources":["../src/Circle.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,UAAU,MAAM,iBAAiB,CAAC;AAkBzC,MAAM,YAAY,GAAG;IACnB,GAAG,EAAE,QAAQ;IACb,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,CAAC;CACV,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,UAAU;IAO5C,+CAA+C;IAC/C,IAAI,QAAQ,KAAK,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACzC,IAAI,QAAQ,CAAC,GAAG,IAAI,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC;IAE3C,wCAAwC;IACxC,IAAI,KAAK,KAAK,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IACvC,yCAAyC;IACzC,IAAI,MAAM,KAAK,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAExC,kCAAkC;IAClC,IAAI,MAAM;QACR,OAAO,IAAI,OAAO,CAChB,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,EAC7B,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAC9B,CAAC;IACJ,CAAC;IAED,YAAY,KAAkB;QAC5B,KAAK,CAAC,KAAK,CAAC,GAAG,IAAI,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,MAAM,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;QAE1E,MAAM,cAAc,mCACf,YAAY,GACZ,KAAK,CACT,CAAC;QAEF,IAAI,CAAC,CAAC,cAAc,CAAC,QAAQ,YAAY,OAAO,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAED,IAAI,CAAC,GAAG,GAAG,cAAc,CAAC,GAAG,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,cAAc,CAAC,QAAQ,CAAC;QACzC,IAAI,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC;QAEpC,IAAI,CAAC,YAAY,EAAE,CAAC;IACtB,CAAC;IAED,4DAA4D;IAC5D,IAAI,CAAC,GAA6B;QAChC,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,GAAG,CAAC,SAAS,EAAE,CAAC;QAChB,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC;QAC5B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QACzD,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,SAAS,EAAE,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,114 @@
1
+ import GameObject from './GameObject.js';
2
+ import Scene from './Scene.js';
3
+ import Camera from './Camera.js';
4
+ /**
5
+ * Options for initializing the Engine.
6
+ */
7
+ export interface EngineOpts {
8
+ /** Width of the game window (e.g., '800px' or '100%'). */
9
+ width: string;
10
+ /** Height of the game window (e.g., '600px' or '100%'). */
11
+ height: string;
12
+ /** Title of the game, set in the document head. */
13
+ title: string;
14
+ /** Background colour of the canvas. */
15
+ backgroundColour: string;
16
+ }
17
+ /**
18
+ * Lifecycle and update callbacks for the engine.
19
+ */
20
+ export interface EngineCallbacks {
21
+ /** Called once after the engine is initialized. */
22
+ onLoad: () => void;
23
+ /** Called every frame for game logic and rendering. */
24
+ update: () => void;
25
+ /** Optional callback for physics or fixed-step logic. */
26
+ fixedUpdate?: () => void;
27
+ }
28
+ /**
29
+ * Specialized Set for managing game objects with helper methods.
30
+ */
31
+ export declare class ObjectSet extends Set<GameObject> {
32
+ /**
33
+ * Find all objects with a specific tag.
34
+ * @param tag The tag to search for.
35
+ */
36
+ findAll: (tag: string) => GameObject[];
37
+ }
38
+ /**
39
+ * The core singleton class that manages the game loop, rendering, and scene state.
40
+ */
41
+ export default class Engine {
42
+ #private;
43
+ /**
44
+ * Global set of game objects if no scene is active.
45
+ */
46
+ static objects: ObjectSet;
47
+ /**
48
+ * Whether the game loop is currently paused.
49
+ */
50
+ static paused: boolean;
51
+ /**
52
+ * Toggle for visual debug mode (hitboxes and stats).
53
+ */
54
+ static debug: boolean;
55
+ /**
56
+ * The currently selected object in debug mode.
57
+ */
58
+ static selectedObject: GameObject | null;
59
+ /**
60
+ * The global camera instance.
61
+ */
62
+ static camera: Camera;
63
+ private static _currentScene;
64
+ /**
65
+ * Gets the currently active scene.
66
+ */
67
+ static get currentScene(): Scene;
68
+ /**
69
+ * Sets the active scene, resetting the camera and calling the scene's onLoad.
70
+ */
71
+ static set currentScene(scene: Scene);
72
+ /** Current background colour. */
73
+ backgroundColour: string;
74
+ /** Registered engine callbacks. */
75
+ callbacks: EngineCallbacks;
76
+ /** Pixel width of the canvas. */
77
+ width: number;
78
+ /** Pixel height of the canvas. */
79
+ height: number;
80
+ /** Current mouse x position in world space. */
81
+ get mouseX(): number;
82
+ /** Current mouse y position in world space. */
83
+ get mouseY(): number;
84
+ /** Current frames per second. */
85
+ fps: number;
86
+ constructor(callbacks: EngineCallbacks, opts?: Partial<EngineOpts>);
87
+ /**
88
+ * Promisified setTimeout.
89
+ * @param timeoutFn The function to run after the timeout.
90
+ * @param time The time in milliseconds to wait.
91
+ */
92
+ setTimeout(timeoutFn: () => void, time: number): Promise<void>;
93
+ /**
94
+ * Run a function repeatedly for a duration and then run a final function.
95
+ * @param milliseconds Total duration.
96
+ * @param fn Function to run every second.
97
+ * @param onEnded Final function to run.
98
+ */
99
+ countdown(milliseconds: number, fn: () => void, onEnded: () => void): void;
100
+ /** Sets the CSS cursor style for the game canvas. */
101
+ set cursor(value: string);
102
+ /**
103
+ * Register a new game object with the active scene or global engine.
104
+ * @param object The object to register.
105
+ */
106
+ static registerObject(object: GameObject): void;
107
+ /**
108
+ * Remove a game object from the active scene or global engine.
109
+ * @param object The object to destroy.
110
+ */
111
+ static destroyObject(object: GameObject): void;
112
+ /** Destroy all objects in the active scene or global engine. */
113
+ static destroyAll(): void;
114
+ }
package/dist/Engine.js ADDED
@@ -0,0 +1,321 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
11
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
12
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
13
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
14
+ };
15
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
16
+ if (kind === "m") throw new TypeError("Private method is not writable");
17
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
18
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
19
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
20
+ };
21
+ var _Engine_instances, _a, _Engine_canvas, _Engine_ctx, _Engine_window, _Engine_title, _Engine_oldTimestamp, _Engine_secondsPassed, _Engine_accumulator, _Engine_fixedDelta, _Engine_onLoad, _Engine_update, _Engine_fixedUpdate, _Engine_setBackground, _Engine_draw, _Engine_drawDebug, _Engine_findAllObjects, _Engine_getSortedArray;
22
+ import Canvas from './Canvas.js';
23
+ import Input from './Input.js';
24
+ import Camera from './Camera.js';
25
+ /**
26
+ * Specialized Set for managing game objects with helper methods.
27
+ */
28
+ export class ObjectSet extends Set {
29
+ constructor() {
30
+ super(...arguments);
31
+ /**
32
+ * Find all objects with a specific tag.
33
+ * @param tag The tag to search for.
34
+ */
35
+ this.findAll = () => [];
36
+ }
37
+ }
38
+ /**
39
+ * The core singleton class that manages the game loop, rendering, and scene state.
40
+ */
41
+ class Engine {
42
+ /**
43
+ * Gets the currently active scene.
44
+ */
45
+ static get currentScene() {
46
+ return this._currentScene;
47
+ }
48
+ /**
49
+ * Sets the active scene, resetting the camera and calling the scene's onLoad.
50
+ */
51
+ static set currentScene(scene) {
52
+ this._currentScene = scene;
53
+ this.camera.reset();
54
+ scene.onLoad();
55
+ }
56
+ /** Current mouse x position in world space. */
57
+ get mouseX() {
58
+ return Input.mouseX;
59
+ }
60
+ /** Current mouse y position in world space. */
61
+ get mouseY() {
62
+ return Input.mouseY;
63
+ }
64
+ constructor(callbacks, opts = {}) {
65
+ _Engine_instances.add(this);
66
+ _Engine_canvas.set(this, void 0);
67
+ _Engine_ctx.set(this, void 0);
68
+ _Engine_window.set(this, void 0);
69
+ _Engine_title.set(this, void 0);
70
+ /** Current frames per second. */
71
+ this.fps = 0;
72
+ _Engine_oldTimestamp.set(this, 0);
73
+ _Engine_secondsPassed.set(this, 0);
74
+ _Engine_accumulator.set(this, 0);
75
+ _Engine_fixedDelta.set(this, 1 / 60);
76
+ const defaultedOpts = Object.assign({ width: '100%', height: '100%', title: 'Example', backgroundColour: 'white' }, opts);
77
+ _a.objects.findAll = __classPrivateFieldGet(this, _Engine_instances, "m", _Engine_findAllObjects).bind(this);
78
+ __classPrivateFieldSet(this, _Engine_title, document.createElement('title'), "f");
79
+ __classPrivateFieldGet(this, _Engine_title, "f").innerHTML = defaultedOpts.title;
80
+ document.getElementsByTagName('head')[0].appendChild(__classPrivateFieldGet(this, _Engine_title, "f"));
81
+ this.backgroundColour = defaultedOpts.backgroundColour;
82
+ this.callbacks = {
83
+ onLoad: () => {
84
+ callbacks.onLoad();
85
+ __classPrivateFieldGet(this, _Engine_instances, "m", _Engine_onLoad).call(this);
86
+ },
87
+ update: callbacks.update,
88
+ };
89
+ __classPrivateFieldSet(this, _Engine_canvas, new Canvas(), "f");
90
+ __classPrivateFieldSet(this, _Engine_ctx, __classPrivateFieldGet(this, _Engine_canvas, "f").canvas.getContext('2d'), "f");
91
+ this.width = __classPrivateFieldGet(this, _Engine_canvas, "f").canvas.width;
92
+ this.height = __classPrivateFieldGet(this, _Engine_canvas, "f").canvas.height;
93
+ __classPrivateFieldSet(this, _Engine_window, document.createElement('div'), "f");
94
+ __classPrivateFieldGet(this, _Engine_window, "f").id = 'canvas-container';
95
+ __classPrivateFieldGet(this, _Engine_window, "f").style.width = defaultedOpts.width;
96
+ __classPrivateFieldGet(this, _Engine_window, "f").style.height = defaultedOpts.height;
97
+ Input.init();
98
+ window.addEventListener('resize', () => {
99
+ __classPrivateFieldGet(this, _Engine_canvas, "f").resize();
100
+ this.width = __classPrivateFieldGet(this, _Engine_canvas, "f").canvas.width;
101
+ this.height = __classPrivateFieldGet(this, _Engine_canvas, "f").canvas.height;
102
+ });
103
+ document.getElementsByTagName('body')[0].appendChild(__classPrivateFieldGet(this, _Engine_window, "f"));
104
+ __classPrivateFieldGet(this, _Engine_window, "f").appendChild(__classPrivateFieldGet(this, _Engine_canvas, "f").canvas);
105
+ setTimeout(() => this.callbacks.onLoad(), 0);
106
+ }
107
+ /**
108
+ * Promisified setTimeout.
109
+ * @param timeoutFn The function to run after the timeout.
110
+ * @param time The time in milliseconds to wait.
111
+ */
112
+ setTimeout(timeoutFn, time) {
113
+ return __awaiter(this, void 0, void 0, function* () {
114
+ yield new Promise((resolve) => {
115
+ setTimeout(resolve, time);
116
+ });
117
+ timeoutFn();
118
+ });
119
+ }
120
+ /**
121
+ * Run a function repeatedly for a duration and then run a final function.
122
+ * @param milliseconds Total duration.
123
+ * @param fn Function to run every second.
124
+ * @param onEnded Final function to run.
125
+ */
126
+ countdown(milliseconds, fn, onEnded) {
127
+ setTimeout(onEnded, milliseconds);
128
+ for (let i = 1; i <= milliseconds; i += 1) {
129
+ if (i % 1000 === 0) {
130
+ setTimeout(fn, i);
131
+ }
132
+ }
133
+ }
134
+ /** Sets the CSS cursor style for the game canvas. */
135
+ set cursor(value) {
136
+ const canvas = document.getElementById('canvas');
137
+ if (canvas)
138
+ canvas.style.cursor = value;
139
+ }
140
+ /**
141
+ * Register a new game object with the active scene or global engine.
142
+ * @param object The object to register.
143
+ */
144
+ static registerObject(object) {
145
+ if (_a.currentScene) {
146
+ _a.currentScene.add(object);
147
+ }
148
+ else {
149
+ this.objects.add(object);
150
+ }
151
+ }
152
+ /**
153
+ * Remove a game object from the active scene or global engine.
154
+ * @param object The object to destroy.
155
+ */
156
+ static destroyObject(object) {
157
+ if (_a.currentScene) {
158
+ _a.currentScene.remove(object);
159
+ }
160
+ else {
161
+ this.objects.delete(object);
162
+ }
163
+ }
164
+ /** Destroy all objects in the active scene or global engine. */
165
+ static destroyAll() {
166
+ if (_a.currentScene) {
167
+ _a.currentScene.clear();
168
+ }
169
+ else {
170
+ this.objects.clear();
171
+ }
172
+ }
173
+ }
174
+ _a = Engine, _Engine_canvas = new WeakMap(), _Engine_ctx = new WeakMap(), _Engine_window = new WeakMap(), _Engine_title = new WeakMap(), _Engine_oldTimestamp = new WeakMap(), _Engine_secondsPassed = new WeakMap(), _Engine_accumulator = new WeakMap(), _Engine_fixedDelta = new WeakMap(), _Engine_instances = new WeakSet(), _Engine_onLoad = function _Engine_onLoad() {
175
+ __classPrivateFieldGet(this, _Engine_instances, "m", _Engine_draw).call(this);
176
+ window.requestAnimationFrame(__classPrivateFieldGet(this, _Engine_instances, "m", _Engine_update).bind(this));
177
+ }, _Engine_update = function _Engine_update(timestamp) {
178
+ if (!_a.paused) {
179
+ __classPrivateFieldSet(this, _Engine_secondsPassed, (timestamp - __classPrivateFieldGet(this, _Engine_oldTimestamp, "f")) / 1000, "f");
180
+ __classPrivateFieldSet(this, _Engine_oldTimestamp, timestamp, "f");
181
+ this.fps = Math.round(1 / __classPrivateFieldGet(this, _Engine_secondsPassed, "f"));
182
+ // Fixed update loop
183
+ __classPrivateFieldSet(this, _Engine_accumulator, __classPrivateFieldGet(this, _Engine_accumulator, "f") + __classPrivateFieldGet(this, _Engine_secondsPassed, "f"), "f");
184
+ while (__classPrivateFieldGet(this, _Engine_accumulator, "f") >= __classPrivateFieldGet(this, _Engine_fixedDelta, "f")) {
185
+ __classPrivateFieldGet(this, _Engine_instances, "m", _Engine_fixedUpdate).call(this);
186
+ __classPrivateFieldSet(this, _Engine_accumulator, __classPrivateFieldGet(this, _Engine_accumulator, "f") - __classPrivateFieldGet(this, _Engine_fixedDelta, "f"), "f");
187
+ }
188
+ if (_a.currentScene) {
189
+ _a.currentScene.update();
190
+ }
191
+ this.callbacks.update();
192
+ __classPrivateFieldGet(this, _Engine_instances, "m", _Engine_draw).call(this);
193
+ }
194
+ else {
195
+ // Still allow drawing in paused mode if debug is on or for initial frame
196
+ __classPrivateFieldGet(this, _Engine_instances, "m", _Engine_draw).call(this);
197
+ }
198
+ window.requestAnimationFrame(__classPrivateFieldGet(this, _Engine_instances, "m", _Engine_update).bind(this));
199
+ }, _Engine_fixedUpdate = function _Engine_fixedUpdate() {
200
+ const objects = _a.currentScene ? _a.currentScene.objects : _a.objects;
201
+ objects.forEach((object) => {
202
+ // Apply acceleration to velocity
203
+ object.velocity.x += object.acceleration.x * __classPrivateFieldGet(this, _Engine_fixedDelta, "f");
204
+ object.velocity.y += object.acceleration.y * __classPrivateFieldGet(this, _Engine_fixedDelta, "f");
205
+ // Apply velocity to position
206
+ object.position.x += object.velocity.x * __classPrivateFieldGet(this, _Engine_fixedDelta, "f");
207
+ object.position.y += object.velocity.y * __classPrivateFieldGet(this, _Engine_fixedDelta, "f");
208
+ });
209
+ if (this.callbacks.fixedUpdate) {
210
+ this.callbacks.fixedUpdate();
211
+ }
212
+ }, _Engine_setBackground = function _Engine_setBackground() {
213
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillStyle = this.backgroundColour;
214
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillRect(0, 0, __classPrivateFieldGet(this, _Engine_canvas, "f").canvas.width, __classPrivateFieldGet(this, _Engine_canvas, "f").canvas.height);
215
+ }, _Engine_draw = function _Engine_draw() {
216
+ __classPrivateFieldGet(this, _Engine_instances, "m", _Engine_setBackground).call(this);
217
+ const objects = _a.currentScene ? _a.currentScene.objects : _a.objects;
218
+ const bounds = _a.camera.getViewportBounds(this.width, this.height);
219
+ __classPrivateFieldGet(this, _Engine_ctx, "f").save();
220
+ // Apply camera transform
221
+ __classPrivateFieldGet(this, _Engine_ctx, "f").scale(_a.camera.zoom, _a.camera.zoom);
222
+ __classPrivateFieldGet(this, _Engine_ctx, "f").translate(-_a.camera.position.x, -_a.camera.position.y);
223
+ __classPrivateFieldGet(_a, _a, "m", _Engine_getSortedArray).call(_a, objects).forEach((object) => {
224
+ // Frustum Culling
225
+ if (object.position.x < bounds.x + bounds.width &&
226
+ object.position.x + object.width > bounds.x &&
227
+ object.position.y < bounds.y + bounds.height &&
228
+ object.position.y + object.height > bounds.y) {
229
+ object.draw(__classPrivateFieldGet(this, _Engine_ctx, "f"));
230
+ }
231
+ });
232
+ if (_a.debug) {
233
+ __classPrivateFieldGet(this, _Engine_instances, "m", _Engine_drawDebug).call(this, objects);
234
+ }
235
+ __classPrivateFieldGet(this, _Engine_ctx, "f").restore();
236
+ }, _Engine_drawDebug = function _Engine_drawDebug(objects) {
237
+ __classPrivateFieldGet(this, _Engine_ctx, "f").strokeStyle = 'red';
238
+ __classPrivateFieldGet(this, _Engine_ctx, "f").lineWidth = 1;
239
+ __classPrivateFieldGet(this, _Engine_ctx, "f").font = '12px monospace';
240
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillStyle = 'red';
241
+ objects.forEach((obj) => {
242
+ // Draw hitbox
243
+ __classPrivateFieldGet(this, _Engine_ctx, "f").strokeStyle = obj === _a.selectedObject ? '#00ff00' : 'red';
244
+ __classPrivateFieldGet(this, _Engine_ctx, "f").lineWidth = obj === _a.selectedObject ? 2 : 1;
245
+ __classPrivateFieldGet(this, _Engine_ctx, "f").strokeRect(obj.position.x, obj.position.y, obj.width, obj.height);
246
+ // Draw tag
247
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillStyle = __classPrivateFieldGet(this, _Engine_ctx, "f").strokeStyle;
248
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillText(obj.tag || 'obj', obj.position.x, obj.position.y - 5);
249
+ });
250
+ // Draw Stats Overlay (Top Right)
251
+ __classPrivateFieldGet(this, _Engine_ctx, "f").save();
252
+ __classPrivateFieldGet(this, _Engine_ctx, "f").setTransform(1, 0, 0, 1, 0, 0); // Reset transform for UI
253
+ const overlayWidth = 180;
254
+ const statsHeight = 80;
255
+ const padding = 10;
256
+ const x = __classPrivateFieldGet(this, _Engine_canvas, "f").canvas.width - overlayWidth - padding;
257
+ let y = padding;
258
+ // Background for Stats
259
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillStyle = 'rgba(0, 0, 0, 0.7)';
260
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillRect(x, y, overlayWidth, statsHeight);
261
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillStyle = 'white';
262
+ __classPrivateFieldGet(this, _Engine_ctx, "f").textAlign = 'left';
263
+ __classPrivateFieldGet(this, _Engine_ctx, "f").textBaseline = 'top';
264
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillText(`FPS: ${this.fps}`, x + 10, y + 10);
265
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillText(`Objects: ${objects.size}`, x + 10, y + 25);
266
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillText(`Mouse X: ${Math.round(this.mouseX)}`, x + 10, y + 45);
267
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillText(`Mouse Y: ${Math.round(this.mouseY)}`, x + 10, y + 60);
268
+ // Inspector Panel (If object selected)
269
+ if (_a.selectedObject) {
270
+ y += statsHeight + 10;
271
+ const obj = _a.selectedObject;
272
+ const properties = [
273
+ ['Tag', obj.tag],
274
+ ['Pos', `${Math.round(obj.position.x)}, ${Math.round(obj.position.y)}`],
275
+ ['Size', `${Math.round(obj.width)}x${Math.round(obj.height)}`],
276
+ ['Vel', `${Math.round(obj.velocity.x)}, ${Math.round(obj.velocity.y)}`],
277
+ ['Acc', `${Math.round(obj.acceleration.x)}, ${Math.round(obj.acceleration.y)}`],
278
+ ['Z-Index', obj.zIndex]
279
+ ];
280
+ const inspectorHeight = 20 + (properties.length * 15);
281
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillStyle = 'rgba(0, 0, 0, 0.7)';
282
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillRect(x, y, overlayWidth, inspectorHeight);
283
+ __classPrivateFieldGet(this, _Engine_ctx, "f").strokeStyle = '#00ff00';
284
+ __classPrivateFieldGet(this, _Engine_ctx, "f").strokeRect(x, y, overlayWidth, inspectorHeight);
285
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillStyle = '#00ff00';
286
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillText('INSPECTOR', x + 10, y + 5);
287
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillStyle = 'white';
288
+ properties.forEach(([key, val], i) => {
289
+ __classPrivateFieldGet(this, _Engine_ctx, "f").fillText(`${key}: ${val}`, x + 10, y + 20 + (i * 15));
290
+ });
291
+ }
292
+ __classPrivateFieldGet(this, _Engine_ctx, "f").restore();
293
+ }, _Engine_findAllObjects = function _Engine_findAllObjects(tag = '') {
294
+ return Array.from(_a.objects).filter((obj) => obj.tag === tag);
295
+ }, _Engine_getSortedArray = function _Engine_getSortedArray(objects = _a.objects) {
296
+ const arr = Array.from(objects);
297
+ arr.sort((a, b) => (a.zIndex > b.zIndex ? 1 : -1));
298
+ return arr;
299
+ };
300
+ /**
301
+ * Global set of game objects if no scene is active.
302
+ */
303
+ Engine.objects = new ObjectSet();
304
+ /**
305
+ * Whether the game loop is currently paused.
306
+ */
307
+ Engine.paused = false;
308
+ /**
309
+ * Toggle for visual debug mode (hitboxes and stats).
310
+ */
311
+ Engine.debug = false;
312
+ /**
313
+ * The currently selected object in debug mode.
314
+ */
315
+ Engine.selectedObject = null;
316
+ /**
317
+ * The global camera instance.
318
+ */
319
+ Engine.camera = new Camera();
320
+ export default Engine;
321
+ //# sourceMappingURL=Engine.js.map