@nice2dev/game-engine 1.3.15 → 1.3.16

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 (434) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/cjs/accessibility/Accessibility.js +152 -165
  3. package/dist/cjs/ai/AI.js +292 -294
  4. package/dist/cjs/ai/BehaviorTree.js +1029 -1113
  5. package/dist/cjs/ai/StateMachine.js +694 -756
  6. package/dist/cjs/animation/Animation.js +232 -241
  7. package/dist/cjs/audio/AudioAdvanced.js +221 -236
  8. package/dist/cjs/audio/AudioBridge.js +441 -435
  9. package/dist/cjs/audio/AudioManager.js +242 -259
  10. package/dist/cjs/build-cloud/BuildOrchestration.js +1059 -1098
  11. package/dist/cjs/build-cloud/GodotBuildCloud.js +641 -670
  12. package/dist/cjs/build-cloud/UnityBuildCloud.js +563 -610
  13. package/dist/cjs/build-cloud/UnrealBuildCloud.js +610 -635
  14. package/dist/cjs/core/EventBus.js +51 -56
  15. package/dist/cjs/core/GameClock.js +62 -66
  16. package/dist/cjs/core/GameConfig.js +72 -79
  17. package/dist/cjs/core/GameLoop.js +80 -89
  18. package/dist/cjs/core/ServiceLocator.js +61 -65
  19. package/dist/cjs/core/Validation.js +72 -82
  20. package/dist/cjs/core/math.js +108 -112
  21. package/dist/cjs/devtools/DevTools.js +542 -563
  22. package/dist/cjs/devtools/DeveloperExperience.js +521 -559
  23. package/dist/cjs/devtools/GameplayAnalytics.js +636 -646
  24. package/dist/cjs/dialogue/DialogueSystem.js +984 -986
  25. package/dist/cjs/docs/DocGenerator.js +339 -364
  26. package/dist/cjs/ecs/World.js +355 -371
  27. package/dist/cjs/editor/AchievementEditor.js +580 -636
  28. package/dist/cjs/editor/AdvancedEditor.js +184 -191
  29. package/dist/cjs/editor/AnimationRetargeting.js +696 -741
  30. package/dist/cjs/editor/AssetBrowser.js +1072 -1160
  31. package/dist/cjs/editor/AssetManager.js +187 -192
  32. package/dist/cjs/editor/ConsolePro.js +971 -1061
  33. package/dist/cjs/editor/CraftingEditor.js +680 -730
  34. package/dist/cjs/editor/DebugTools.js +187 -185
  35. package/dist/cjs/editor/DialogueSystem.js +844 -901
  36. package/dist/cjs/editor/LeaderboardSystem.js +429 -483
  37. package/dist/cjs/editor/NiceGameEditor.js +1903 -1201
  38. package/dist/cjs/editor/PrefabSystem.js +772 -838
  39. package/dist/cjs/editor/ProfilerPanel.js +649 -700
  40. package/dist/cjs/editor/QuestEditor.js +792 -839
  41. package/dist/cjs/editor/ReplaySystem.js +585 -634
  42. package/dist/cjs/editor/SceneEditor.js +176 -200
  43. package/dist/cjs/editor/ScreenshotMode.js +621 -688
  44. package/dist/cjs/editor/ShaderGraph.js +1556 -1582
  45. package/dist/cjs/editor/TimelineEditor.js +715 -778
  46. package/dist/cjs/editor/UndoRedoPro.js +830 -904
  47. package/dist/cjs/editor/VRARMode.js +582 -645
  48. package/dist/cjs/engine/NiceGameEngine.js +141 -164
  49. package/dist/cjs/engine/SaveSystem.js +441 -495
  50. package/dist/cjs/enterprise/Enterprise.js +254 -261
  51. package/dist/cjs/export/BevyExporter.js +927 -967
  52. package/dist/cjs/export/CocosExporter.js +644 -673
  53. package/dist/cjs/export/Construct3Exporter.js +783 -794
  54. package/dist/cjs/export/DefoldExporter.js +1028 -1069
  55. package/dist/cjs/export/GDevelopExporter.js +674 -708
  56. package/dist/cjs/export/GameMakerExporter.js +791 -805
  57. package/dist/cjs/export/GodotExporter.js +1003 -1045
  58. package/dist/cjs/export/MinecraftBedrockExporter.js +573 -578
  59. package/dist/cjs/export/MonoGameExporter.js +1265 -1293
  60. package/dist/cjs/export/Pico8Exporter.js +766 -812
  61. package/dist/cjs/export/PlatformExporter.js +188 -206
  62. package/dist/cjs/export/RPGMakerExporter.js +860 -879
  63. package/dist/cjs/export/RobloxExporter.js +883 -919
  64. package/dist/cjs/export/Solar2DExporter.js +1218 -1256
  65. package/dist/cjs/export/ThreeJSExporter.js +1006 -1073
  66. package/dist/cjs/export/Tic80Exporter.js +1210 -1267
  67. package/dist/cjs/export/UnityExporter.js +1116 -1131
  68. package/dist/cjs/export/UnrealExporter.js +889 -919
  69. package/dist/cjs/export/WebExporter.js +931 -970
  70. package/dist/cjs/export/index.js +42 -65
  71. package/dist/cjs/godot-integration/GodotAssetLibrary.js +659 -692
  72. package/dist/cjs/godot-integration/GodotImport.js +929 -1027
  73. package/dist/cjs/godot-integration/GodotLiveLink.js +915 -945
  74. package/dist/cjs/godot-integration/components/GodotProjectBrowser.js +911 -611
  75. package/dist/cjs/i18n/I18n.js +860 -900
  76. package/dist/cjs/i18n/useTranslation.js +84 -89
  77. package/dist/cjs/import/AsepriteImporter.js +658 -716
  78. package/dist/cjs/import/DragonBonesImporter.js +437 -461
  79. package/dist/cjs/import/GameMakerImporter.js +511 -521
  80. package/dist/cjs/import/GodotSceneImporter.js +788 -822
  81. package/dist/cjs/import/LDtkImporter.js +436 -454
  82. package/dist/cjs/import/Live2DImporter.js +497 -518
  83. package/dist/cjs/import/NdgFormat.js +424 -457
  84. package/dist/cjs/import/OgmoImporter.js +466 -493
  85. package/dist/cjs/import/RPGMakerImporter.js +451 -477
  86. package/dist/cjs/import/SceneImporter.js +378 -423
  87. package/dist/cjs/import/SpineImporter.js +511 -546
  88. package/dist/cjs/import/SpriterImporter.js +590 -613
  89. package/dist/cjs/import/TiledMapImporter.js +811 -846
  90. package/dist/cjs/import/UnitySceneImporter.js +687 -703
  91. package/dist/cjs/import/index.js +206 -251
  92. package/dist/cjs/index.js +275 -278
  93. package/dist/cjs/input/GamepadNavigation.js +185 -205
  94. package/dist/cjs/input/InputManager.js +397 -421
  95. package/dist/cjs/input/useGamepads.js +70 -81
  96. package/dist/cjs/integration/IconSprite.js +129 -256
  97. package/dist/cjs/inventory/InventorySystem.js +920 -995
  98. package/dist/cjs/kids/KidMode.js +997 -1022
  99. package/dist/cjs/kids/KidTools.js +570 -594
  100. package/dist/cjs/monetization/Monetization.js +170 -177
  101. package/dist/cjs/multiplayer/LocalMultiplayer.js +287 -287
  102. package/dist/cjs/multiplayer/MiniGameTypes.js +49 -59
  103. package/dist/cjs/native-engine/AnimationSystem.js +731 -806
  104. package/dist/cjs/native-engine/AssetPipeline.js +454 -515
  105. package/dist/cjs/native-engine/AudioEngine.js +763 -804
  106. package/dist/cjs/native-engine/InputSystem.js +1075 -1145
  107. package/dist/cjs/native-engine/NetworkingSystem.js +733 -793
  108. package/dist/cjs/native-engine/PhysicsEngine.js +583 -607
  109. package/dist/cjs/native-engine/RenderingEngine.js +302 -350
  110. package/dist/cjs/native-engine/SceneGraph.js +769 -808
  111. package/dist/cjs/network/MultiplayerTransport.js +97 -132
  112. package/dist/cjs/network/Networking.js +549 -564
  113. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/AbortController.js +21 -29
  114. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/AccessTokenHttpClient.js +40 -48
  115. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/DefaultHttpClient.js +35 -43
  116. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/DefaultReconnectPolicy.js +10 -15
  117. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Errors.js +103 -135
  118. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/FetchHttpClient.js +131 -158
  119. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HandshakeProtocol.js +39 -53
  120. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HeaderNames.js +5 -8
  121. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HttpClient.js +40 -48
  122. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HttpConnection.js +494 -572
  123. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HubConnection.js +826 -953
  124. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/HubConnectionBuilder.js +125 -146
  125. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/IHubProtocol.js +13 -23
  126. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ILogger.js +11 -25
  127. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ITransport.js +13 -24
  128. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/JsonHubProtocol.js +108 -121
  129. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Loggers.js +10 -14
  130. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/LongPollingTransport.js +150 -185
  131. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/MessageBuffer.js +158 -196
  132. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/ServerSentEventsTransport.js +90 -105
  133. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Subject.js +30 -35
  134. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/TextMessageFormat.js +16 -21
  135. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/Utils.js +215 -248
  136. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/WebSocketTransport.js +135 -157
  137. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/XhrHttpClient.js +76 -85
  138. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/index.js +24 -27
  139. package/dist/cjs/node_modules/@microsoft/signalr/dist/esm/pkg-version.js +3 -4
  140. package/dist/cjs/pathfinding/Pathfinding.js +245 -263
  141. package/dist/cjs/performance/AssetStreaming.js +561 -635
  142. package/dist/cjs/performance/BenchmarkSuite.js +283 -311
  143. package/dist/cjs/performance/DeltaCompression.js +467 -526
  144. package/dist/cjs/performance/DeterministicPhysics.js +450 -498
  145. package/dist/cjs/performance/ECSOptimization.js +644 -695
  146. package/dist/cjs/performance/GameSaveSystem.js +509 -556
  147. package/dist/cjs/performance/HotReload.js +447 -500
  148. package/dist/cjs/performance/InputRecording.js +511 -561
  149. package/dist/cjs/performance/InterestManagement.js +453 -500
  150. package/dist/cjs/performance/LocalizationRuntime.js +376 -423
  151. package/dist/cjs/performance/MemoryManagement.js +410 -470
  152. package/dist/cjs/performance/ModSupport.js +445 -496
  153. package/dist/cjs/performance/MultiThreadedPhysics.js +400 -443
  154. package/dist/cjs/performance/NetworkPrediction.js +424 -482
  155. package/dist/cjs/performance/ObjectPooling.js +569 -617
  156. package/dist/cjs/performance/Performance.js +174 -190
  157. package/dist/cjs/performance/PerformanceAdvanced.js +614 -637
  158. package/dist/cjs/performance/WebGPURenderer.js +656 -683
  159. package/dist/cjs/physics/PhysicsAdvanced.js +345 -379
  160. package/dist/cjs/physics/PhysicsEngine2D.js +391 -427
  161. package/dist/cjs/plugins/PluginSDK.js +432 -466
  162. package/dist/cjs/plugins/PluginTestKit.js +307 -330
  163. package/dist/cjs/procedural/Procedural.js +243 -254
  164. package/dist/cjs/procedural/WorldBuilding.js +297 -314
  165. package/dist/cjs/quest/QuestSystem.js +975 -932
  166. package/dist/cjs/release/MobileExport.js +157 -163
  167. package/dist/cjs/release/Release.js +225 -238
  168. package/dist/cjs/rendering/Camera2D.js +121 -124
  169. package/dist/cjs/rendering/Renderer2D.js +321 -335
  170. package/dist/cjs/rendering/WebGPURenderPipeline.js +632 -651
  171. package/dist/cjs/runtime3d/Runtime3D.js +359 -378
  172. package/dist/cjs/runtime3d/SceneEditor3D.js +252 -263
  173. package/dist/cjs/scene/SceneManager.js +177 -193
  174. package/dist/cjs/scripting/GraphToAST.js +574 -547
  175. package/dist/cjs/scripting/LanguageExporter.js +254 -279
  176. package/dist/cjs/scripting/NodeGraph.js +546 -570
  177. package/dist/cjs/scripting/ScriptAST.js +31 -39
  178. package/dist/cjs/scripting/VisualScripting2.js +1016 -1065
  179. package/dist/cjs/scripting/exporters/CSharpExporter.js +464 -496
  180. package/dist/cjs/scripting/exporters/GDScriptExporter.js +390 -442
  181. package/dist/cjs/scripting/exporters/LuaExporter.js +406 -447
  182. package/dist/cjs/scripting/exporters/PythonExporter.js +484 -549
  183. package/dist/cjs/scripting/exporters/RustExporter.js +459 -512
  184. package/dist/cjs/scripting/exporters/TypeScriptExporter.js +505 -556
  185. package/dist/cjs/social/Social.js +72 -80
  186. package/dist/cjs/systems/LightingSystem.js +844 -931
  187. package/dist/cjs/systems/ParticleSystem2.js +1447 -1451
  188. package/dist/cjs/systems/PhysicsDebugSystem.js +1070 -1141
  189. package/dist/cjs/systems/TerrainSystem.js +985 -1098
  190. package/dist/cjs/templates/ActionTemplates.js +296 -309
  191. package/dist/cjs/templates/FightingTemplate.js +417 -463
  192. package/dist/cjs/templates/MetroidvaniaTemplate.js +353 -405
  193. package/dist/cjs/templates/PartyTemplates.js +190 -202
  194. package/dist/cjs/templates/PuzzleTemplates.js +245 -261
  195. package/dist/cjs/templates/RPGTemplates.js +160 -178
  196. package/dist/cjs/templates/SportsTemplates.js +237 -250
  197. package/dist/cjs/templates/StrategyTemplates.js +143 -153
  198. package/dist/cjs/templates/SurvivalTemplate.js +336 -380
  199. package/dist/cjs/templates/WaveDefense.js +499 -526
  200. package/dist/cjs/tilemap/Tilemap.js +207 -214
  201. package/dist/cjs/tutorials/TutorialBranching.js +396 -417
  202. package/dist/cjs/tutorials/TutorialEngine.js +888 -931
  203. package/dist/cjs/tutorials/TutorialOverlay.js +602 -640
  204. package/dist/cjs/tutorials/content/Tutorials_T05_T08.js +787 -809
  205. package/dist/cjs/tutorials/content/Tutorials_T09_T11.js +736 -756
  206. package/dist/cjs/tutorials/content/Tutorials_T12_T15.js +754 -778
  207. package/dist/cjs/ui/GameUI.js +295 -312
  208. package/dist/cjs/unity-integration/UnityAssetStore.js +700 -741
  209. package/dist/cjs/unity-integration/UnityImport.js +1066 -1176
  210. package/dist/cjs/unity-integration/UnityLiveLink.js +934 -981
  211. package/dist/cjs/unity-integration/components/UnityAssetStoreBrowser.js +1233 -757
  212. package/dist/cjs/unity-integration/components/UnityProjectBrowser.js +1240 -768
  213. package/dist/cjs/unreal-integration/UnrealImport.js +391 -412
  214. package/dist/cjs/unreal-integration/UnrealLiveLink.js +1102 -1137
  215. package/dist/cjs/unreal-integration/UnrealMarketplace.js +436 -473
  216. package/dist/cjs/unreal-integration/components/UnrealProjectBrowser.js +1150 -767
  217. package/dist/cjs/xr/ARVR.js +167 -175
  218. package/dist/esm/accessibility/Accessibility.js +160 -164
  219. package/dist/esm/ai/AI.js +310 -293
  220. package/dist/esm/ai/BehaviorTree.js +1057 -1112
  221. package/dist/esm/ai/StateMachine.js +709 -755
  222. package/dist/esm/animation/Animation.js +237 -240
  223. package/dist/esm/audio/AudioAdvanced.js +239 -235
  224. package/dist/esm/audio/AudioBridge.js +448 -434
  225. package/dist/esm/audio/AudioManager.js +243 -258
  226. package/dist/esm/build-cloud/BuildOrchestration.js +1071 -1097
  227. package/dist/esm/build-cloud/GodotBuildCloud.js +647 -669
  228. package/dist/esm/build-cloud/UnityBuildCloud.js +571 -609
  229. package/dist/esm/build-cloud/UnrealBuildCloud.js +615 -634
  230. package/dist/esm/core/EventBus.js +52 -55
  231. package/dist/esm/core/GameClock.js +63 -65
  232. package/dist/esm/core/GameConfig.js +77 -78
  233. package/dist/esm/core/GameLoop.js +81 -88
  234. package/dist/esm/core/ServiceLocator.js +63 -64
  235. package/dist/esm/core/Validation.js +82 -81
  236. package/dist/esm/core/math.js +109 -111
  237. package/dist/esm/devtools/DevTools.js +546 -562
  238. package/dist/esm/devtools/DeveloperExperience.js +535 -558
  239. package/dist/esm/devtools/GameplayAnalytics.js +647 -645
  240. package/dist/esm/dialogue/DialogueSystem.js +998 -985
  241. package/dist/esm/docs/DocGenerator.js +342 -363
  242. package/dist/esm/ecs/World.js +358 -370
  243. package/dist/esm/editor/AchievementEditor.js +584 -635
  244. package/dist/esm/editor/AdvancedEditor.js +191 -190
  245. package/dist/esm/editor/AnimationRetargeting.js +700 -740
  246. package/dist/esm/editor/AssetBrowser.js +1078 -1159
  247. package/dist/esm/editor/AssetManager.js +188 -191
  248. package/dist/esm/editor/ConsolePro.js +977 -1060
  249. package/dist/esm/editor/CraftingEditor.js +684 -729
  250. package/dist/esm/editor/DebugTools.js +194 -184
  251. package/dist/esm/editor/DialogueSystem.js +849 -900
  252. package/dist/esm/editor/LeaderboardSystem.js +433 -482
  253. package/dist/esm/editor/NiceGameEditor.js +1908 -1200
  254. package/dist/esm/editor/PrefabSystem.js +777 -837
  255. package/dist/esm/editor/ProfilerPanel.js +654 -699
  256. package/dist/esm/editor/QuestEditor.js +795 -838
  257. package/dist/esm/editor/ReplaySystem.js +591 -633
  258. package/dist/esm/editor/SceneEditor.js +189 -199
  259. package/dist/esm/editor/ScreenshotMode.js +628 -687
  260. package/dist/esm/editor/ShaderGraph.js +1565 -1581
  261. package/dist/esm/editor/TimelineEditor.js +733 -777
  262. package/dist/esm/editor/UndoRedoPro.js +835 -903
  263. package/dist/esm/editor/VRARMode.js +586 -644
  264. package/dist/esm/engine/NiceGameEngine.js +142 -163
  265. package/dist/esm/engine/SaveSystem.js +447 -494
  266. package/dist/esm/enterprise/Enterprise.js +265 -260
  267. package/dist/esm/export/BevyExporter.js +929 -966
  268. package/dist/esm/export/CocosExporter.js +646 -672
  269. package/dist/esm/export/Construct3Exporter.js +785 -793
  270. package/dist/esm/export/DefoldExporter.js +1030 -1068
  271. package/dist/esm/export/GDevelopExporter.js +676 -707
  272. package/dist/esm/export/GameMakerExporter.js +793 -804
  273. package/dist/esm/export/GodotExporter.js +1004 -1044
  274. package/dist/esm/export/MinecraftBedrockExporter.js +575 -577
  275. package/dist/esm/export/MonoGameExporter.js +1267 -1292
  276. package/dist/esm/export/Pico8Exporter.js +768 -811
  277. package/dist/esm/export/PlatformExporter.js +193 -205
  278. package/dist/esm/export/RPGMakerExporter.js +862 -878
  279. package/dist/esm/export/RobloxExporter.js +885 -918
  280. package/dist/esm/export/Solar2DExporter.js +1220 -1255
  281. package/dist/esm/export/ThreeJSExporter.js +1007 -1072
  282. package/dist/esm/export/Tic80Exporter.js +1212 -1266
  283. package/dist/esm/export/UnityExporter.js +1117 -1130
  284. package/dist/esm/export/UnrealExporter.js +891 -918
  285. package/dist/esm/export/WebExporter.js +933 -969
  286. package/dist/esm/export/index.js +86 -71
  287. package/dist/esm/godot-integration/GodotAssetLibrary.js +663 -691
  288. package/dist/esm/godot-integration/GodotImport.js +935 -1026
  289. package/dist/esm/godot-integration/GodotLiveLink.js +918 -944
  290. package/dist/esm/godot-integration/components/GodotProjectBrowser.js +912 -610
  291. package/dist/esm/i18n/I18n.js +871 -899
  292. package/dist/esm/i18n/useTranslation.js +88 -88
  293. package/dist/esm/import/AsepriteImporter.js +637 -715
  294. package/dist/esm/import/DragonBonesImporter.js +417 -460
  295. package/dist/esm/import/GameMakerImporter.js +491 -520
  296. package/dist/esm/import/GodotSceneImporter.js +767 -821
  297. package/dist/esm/import/LDtkImporter.js +415 -453
  298. package/dist/esm/import/Live2DImporter.js +477 -517
  299. package/dist/esm/import/NdgFormat.js +410 -456
  300. package/dist/esm/import/OgmoImporter.js +446 -492
  301. package/dist/esm/import/RPGMakerImporter.js +431 -476
  302. package/dist/esm/import/SceneImporter.js +385 -422
  303. package/dist/esm/import/SpineImporter.js +491 -545
  304. package/dist/esm/import/SpriterImporter.js +570 -612
  305. package/dist/esm/import/TiledMapImporter.js +790 -845
  306. package/dist/esm/import/UnitySceneImporter.js +666 -702
  307. package/dist/esm/import/index.js +247 -258
  308. package/dist/esm/index.js +1332 -188
  309. package/dist/esm/input/GamepadNavigation.js +187 -204
  310. package/dist/esm/input/InputManager.js +401 -420
  311. package/dist/esm/input/useGamepads.js +72 -80
  312. package/dist/esm/integration/IconSprite.js +143 -255
  313. package/dist/esm/inventory/InventorySystem.js +925 -994
  314. package/dist/esm/kids/KidMode.js +1003 -1021
  315. package/dist/esm/kids/KidTools.js +573 -593
  316. package/dist/esm/monetization/Monetization.js +180 -176
  317. package/dist/esm/multiplayer/LocalMultiplayer.js +290 -286
  318. package/dist/esm/multiplayer/MiniGameTypes.js +58 -58
  319. package/dist/esm/native-engine/AnimationSystem.js +735 -805
  320. package/dist/esm/native-engine/AssetPipeline.js +456 -514
  321. package/dist/esm/native-engine/AudioEngine.js +765 -803
  322. package/dist/esm/native-engine/InputSystem.js +1079 -1144
  323. package/dist/esm/native-engine/NetworkingSystem.js +740 -792
  324. package/dist/esm/native-engine/PhysicsEngine.js +585 -606
  325. package/dist/esm/native-engine/RenderingEngine.js +304 -349
  326. package/dist/esm/native-engine/SceneGraph.js +773 -807
  327. package/dist/esm/network/MultiplayerTransport.js +99 -131
  328. package/dist/esm/network/Networking.js +556 -563
  329. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/AbortController.js +22 -28
  330. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/AccessTokenHttpClient.js +41 -47
  331. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/DefaultHttpClient.js +36 -42
  332. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/DefaultReconnectPolicy.js +11 -14
  333. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Errors.js +111 -134
  334. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/FetchHttpClient.js +132 -157
  335. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HandshakeProtocol.js +40 -52
  336. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HeaderNames.js +6 -7
  337. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HttpClient.js +42 -47
  338. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HttpConnection.js +496 -571
  339. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HubConnection.js +828 -952
  340. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/HubConnectionBuilder.js +126 -145
  341. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/IHubProtocol.js +14 -23
  342. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ILogger.js +12 -25
  343. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ITransport.js +15 -24
  344. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/JsonHubProtocol.js +109 -120
  345. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Loggers.js +11 -13
  346. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/LongPollingTransport.js +151 -184
  347. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/MessageBuffer.js +159 -195
  348. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/ServerSentEventsTransport.js +91 -104
  349. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Subject.js +31 -34
  350. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/TextMessageFormat.js +17 -20
  351. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/Utils.js +230 -248
  352. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/WebSocketTransport.js +136 -156
  353. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/XhrHttpClient.js +77 -84
  354. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/index.js +31 -12
  355. package/dist/esm/node_modules/@microsoft/signalr/dist/esm/pkg-version.js +4 -3
  356. package/dist/esm/pathfinding/Pathfinding.js +249 -262
  357. package/dist/esm/performance/AssetStreaming.js +567 -634
  358. package/dist/esm/performance/BenchmarkSuite.js +285 -310
  359. package/dist/esm/performance/DeltaCompression.js +478 -525
  360. package/dist/esm/performance/DeterministicPhysics.js +479 -497
  361. package/dist/esm/performance/ECSOptimization.js +653 -694
  362. package/dist/esm/performance/GameSaveSystem.js +515 -555
  363. package/dist/esm/performance/HotReload.js +454 -499
  364. package/dist/esm/performance/InputRecording.js +520 -560
  365. package/dist/esm/performance/InterestManagement.js +460 -499
  366. package/dist/esm/performance/LocalizationRuntime.js +382 -422
  367. package/dist/esm/performance/MemoryManagement.js +415 -469
  368. package/dist/esm/performance/ModSupport.js +455 -495
  369. package/dist/esm/performance/MultiThreadedPhysics.js +408 -442
  370. package/dist/esm/performance/NetworkPrediction.js +436 -481
  371. package/dist/esm/performance/ObjectPooling.js +582 -616
  372. package/dist/esm/performance/Performance.js +182 -189
  373. package/dist/esm/performance/PerformanceAdvanced.js +621 -636
  374. package/dist/esm/performance/WebGPURenderer.js +660 -682
  375. package/dist/esm/physics/PhysicsAdvanced.js +359 -378
  376. package/dist/esm/physics/PhysicsEngine2D.js +393 -426
  377. package/dist/esm/plugins/PluginSDK.js +435 -465
  378. package/dist/esm/plugins/PluginTestKit.js +315 -329
  379. package/dist/esm/procedural/Procedural.js +248 -253
  380. package/dist/esm/procedural/WorldBuilding.js +316 -313
  381. package/dist/esm/quest/QuestSystem.js +982 -931
  382. package/dist/esm/release/MobileExport.js +163 -162
  383. package/dist/esm/release/Release.js +234 -237
  384. package/dist/esm/rendering/Camera2D.js +122 -123
  385. package/dist/esm/rendering/Renderer2D.js +323 -334
  386. package/dist/esm/rendering/WebGPURenderPipeline.js +647 -650
  387. package/dist/esm/runtime3d/Runtime3D.js +368 -377
  388. package/dist/esm/runtime3d/SceneEditor3D.js +268 -262
  389. package/dist/esm/scene/SceneManager.js +178 -192
  390. package/dist/esm/scripting/GraphToAST.js +576 -546
  391. package/dist/esm/scripting/LanguageExporter.js +263 -278
  392. package/dist/esm/scripting/NodeGraph.js +550 -569
  393. package/dist/esm/scripting/ScriptAST.js +45 -38
  394. package/dist/esm/scripting/VisualScripting2.js +1025 -1064
  395. package/dist/esm/scripting/exporters/CSharpExporter.js +465 -495
  396. package/dist/esm/scripting/exporters/GDScriptExporter.js +391 -441
  397. package/dist/esm/scripting/exporters/LuaExporter.js +407 -446
  398. package/dist/esm/scripting/exporters/PythonExporter.js +485 -548
  399. package/dist/esm/scripting/exporters/RustExporter.js +460 -511
  400. package/dist/esm/scripting/exporters/TypeScriptExporter.js +506 -555
  401. package/dist/esm/social/Social.js +77 -79
  402. package/dist/esm/systems/LightingSystem.js +855 -930
  403. package/dist/esm/systems/ParticleSystem2.js +1453 -1450
  404. package/dist/esm/systems/PhysicsDebugSystem.js +1078 -1140
  405. package/dist/esm/systems/TerrainSystem.js +996 -1097
  406. package/dist/esm/templates/ActionTemplates.js +307 -308
  407. package/dist/esm/templates/FightingTemplate.js +439 -462
  408. package/dist/esm/templates/MetroidvaniaTemplate.js +391 -404
  409. package/dist/esm/templates/PartyTemplates.js +206 -201
  410. package/dist/esm/templates/PuzzleTemplates.js +260 -260
  411. package/dist/esm/templates/RPGTemplates.js +172 -177
  412. package/dist/esm/templates/SportsTemplates.js +251 -249
  413. package/dist/esm/templates/StrategyTemplates.js +158 -152
  414. package/dist/esm/templates/SurvivalTemplate.js +367 -379
  415. package/dist/esm/templates/WaveDefense.js +501 -525
  416. package/dist/esm/tilemap/Tilemap.js +209 -213
  417. package/dist/esm/tutorials/TutorialBranching.js +399 -416
  418. package/dist/esm/tutorials/TutorialEngine.js +893 -930
  419. package/dist/esm/tutorials/TutorialOverlay.js +603 -639
  420. package/dist/esm/tutorials/content/Tutorials_T05_T08.js +792 -808
  421. package/dist/esm/tutorials/content/Tutorials_T09_T11.js +740 -755
  422. package/dist/esm/tutorials/content/Tutorials_T12_T15.js +759 -777
  423. package/dist/esm/ui/GameUI.js +296 -311
  424. package/dist/esm/unity-integration/UnityAssetStore.js +704 -740
  425. package/dist/esm/unity-integration/UnityImport.js +1071 -1175
  426. package/dist/esm/unity-integration/UnityLiveLink.js +938 -980
  427. package/dist/esm/unity-integration/components/UnityAssetStoreBrowser.js +1234 -756
  428. package/dist/esm/unity-integration/components/UnityProjectBrowser.js +1241 -767
  429. package/dist/esm/unreal-integration/UnrealImport.js +395 -411
  430. package/dist/esm/unreal-integration/UnrealLiveLink.js +1105 -1136
  431. package/dist/esm/unreal-integration/UnrealMarketplace.js +442 -472
  432. package/dist/esm/unreal-integration/components/UnrealProjectBrowser.js +1151 -766
  433. package/dist/esm/xr/ARVR.js +181 -174
  434. package/package.json +7 -12
