@nice2dev/game-engine 1.0.2 → 1.0.3

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 (188) hide show
  1. package/dist/cjs/ai/BehaviorTree.js +1215 -0
  2. package/dist/cjs/ai/BehaviorTree.js.map +1 -0
  3. package/dist/cjs/ai/StateMachine.js +783 -0
  4. package/dist/cjs/ai/StateMachine.js.map +1 -0
  5. package/dist/cjs/editor/ShaderGraph.js +1616 -0
  6. package/dist/cjs/editor/ShaderGraph.js.map +1 -0
  7. package/dist/cjs/editor/TimelineEditor.js +819 -0
  8. package/dist/cjs/editor/TimelineEditor.js.map +1 -0
  9. package/dist/cjs/export/GodotExporter.js +1102 -0
  10. package/dist/cjs/export/GodotExporter.js.map +1 -0
  11. package/dist/cjs/export/PlatformExporter.js +236 -0
  12. package/dist/cjs/export/PlatformExporter.js.map +1 -0
  13. package/dist/cjs/export/ThreeJSExporter.js +1116 -0
  14. package/dist/cjs/export/ThreeJSExporter.js.map +1 -0
  15. package/dist/cjs/export/UnityExporter.js +1193 -0
  16. package/dist/cjs/export/UnityExporter.js.map +1 -0
  17. package/dist/cjs/export/WebExporter.js +1036 -0
  18. package/dist/cjs/export/WebExporter.js.map +1 -0
  19. package/dist/cjs/export/index.js +58 -0
  20. package/dist/cjs/export/index.js.map +1 -0
  21. package/dist/cjs/import/AsepriteImporter.js +761 -0
  22. package/dist/cjs/import/AsepriteImporter.js.map +1 -0
  23. package/dist/cjs/import/DragonBonesImporter.js +499 -0
  24. package/dist/cjs/import/DragonBonesImporter.js.map +1 -0
  25. package/dist/cjs/import/GameMakerImporter.js +559 -0
  26. package/dist/cjs/import/GameMakerImporter.js.map +1 -0
  27. package/dist/cjs/import/GodotSceneImporter.js +824 -0
  28. package/dist/cjs/import/GodotSceneImporter.js.map +1 -0
  29. package/dist/cjs/import/LDtkImporter.js +481 -0
  30. package/dist/cjs/import/LDtkImporter.js.map +1 -0
  31. package/dist/cjs/import/Live2DImporter.js +553 -0
  32. package/dist/cjs/import/Live2DImporter.js.map +1 -0
  33. package/dist/cjs/import/NdgFormat.js +499 -0
  34. package/dist/cjs/import/NdgFormat.js.map +1 -0
  35. package/dist/cjs/import/OgmoImporter.js +529 -0
  36. package/dist/cjs/import/OgmoImporter.js.map +1 -0
  37. package/dist/cjs/import/RPGMakerImporter.js +520 -0
  38. package/dist/cjs/import/RPGMakerImporter.js.map +1 -0
  39. package/dist/cjs/import/SceneImporter.js +449 -0
  40. package/dist/cjs/import/SceneImporter.js.map +1 -0
  41. package/dist/cjs/import/SpineImporter.js +583 -0
  42. package/dist/cjs/import/SpineImporter.js.map +1 -0
  43. package/dist/cjs/import/SpriterImporter.js +652 -0
  44. package/dist/cjs/import/SpriterImporter.js.map +1 -0
  45. package/dist/cjs/import/TiledMapImporter.js +859 -0
  46. package/dist/cjs/import/TiledMapImporter.js.map +1 -0
  47. package/dist/cjs/import/UnitySceneImporter.js +732 -0
  48. package/dist/cjs/import/UnitySceneImporter.js.map +1 -0
  49. package/dist/cjs/import/index.js +305 -0
  50. package/dist/cjs/import/index.js.map +1 -0
  51. package/dist/cjs/index.js +201 -0
  52. package/dist/cjs/index.js.map +1 -1
  53. package/dist/cjs/scripting/GraphToAST.js +567 -0
  54. package/dist/cjs/scripting/GraphToAST.js.map +1 -0
  55. package/dist/cjs/scripting/LanguageExporter.js +321 -0
  56. package/dist/cjs/scripting/LanguageExporter.js.map +1 -0
  57. package/dist/cjs/scripting/ScriptAST.js +67 -0
  58. package/dist/cjs/scripting/ScriptAST.js.map +1 -0
  59. package/dist/cjs/scripting/VisualScripting2.js +1140 -0
  60. package/dist/cjs/scripting/VisualScripting2.js.map +1 -0
  61. package/dist/cjs/scripting/exporters/CSharpExporter.js +503 -0
  62. package/dist/cjs/scripting/exporters/CSharpExporter.js.map +1 -0
  63. package/dist/cjs/scripting/exporters/GDScriptExporter.js +452 -0
  64. package/dist/cjs/scripting/exporters/GDScriptExporter.js.map +1 -0
  65. package/dist/cjs/scripting/exporters/LuaExporter.js +457 -0
  66. package/dist/cjs/scripting/exporters/LuaExporter.js.map +1 -0
  67. package/dist/cjs/scripting/exporters/PythonExporter.js +565 -0
  68. package/dist/cjs/scripting/exporters/PythonExporter.js.map +1 -0
  69. package/dist/cjs/scripting/exporters/RustExporter.js +525 -0
  70. package/dist/cjs/scripting/exporters/RustExporter.js.map +1 -0
  71. package/dist/cjs/scripting/exporters/TypeScriptExporter.js +570 -0
  72. package/dist/cjs/scripting/exporters/TypeScriptExporter.js.map +1 -0
  73. package/dist/cjs/systems/ParticleSystem2.js +1478 -0
  74. package/dist/cjs/systems/ParticleSystem2.js.map +1 -0
  75. package/dist/esm/ai/BehaviorTree.js +1186 -0
  76. package/dist/esm/ai/BehaviorTree.js.map +1 -0
  77. package/dist/esm/ai/StateMachine.js +767 -0
  78. package/dist/esm/ai/StateMachine.js.map +1 -0
  79. package/dist/esm/editor/ShaderGraph.js +1606 -0
  80. package/dist/esm/editor/ShaderGraph.js.map +1 -0
  81. package/dist/esm/editor/TimelineEditor.js +800 -0
  82. package/dist/esm/editor/TimelineEditor.js.map +1 -0
  83. package/dist/esm/export/GodotExporter.js +1100 -0
  84. package/dist/esm/export/GodotExporter.js.map +1 -0
  85. package/dist/esm/export/PlatformExporter.js +230 -0
  86. package/dist/esm/export/PlatformExporter.js.map +1 -0
  87. package/dist/esm/export/ThreeJSExporter.js +1114 -0
  88. package/dist/esm/export/ThreeJSExporter.js.map +1 -0
  89. package/dist/esm/export/UnityExporter.js +1191 -0
  90. package/dist/esm/export/UnityExporter.js.map +1 -0
  91. package/dist/esm/export/WebExporter.js +1033 -0
  92. package/dist/esm/export/WebExporter.js.map +1 -0
  93. package/dist/esm/export/index.js +44 -0
  94. package/dist/esm/export/index.js.map +1 -0
  95. package/dist/esm/import/AsepriteImporter.js +759 -0
  96. package/dist/esm/import/AsepriteImporter.js.map +1 -0
  97. package/dist/esm/import/DragonBonesImporter.js +496 -0
  98. package/dist/esm/import/DragonBonesImporter.js.map +1 -0
  99. package/dist/esm/import/GameMakerImporter.js +556 -0
  100. package/dist/esm/import/GameMakerImporter.js.map +1 -0
  101. package/dist/esm/import/GodotSceneImporter.js +822 -0
  102. package/dist/esm/import/GodotSceneImporter.js.map +1 -0
  103. package/dist/esm/import/LDtkImporter.js +479 -0
  104. package/dist/esm/import/LDtkImporter.js.map +1 -0
  105. package/dist/esm/import/Live2DImporter.js +550 -0
  106. package/dist/esm/import/Live2DImporter.js.map +1 -0
  107. package/dist/esm/import/NdgFormat.js +490 -0
  108. package/dist/esm/import/NdgFormat.js.map +1 -0
  109. package/dist/esm/import/OgmoImporter.js +526 -0
  110. package/dist/esm/import/OgmoImporter.js.map +1 -0
  111. package/dist/esm/import/RPGMakerImporter.js +517 -0
  112. package/dist/esm/import/RPGMakerImporter.js.map +1 -0
  113. package/dist/esm/import/SceneImporter.js +441 -0
  114. package/dist/esm/import/SceneImporter.js.map +1 -0
  115. package/dist/esm/import/SpineImporter.js +580 -0
  116. package/dist/esm/import/SpineImporter.js.map +1 -0
  117. package/dist/esm/import/SpriterImporter.js +649 -0
  118. package/dist/esm/import/SpriterImporter.js.map +1 -0
  119. package/dist/esm/import/TiledMapImporter.js +857 -0
  120. package/dist/esm/import/TiledMapImporter.js.map +1 -0
  121. package/dist/esm/import/UnitySceneImporter.js +730 -0
  122. package/dist/esm/import/UnitySceneImporter.js.map +1 -0
  123. package/dist/esm/import/index.js +279 -0
  124. package/dist/esm/import/index.js.map +1 -0
  125. package/dist/esm/index.js +36 -0
  126. package/dist/esm/index.js.map +1 -1
  127. package/dist/esm/scripting/GraphToAST.js +564 -0
  128. package/dist/esm/scripting/GraphToAST.js.map +1 -0
  129. package/dist/esm/scripting/LanguageExporter.js +311 -0
  130. package/dist/esm/scripting/LanguageExporter.js.map +1 -0
  131. package/dist/esm/scripting/ScriptAST.js +52 -0
  132. package/dist/esm/scripting/ScriptAST.js.map +1 -0
  133. package/dist/esm/scripting/VisualScripting2.js +1130 -0
  134. package/dist/esm/scripting/VisualScripting2.js.map +1 -0
  135. package/dist/esm/scripting/exporters/CSharpExporter.js +501 -0
  136. package/dist/esm/scripting/exporters/CSharpExporter.js.map +1 -0
  137. package/dist/esm/scripting/exporters/GDScriptExporter.js +450 -0
  138. package/dist/esm/scripting/exporters/GDScriptExporter.js.map +1 -0
  139. package/dist/esm/scripting/exporters/LuaExporter.js +455 -0
  140. package/dist/esm/scripting/exporters/LuaExporter.js.map +1 -0
  141. package/dist/esm/scripting/exporters/PythonExporter.js +563 -0
  142. package/dist/esm/scripting/exporters/PythonExporter.js.map +1 -0
  143. package/dist/esm/scripting/exporters/RustExporter.js +523 -0
  144. package/dist/esm/scripting/exporters/RustExporter.js.map +1 -0
  145. package/dist/esm/scripting/exporters/TypeScriptExporter.js +568 -0
  146. package/dist/esm/scripting/exporters/TypeScriptExporter.js.map +1 -0
  147. package/dist/esm/systems/ParticleSystem2.js +1471 -0
  148. package/dist/esm/systems/ParticleSystem2.js.map +1 -0
  149. package/dist/types/ai/BehaviorTree.d.ts +375 -0
  150. package/dist/types/ai/StateMachine.d.ts +296 -0
  151. package/dist/types/editor/ShaderGraph.d.ts +207 -0
  152. package/dist/types/editor/TimelineEditor.d.ts +393 -0
  153. package/dist/types/export/GodotExporter.d.ts +56 -0
  154. package/dist/types/export/PlatformExporter.d.ts +201 -0
  155. package/dist/types/export/ThreeJSExporter.d.ts +40 -0
  156. package/dist/types/export/UnityExporter.d.ts +69 -0
  157. package/dist/types/export/WebExporter.d.ts +58 -0
  158. package/dist/types/export/index.d.ts +19 -0
  159. package/dist/types/import/AsepriteImporter.d.ts +46 -0
  160. package/dist/types/import/DragonBonesImporter.d.ts +331 -0
  161. package/dist/types/import/GameMakerImporter.d.ts +375 -0
  162. package/dist/types/import/GodotSceneImporter.d.ts +34 -0
  163. package/dist/types/import/LDtkImporter.d.ts +177 -0
  164. package/dist/types/import/Live2DImporter.d.ts +237 -0
  165. package/dist/types/import/NdgFormat.d.ts +387 -0
  166. package/dist/types/import/OgmoImporter.d.ts +237 -0
  167. package/dist/types/import/RPGMakerImporter.d.ts +186 -0
  168. package/dist/types/import/SceneImporter.d.ts +276 -0
  169. package/dist/types/import/SpineImporter.d.ts +372 -0
  170. package/dist/types/import/SpriterImporter.d.ts +230 -0
  171. package/dist/types/import/TiledMapImporter.d.ts +57 -0
  172. package/dist/types/import/UnitySceneImporter.d.ts +87 -0
  173. package/dist/types/import/index.d.ts +59 -0
  174. package/dist/types/index.d.ts +29 -17
  175. package/dist/types/scripting/GraphToAST.d.ts +55 -0
  176. package/dist/types/scripting/LanguageExporter.d.ts +136 -0
  177. package/dist/types/scripting/ScriptAST.d.ts +312 -0
  178. package/dist/types/scripting/VisualScripting2.d.ts +353 -0
  179. package/dist/types/scripting/exporters/CSharpExporter.d.ts +44 -0
  180. package/dist/types/scripting/exporters/GDScriptExporter.d.ts +46 -0
  181. package/dist/types/scripting/exporters/LuaExporter.d.ts +46 -0
  182. package/dist/types/scripting/exporters/PythonExporter.d.ts +49 -0
  183. package/dist/types/scripting/exporters/RustExporter.d.ts +46 -0
  184. package/dist/types/scripting/exporters/TypeScriptExporter.d.ts +48 -0
  185. package/dist/types/scripting/exporters/index.d.ts +8 -0
  186. package/dist/types/scripting/index.d.ts +11 -0
  187. package/dist/types/systems/ParticleSystem2.d.ts +646 -0
  188. package/package.json +2 -2
