@nice2dev/game-engine 1.0.2 → 1.0.4

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