@@ -1,842 +1,799 @@
1
- import { PlatformExporter } from './PlatformExporter.js';
2
-
3
- /* ────────────────────────────────────────────────────────────────
4
- PICO-8 Exporter — Fantasy Console Export
5
-
6
- Exports Nice2Dev projects to PICO-8 format:
7
- - P8 cartridge file format
8
- - Lua code section
9
- - Graphics data (sprites, map)
10
- - Sound effects
11
- - Music patterns
12
-
13
- Constraints:
14
- - 128x128 pixels
15
- - 16 colors palette
16
- - 8192 tokens max
17
- - 32KB cartridge size
18
- ──────────────────────────────────────────────────────────────── */
19
- /* ── PICO-8 Constants ─────────────────────────────────────────── */
1
+ import { PlatformExporter } from "./PlatformExporter.js";
20
2
  const PICO8_PALETTE = [
21
- '#000000', // 0 - black
22
- '#1D2B53', // 1 - dark blue
23
- '#7E2553', // 2 - dark purple
24
- '#008751', // 3 - dark green
25
- '#AB5236', // 4 - brown
26
- '#5F574F', // 5 - dark gray
27
- '#C2C3C7', // 6 - light gray
28
- '#FFF1E8', // 7 - white
29
- '#FF004D', // 8 - red
30
- '#FFA300', // 9 - orange
31
- '#FFEC27', // 10 - yellow
32
- '#00E436', // 11 - green
33
- '#29ADFF', // 12 - blue
34
- '#83769C', // 13 - indigo
35
- '#FF77A8', // 14 - pink
36
- '#FFCCAA', // 15 - peach
3
+ "#000000",
4
+ // 0 - black
5
+ "#1D2B53",
6
+ // 1 - dark blue
7
+ "#7E2553",
8
+ // 2 - dark purple
9
+ "#008751",
10
+ // 3 - dark green
11
+ "#AB5236",
12
+ // 4 - brown
13
+ "#5F574F",
14
+ // 5 - dark gray
15
+ "#C2C3C7",
16
+ // 6 - light gray
17
+ "#FFF1E8",
18
+ // 7 - white
19
+ "#FF004D",
20
+ // 8 - red
21
+ "#FFA300",
22
+ // 9 - orange
23
+ "#FFEC27",
24
+ // 10 - yellow
25
+ "#00E436",
26
+ // 11 - green
27
+ "#29ADFF",
28
+ // 12 - blue
29
+ "#83769C",
30
+ // 13 - indigo
31
+ "#FF77A8",
32
+ // 14 - pink
33
+ "#FFCCAA"
34
+ // 15 - peach
37
35
  ];