@@ -0,0 +1,1033 @@
1
+ import { PlatformExporter } from './PlatformExporter.js';
2
+ import { TypeScriptExporter } from '../scripting/exporters/TypeScriptExporter.js';
3
+ import { GraphToAST } from '../scripting/GraphToAST.js';
4
+
5
+ /* ────────────────────────────────────────────────────────────────
6
+ Web/HTML5 Platform Exporter
7
+
8
+ Base exporter for web-based game engines.
9
+ Generates HTML, JavaScript/TypeScript, and bundled assets.
10
+ ──────────────────────────────────────────────────────────────── */
11
+ /* ── PixiJS Exporter ──────────────────────────────────────────── */
12
+ class PixiJSExporter extends PlatformExporter {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.platformId = 'pixijs';
16
+ this.platformInfo = {
17
+ id: 'pixijs',
18
+ name: 'PixiJS',
19
+ description: 'Fast 2D WebGL renderer',
20
+ website: 'https://pixijs.com',
21
+ features: ['2d-rendering', 'particles', 'animation'],
22
+ supportedAssets: ['sprite', 'tileset', 'audio', 'font', 'script', 'animation'],
23
+ exportFormats: ['.html', '.js', '.ts'],
24
+ };
25
+ this.tsExporter = new TypeScriptExporter();
26
+ this.graphToAST = new GraphToAST();
27
+ }
28
+ async doExport(project, options) {
29
+ const web = options.platformOptions;
30
+ const useTS = (web === null || web === void 0 ? void 0 : web.typescript) !== false;
31
+ const bundler = (web === null || web === void 0 ? void 0 : web.bundler) || 'vite';
32
+ // 1. Generate package.json
33
+ this.exportPackageJson(project, web);
34
+ // 2. Generate HTML entry
35
+ this.exportIndexHtml(project, options, web);
36
+ // 3. Generate main game file
37
+ this.exportMainGame(project, options, useTS);
38
+ // 4. Export scenes
39
+ this.exportScenes(project, options, useTS);
40
+ // 5. Export scripts
41
+ await this.exportScripts(project, options, useTS);
42
+ // 6. Export asset manifest
43
+ this.exportAssetManifest(project);
44
+ // 7. Generate bundler config
45
+ if (bundler !== 'none') {
46
+ this.exportBundlerConfig(project, bundler, useTS);
47
+ }
48
+ // 8. Generate PWA files
49
+ if (web === null || web === void 0 ? void 0 : web.pwa) {
50
+ this.exportPWAFiles(project);
51
+ }
52
+ // 9. Generate utility classes
53
+ this.exportUtilities(project, useTS);
54
+ // 10. Generate tsconfig if TypeScript
55
+ if (useTS) {
56
+ this.exportTSConfig();
57
+ }
58
+ }
59
+ exportPackageJson(project, web) {
60
+ const useTS = (web === null || web === void 0 ? void 0 : web.typescript) !== false;
61
+ const bundler = (web === null || web === void 0 ? void 0 : web.bundler) || 'vite';
62
+ const pixiVersion = (web === null || web === void 0 ? void 0 : web.frameworkVersion) || '^8.0.0';
63
+ const packageJson = {
64
+ name: project.name.toLowerCase().replace(/\s+/g, '-'),
65
+ version: project.version,
66
+ description: project.description || `${project.name} - Built with Nice2Dev`,
67
+ type: 'module',
68
+ scripts: {
69
+ dev: bundler === 'vite'
70
+ ? 'vite'
71
+ : bundler === 'webpack'
72
+ ? 'webpack serve'
73
+ : 'parcel index.html',
74
+ build: bundler === 'vite'
75
+ ? 'vite build'
76
+ : bundler === 'webpack'
77
+ ? 'webpack'
78
+ : 'parcel build index.html',
79
+ preview: bundler === 'vite' ? 'vite preview' : 'serve dist',
80
+ },
81
+ dependencies: {
82
+ pixi: pixiVersion,
83
+ '@pixi/sound': '^5.0.0',
84
+ },
85
+ devDependencies: {
86
+ ...(useTS ? { typescript: '^5.0.0' } : {}),
87
+ ...(bundler === 'vite' ? { vite: '^5.0.0' } : {}),
88
+ ...(bundler === 'webpack'
89
+ ? { webpack: '^5.0.0', 'webpack-cli': '^5.0.0', 'webpack-dev-server': '^4.0.0' }
90
+ : {}),
91
+ ...(bundler === 'parcel' ? { parcel: '^2.0.0' } : {}),
92
+ },
93
+ };
94
+ this.addTextFile('package.json', JSON.stringify(packageJson, null, 2));
95
+ }
96
+ exportIndexHtml(project, options, web) {
97
+ var _a;
98
+ const responsive = (web === null || web === void 0 ? void 0 : web.responsive) !== false;
99
+ const { width, height } = project.settings.resolution;
100
+ const html = `<!DOCTYPE html>
101
+ <html lang="en">
102
+ <head>
103
+ <meta charset="UTF-8">
104
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
105
+ <title>${project.name}</title>
106
+ <style>
107
+ * {
108
+ margin: 0;
109
+ padding: 0;
110
+ box-sizing: border-box;
111
+ }
112
+
113
+ body {
114
+ background-color: ${project.settings.backgroundColor};
115
+ overflow: hidden;
116
+ display: flex;
117
+ justify-content: center;
118
+ align-items: center;
119
+ min-height: 100vh;
120
+ }
121
+
122
+ #game-container {
123
+ ${responsive
124
+ ? `
125
+ width: 100%;
126
+ max-width: ${width}px;
127
+ aspect-ratio: ${width} / ${height};
128
+ `
129
+ : `
130
+ width: ${width}px;
131
+ height: ${height}px;
132
+ `}
133
+ }
134
+
135
+ canvas {
136
+ display: block;
137
+ width: 100%;
138
+ height: 100%;
139
+ ${((_a = project.settings.rendering) === null || _a === void 0 ? void 0 : _a.pixelArt) ? 'image-rendering: pixelated;' : ''}
140
+ }
141
+ </style>
142
+ </head>
143
+ <body>
144
+ <div id="game-container"></div>
145
+ <script type="module" src="/src/main.ts"></script>
146
+ </body>
147
+ </html>
148
+ `;
149
+ this.addTextFile('index.html', html);
150
+ }
151
+ exportMainGame(project, options, useTS) {
152
+ var _a, _b;
153
+ const { width, height } = project.settings.resolution;
154
+ const ext = useTS ? 'ts' : 'js';
155
+ const pixelArt = (_a = project.settings.rendering) === null || _a === void 0 ? void 0 : _a.pixelArt;
156
+ const main = `import { Application, Assets } from 'pixi.js';
157
+ import { sound } from '@pixi/sound';
158
+ import { assetManifest } from './assets/manifest${useTS ? '' : '.js'}';
159
+ import { GameManager } from './game/GameManager${useTS ? '' : '.js'}';
160
+ import { loadScene } from './scenes/index${useTS ? '' : '.js'}';
161
+
162
+ ${useTS
163
+ ? `
164
+ interface GameConfig {
165
+ width: number;
166
+ height: number;
167
+ backgroundColor: number;
168
+ }
169
+ `
170
+ : ''}
171
+
172
+ class Game {
173
+ ${useTS ? 'private app: Application;' : ''}
174
+ ${useTS ? 'private gameManager: GameManager;' : ''}
175
+
176
+ async init()${useTS ? ': Promise<void>' : ''} {
177
+ // Create PixiJS application
178
+ this.app = new Application();
179
+
180
+ await this.app.init({
181
+ width: ${width},
182
+ height: ${height},
183
+ backgroundColor: ${this.hexToNumber(project.settings.backgroundColor)},
184
+ resolution: window.devicePixelRatio || 1,
185
+ autoDensity: true,
186
+ ${pixelArt
187
+ ? `
188
+ roundPixels: true,
189
+ antialias: false,`
190
+ : `
191
+ antialias: true,`}
192
+ });
193
+
194
+ // Add canvas to DOM
195
+ const container = document.getElementById('game-container');
196
+ if (container) {
197
+ container.appendChild(this.app.canvas);
198
+ }
199
+
200
+ // Load assets
201
+ await this.loadAssets();
202
+
203
+ // Initialize game manager
204
+ this.gameManager = new GameManager(this.app);
205
+
206
+ // Load first scene
207
+ await loadScene('${((_b = project.scenes[0]) === null || _b === void 0 ? void 0 : _b.name) || 'main'}', this.app, this.gameManager);
208
+
209
+ // Start game loop
210
+ this.app.ticker.add(this.update.bind(this));
211
+
212
+ console.log('${project.name} initialized!');
213
+ }
214
+
215
+ private async loadAssets()${useTS ? ': Promise<void>' : ''} {
216
+ // Register asset bundles
217
+ await Assets.init({ manifest: assetManifest });
218
+
219
+ // Load all bundles
220
+ const bundles = assetManifest.bundles.map(b => b.name);
221
+ await Assets.loadBundle(bundles);
222
+ }
223
+
224
+ private update(ticker${useTS ? ': { deltaTime: number }' : ''})${useTS ? ': void' : ''} {
225
+ const delta = ticker.deltaTime;
226
+ this.gameManager.update(delta);
227
+ }
228
+ }
229
+
230
+ // Start game
231
+ const game = new Game();
232
+ game.init().catch(console.error);
233
+ `;
234
+ this.addTextFile(`src/main.${ext}`, main);
235
+ }
236
+ exportScenes(project, options, useTS) {
237
+ const ext = useTS ? 'ts' : 'js';
238
+ // Scene index
239
+ let sceneIndex = `import { Application, Container } from 'pixi.js';
240
+ import { GameManager } from '../game/GameManager${useTS ? '' : '.js'}';
241
+
242
+ ${useTS
243
+ ? `
244
+ export interface Scene {
245
+ name: string;
246
+ container: Container;
247
+ init: () => Promise<void>;
248
+ update: (delta: number) => void;
249
+ destroy: () => void;
250
+ }
251
+ `
252
+ : ''}
253
+
254
+ const scenes${useTS ? ': Map<string, () => Promise<Scene>>' : ''} = new Map();
255
+
256
+ `;
257
+ for (const scene of project.scenes) {
258
+ const sceneName = this.sanitizeName(scene.name);
259
+ sceneIndex += `scenes.set('${scene.name}', () => import('./${sceneName}${useTS ? '' : '.js'}').then(m => m.default));\n`;
260
+ }
261
+ sceneIndex += `
262
+ export async function loadScene(
263
+ name${useTS ? ': string' : ''},
264
+ app${useTS ? ': Application' : ''},
265
+ gameManager${useTS ? ': GameManager' : ''}
266
+ )${useTS ? ': Promise<Scene | null>' : ''} {
267
+ const loader = scenes.get(name);
268
+ if (!loader) {
269
+ console.error(\`Scene "\${name}" not found\`);
270
+ return null;
271
+ }
272
+
273
+ const SceneClass = await loader();
274
+ const scene = new SceneClass(app, gameManager);
275
+ await scene.init();
276
+
277
+ app.stage.addChild(scene.container);
278
+ gameManager.setCurrentScene(scene);
279
+
280
+ return scene;
281
+ }
282
+
283
+ export { scenes };
284
+ `;
285
+ this.addTextFile(`src/scenes/index.${ext}`, sceneIndex);
286
+ // Individual scene files
287
+ for (const scene of project.scenes) {
288
+ this.exportScene(scene, project, useTS);
289
+ }
290
+ }
291
+ exportScene(scene, project, useTS) {
292
+ const ext = useTS ? 'ts' : 'js';
293
+ const sceneName = this.sanitizeName(scene.name);
294
+ let content = `import { Application, Container, Sprite, Assets } from 'pixi.js';
295
+ import { GameManager } from '../game/GameManager${useTS ? '' : '.js'}';
296
+ ${useTS ? `import type { Scene } from './index';` : ''}
297
+
298
+ export default class ${sceneName}Scene ${useTS ? 'implements Scene' : ''} {
299
+ ${useTS ? 'public name: string;' : ''}
300
+ ${useTS ? 'public container: Container;' : ''}
301
+ ${useTS ? 'private app: Application;' : ''}
302
+ ${useTS ? 'private gameManager: GameManager;' : ''}
303
+ ${useTS ? 'private entities: Map<string, Container> = new Map();' : ''}
304
+
305
+ constructor(app${useTS ? ': Application' : ''}, gameManager${useTS ? ': GameManager' : ''}) {
306
+ this.name = '${scene.name}';
307
+ this.app = app;
308
+ this.gameManager = gameManager;
309
+ this.container = new Container();
310
+ ${useTS ? '' : 'this.entities = new Map();'}
311
+ }
312
+
313
+ async init()${useTS ? ': Promise<void>' : ''} {
314
+ `;
315
+ // Create entities
316
+ for (const entity of scene.entities) {
317
+ content += this.generateEntityCode(entity, project, useTS);
318
+ }
319
+ content += ` }
320
+
321
+ update(delta${useTS ? ': number' : ''})${useTS ? ': void' : ''} {
322
+ // Update logic for scene
323
+ for (const [id, entity] of this.entities) {
324
+ // Entity update logic
325
+ }
326
+ }
327
+
328
+ destroy()${useTS ? ': void' : ''} {
329
+ this.container.destroy({ children: true });
330
+ this.entities.clear();
331
+ }
332
+ }
333
+ `;
334
+ this.addTextFile(`src/scenes/${sceneName}.${ext}`, content);
335
+ }
336
+ generateEntityCode(entity, project, useTS) {
337
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
338
+ let code = `
339
+ // Entity: ${entity.name}
340
+ {
341
+ const entity = new Container();
342
+ entity.position.set(${(_b = (_a = entity.position) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0}, ${(_d = (_c = entity.position) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0});
343
+ entity.rotation = ${(_e = entity.rotation) !== null && _e !== void 0 ? _e : 0};
344
+ entity.scale.set(${(_g = (_f = entity.scale) === null || _f === void 0 ? void 0 : _f.x) !== null && _g !== void 0 ? _g : 1}, ${(_j = (_h = entity.scale) === null || _h === void 0 ? void 0 : _h.y) !== null && _j !== void 0 ? _j : 1});
345
+ `;
346
+ for (const component of entity.components) {
347
+ switch (component.type) {
348
+ case 'sprite': {
349
+ const spriteId = (_k = component.properties) === null || _k === void 0 ? void 0 : _k.spriteId;
350
+ const asset = project.assets.find((a) => a.id === spriteId);
351
+ if (asset) {
352
+ code += `
353
+ const sprite = Sprite.from('${asset.name}');
354
+ sprite.anchor.set(0.5);
355
+ entity.addChild(sprite);
356
+ `;
357
+ }
358
+ break;
359
+ }
360
+ case 'animated-sprite': {
361
+ code += `
362
+ // Animated sprite would need AnimatedSprite setup
363
+ // const animSprite = new AnimatedSprite(textures);
364
+ `;
365
+ break;
366
+ }
367
+ }
368
+ }
369
+ code += `
370
+ this.container.addChild(entity);
371
+ this.entities.set('${entity.id}', entity);
372
+ }
373
+ `;
374
+ // Process children
375
+ if (entity.children) {
376
+ for (const child of entity.children) {
377
+ code += this.generateEntityCode(child, project, useTS);
378
+ }
379
+ }
380
+ return code;
381
+ }
382
+ async exportScripts(project, options, useTS) {
383
+ for (const script of project.scripts) {
384
+ try {
385
+ const ast = this.graphToAST.convert(script);
386
+ const result = this.tsExporter.export(ast, {
387
+ includeDebugComments: options.debug,
388
+ });
389
+ for (const file of result.files) {
390
+ this.addTextFile(`src/scripts/${file.path}`, file.content);
391
+ }
392
+ }
393
+ catch (error) {
394
+ this.addWarning('SCRIPT_EXPORT_ERROR', `Failed to export script "${script.name}": ${error}`);
395
+ }
396
+ }
397
+ }
398
+ exportAssetManifest(project) {
399
+ const bundles = [];
400
+ // Group assets by type
401
+ const spriteAssets = project.assets.filter((a) => a.type === 'sprite');
402
+ const audioAssets = project.assets.filter((a) => a.type === 'audio');
403
+ const fontAssets = project.assets.filter((a) => a.type === 'font');
404
+ // Sprites bundle
405
+ if (spriteAssets.length > 0) {
406
+ bundles.push({
407
+ name: 'sprites',
408
+ assets: spriteAssets.map((a) => ({
409
+ alias: a.name,
410
+ src: `assets/sprites/${a.path}`,
411
+ })),
412
+ });
413
+ }
414
+ // Audio bundle
415
+ if (audioAssets.length > 0) {
416
+ bundles.push({
417
+ name: 'audio',
418
+ assets: audioAssets.map((a) => ({
419
+ alias: a.name,
420
+ src: `assets/audio/${a.path}`,
421
+ })),
422
+ });
423
+ }
424
+ // Fonts bundle
425
+ if (fontAssets.length > 0) {
426
+ bundles.push({
427
+ name: 'fonts',
428
+ assets: fontAssets.map((a) => ({
429
+ alias: a.name,
430
+ src: `assets/fonts/${a.path}`,
431
+ })),
432
+ });
433
+ }
434
+ const manifest = {
435
+ bundles,
436
+ };
437
+ this.addTextFile('src/assets/manifest.ts', `export const assetManifest = ${JSON.stringify(manifest, null, 2)};`);
438
+ }
439
+ exportBundlerConfig(project, bundler, useTS) {
440
+ switch (bundler) {
441
+ case 'vite':
442
+ this.addTextFile('vite.config.ts', `import { defineConfig } from 'vite';
443
+
444
+ export default defineConfig({
445
+ base: './',
446
+ build: {
447
+ outDir: 'dist',
448
+ assetsDir: 'assets',
449
+ sourcemap: true,
450
+ },
451
+ server: {
452
+ port: 3000,
453
+ open: true,
454
+ },
455
+ });
456
+ `);
457
+ break;
458
+ case 'webpack':
459
+ this.addTextFile('webpack.config.js', `const path = require('path');
460
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
461
+
462
+ module.exports = {
463
+ entry: './src/main.${useTS ? 'ts' : 'js'}',
464
+ output: {
465
+ filename: 'bundle.js',
466
+ path: path.resolve(__dirname, 'dist'),
467
+ },
468
+ resolve: {
469
+ extensions: ['.ts', '.js'],
470
+ },
471
+ module: {
472
+ rules: [
473
+ {
474
+ test: /\\.ts$/,
475
+ use: 'ts-loader',
476
+ exclude: /node_modules/,
477
+ },
478
+ ],
479
+ },
480
+ plugins: [
481
+ new HtmlWebpackPlugin({
482
+ template: 'index.html',
483
+ }),
484
+ ],
485
+ devServer: {
486
+ static: './dist',
487
+ port: 3000,
488
+ open: true,
489
+ },
490
+ };
491
+ `);
492
+ break;
493
+ }
494
+ }
495
+ exportPWAFiles(project) {
496
+ // manifest.json
497
+ const manifest = {
498
+ name: project.name,
499
+ short_name: project.name.slice(0, 12),
500
+ description: project.description || '',
501
+ start_url: '/',
502
+ display: 'fullscreen',
503
+ background_color: project.settings.backgroundColor,
504
+ theme_color: project.settings.backgroundColor,
505
+ icons: [
506
+ { src: 'icon-192.png', sizes: '192x192', type: 'image/png' },
507
+ { src: 'icon-512.png', sizes: '512x512', type: 'image/png' },
508
+ ],
509
+ };
510
+ this.addTextFile('public/manifest.json', JSON.stringify(manifest, null, 2));
511
+ // service-worker.js
512
+ this.addTextFile('public/sw.js', `const CACHE_NAME = '${project.name}-v${project.version}';
513
+ const urlsToCache = [
514
+ '/',
515
+ '/index.html',
516
+ '/src/main.ts',
517
+ ];
518
+
519
+ self.addEventListener('install', (event) => {
520
+ event.waitUntil(
521
+ caches.open(CACHE_NAME)
522
+ .then((cache) => cache.addAll(urlsToCache))
523
+ );
524
+ });
525
+
526
+ self.addEventListener('fetch', (event) => {
527
+ event.respondWith(
528
+ caches.match(event.request)
529
+ .then((response) => response || fetch(event.request))
530
+ );
531
+ });
532
+ `);
533
+ }
534
+ exportUtilities(project, useTS) {
535
+ const ext = useTS ? 'ts' : 'js';
536
+ // GameManager
537
+ const gameManager = `import { Application, Container } from 'pixi.js';
538
+ ${useTS ? `import type { Scene } from '../scenes/index';` : ''}
539
+
540
+ export class GameManager {
541
+ ${useTS ? 'private app: Application;' : ''}
542
+ ${useTS ? 'private currentScene: Scene | null = null;' : ''}
543
+ ${useTS ? 'private entities: Map<string, Container> = new Map();' : ''}
544
+ ${useTS ? 'private isPaused: boolean = false;' : ''}
545
+
546
+ constructor(app${useTS ? ': Application' : ''}) {
547
+ this.app = app;
548
+ ${useTS
549
+ ? ''
550
+ : `
551
+ this.currentScene = null;
552
+ this.entities = new Map();
553
+ this.isPaused = false;`}
554
+ }
555
+
556
+ setCurrentScene(scene${useTS ? ': Scene' : ''})${useTS ? ': void' : ''} {
557
+ if (this.currentScene) {
558
+ this.currentScene.destroy();
559
+ this.app.stage.removeChild(this.currentScene.container);
560
+ }
561
+ this.currentScene = scene;
562
+ }
563
+
564
+ registerEntity(id${useTS ? ': string' : ''}, entity${useTS ? ': Container' : ''})${useTS ? ': void' : ''} {
565
+ this.entities.set(id, entity);
566
+ }
567
+
568
+ getEntity(id${useTS ? ': string' : ''})${useTS ? ': Container | undefined' : ''} {
569
+ return this.entities.get(id);
570
+ }
571
+
572
+ update(delta${useTS ? ': number' : ''})${useTS ? ': void' : ''} {
573
+ if (this.isPaused) return;
574
+
575
+ if (this.currentScene) {
576
+ this.currentScene.update(delta);
577
+ }
578
+ }
579
+
580
+ pause()${useTS ? ': void' : ''} {
581
+ this.isPaused = true;
582
+ }
583
+
584
+ resume()${useTS ? ': void' : ''} {
585
+ this.isPaused = false;
586
+ }
587
+
588
+ get paused()${useTS ? ': boolean' : ''} {
589
+ return this.isPaused;
590
+ }
591
+ }
592
+ `;
593
+ this.addTextFile(`src/game/GameManager.${ext}`, gameManager);
594
+ // Input manager
595
+ const inputManager = `export class InputManager {
596
+ ${useTS ? 'private keys: Set<string> = new Set();' : ''}
597
+ ${useTS ? 'private keysJustPressed: Set<string> = new Set();' : ''}
598
+ ${useTS ? 'private mousePosition: { x: number; y: number } = { x: 0, y: 0 };' : ''}
599
+ ${useTS ? 'private mouseButtons: Set<number> = new Set();' : ''}
600
+
601
+ constructor() {
602
+ ${useTS
603
+ ? ''
604
+ : `
605
+ this.keys = new Set();
606
+ this.keysJustPressed = new Set();
607
+ this.mousePosition = { x: 0, y: 0 };
608
+ this.mouseButtons = new Set();`}
609
+
610
+ window.addEventListener('keydown', this.onKeyDown.bind(this));
611
+ window.addEventListener('keyup', this.onKeyUp.bind(this));
612
+ window.addEventListener('mousemove', this.onMouseMove.bind(this));
613
+ window.addEventListener('mousedown', this.onMouseDown.bind(this));
614
+ window.addEventListener('mouseup', this.onMouseUp.bind(this));
615
+ }
616
+
617
+ private onKeyDown(e${useTS ? ': KeyboardEvent' : ''})${useTS ? ': void' : ''} {
618
+ if (!this.keys.has(e.code)) {
619
+ this.keysJustPressed.add(e.code);
620
+ }
621
+ this.keys.add(e.code);
622
+ }
623
+
624
+ private onKeyUp(e${useTS ? ': KeyboardEvent' : ''})${useTS ? ': void' : ''} {
625
+ this.keys.delete(e.code);
626
+ }
627
+
628
+ private onMouseMove(e${useTS ? ': MouseEvent' : ''})${useTS ? ': void' : ''} {
629
+ this.mousePosition.x = e.clientX;
630
+ this.mousePosition.y = e.clientY;
631
+ }
632
+
633
+ private onMouseDown(e${useTS ? ': MouseEvent' : ''})${useTS ? ': void' : ''} {
634
+ this.mouseButtons.add(e.button);
635
+ }
636
+
637
+ private onMouseUp(e${useTS ? ': MouseEvent' : ''})${useTS ? ': void' : ''} {
638
+ this.mouseButtons.delete(e.button);
639
+ }
640
+
641
+ isKeyPressed(code${useTS ? ': string' : ''})${useTS ? ': boolean' : ''} {
642
+ return this.keys.has(code);
643
+ }
644
+
645
+ isKeyJustPressed(code${useTS ? ': string' : ''})${useTS ? ': boolean' : ''} {
646
+ const pressed = this.keysJustPressed.has(code);
647
+ this.keysJustPressed.delete(code);
648
+ return pressed;
649
+ }
650
+
651
+ isMouseButtonPressed(button${useTS ? ': number' : ''})${useTS ? ': boolean' : ''} {
652
+ return this.mouseButtons.has(button);
653
+ }
654
+
655
+ getMousePosition()${useTS ? ': { x: number; y: number }' : ''} {
656
+ return { ...this.mousePosition };
657
+ }
658
+
659
+ update()${useTS ? ': void' : ''} {
660
+ this.keysJustPressed.clear();
661
+ }
662
+ }
663
+
664
+ export const input = new InputManager();
665
+ `;
666
+ this.addTextFile(`src/game/InputManager.${ext}`, inputManager);
667
+ }
668
+ exportTSConfig() {
669
+ const tsconfig = {
670
+ compilerOptions: {
671
+ target: 'ES2020',
672
+ useDefineForClassFields: true,
673
+ module: 'ESNext',
674
+ lib: ['ES2020', 'DOM', 'DOM.Iterable'],
675
+ skipLibCheck: true,
676
+ moduleResolution: 'bundler',
677
+ allowImportingTsExtensions: true,
678
+ resolveJsonModule: true,
679
+ isolatedModules: true,
680
+ noEmit: true,
681
+ strict: true,
682
+ noUnusedLocals: true,
683
+ noUnusedParameters: true,
684
+ noFallthroughCasesInSwitch: true,
685
+ },
686
+ include: ['src'],
687
+ };
688
+ this.addTextFile('tsconfig.json', JSON.stringify(tsconfig, null, 2));
689
+ }
690
+ hexToNumber(hex) {
691
+ return parseInt(hex.replace('#', ''), 16);
692
+ }
693
+ sanitizeName(name) {
694
+ return name.replace(/[^a-zA-Z0-9]/g, '');
695
+ }
696
+ }
697
+ /* ── Phaser Exporter ──────────────────────────────────────────── */
698
+ class PhaserExporter extends PlatformExporter {
699
+ constructor() {
700
+ super(...arguments);
701
+ this.platformId = 'phaser';
702
+ this.platformInfo = {
703
+ id: 'phaser',
704
+ name: 'Phaser',
705
+ description: 'Desktop and mobile HTML5 game framework',
706
+ website: 'https://phaser.io',
707
+ features: ['2d-rendering', 'physics-2d', 'audio', 'tilemaps', 'particles', 'animation'],
708
+ supportedAssets: ['sprite', 'tileset', 'audio', 'font', 'script', 'animation', 'tilemap'],
709
+ exportFormats: ['.html', '.js', '.ts'],
710
+ };
711
+ this.tsExporter = new TypeScriptExporter();
712
+ this.graphToAST = new GraphToAST();
713
+ }
714
+ async doExport(project, options) {
715
+ const web = options.platformOptions;
716
+ const useTS = (web === null || web === void 0 ? void 0 : web.typescript) !== false;
717
+ const bundler = (web === null || web === void 0 ? void 0 : web.bundler) || 'vite';
718
+ // 1. Generate package.json
719
+ this.exportPackageJson(project, web);
720
+ // 2. Generate HTML entry
721
+ this.exportIndexHtml(project);
722
+ // 3. Generate main game config
723
+ this.exportMainGame(project, options, useTS);
724
+ // 4. Export scenes
725
+ this.exportScenes(project, options, useTS);
726
+ // 5. Export scripts
727
+ await this.exportScripts(project, options, useTS);
728
+ // 6. Generate bundler config
729
+ if (bundler !== 'none') {
730
+ this.exportBundlerConfig(bundler, useTS);
731
+ }
732
+ // 7. Generate tsconfig if TypeScript
733
+ if (useTS) {
734
+ this.exportTSConfig();
735
+ }
736
+ }
737
+ exportPackageJson(project, web) {
738
+ const useTS = (web === null || web === void 0 ? void 0 : web.typescript) !== false;
739
+ const bundler = (web === null || web === void 0 ? void 0 : web.bundler) || 'vite';
740
+ const phaserVersion = (web === null || web === void 0 ? void 0 : web.frameworkVersion) || '^3.70.0';
741
+ const packageJson = {
742
+ name: project.name.toLowerCase().replace(/\s+/g, '-'),
743
+ version: project.version,
744
+ type: 'module',
745
+ scripts: {
746
+ dev: bundler === 'vite' ? 'vite' : 'webpack serve',
747
+ build: bundler === 'vite' ? 'vite build' : 'webpack',
748
+ },
749
+ dependencies: {
750
+ phaser: phaserVersion,
751
+ },
752
+ devDependencies: {
753
+ ...(useTS ? { typescript: '^5.0.0' } : {}),
754
+ ...(bundler === 'vite' ? { vite: '^5.0.0' } : {}),
755
+ },
756
+ };
757
+ this.addTextFile('package.json', JSON.stringify(packageJson, null, 2));
758
+ }
759
+ exportIndexHtml(project) {
760
+ var _a;
761
+ const html = `<!DOCTYPE html>
762
+ <html lang="en">
763
+ <head>
764
+ <meta charset="UTF-8">
765
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
766
+ <title>${project.name}</title>
767
+ <style>
768
+ * { margin: 0; padding: 0; }
769
+ body {
770
+ background: ${project.settings.backgroundColor};
771
+ display: flex;
772
+ justify-content: center;
773
+ align-items: center;
774
+ min-height: 100vh;
775
+ }
776
+ canvas {
777
+ ${((_a = project.settings.rendering) === null || _a === void 0 ? void 0 : _a.pixelArt) ? 'image-rendering: pixelated;' : ''}
778
+ }
779
+ </style>
780
+ </head>
781
+ <body>
782
+ <script type="module" src="/src/main.ts"></script>
783
+ </body>
784
+ </html>`;
785
+ this.addTextFile('index.html', html);
786
+ }
787
+ exportMainGame(project, options, useTS) {
788
+ var _a, _b, _c, _d, _e, _f;
789
+ const ext = useTS ? 'ts' : 'js';
790
+ const { width, height } = project.settings.resolution;
791
+ const pixelArt = (_a = project.settings.rendering) === null || _a === void 0 ? void 0 : _a.pixelArt;
792
+ const hasPhysics = (_b = project.settings.physics) === null || _b === void 0 ? void 0 : _b.enabled;
793
+ let sceneImports = '';
794
+ let sceneList = '';
795
+ for (const scene of project.scenes) {
796
+ const sceneName = this.sanitizeName(scene.name);
797
+ sceneImports += `import { ${sceneName}Scene } from './scenes/${sceneName}${useTS ? '' : '.js'}';\n`;
798
+ sceneList += `${sceneName}Scene, `;
799
+ }
800
+ const main = `import Phaser from 'phaser';
801
+ ${sceneImports}
802
+
803
+ const config${useTS ? ': Phaser.Types.Core.GameConfig' : ''} = {
804
+ type: Phaser.AUTO,
805
+ width: ${width},
806
+ height: ${height},
807
+ backgroundColor: '${project.settings.backgroundColor}',
808
+ parent: 'game-container',
809
+ ${pixelArt
810
+ ? `
811
+ pixelArt: true,
812
+ roundPixels: true,`
813
+ : ''}
814
+ ${hasPhysics
815
+ ? `
816
+ physics: {
817
+ default: 'arcade',
818
+ arcade: {
819
+ gravity: { x: ${(_d = (_c = project.settings.physics) === null || _c === void 0 ? void 0 : _c.gravity.x) !== null && _d !== void 0 ? _d : 0}, y: ${(_f = (_e = project.settings.physics) === null || _e === void 0 ? void 0 : _e.gravity.y) !== null && _f !== void 0 ? _f : 300} },
820
+ debug: ${options.debug || false}
821
+ }
822
+ },`
823
+ : ''}
824
+ scene: [${sceneList}],
825
+ scale: {
826
+ mode: Phaser.Scale.FIT,
827
+ autoCenter: Phaser.Scale.CENTER_BOTH,
828
+ },
829
+ };
830
+
831
+ const game = new Phaser.Game(config);
832
+ `;
833
+ this.addTextFile(`src/main.${ext}`, main);
834
+ }
835
+ exportScenes(project, options, useTS) {
836
+ for (const scene of project.scenes) {
837
+ this.exportScene(scene, project, useTS);
838
+ }
839
+ }
840
+ exportScene(scene, project, useTS) {
841
+ var _a;
842
+ const ext = useTS ? 'ts' : 'js';
843
+ const sceneName = this.sanitizeName(scene.name);
844
+ let content = `import Phaser from 'phaser';
845
+
846
+ export class ${sceneName}Scene extends Phaser.Scene {
847
+ constructor() {
848
+ super({ key: '${scene.name}' });
849
+ }
850
+
851
+ preload()${useTS ? ': void' : ''} {
852
+ `;
853
+ // Preload assets used in this scene
854
+ const usedAssets = this.getUsedAssets(scene, project);
855
+ for (const asset of usedAssets) {
856
+ switch (asset.type) {
857
+ case 'sprite':
858
+ content += ` this.load.image('${asset.name}', 'assets/sprites/${asset.path}');\n`;
859
+ break;
860
+ case 'audio':
861
+ content += ` this.load.audio('${asset.name}', 'assets/audio/${asset.path}');\n`;
862
+ break;
863
+ case 'tileset':
864
+ content += ` this.load.image('${asset.name}', 'assets/tilesets/${asset.path}');\n`;
865
+ break;
866
+ }
867
+ }
868
+ content += ` }
869
+
870
+ create()${useTS ? ': void' : ''} {
871
+ `;
872
+ // Create entities
873
+ for (const entity of scene.entities) {
874
+ content += this.generateEntityCode(entity, project, useTS);
875
+ }
876
+ // Create tilemaps
877
+ for (const tilemap of (_a = scene.tilemaps) !== null && _a !== void 0 ? _a : []) {
878
+ content += this.generateTilemapCode(tilemap, project);
879
+ }
880
+ content += ` }
881
+
882
+ update(time${useTS ? ': number' : ''}, delta${useTS ? ': number' : ''})${useTS ? ': void' : ''} {
883
+ // Update logic
884
+ }
885
+ }
886
+ `;
887
+ this.addTextFile(`src/scenes/${sceneName}.${ext}`, content);
888
+ }
889
+ generateEntityCode(entity, project, useTS) {
890
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4;
891
+ let code = `
892
+ // Entity: ${entity.name}
893
+ `;
894
+ for (const component of entity.components) {
895
+ switch (component.type) {
896
+ case 'sprite': {
897
+ const spriteId = (_a = component.properties) === null || _a === void 0 ? void 0 : _a.spriteId;
898
+ const asset = project.assets.find((a) => a.id === spriteId);
899
+ if (asset) {
900
+ const hasPhysics = entity.components.some((c) => c.type === 'rigidbody-2d' ||
901
+ c.type === 'box-collider-2d' ||
902
+ c.type === 'circle-collider-2d');
903
+ if (hasPhysics) {
904
+ code += ` const ${this.varName(entity.name)} = this.physics.add.sprite(${(_c = (_b = entity.position) === null || _b === void 0 ? void 0 : _b.x) !== null && _c !== void 0 ? _c : 0}, ${(_e = (_d = entity.position) === null || _d === void 0 ? void 0 : _d.y) !== null && _e !== void 0 ? _e : 0}, '${asset.name}');\n`;
905
+ }
906
+ else {
907
+ code += ` const ${this.varName(entity.name)} = this.add.sprite(${(_g = (_f = entity.position) === null || _f === void 0 ? void 0 : _f.x) !== null && _g !== void 0 ? _g : 0}, ${(_j = (_h = entity.position) === null || _h === void 0 ? void 0 : _h.y) !== null && _j !== void 0 ? _j : 0}, '${asset.name}');\n`;
908
+ }
909
+ code += ` ${this.varName(entity.name)}.setScale(${(_l = (_k = entity.scale) === null || _k === void 0 ? void 0 : _k.x) !== null && _l !== void 0 ? _l : 1}, ${(_o = (_m = entity.scale) === null || _m === void 0 ? void 0 : _m.y) !== null && _o !== void 0 ? _o : 1});\n`;
910
+ code += ` ${this.varName(entity.name)}.setRotation(${(_p = entity.rotation) !== null && _p !== void 0 ? _p : 0});\n`;
911
+ }
912
+ break;
913
+ }
914
+ case 'ui-text': {
915
+ code += ` const ${this.varName(entity.name)} = this.add.text(${(_r = (_q = entity.position) === null || _q === void 0 ? void 0 : _q.x) !== null && _r !== void 0 ? _r : 0}, ${(_t = (_s = entity.position) === null || _s === void 0 ? void 0 : _s.y) !== null && _t !== void 0 ? _t : 0}, '${((_u = component.properties) === null || _u === void 0 ? void 0 : _u.text) || ''}', {
916
+ fontSize: '${((_v = component.properties) === null || _v === void 0 ? void 0 : _v.fontSize) || 32}px',
917
+ color: '${((_w = component.properties) === null || _w === void 0 ? void 0 : _w.color) || '#ffffff'}',
918
+ });\n`;
919
+ break;
920
+ }
921
+ case 'particle-system': {
922
+ code += ` const ${this.varName(entity.name)}Particles = this.add.particles(${(_y = (_x = entity.position) === null || _x === void 0 ? void 0 : _x.x) !== null && _y !== void 0 ? _y : 0}, ${(_0 = (_z = entity.position) === null || _z === void 0 ? void 0 : _z.y) !== null && _0 !== void 0 ? _0 : 0});\n`;
923
+ break;
924
+ }
925
+ case 'audio-source': {
926
+ const clipId = (_1 = component.properties) === null || _1 === void 0 ? void 0 : _1.clipId;
927
+ const clip = project.assets.find((a) => a.id === clipId);
928
+ if (clip && ((_2 = component.properties) === null || _2 === void 0 ? void 0 : _2.playOnAwake)) {
929
+ code += ` this.sound.play('${clip.name}', { loop: ${((_3 = component.properties) === null || _3 === void 0 ? void 0 : _3.loop) || false}, volume: ${((_4 = component.properties) === null || _4 === void 0 ? void 0 : _4.volume) || 1} });\n`;
930
+ }
931
+ break;
932
+ }
933
+ }
934
+ }
935
+ // Process children
936
+ if (entity.children) {
937
+ for (const child of entity.children) {
938
+ code += this.generateEntityCode(child, project, useTS);
939
+ }
940
+ }
941
+ return code;
942
+ }
943
+ generateTilemapCode(tilemap, project) {
944
+ const tilesetAsset = project.assets.find((a) => a.id === tilemap.tilesetId);
945
+ if (!tilesetAsset)
946
+ return '';
947
+ return `
948
+ // Tilemap: ${tilemap.name}
949
+ const ${this.varName(tilemap.name)}Map = this.make.tilemap({
950
+ width: ${tilemap.width},
951
+ height: ${tilemap.height},
952
+ tileWidth: ${tilemap.tileSize},
953
+ tileHeight: ${tilemap.tileSize}
954
+ });
955
+ const ${this.varName(tilemap.name)}Tileset = ${this.varName(tilemap.name)}Map.addTilesetImage('${tilesetAsset.name}');
956
+ `;
957
+ }
958
+ getUsedAssets(scene, project) {
959
+ var _a;
960
+ const assetIds = new Set();
961
+ const collectFromEntity = (entity) => {
962
+ var _a, _b;
963
+ for (const component of entity.components) {
964
+ if ((_a = component.properties) === null || _a === void 0 ? void 0 : _a.spriteId) {
965
+ assetIds.add(component.properties.spriteId);
966
+ }
967
+ if ((_b = component.properties) === null || _b === void 0 ? void 0 : _b.clipId) {
968
+ assetIds.add(component.properties.clipId);
969
+ }
970
+ }
971
+ if (entity.children) {
972
+ entity.children.forEach(collectFromEntity);
973
+ }
974
+ };
975
+ scene.entities.forEach(collectFromEntity);
976
+ ((_a = scene.tilemaps) !== null && _a !== void 0 ? _a : []).forEach((tm) => assetIds.add(tm.tilesetId));
977
+ return project.assets.filter((a) => assetIds.has(a.id));
978
+ }
979
+ async exportScripts(project, options, useTS) {
980
+ for (const script of project.scripts) {
981
+ try {
982
+ const ast = this.graphToAST.convert(script);
983
+ const result = this.tsExporter.export(ast, {
984
+ includeDebugComments: options.debug,
985
+ });
986
+ for (const file of result.files) {
987
+ this.addTextFile(`src/scripts/${file.path}`, file.content);
988
+ }
989
+ }
990
+ catch (error) {
991
+ this.addWarning('SCRIPT_EXPORT_ERROR', `Failed to export script "${script.name}": ${error}`);
992
+ }
993
+ }
994
+ }
995
+ exportBundlerConfig(bundler, useTS) {
996
+ if (bundler === 'vite') {
997
+ this.addTextFile('vite.config.ts', `import { defineConfig } from 'vite';
998
+
999
+ export default defineConfig({
1000
+ base: './',
1001
+ build: {
1002
+ outDir: 'dist',
1003
+ },
1004
+ });
1005
+ `);
1006
+ }
1007
+ }
1008
+ exportTSConfig() {
1009
+ const tsconfig = {
1010
+ compilerOptions: {
1011
+ target: 'ES2020',
1012
+ module: 'ESNext',
1013
+ moduleResolution: 'bundler',
1014
+ strict: true,
1015
+ noEmit: true,
1016
+ skipLibCheck: true,
1017
+ lib: ['ES2020', 'DOM'],
1018
+ },
1019
+ include: ['src'],
1020
+ };
1021
+ this.addTextFile('tsconfig.json', JSON.stringify(tsconfig, null, 2));
1022
+ }
1023
+ sanitizeName(name) {
1024
+ return name.replace(/[^a-zA-Z0-9]/g, '');
1025
+ }
1026
+ varName(name) {
1027
+ const sanitized = this.sanitizeName(name);
1028
+ return sanitized.charAt(0).toLowerCase() + sanitized.slice(1);
1029
+ }
1030
+ }
1031
+
1032
+ export { PhaserExporter, PixiJSExporter };
1033
+ //# sourceMappingURL=WebExporter.js.map