38
- /* ── Exporter Implementation ──────────────────────────────────── */
39
36
  class Pico8Exporter extends PlatformExporter {
40
- constructor() {
41
- super(...arguments);
42
- this.platformId = 'pico8';
43
- this.platformInfo = {
44
- id: 'pico8',
45
- name: 'PICO-8',
46
- description: 'PICO-8 Fantasy Console - Retro game development platform',
47
- website: 'https://www.lexaloffle.com/pico-8.php',
48
- features: ['2d-rendering', 'pixel-graphics', 'audio', 'music', 'retro'],
49
- supportedAssets: ['sprite', 'tilemap', 'audio', 'music'],
50
- exportFormats: ['.p8'],
51
- };
52
- }
53
- async doExport(project, options) {
54
- options.platformOptions ?? {};
55
- // Generate main P8 cartridge
56
- await this.generateCartridge(project, options);
57
- // Generate standalone Lua for reference
58
- await this.generateLuaSource(project, options);
59
- // Generate README
60
- await this.generateReadme(project, options);
37
+ constructor() {
38
+ super(...arguments);
39
+ this.platformId = "pico8";
40
+ this.platformInfo = {
41
+ id: "pico8",
42
+ name: "PICO-8",
43
+ description: "PICO-8 Fantasy Console - Retro game development platform",
44
+ website: "https://www.lexaloffle.com/pico-8.php",
45
+ features: ["2d-rendering", "pixel-graphics", "audio", "music", "retro"],
46
+ supportedAssets: ["sprite", "tilemap", "audio", "music"],
47
+ exportFormats: [".p8"]
48
+ };
49
+ }
50
+ async doExport(project, options) {
51
+ options.platformOptions ?? {};
52
+ await this.generateCartridge(project, options);
53
+ await this.generateLuaSource(project, options);
54
+ await this.generateReadme(project, options);
55
+ }
56
+ /* ── Cartridge Generation ───────────────────────────────────── */
57
+ async generateCartridge(project, options) {
58
+ options.platformOptions ?? {};
59
+ const safeName = (options.projectName ?? project.name).toLowerCase().replace(/[^a-z0-9_]/g, "_");
60
+ const code = this.generateCode(project, options);
61
+ const gfx = this.generateGfxSection(project, options);
62
+ const gff = this.generateGffSection(project);
63
+ const map = this.generateMapSection(project);
64
+ const sfx = this.generateSfxSection(project, options);
65
+ const music = this.generateMusicSection(project, options);
66
+ const cartridge = `pico-8 cartridge // http://www.pico-8.com
67
+ version 41
68
+ __lua__
69
+ ${code}
70
+ __gfx__
71
+ ${gfx}
72
+ __gff__
73
+ ${gff}
74
+ __map__
75
+ ${map}
76
+ __sfx__
77
+ ${sfx}
78
+ __music__
79
+ ${music}
80
+ `;
81
+ this.addTextFile(`${safeName}.p8`, cartridge);
82
+ }
83
+ /* ── Code Generation ────────────────────────────────────────── */
84
+ generateCode(project, options) {
85
+ const platformOpts = options.platformOptions ?? {};
86
+ const optimizeTokens = platformOpts.optimizeTokens ?? false;
87
+ const lines = [];
88
+ lines.push(`-- ${project.name} v${project.version}`);
89
+ lines.push("-- generated from nice2dev");
90
+ lines.push("");
91
+ lines.push("-- game state");
92
+ lines.push("game={");
93
+ lines.push(' state="play",');
94
+ lines.push(" frame=0,");
95
+ lines.push(" cam={x=0,y=0},");
96
+ lines.push(" entities={},");
97
+ lines.push(" debug=" + (platformOpts.includeDebug ? "true" : "false"));
98
+ lines.push("}");
99
+ lines.push("");
100
+ lines.push(this.generateCoreFunctions(project, options));
101
+ lines.push(this.generateEntitySystem(project, options));
102
+ lines.push(this.generateEntityDefinitions(project, options));
103
+ lines.push(this.generateSceneSetup(project, options));
104
+ lines.push(this.generateUtilityFunctions(optimizeTokens));
105
+ if (platformOpts.includeDebug) {
106
+ lines.push(this.generateDebugOverlay());
61
107
  }
62
- /* ── Cartridge Generation ───────────────────────────────────── */
63
- async generateCartridge(project, options) {
64
- options.platformOptions ?? {};
65
- const safeName = (options.projectName ?? project.name)
66
- .toLowerCase()
67
- .replace(/[^a-z0-9_]/g, '_');
68
- // Generate code section
69
- const code = this.generateCode(project, options);
70
- // Generate graphics section (placeholder)
71
- const gfx = this.generateGfxSection(project, options);
72
- // Generate gff (sprite flags) section
73
- const gff = this.generateGffSection(project);
74
- // Generate map section
75
- const map = this.generateMapSection(project);
76
- // Generate sfx section
77
- const sfx = this.generateSfxSection(project, options);
78
- // Generate music section
79
- const music = this.generateMusicSection(project, options);
80
- // Assemble cartridge
81
- const cartridge = `pico-8 cartridge // http://www.pico-8.com
82
- version 41
83
- __lua__
84
- ${code}
85
- __gfx__
86
- ${gfx}
87
- __gff__
88
- ${gff}
89
- __map__
90
- ${map}
91
- __sfx__
92
- ${sfx}
93
- __music__
94
- ${music}
108
+ return lines.join("\n");
109
+ }
110
+ generateCoreFunctions(project, _options) {
111
+ return `
112
+ -- initialization
113
+ function _init()
114
+ -- setup palette
115
+ palt(0,false)
116
+ palt(14,true) -- pink as transparent
117
+
118
+ -- initialize game
119
+ game.frame=0
120
+ game.entities={}
121
+
122
+ -- load first scene
123
+ load_scene(1)
124
+ end
125
+
126
+ -- update (60fps)
127
+ function _update60()
128
+ if game.state=="play" then
129
+ game.frame+=1
130
+
131
+ -- update all entities
132
+ for e in all(game.entities) do
133
+ if e.update then
134
+ e:update()
135
+ end
136
+ end
137
+
138
+ -- handle collisions
139
+ check_collisions()
140
+
141
+ -- clean dead entities
142
+ for i=#game.entities,1,-1 do
143
+ if game.entities[i].dead then
144
+ del(game.entities,game.entities[i])
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ -- draw
151
+ function _draw()
152
+ cls(${this.getClosestPico8Color(project.scenes[0]?.background ?? "#000000")})
153
+
154
+ -- apply camera
155
+ camera(game.cam.x,game.cam.y)
156
+
157
+ -- draw map
158
+ map(0,0,0,0,128,64)
159
+
160
+ -- draw entities (sorted by y)
161
+ sort_entities()
162
+ for e in all(game.entities) do
163
+ if e.draw then
164
+ e:draw()
165
+ end
166
+ end
167
+
168
+ camera()
169
+
170
+ -- ui
171
+ draw_ui()
172
+
173
+ -- debug
174
+ if game.debug then
175
+ draw_debug()
176
+ end
177
+ end
95
178
  `;
96
- this.addTextFile(`${safeName}.p8`, cartridge);
179
+ }
180
+ generateEntitySystem(_project, _options) {
181
+ return `
182
+ -- entity system
183
+ function make_entity(type,x,y,props)
184
+ local e={
185
+ type=type,
186
+ x=x,
187
+ y=y,
188
+ dx=0,
189
+ dy=0,
190
+ w=8,
191
+ h=8,
192
+ spr=0,
193
+ flip_x=false,
194
+ anim={frames={0},speed=0.1,t=0,i=1},
195
+ dead=false,
196
+ tags={}
197
+ }
198
+ -- apply props
199
+ if props then
200
+ for k,v in pairs(props) do
201
+ e[k]=v
202
+ end
203
+ end
204
+ -- type-specific init
205
+ if entity_types[type] then
206
+ for k,v in pairs(entity_types[type]) do
207
+ if type(v)!="function" then
208
+ e[k]=v
209
+ else
210
+ e[k]=v
211
+ end
212
+ end
213
+ if entity_types[type].init then
214
+ entity_types[type].init(e)
215
+ end
216
+ end
217
+ add(game.entities,e)
218
+ return e
219
+ end
220
+
221
+ function kill_entity(e)
222
+ e.dead=true
223
+ end
224
+
225
+ function has_tag(e,tag)
226
+ for t in all(e.tags) do
227
+ if t==tag then return true end
228
+ end
229
+ return false
230
+ end
231
+
232
+ -- collision
233
+ function check_collisions()
234
+ for i=1,#game.entities do
235
+ local a=game.entities[i]
236
+ if not a.dead and a.solid then
237
+ for j=i+1,#game.entities do
238
+ local b=game.entities[j]
239
+ if not b.dead and b.solid then
240
+ if collides(a,b) then
241
+ if a.on_collision then a:on_collision(b) end
242
+ if b.on_collision then b:on_collision(a) end
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
249
+
250
+ function collides(a,b)
251
+ return a.x<b.x+b.w and
252
+ a.x+a.w>b.x and
253
+ a.y<b.y+b.h and
254
+ a.y+a.h>b.y
255
+ end
256
+ `;
257
+ }
258
+ generateEntityDefinitions(project, _options) {
259
+ const lines = [];
260
+ lines.push("");
261
+ lines.push("-- entity types");
262
+ lines.push("entity_types={}");
263
+ lines.push("");
264
+ const entityTypes = /* @__PURE__ */ new Map();
265
+ for (const prefab of project.prefabs) {
266
+ entityTypes.set(prefab.name.toLowerCase().replace(/[^a-z0-9_]/g, "_"), prefab.entity);
97
267
  }
98
- /* ── Code Generation ────────────────────────────────────────── */
99
- generateCode(project, options) {
100
- const platformOpts = options.platformOptions ?? {};
101
- const optimizeTokens = platformOpts.optimizeTokens ?? false;
102
- const lines = [];
103
- // Header comment
104
- lines.push(`-- ${project.name} v${project.version}`);
105
- lines.push('-- generated from nice2dev');
106
- lines.push('');
107
- // Game state
108
- lines.push('-- game state');
109
- lines.push('game={');
110
- lines.push(' state="play",');
111
- lines.push(' frame=0,');
112
- lines.push(' cam={x=0,y=0},');
113
- lines.push(' entities={},');
114
- lines.push(' debug=' + (platformOpts.includeDebug ? 'true' : 'false'));
115
- lines.push('}');
116
- lines.push('');
117
- // Core functions
118
- lines.push(this.generateCoreFunctions(project, options));
119
- // Entity system
120
- lines.push(this.generateEntitySystem(project, options));
121
- // Entity definitions
122
- lines.push(this.generateEntityDefinitions(project, options));
123
- // Scene setup
124
- lines.push(this.generateSceneSetup(project, options));
125
- // Utility functions
126
- lines.push(this.generateUtilityFunctions(optimizeTokens));
127
- // Debug overlay
128
- if (platformOpts.includeDebug) {
129
- lines.push(this.generateDebugOverlay());
268
+ for (const scene of project.scenes) {
269
+ for (const entity of scene.entities) {
270
+ const typeName = (entity.name ?? entity.id).toLowerCase().replace(/[^a-z0-9_]/g, "_");
271
+ if (!entityTypes.has(typeName)) {
272
+ entityTypes.set(typeName, entity);
130
273
  }
131
- return lines.join('\n');
274
+ }
132
275
  }
133
- generateCoreFunctions(project, _options) {
134
- return `
135
- -- initialization
136
- function _init()
137
- -- setup palette
138
- palt(0,false)
139
- palt(14,true) -- pink as transparent
140
-
141
- -- initialize game
142
- game.frame=0
143
- game.entities={}
144
-
145
- -- load first scene
146
- load_scene(1)
147
- end
148
-
149
- -- update (60fps)
150
- function _update60()
151
- if game.state=="play" then
152
- game.frame+=1
153
-
154
- -- update all entities
155
- for e in all(game.entities) do
156
- if e.update then
157
- e:update()
158
- end
159
- end
160
-
161
- -- handle collisions
162
- check_collisions()
163
-
164
- -- clean dead entities
165
- for i=#game.entities,1,-1 do
166
- if game.entities[i].dead then
167
- del(game.entities,game.entities[i])
168
- end
169
- end
170
- end
171
- end
172
-
173
- -- draw
174
- function _draw()
175
- cls(${this.getClosestPico8Color(project.scenes[0]?.background ?? '#000000')})
176
-
177
- -- apply camera
178
- camera(game.cam.x,game.cam.y)
179
-
180
- -- draw map
181
- map(0,0,0,0,128,64)
182
-
183
- -- draw entities (sorted by y)
184
- sort_entities()
185
- for e in all(game.entities) do
186
- if e.draw then
187
- e:draw()
188
- end
189
- end
190
-
191
- camera()
192
-
193
- -- ui
194
- draw_ui()
195
-
196
- -- debug
197
- if game.debug then
198
- draw_debug()
199
- end
200
- end
201
- `;
276
+ for (const [typeName, entity] of entityTypes) {
277
+ lines.push(this.entityTypeToLua(typeName, entity));
202
278
  }
203
- generateEntitySystem(_project, _options) {
204
- return `
205
- -- entity system
206
- function make_entity(type,x,y,props)
207
- local e={
208
- type=type,
209
- x=x,
210
- y=y,
211
- dx=0,
212
- dy=0,
213
- w=8,
214
- h=8,
215
- spr=0,
216
- flip_x=false,
217
- anim={frames={0},speed=0.1,t=0,i=1},
218
- dead=false,
219
- tags={}
220
- }
221
- -- apply props
222
- if props then
223
- for k,v in pairs(props) do
224
- e[k]=v
225
- end
226
- end
227
- -- type-specific init
228
- if entity_types[type] then
229
- for k,v in pairs(entity_types[type]) do
230
- if type(v)!="function" then
231
- e[k]=v
232
- else
233
- e[k]=v
234
- end
235
- end
236
- if entity_types[type].init then
237
- entity_types[type].init(e)
238
- end
239
- end
240
- add(game.entities,e)
241
- return e
242
- end
243
-
244
- function kill_entity(e)
245
- e.dead=true
246
- end
247
-
248
- function has_tag(e,tag)
249
- for t in all(e.tags) do
250
- if t==tag then return true end
251
- end
252
- return false
253
- end
254
-
255
- -- collision
256
- function check_collisions()
257
- for i=1,#game.entities do
258
- local a=game.entities[i]
259
- if not a.dead and a.solid then
260
- for j=i+1,#game.entities do
261
- local b=game.entities[j]
262
- if not b.dead and b.solid then
263
- if collides(a,b) then
264
- if a.on_collision then a:on_collision(b) end
265
- if b.on_collision then b:on_collision(a) end
266
- end
267
- end
268
- end
269
- end
270
- end
271
- end
272
-
273
- function collides(a,b)
274
- return a.x<b.x+b.w and
275
- a.x+a.w>b.x and
276
- a.y<b.y+b.h and
277
- a.y+a.h>b.y
278
- end
279
+ return lines.join("\n");
280
+ }
281
+ entityTypeToLua(typeName, entity) {
282
+ const tags = entity.tags ?? [];
283
+ entity.components.some((c) => c.type === "sprite");
284
+ const hasPhysics = entity.components.some((c) => c.type === "rigidbody");
285
+ entity.components.some((c) => c.type === "script");
286
+ const sprIndex = this.getEntitySpriteIndex(entity);
287
+ const speed = this.getComponentProperty(entity, "movement", "speed", 1);
288
+ return `entity_types.${typeName}={
289
+ spr=${sprIndex},
290
+ w=8,h=8,
291
+ solid=${hasPhysics},
292
+ tags={${tags.map((t) => `"${t}"`).join(",")}},
293
+ speed=${speed / 50},
294
+ hp=${this.getComponentProperty(entity, "health", "max", 3)},
295
+ max_hp=${this.getComponentProperty(entity, "health", "max", 3)},
296
+
297
+ init=function(self)
298
+ -- custom init
299
+ end,
300
+
301
+ update=function(self)
302
+ -- movement
303
+ self.x+=self.dx
304
+ self.y+=self.dy
305
+
306
+ -- friction
307
+ self.dx*=0.9
308
+ self.dy*=0.9
309
+
310
+ -- animation
311
+ if self.anim.speed>0 then
312
+ self.anim.t+=self.anim.speed
313
+ if self.anim.t>=1 then
314
+ self.anim.t=0
315
+ self.anim.i+=1
316
+ if self.anim.i>#self.anim.frames then
317
+ self.anim.i=1
318
+ end
319
+ self.spr=self.anim.frames[self.anim.i]
320
+ end
321
+ end
322
+ end,
323
+
324
+ draw=function(self)
325
+ spr(self.spr,self.x,self.y,1,1,self.flip_x)
326
+ end,
327
+
328
+ on_collision=function(self,other)
329
+ -- handle collision
330
+ end,
331
+
332
+ hurt=function(self,dmg)
333
+ self.hp-=(dmg or 1)
334
+ if self.hp<=0 then
335
+ self:die()
336
+ end
337
+ end,
338
+
339
+ die=function(self)
340
+ -- spawn particles
341
+ for i=1,4 do
342
+ spawn_particle(self.x+4,self.y+4,7)
343
+ end
344
+ kill_entity(self)
345
+ end
346
+ }
347
+
279
348
  `;
349
+ }
350
+ getEntitySpriteIndex(entity) {
351
+ const name = (entity.name ?? "entity").toLowerCase();
352
+ if (name.includes("player")) {
353
+ return 1;
280
354
  }
281
- generateEntityDefinitions(project, _options) {
282
- const lines = [];
283
- lines.push('');
284
- lines.push('-- entity types');
285
- lines.push('entity_types={}');
286
- lines.push('');
287
- // Generate entity types from prefabs and entities
288
- const entityTypes = new Map();
289
- for (const prefab of project.prefabs) {
290
- entityTypes.set(prefab.name.toLowerCase().replace(/[^a-z0-9_]/g, '_'), prefab.entity);
291
- }
292
- for (const scene of project.scenes) {
293
- for (const entity of scene.entities) {
294
- const typeName = (entity.name ?? entity.id).toLowerCase().replace(/[^a-z0-9_]/g, '_');
295
- if (!entityTypes.has(typeName)) {
296
- entityTypes.set(typeName, entity);
297
- }
298
- }
299
- }
300
- for (const [typeName, entity] of entityTypes) {
301
- lines.push(this.entityTypeToLua(typeName, entity));
302
- }
303
- return lines.join('\n');
355
+ if (name.includes("enemy")) {
356
+ return 16;
304
357
  }
305
- entityTypeToLua(typeName, entity) {
306
- const tags = entity.tags ?? [];
307
- entity.components.some((c) => c.type === 'sprite');
308
- const hasPhysics = entity.components.some((c) => c.type === 'rigidbody');
309
- entity.components.some((c) => c.type === 'script');
310
- const sprIndex = this.getEntitySpriteIndex(entity);
311
- const speed = this.getComponentProperty(entity, 'movement', 'speed', 1);
312
- return `entity_types.${typeName}={
313
- spr=${sprIndex},
314
- w=8,h=8,
315
- solid=${hasPhysics},
316
- tags={${tags.map((t) => `"${t}"`).join(',')}},
317
- speed=${speed / 50},
318
- hp=${this.getComponentProperty(entity, 'health', 'max', 3)},
319
- max_hp=${this.getComponentProperty(entity, 'health', 'max', 3)},
320
-
321
- init=function(self)
322
- -- custom init
323
- end,
324
-
325
- update=function(self)
326
- -- movement
327
- self.x+=self.dx
328
- self.y+=self.dy
329
-
330
- -- friction
331
- self.dx*=0.9
332
- self.dy*=0.9
333
-
334
- -- animation
335
- if self.anim.speed>0 then
336
- self.anim.t+=self.anim.speed
337
- if self.anim.t>=1 then
338
- self.anim.t=0
339
- self.anim.i+=1
340
- if self.anim.i>#self.anim.frames then
341
- self.anim.i=1
342
- end
343
- self.spr=self.anim.frames[self.anim.i]
344
- end
345
- end
346
- end,
347
-
348
- draw=function(self)
349
- spr(self.spr,self.x,self.y,1,1,self.flip_x)
350
- end,
351
-
352
- on_collision=function(self,other)
353
- -- handle collision
354
- end,
355
-
356
- hurt=function(self,dmg)
357
- self.hp-=(dmg or 1)
358
- if self.hp<=0 then
359
- self:die()
360
- end
361
- end,
362
-
363
- die=function(self)
364
- -- spawn particles
365
- for i=1,4 do
366
- spawn_particle(self.x+4,self.y+4,7)
367
- end
368
- kill_entity(self)
369
- end
370
- }
371
-
372
- `;
358
+ if (name.includes("item")) {
359
+ return 32;
373
360
  }
374
- getEntitySpriteIndex(entity) {
375
- // Map entity types to sprite indices (placeholder logic)
376
- const name = (entity.name ?? 'entity').toLowerCase();
377
- if (name.includes('player')) {
378
- return 1;
379
- }
380
- if (name.includes('enemy')) {
381
- return 16;
382
- }
383
- if (name.includes('item')) {
384
- return 32;
385
- }
386
- if (name.includes('bullet') || name.includes('projectile')) {
387
- return 48;
388
- }
389
- return 0;
361
+ if (name.includes("bullet") || name.includes("projectile")) {
362
+ return 48;
390
363
  }
391
- getComponentProperty(entity, componentType, property, defaultValue) {
392
- const comp = entity.components.find((c) => c.type === componentType);
393
- if (comp && comp.properties && property in comp.properties) {
394
- return comp.properties[property];
395
- }
396
- return defaultValue;
364
+ return 0;
365
+ }
366
+ getComponentProperty(entity, componentType, property, defaultValue) {
367
+ const comp = entity.components.find((c) => c.type === componentType);
368
+ if (comp && comp.properties && property in comp.properties) {
369
+ return comp.properties[property];
397
370
  }
398
- generateSceneSetup(project, _options) {
399
- const lines = [];
400
- lines.push('');
401
- lines.push('-- scenes');
402
- lines.push('scenes={}');
403
- lines.push('');
404
- for (let i = 0; i < project.scenes.length; i++) {
405
- const scene = project.scenes[i];
406
- const sceneName = scene.name.toLowerCase().replace(/[^a-z0-9_]/g, '_');
407
- lines.push(`scenes[${i + 1}]={`);
408
- lines.push(` name="${sceneName}",`);
409
- lines.push(` entities={`);
410
- for (const entity of scene.entities) {
411
- const typeName = (entity.name ?? entity.id).toLowerCase().replace(/[^a-z0-9_]/g, '_');
412
- const pos = entity.position ?? { x: 0, y: 0 };
413
- // Scale position for PICO-8 (128x128)
414
- const x = Math.floor((pos.x / project.settings.resolution.width) * 128);
415
- const y = Math.floor((pos.y / project.settings.resolution.height) * 128);
416
- lines.push(` {type="${typeName}",x=${x},y=${y}},`);
417
- }
418
- lines.push(` }`);
419
- lines.push(`}`);
420
- lines.push('');
421
- }
422
- lines.push('function load_scene(n)');
423
- lines.push(' game.entities={}');
424
- lines.push(' local s=scenes[n]');
425
- lines.push(' if s then');
426
- lines.push(' for e in all(s.entities) do');
427
- lines.push(' make_entity(e.type,e.x,e.y)');
428
- lines.push(' end');
429
- lines.push(' end');
430
- lines.push('end');
431
- return lines.join('\n');
371
+ return defaultValue;
372
+ }
373
+ generateSceneSetup(project, _options) {
374
+ const lines = [];
375
+ lines.push("");
376
+ lines.push("-- scenes");
377
+ lines.push("scenes={}");
378
+ lines.push("");
379
+ for (let i = 0; i < project.scenes.length; i++) {
380
+ const scene = project.scenes[i];
381
+ const sceneName = scene.name.toLowerCase().replace(/[^a-z0-9_]/g, "_");
382
+ lines.push(`scenes[${i + 1}]={`);
383
+ lines.push(` name="${sceneName}",`);
384
+ lines.push(` entities={`);
385
+ for (const entity of scene.entities) {
386
+ const typeName = (entity.name ?? entity.id).toLowerCase().replace(/[^a-z0-9_]/g, "_");
387
+ const pos = entity.position ?? { x: 0, y: 0 };
388
+ const x = Math.floor(pos.x / project.settings.resolution.width * 128);
389
+ const y = Math.floor(pos.y / project.settings.resolution.height * 128);
390
+ lines.push(` {type="${typeName}",x=${x},y=${y}},`);
391
+ }
392
+ lines.push(` }`);
393
+ lines.push(`}`);
394
+ lines.push("");
432
395
  }
433
- generateUtilityFunctions(optimizeTokens) {
434
- if (optimizeTokens) {
435
- return `
436
- -- utils (optimized)
437
- function v(x,y) return {x=x,y=y} end
438
- function dist(a,b) return sqrt((b.x-a.x)^2+(b.y-a.y)^2) end
439
- function lerp(a,b,t) return a+(b-a)*t end
440
- function clamp(v,mn,mx) return max(mn,min(mx,v)) end
441
- function rnd_range(a,b) return a+rnd(b-a) end
442
- function sign(v) return v>0 and 1 or v<0 and -1 or 0 end
443
-
444
- function sort_entities()
445
- for i=1,#game.entities do
446
- local j=i
447
- while j>1 and game.entities[j-1].y>game.entities[j].y do
448
- game.entities[j],game.entities[j-1]=game.entities[j-1],game.entities[j]
449
- j-=1
450
- end
451
- end
452
- end
453
-
454
- function spawn_particle(x,y,c)
455
- local p={x=x,y=y,dx=rnd(2)-1,dy=rnd(2)-1,c=c,life=15+rnd(10),draw=function(s) pset(s.x,s.y,s.c) end,update=function(s) s.x+=s.dx s.y+=s.dy s.life-=1 if s.life<=0 then s.dead=true end end}
456
- add(game.entities,p)
457
- end
458
-
459
- function draw_ui()
460
- -- hud here
461
- end
462
- `;
463
- }
464
- return `
465
- -- utility functions
466
- function vec(x,y)
467
- return {x=x,y=y}
468
- end
469
-
470
- function dist(a,b)
471
- local dx=b.x-a.x
472
- local dy=b.y-a.y
473
- return sqrt(dx*dx+dy*dy)
474
- end
475
-
476
- function lerp(a,b,t)
477
- return a+(b-a)*t
478
- end
479
-
480
- function clamp(val,min_val,max_val)
481
- return max(min_val,min(max_val,val))
482
- end
483
-
484
- function rnd_range(min_val,max_val)
485
- return min_val+rnd(max_val-min_val)
486
- end
487
-
488
- function sign(val)
489
- if val>0 then return 1 end
490
- if val<0 then return -1 end
491
- return 0
492
- end
493
-
494
- function sort_entities()
495
- -- insertion sort by y
496
- for i=1,#game.entities do
497
- local j=i
498
- while j>1 and game.entities[j-1].y>game.entities[j].y do
499
- game.entities[j],game.entities[j-1]=game.entities[j-1],game.entities[j]
500
- j-=1
501
- end
502
- end
503
- end
504
-
505
- function spawn_particle(x,y,color)
506
- local p={
507
- x=x,
508
- y=y,
509
- dx=rnd(2)-1,
510
- dy=rnd(2)-1,
511
- c=color,
512
- life=15+rnd(10),
513
- dead=false,
514
- draw=function(self)
515
- pset(self.x,self.y,self.c)
516
- end,
517
- update=function(self)
518
- self.x+=self.dx
519
- self.y+=self.dy
520
- self.dy+=0.05 -- gravity
521
- self.life-=1
522
- if self.life<=0 then
523
- self.dead=true
524
- end
525
- end
526
- }
527
- add(game.entities,p)
528
- end
529
-
530
- function screensh()
531
- -- screenshake
532
- if game.shake and game.shake>0 then
533
- game.cam.x=rnd(game.shake)-game.shake/2
534
- game.cam.y=rnd(game.shake)-game.shake/2
535
- game.shake-=0.5
536
- else
537
- game.shake=0
538
- game.cam.x=0
539
- game.cam.y=0
540
- end
541
- end
542
-
543
- function shake(amount)
544
- game.shake=(game.shake or 0)+amount
545
- end
546
-
547
- function draw_ui()
548
- -- hud
549
- print("nice2dev",1,1,7)
550
- end
551
-
552
- -- input helpers
553
- function btn_pressed(b)
554
- return btn(b) and not btnp(b)
555
- end
396
+ lines.push("function load_scene(n)");
397
+ lines.push(" game.entities={}");
398
+ lines.push(" local s=scenes[n]");
399
+ lines.push(" if s then");
400
+ lines.push(" for e in all(s.entities) do");
401
+ lines.push(" make_entity(e.type,e.x,e.y)");
402
+ lines.push(" end");
403
+ lines.push(" end");
404
+ lines.push("end");
405
+ return lines.join("\n");
406
+ }
407
+ generateUtilityFunctions(optimizeTokens) {
408
+ if (optimizeTokens) {
409
+ return `
410
+ -- utils (optimized)
411
+ function v(x,y) return {x=x,y=y} end
412
+ function dist(a,b) return sqrt((b.x-a.x)^2+(b.y-a.y)^2) end
413
+ function lerp(a,b,t) return a+(b-a)*t end
414
+ function clamp(v,mn,mx) return max(mn,min(mx,v)) end
415
+ function rnd_range(a,b) return a+rnd(b-a) end
416
+ function sign(v) return v>0 and 1 or v<0 and -1 or 0 end
417
+
418
+ function sort_entities()
419
+ for i=1,#game.entities do
420
+ local j=i
421
+ while j>1 and game.entities[j-1].y>game.entities[j].y do
422
+ game.entities[j],game.entities[j-1]=game.entities[j-1],game.entities[j]
423
+ j-=1
424
+ end
425
+ end
426
+ end
427
+
428
+ function spawn_particle(x,y,c)
429
+ local p={x=x,y=y,dx=rnd(2)-1,dy=rnd(2)-1,c=c,life=15+rnd(10),draw=function(s) pset(s.x,s.y,s.c) end,update=function(s) s.x+=s.dx s.y+=s.dy s.life-=1 if s.life<=0 then s.dead=true end end}
430
+ add(game.entities,p)
431
+ end
432
+
433
+ function draw_ui()
434
+ -- hud here
435
+ end
556
436
  `;
557
437
  }
558
- generateDebugOverlay() {
559
- return `
560
- -- debug overlay
561
- function draw_debug()
562
- local mem=flr(stat(0)/1024*100)/100
563
- local cpu=flr(stat(1)*100)
564
-
565
- rectfill(0,0,127,12,0)
566
- print("fps:"..stat(7).." cpu:"..cpu.."%",1,1,7)
567
- print("mem:"..mem.."kb ent:"..#game.entities,1,7,7)
568
-
569
- -- draw hitboxes
570
- for e in all(game.entities) do
571
- if e.solid then
572
- rect(e.x,e.y,e.x+e.w-1,e.y+e.h-1,8)
573
- end
574
- end
575
- end
438
+ return `
439
+ -- utility functions
440
+ function vec(x,y)
441
+ return {x=x,y=y}
442
+ end
443
+
444
+ function dist(a,b)
445
+ local dx=b.x-a.x
446
+ local dy=b.y-a.y
447
+ return sqrt(dx*dx+dy*dy)
448
+ end
449
+
450
+ function lerp(a,b,t)
451
+ return a+(b-a)*t
452
+ end
453
+
454
+ function clamp(val,min_val,max_val)
455
+ return max(min_val,min(max_val,val))
456
+ end
457
+
458
+ function rnd_range(min_val,max_val)
459
+ return min_val+rnd(max_val-min_val)
460
+ end
461
+
462
+ function sign(val)
463
+ if val>0 then return 1 end
464
+ if val<0 then return -1 end
465
+ return 0
466
+ end
467
+
468
+ function sort_entities()
469
+ -- insertion sort by y
470
+ for i=1,#game.entities do
471
+ local j=i
472
+ while j>1 and game.entities[j-1].y>game.entities[j].y do
473
+ game.entities[j],game.entities[j-1]=game.entities[j-1],game.entities[j]
474
+ j-=1
475
+ end
476
+ end
477
+ end
478
+
479
+ function spawn_particle(x,y,color)
480
+ local p={
481
+ x=x,
482
+ y=y,
483
+ dx=rnd(2)-1,
484
+ dy=rnd(2)-1,
485
+ c=color,
486
+ life=15+rnd(10),
487
+ dead=false,
488
+ draw=function(self)
489
+ pset(self.x,self.y,self.c)
490
+ end,
491
+ update=function(self)
492
+ self.x+=self.dx
493
+ self.y+=self.dy
494
+ self.dy+=0.05 -- gravity
495
+ self.life-=1
496
+ if self.life<=0 then
497
+ self.dead=true
498
+ end
499
+ end
500
+ }
501
+ add(game.entities,p)
502
+ end
503
+
504
+ function screensh()
505
+ -- screenshake
506
+ if game.shake and game.shake>0 then
507
+ game.cam.x=rnd(game.shake)-game.shake/2
508
+ game.cam.y=rnd(game.shake)-game.shake/2
509
+ game.shake-=0.5
510
+ else
511
+ game.shake=0
512
+ game.cam.x=0
513
+ game.cam.y=0
514
+ end
515
+ end
516
+
517
+ function shake(amount)
518
+ game.shake=(game.shake or 0)+amount
519
+ end
520
+
521
+ function draw_ui()
522
+ -- hud
523
+ print("nice2dev",1,1,7)
524
+ end
525
+
526
+ -- input helpers
527
+ function btn_pressed(b)
528
+ return btn(b) and not btnp(b)
529
+ end
576
530
  `;
577
- }
578
- /* ── Data Sections ──────────────────────────────────────────── */
579
- generateGfxSection(_project, _options) {
580
- // Generate placeholder sprite sheet (128x128 = 256 lines of 128 hex chars)
581
- // Each pixel is 4 bits (one hex char)
582
- const lines = [];
583
- // Basic placeholder sprites
584
- // Sprite 0: Empty
585
- // Sprite 1: Player placeholder (simple face)
586
- // Sprite 16: Enemy placeholder
587
- // Sprite 32: Item placeholder
588
- for (let row = 0; row < 128; row++) {
589
- let line = '';
590
- for (let col = 0; col < 128; col++) {
591
- const spriteX = col % 8;
592
- const spriteY = row % 8;
593
- const spriteIndex = Math.floor(col / 8) + Math.floor(row / 8) * 16;
594
- let pixel = 0;
595
- // Sprite 1: Player (simple character)
596
- if (spriteIndex === 1) {
597
- // Draw a simple face
598
- if (spriteY === 1 && (spriteX === 2 || spriteX === 5)) {
599
- pixel = 12;
600
- } // eyes (blue)
601
- else if (spriteY === 3 && spriteX >= 2 && spriteX <= 5) {
602
- pixel = 8;
603
- } // mouth (red)
604
- else if (spriteY >= 1 && spriteY <= 5 && spriteX >= 1 && spriteX <= 6) {
605
- pixel = 15;
606
- } // face (peach)
607
- else if ((spriteY === 0 || spriteY === 6) && spriteX >= 2 && spriteX <= 5) {
608
- pixel = 4;
609
- } // hair
610
- else if ((spriteX === 0 || spriteX === 7) && spriteY >= 1 && spriteY <= 5) {
611
- pixel = 4;
612
- } // hair sides
613
- }
614
- // Sprite 16: Enemy (red square)
615
- else if (spriteIndex === 16) {
616
- if (spriteX >= 1 && spriteX <= 6 && spriteY >= 1 && spriteY <= 6) {
617
- pixel = 8;
618
- } // red body
619
- if (spriteY === 2 && (spriteX === 2 || spriteX === 5)) {
620
- pixel = 7;
621
- } // eyes
622
- }
623
- // Sprite 32: Item (yellow coin)
624
- else if (spriteIndex === 32) {
625
- if (spriteX >= 2 && spriteX <= 5 && spriteY >= 1 && spriteY <= 6) {
626
- pixel = 10;
627
- } // yellow
628
- if (spriteY >= 2 && spriteY <= 5 && (spriteX === 1 || spriteX === 6)) {
629
- pixel = 10;
630
- }
631
- if (spriteX >= 3 && spriteX <= 4 && spriteY >= 3 && spriteY <= 4) {
632
- pixel = 9;
633
- } // orange center
634
- }
635
- line += pixel.toString(16);
636
- }
637
- lines.push(line);
531
+ }
532
+ generateDebugOverlay() {
533
+ return `
534
+ -- debug overlay
535
+ function draw_debug()
536
+ local mem=flr(stat(0)/1024*100)/100
537
+ local cpu=flr(stat(1)*100)
538
+
539
+ rectfill(0,0,127,12,0)
540
+ print("fps:"..stat(7).." cpu:"..cpu.."%",1,1,7)
541
+ print("mem:"..mem.."kb ent:"..#game.entities,1,7,7)
542
+
543
+ -- draw hitboxes
544
+ for e in all(game.entities) do
545
+ if e.solid then
546
+ rect(e.x,e.y,e.x+e.w-1,e.y+e.h-1,8)
547
+ end
548
+ end
549
+ end
550
+ `;
551
+ }
552
+ /* ── Data Sections ──────────────────────────────────────────── */
553
+ generateGfxSection(_project, _options) {
554
+ const lines = [];
555
+ for (let row = 0; row < 128; row++) {
556
+ let line = "";
557
+ for (let col = 0; col < 128; col++) {
558
+ const spriteX = col % 8;
559
+ const spriteY = row % 8;
560
+ const spriteIndex = Math.floor(col / 8) + Math.floor(row / 8) * 16;
561
+ let pixel = 0;
562
+ if (spriteIndex === 1) {
563
+ if (spriteY === 1 && (spriteX === 2 || spriteX === 5)) {
564
+ pixel = 12;
565
+ } else if (spriteY === 3 && spriteX >= 2 && spriteX <= 5) {
566
+ pixel = 8;
567
+ } else if (spriteY >= 1 && spriteY <= 5 && spriteX >= 1 && spriteX <= 6) {
568
+ pixel = 15;
569
+ } else if ((spriteY === 0 || spriteY === 6) && spriteX >= 2 && spriteX <= 5) {
570
+ pixel = 4;
571
+ } else if ((spriteX === 0 || spriteX === 7) && spriteY >= 1 && spriteY <= 5) {
572
+ pixel = 4;
573
+ }
574
+ } else if (spriteIndex === 16) {
575
+ if (spriteX >= 1 && spriteX <= 6 && spriteY >= 1 && spriteY <= 6) {
576
+ pixel = 8;
577
+ }
578
+ if (spriteY === 2 && (spriteX === 2 || spriteX === 5)) {
579
+ pixel = 7;
580
+ }
581
+ } else if (spriteIndex === 32) {
582
+ if (spriteX >= 2 && spriteX <= 5 && spriteY >= 1 && spriteY <= 6) {
583
+ pixel = 10;
584
+ }
585
+ if (spriteY >= 2 && spriteY <= 5 && (spriteX === 1 || spriteX === 6)) {
586
+ pixel = 10;
587
+ }
588
+ if (spriteX >= 3 && spriteX <= 4 && spriteY >= 3 && spriteY <= 4) {
589
+ pixel = 9;
590
+ }
638
591
  }
639
- return lines.join('\n');
592
+ line += pixel.toString(16);
593
+ }
594
+ lines.push(line);
640
595
  }
641
- generateGffSection(_project) {
642
- // Sprite flags: 256 bytes (2 per line, 128 lines)
643
- // All zeros for placeholder
644
- const lines = [];
645
- for (let i = 0; i < 2; i++) {
646
- lines.push('0'.repeat(256));
647
- }
648
- return lines.join('\n');
596
+ return lines.join("\n");
597
+ }
598
+ generateGffSection(_project) {
599
+ const lines = [];
600
+ for (let i = 0; i < 2; i++) {
601
+ lines.push("0".repeat(256));
649
602
  }
650
- generateMapSection(_project) {
651
- // Map: 128x64 tiles, stored as 128 bytes per row, 64 rows
652
- // Actually stored as 128x32 in __map__ section
653
- const lines = [];
654
- for (let i = 0; i < 32; i++) {
655
- lines.push('0'.repeat(256));
656
- }
657
- return lines.join('\n');
603
+ return lines.join("\n");
604
+ }
605
+ generateMapSection(_project) {
606
+ const lines = [];
607
+ for (let i = 0; i < 32; i++) {
608
+ lines.push("0".repeat(256));
658
609
  }
659
- generateSfxSection(project, options) {
660
- const platformOpts = options.platformOptions ?? {};
661
- if (!platformOpts.sfxPlaceholders) {
662
- // Empty sfx section
663
- return '';
664
- }
665
- // Placeholder sound effects
666
- const lines = [];
667
- // SFX 0: Jump sound
668
- lines.push('000100000c0500c0500b0500a050090500805007050060500505004050030500205001050000500005000050000500005000050000500005000050000500005');
669
- // SFX 1: Hit sound
670
- lines.push('001000001805018050170501605015050140501305012050110501005010050100500005000050000500005000050000500005000050000500005000050');
671
- // SFX 2: Pickup sound
672
- lines.push('000600002405024050260502805030050320503305034050350503605036050350503405033050300502705024050000500005000050000500005000050');
673
- // Fill rest with empty
674
- for (let i = 3; i < 64; i++) {
675
- lines.push('001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000');
676
- }
677
- return lines.join('\n');
610
+ return lines.join("\n");
611
+ }
612
+ generateSfxSection(project, options) {
613
+ const platformOpts = options.platformOptions ?? {};
614
+ if (!platformOpts.sfxPlaceholders) {
615
+ return "";
678
616
  }
679
- generateMusicSection(project, options) {
680
- const platformOpts = options.platformOptions ?? {};
681
- if (!platformOpts.musicPatterns) {
682
- return '';
683
- }
684
- // Placeholder music patterns
685
- const lines = [];
686
- // Pattern 0: Simple loop
687
- lines.push('00 41424344');
688
- // Fill rest with empty
689
- for (let i = 1; i < 64; i++) {
690
- lines.push('00 41424344'.replace(/\d/g, '4'));
691
- }
692
- return lines.join('\n');
617
+ const lines = [];
618
+ lines.push(
619
+ "000100000c0500c0500b0500a050090500805007050060500505004050030500205001050000500005000050000500005000050000500005000050000500005"
620
+ );
621
+ lines.push(
622
+ "001000001805018050170501605015050140501305012050110501005010050100500005000050000500005000050000500005000050000500005000050"
623
+ );
624
+ lines.push(
625
+ "000600002405024050260502805030050320503305034050350503605036050350503405033050300502705024050000500005000050000500005000050"
626
+ );
627
+ for (let i = 3; i < 64; i++) {
628
+ lines.push(
629
+ "001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
630
+ );
693
631
  }
694
- /* ── Lua Source ─────────────────────────────────────────────── */
695
- async generateLuaSource(project, options) {
696
- const code = this.generateCode(project, options);
697
- this.addTextFile('source.lua', `-- ${project.name} - Source Code\n-- For reference only (use .p8 file in PICO-8)\n\n${code}`);
632
+ return lines.join("\n");
633
+ }
634
+ generateMusicSection(project, options) {
635
+ const platformOpts = options.platformOptions ?? {};
636
+ if (!platformOpts.musicPatterns) {
637
+ return "";
698
638
  }
699
- /* ── Color Utilities ────────────────────────────────────────── */
700
- getClosestPico8Color(hex) {
701
- const cleanHex = hex.replace('#', '').toLowerCase();
702
- const r = parseInt(cleanHex.substring(0, 2), 16);
703
- const g = parseInt(cleanHex.substring(2, 4), 16);
704
- const b = parseInt(cleanHex.substring(4, 6), 16);
705
- let closestIndex = 0;
706
- let closestDist = Infinity;
707
- for (let i = 0; i < PICO8_PALETTE.length; i++) {
708
- const palHex = PICO8_PALETTE[i].replace('#', '');
709
- const pr = parseInt(palHex.substring(0, 2), 16);
710
- const pg = parseInt(palHex.substring(2, 4), 16);
711
- const pb = parseInt(palHex.substring(4, 6), 16);
712
- const dist = Math.sqrt(Math.pow(r - pr, 2) + Math.pow(g - pg, 2) + Math.pow(b - pb, 2));
713
- if (dist < closestDist) {
714
- closestDist = dist;
715
- closestIndex = i;
716
- }
717
- }
718
- return closestIndex;
639
+ const lines = [];
640
+ lines.push("00 41424344");
641
+ for (let i = 1; i < 64; i++) {
642
+ lines.push("00 41424344".replace(/\d/g, "4"));
719
643
  }
720
- /* ── README ─────────────────────────────────────────────────── */
721
- async generateReadme(project, options) {
722
- const safeName = (options.projectName ?? project.name)
723
- .toLowerCase()
724
- .replace(/[^a-z0-9_]/g, '_');
725
- const readme = `# ${project.name} - PICO-8 Export
726
-
727
- Generated from Nice2Dev project v${project.version}
728
-
729
- ## Requirements
730
-
731
- - PICO-8 ($15 from https://www.lexaloffle.com/pico-8.php)
732
-
733
- ## Installation
734
-
735
- 1. Open PICO-8
736
- 2. Type: \`load ${safeName}\`
737
- 3. Press Ctrl+R or type \`run\`
738
-
739
- ## Files
740
-
741
- - \`${safeName}.p8\` - PICO-8 cartridge file
742
- - \`source.lua\` - Extracted Lua source (for reference)
743
-
744
- ## PICO-8 Constraints
745
-
746
- This export is designed for PICO-8's limitations:
747
- - **Display**: 128x128 pixels
748
- - **Colors**: 16 color palette
749
- - **Code**: 8192 tokens max
750
- - **Memory**: 32KB cartridge
751
- - **Sprites**: 128 8x8 sprites
752
- - **Map**: 128x64 tiles
753
- - **Sound**: 64 SFX slots
754
- - **Music**: 64 patterns
755
-
756
- ## Controls
757
-
758
- - ⬅️➡️⬆️⬇️ / ESDF: Move
759
- - 🅾️ (Z/C): Action 1
760
- - ❎ (X/V): Action 2
761
- - P: Pause menu
762
-
763
- ## Code Structure
764
-
765
- \`\`\`lua
766
- -- _init() - Called once at start
767
- -- _update60() - Called 60 times per second
768
- -- _draw() - Called after update for rendering
769
- \`\`\`
770
-
771
- ### Entity System
772
-
773
- \`\`\`lua
774
- -- Create entity
775
- local e = make_entity("player", 64, 64)
776
-
777
- -- Kill entity
778
- kill_entity(e)
779
-
780
- -- Check tag
781
- if has_tag(e, "enemy") then
782
- -- ...
783
- end
784
- \`\`\`
785
-
786
- ### Scenes
787
-
788
- ${project.scenes.map((s, i) => `- Scene ${i + 1}: ${s.name} (${s.entities.length} entities)`).join('\n')}
789
-
790
- Load scene with: \`load_scene(1)\`
791
-
792
- ## Customization
793
-
794
- ### Adding Sprites
795
-
796
- 1. In PICO-8, press Ctrl+S to open sprite editor
797
- 2. Draw your sprites (8x8 pixels each)
798
- 3. Update entity_types sprite indices
799
-
800
- ### Adding Sounds
801
-
802
- 1. Press Ctrl+N for SFX editor
803
- 2. Create sounds in slots 0-63
804
- 3. Play with: \`sfx(0)\`
805
-
806
- ### Adding Music
807
-
808
- 1. Press Ctrl+M for music editor
809
- 2. Create patterns using SFX
810
- 3. Play with: \`music(0)\`
811
-
812
- ## Debug Mode
813
-
814
- Set \`game.debug=true\` to show:
815
- - FPS counter
816
- - CPU usage
817
- - Memory usage
818
- - Entity hitboxes
819
-
820
- ## Tips
821
-
822
- - Keep code under 8192 tokens
823
- - Use shorter variable names to save tokens
824
- - Reuse sprites with flip flags
825
- - Use map for static backgrounds
826
- - Pool entities to avoid garbage
827
-
828
- ## Links
829
-
830
- - PICO-8 Manual: https://www.lexaloffle.com/dl/docs/pico-8_manual.html
831
- - PICO-8 Wiki: https://pico-8.fandom.com/
832
- - Splore: Built-in game browser (type \`splore\`)
833
- `;
834
- this.addTextFile('README.md', readme);
644
+ return lines.join("\n");
645
+ }
646
+ /* ── Lua Source ─────────────────────────────────────────────── */
647
+ async generateLuaSource(project, options) {
648
+ const code = this.generateCode(project, options);
649
+ this.addTextFile(
650
+ "source.lua",
651
+ `-- ${project.name} - Source Code
652
+ -- For reference only (use .p8 file in PICO-8)
653
+
654
+ ${code}`
655
+ );
656
+ }
657
+ /* ── Color Utilities ────────────────────────────────────────── */
658
+ getClosestPico8Color(hex) {
659
+ const cleanHex = hex.replace("#", "").toLowerCase();
660
+ const r = parseInt(cleanHex.substring(0, 2), 16);
661
+ const g = parseInt(cleanHex.substring(2, 4), 16);
662
+ const b = parseInt(cleanHex.substring(4, 6), 16);
663
+ let closestIndex = 0;
664
+ let closestDist = Infinity;
665
+ for (let i = 0; i < PICO8_PALETTE.length; i++) {
666
+ const palHex = PICO8_PALETTE[i].replace("#", "");
667
+ const pr = parseInt(palHex.substring(0, 2), 16);
668
+ const pg = parseInt(palHex.substring(2, 4), 16);
669
+ const pb = parseInt(palHex.substring(4, 6), 16);
670
+ const dist = Math.sqrt(Math.pow(r - pr, 2) + Math.pow(g - pg, 2) + Math.pow(b - pb, 2));
671
+ if (dist < closestDist) {
672
+ closestDist = dist;
673
+ closestIndex = i;
674
+ }
835
675
  }
676
+ return closestIndex;
677
+ }
678
+ /* ── README ─────────────────────────────────────────────────── */
679
+ async generateReadme(project, options) {
680
+ const safeName = (options.projectName ?? project.name).toLowerCase().replace(/[^a-z0-9_]/g, "_");
681
+ const readme = `# ${project.name} - PICO-8 Export
682
+
683
+ Generated from Nice2Dev project v${project.version}
684
+
685
+ ## Requirements
686
+
687
+ - PICO-8 ($15 from https://www.lexaloffle.com/pico-8.php)
688
+
689
+ ## Installation
690
+
691
+ 1. Open PICO-8
692
+ 2. Type: \`load ${safeName}\`
693
+ 3. Press Ctrl+R or type \`run\`
694
+
695
+ ## Files
696
+
697
+ - \`${safeName}.p8\` - PICO-8 cartridge file
698
+ - \`source.lua\` - Extracted Lua source (for reference)
699
+
700
+ ## PICO-8 Constraints
701
+
702
+ This export is designed for PICO-8's limitations:
703
+ - **Display**: 128x128 pixels
704
+ - **Colors**: 16 color palette
705
+ - **Code**: 8192 tokens max
706
+ - **Memory**: 32KB cartridge
707
+ - **Sprites**: 128 8x8 sprites
708
+ - **Map**: 128x64 tiles
709
+ - **Sound**: 64 SFX slots
710
+ - **Music**: 64 patterns
711
+
712
+ ## Controls
713
+
714
+ - ⬅️➡️⬆️⬇️ / ESDF: Move
715
+ - 🅾️ (Z/C): Action 1
716
+ - ❎ (X/V): Action 2
717
+ - P: Pause menu
718
+
719
+ ## Code Structure
720
+
721
+ \`\`\`lua
722
+ -- _init() - Called once at start
723
+ -- _update60() - Called 60 times per second
724
+ -- _draw() - Called after update for rendering
725
+ \`\`\`
726
+
727
+ ### Entity System
728
+
729
+ \`\`\`lua
730
+ -- Create entity
731
+ local e = make_entity("player", 64, 64)
732
+
733
+ -- Kill entity
734
+ kill_entity(e)
735
+
736
+ -- Check tag
737
+ if has_tag(e, "enemy") then
738
+ -- ...
739
+ end
740
+ \`\`\`
741
+
742
+ ### Scenes
743
+
744
+ ${project.scenes.map((s, i) => `- Scene ${i + 1}: ${s.name} (${s.entities.length} entities)`).join("\n")}
745
+
746
+ Load scene with: \`load_scene(1)\`
747
+
748
+ ## Customization
749
+
750
+ ### Adding Sprites
751
+
752
+ 1. In PICO-8, press Ctrl+S to open sprite editor
753
+ 2. Draw your sprites (8x8 pixels each)
754
+ 3. Update entity_types sprite indices
755
+
756
+ ### Adding Sounds
757
+
758
+ 1. Press Ctrl+N for SFX editor
759
+ 2. Create sounds in slots 0-63
760
+ 3. Play with: \`sfx(0)\`
761
+
762
+ ### Adding Music
763
+
764
+ 1. Press Ctrl+M for music editor
765
+ 2. Create patterns using SFX
766
+ 3. Play with: \`music(0)\`
767
+
768
+ ## Debug Mode
769
+
770
+ Set \`game.debug=true\` to show:
771
+ - FPS counter
772
+ - CPU usage
773
+ - Memory usage
774
+ - Entity hitboxes
775
+
776
+ ## Tips
777
+
778
+ - Keep code under 8192 tokens
779
+ - Use shorter variable names to save tokens
780
+ - Reuse sprites with flip flags
781
+ - Use map for static backgrounds
782
+ - Pool entities to avoid garbage
783
+
784
+ ## Links
785
+
786
+ - PICO-8 Manual: https://www.lexaloffle.com/dl/docs/pico-8_manual.html
787
+ - PICO-8 Wiki: https://pico-8.fandom.com/
788
+ - Splore: Built-in game browser (type \`splore\`)
789
+ `;
790
+ this.addTextFile("README.md", readme);
791
+ }
836
792
  }
837
- /* ── Factory ──────────────────────────────────────────────────── */
838
793
  function createPico8Exporter() {
839
- return new Pico8Exporter();
794
+ return new Pico8Exporter();
840
795
  }
841
-
842
- export { Pico8Exporter, createPico8Exporter };
796
+ export {
797
+ Pico8Exporter,
798
+ createPico8Exporter
799
+ };