webtalekit-alpha 0.2.11 → 0.2.13

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 (389) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.clinerules +65 -0
  3. package/.history/README_20240812174230.md +193 -0
  4. package/.history/README_20240812175424.md +185 -0
  5. package/.history/README_20240812191012.md +185 -0
  6. package/.history/README_20240812191155.md +185 -0
  7. package/.history/README_20240812191211.md +185 -0
  8. package/.history/README_20240812192035.md +185 -0
  9. package/.history/dist/src/core/index_20240815021552.js +474 -0
  10. package/.history/dist/src/core/index_20240815022042.js +476 -0
  11. package/.history/dist/src/core/index_20240815022206.js +476 -0
  12. package/.history/dist/src/core/index_20240815023104.js +478 -0
  13. package/.history/dist/src/core/index_20240817022019.js +494 -0
  14. package/.history/dist/src/core/index_20240818013827.js +493 -0
  15. package/.history/dist/src/core/index_20240820001418.js +502 -0
  16. package/.history/package_20240812174230.json +45 -0
  17. package/.history/package_20240825011731.json +45 -0
  18. package/.history/package_20240825011739.json +44 -0
  19. package/.history/parser/parser_20240812174230.js +50 -0
  20. package/.history/parser/parser_20240825012739.js +47 -0
  21. package/.history/parser/parser_20240825012835.js +52 -0
  22. package/.history/src/core/drawer_20240813091343.ts +262 -0
  23. package/.history/src/core/drawer_20240815232345.ts +262 -0
  24. package/.history/src/core/drawer_20240815232350.ts +262 -0
  25. package/.history/src/core/drawer_20240816025257.ts +357 -0
  26. package/.history/src/core/drawer_20240816025358.ts +357 -0
  27. package/.history/src/core/drawer_20240816030148.ts +365 -0
  28. package/.history/src/core/drawer_20240816231033.ts +294 -0
  29. package/.history/src/core/drawer_20240816231107.ts +262 -0
  30. package/.history/src/core/drawer_20240816231234.ts +268 -0
  31. package/.history/src/core/drawer_20240817013836.ts +290 -0
  32. package/.history/src/core/drawer_20240817015150.ts +289 -0
  33. package/.history/src/core/drawer_20240817015353.ts +290 -0
  34. package/.history/src/core/drawer_20240817021254.ts +291 -0
  35. package/.history/src/core/drawer_20240817023440.ts +295 -0
  36. package/.history/src/core/drawer_20240817023445.ts +295 -0
  37. package/.history/src/core/drawer_20240818015327.ts +295 -0
  38. package/.history/src/core/drawer_20240819231006.ts +318 -0
  39. package/.history/src/core/drawer_20240820002829.ts +317 -0
  40. package/.history/src/core/drawer_20240820003141.ts +295 -0
  41. package/.history/src/core/drawer_20240824010043.ts +295 -0
  42. package/.history/src/core/drawer_20240825013311.ts +293 -0
  43. package/.history/src/core/drawer_20240902235257.ts +295 -0
  44. package/.history/src/core/drawer_20240904002038.ts +262 -0
  45. package/.history/src/core/drawer_20240904004020.ts +262 -0
  46. package/.history/src/core/drawer_20240904004238.ts +262 -0
  47. package/.history/src/core/drawer_20240904005648.ts +262 -0
  48. package/.history/src/core/drawer_20240904005808.ts +262 -0
  49. package/.history/src/core/drawer_20240904010523.ts +262 -0
  50. package/.history/src/core/drawer_20240904011611.ts +262 -0
  51. package/.history/src/core/drawer_20240904011740.ts +262 -0
  52. package/.history/src/core/index_20240812190102.js +443 -0
  53. package/.history/src/core/index_20240812190105.js +443 -0
  54. package/.history/src/core/index_20240812205421.js +452 -0
  55. package/.history/src/core/index_20240812213441.js +452 -0
  56. package/.history/src/core/index_20240812214203.js +453 -0
  57. package/.history/src/core/index_20240813090823.js +453 -0
  58. package/.history/src/core/index_20240813230449.js +452 -0
  59. package/.history/src/core/index_20240813230539.js +452 -0
  60. package/.history/src/core/index_20240813231447.js +453 -0
  61. package/.history/src/core/index_20240813231449.js +453 -0
  62. package/.history/src/core/index_20240813231511.js +453 -0
  63. package/.history/src/core/index_20240813231531.js +453 -0
  64. package/.history/src/core/index_20240813231913.js +453 -0
  65. package/.history/src/core/index_20240813232356.js +453 -0
  66. package/.history/src/core/index_20240813232640.js +453 -0
  67. package/.history/src/core/index_20240813232900.js +453 -0
  68. package/.history/src/core/index_20240814221127.js +454 -0
  69. package/.history/src/core/index_20240814221322.js +454 -0
  70. package/.history/src/core/index_20240814221526.js +454 -0
  71. package/.history/src/core/index_20240814222048.js +454 -0
  72. package/.history/src/core/index_20240814222918.js +459 -0
  73. package/.history/src/core/index_20240814223136.js +459 -0
  74. package/.history/src/core/index_20240814223501.js +464 -0
  75. package/.history/src/core/index_20240814224347.js +468 -0
  76. package/.history/src/core/index_20240815013712.js +474 -0
  77. package/.history/src/core/index_20240815021534.js +474 -0
  78. package/.history/src/core/index_20240815023143.js +477 -0
  79. package/.history/src/core/index_20240815023207.js +479 -0
  80. package/.history/src/core/index_20240815023344.js +481 -0
  81. package/.history/src/core/index_20240815035600.js +479 -0
  82. package/.history/src/core/index_20240815041549.js +480 -0
  83. package/.history/src/core/index_20240815185515.js +481 -0
  84. package/.history/src/core/index_20240815192158.js +481 -0
  85. package/.history/src/core/index_20240815222912.js +482 -0
  86. package/.history/src/core/index_20240815224052.js +483 -0
  87. package/.history/src/core/index_20240815224843.js +484 -0
  88. package/.history/src/core/index_20240815224850.js +483 -0
  89. package/.history/src/core/index_20240815231706.js +479 -0
  90. package/.history/src/core/index_20240816025748.js +483 -0
  91. package/.history/src/core/index_20240816030102.js +484 -0
  92. package/.history/src/core/index_20240817013329.js +485 -0
  93. package/.history/src/core/index_20240817013526.js +485 -0
  94. package/.history/src/core/index_20240817013819.js +488 -0
  95. package/.history/src/core/index_20240817013829.js +488 -0
  96. package/.history/src/core/index_20240817014921.js +494 -0
  97. package/.history/src/core/index_20240817022057.js +494 -0
  98. package/.history/src/core/index_20240817023316.js +493 -0
  99. package/.history/src/core/index_20240818005637.js +493 -0
  100. package/.history/src/core/index_20240818005721.js +493 -0
  101. package/.history/src/core/index_20240818011804.js +493 -0
  102. package/.history/src/core/index_20240818013835.js +493 -0
  103. package/.history/src/core/index_20240818014310.js +493 -0
  104. package/.history/src/core/index_20240818014323.js +493 -0
  105. package/.history/src/core/index_20240818014333.js +493 -0
  106. package/.history/src/core/index_20240818020725.js +496 -0
  107. package/.history/src/core/index_20240819195504.js +497 -0
  108. package/.history/src/core/index_20240819202012.js +495 -0
  109. package/.history/src/core/index_20240819231228.js +501 -0
  110. package/.history/src/core/index_20240819232555.js +502 -0
  111. package/.history/src/core/index_20240819233404.js +502 -0
  112. package/.history/src/core/index_20240820003114.js +495 -0
  113. package/.history/src/core/index_20240820003120.js +495 -0
  114. package/.history/src/core/index_20240820003331.js +495 -0
  115. package/.history/src/core/index_20240820004126.js +498 -0
  116. package/.history/src/core/index_20240820004357.js +497 -0
  117. package/.history/src/core/index_20240820005103.js +498 -0
  118. package/.history/src/core/index_20240820005110.js +499 -0
  119. package/.history/src/core/index_20240820005206.js +497 -0
  120. package/.history/src/core/index_20240820005352.js +497 -0
  121. package/{src/core/index.js → .history/src/core/index_20240823224904.ts} +75 -231
  122. package/.history/src/core/index_20240823224905.js +505 -0
  123. package/.history/src/core/index_20240823231631.ts +530 -0
  124. package/.history/src/core/index_20240823231735.ts +530 -0
  125. package/.history/src/core/index_20240823232123.ts +539 -0
  126. package/.history/src/core/index_20240823232329.ts +539 -0
  127. package/.history/src/core/index_20240823233058.ts +539 -0
  128. package/.history/src/core/index_20240823234946.ts +539 -0
  129. package/.history/src/core/index_20240824005956.ts +534 -0
  130. package/.history/src/core/index_20240824010113.ts +534 -0
  131. package/.history/src/core/index_20240824010124.ts +534 -0
  132. package/.history/src/core/index_20240824010212.ts +534 -0
  133. package/.history/src/core/index_20240824010218.ts +534 -0
  134. package/.history/src/core/index_20240824010407.ts +534 -0
  135. package/.history/src/core/index_20240824010611.ts +534 -0
  136. package/.history/src/core/index_20240824010623.ts +534 -0
  137. package/.history/src/core/index_20240824010652.ts +534 -0
  138. package/.history/src/core/index_20240824011007.ts +534 -0
  139. package/.history/src/core/index_20240824210450.ts +534 -0
  140. package/.history/src/core/index_20240824210703.ts +534 -0
  141. package/.history/src/core/index_20240824210708.ts +534 -0
  142. package/.history/src/core/index_20240824211001.ts +537 -0
  143. package/.history/src/core/index_20240824211258.ts +537 -0
  144. package/.history/src/core/index_20240824211654.ts +537 -0
  145. package/.history/src/core/index_20240824211723.ts +537 -0
  146. package/.history/src/core/index_20240824211808.ts +538 -0
  147. package/.history/src/core/index_20240824214041.js +538 -0
  148. package/.history/src/core/index_20240824215312.ts +538 -0
  149. package/.history/src/core/index_20240824215341.ts +538 -0
  150. package/.history/src/core/index_20240824220703.ts +538 -0
  151. package/.history/src/core/index_20240824220709.ts +538 -0
  152. package/.history/src/core/index_20240825012244.ts +536 -0
  153. package/.history/src/core/index_20240825012435.ts +539 -0
  154. package/.history/src/core/index_20240825012440.ts +539 -0
  155. package/.history/src/core/index_20240826005054.ts +539 -0
  156. package/.history/src/core/index_20240826005321.ts +540 -0
  157. package/.history/src/core/index_20240826005410.ts +539 -0
  158. package/.history/src/core/index_20240826005418.ts +539 -0
  159. package/.history/src/core/index_20240830231825.ts +539 -0
  160. package/.history/src/core/index_20240831022416.ts +539 -0
  161. package/.history/src/core/index_20240901222314.js +459 -0
  162. package/.history/src/core/index_20240901222951.js +459 -0
  163. package/.history/src/core/index_20240901223824.js +471 -0
  164. package/.history/src/core/index_20240901223833.js +468 -0
  165. package/.history/src/core/index_20240902223954.js +447 -0
  166. package/.history/src/core/index_20240902224000.js +446 -0
  167. package/.history/src/core/index_20240902230345.js +448 -0
  168. package/.history/src/core/index_20240902231130.js +449 -0
  169. package/.history/src/core/index_20240902231559.js +449 -0
  170. package/.history/src/core/index_20240902232135.js +449 -0
  171. package/.history/src/core/index_20240902232809.js +452 -0
  172. package/.history/src/core/index_20240902232815.js +452 -0
  173. package/.history/src/core/index_20240903000104.js +467 -0
  174. package/.history/src/core/index_20240904001731.js +444 -0
  175. package/.history/src/core/index_20240904002038.ts +539 -0
  176. package/.history/src/core/index_20240904011848.js +444 -0
  177. package/.history/src/core/index_20240904012138.js +444 -0
  178. package/.history/src/core/index_20240904012743.js +444 -0
  179. package/.history/src/core/index_20240904013051.js +444 -0
  180. package/.history/src/core/resourceManager_20240403231531.ts +16 -0
  181. package/.history/src/core/resourceManager_20240823232627.ts +17 -0
  182. package/.history/src/core/resourceManager_20240824214014.js +16 -0
  183. package/.history/src/core/resourceManager_20240824214620.js +17 -0
  184. package/.history/src/core/scenarioManager_20240812203410.ts +86 -0
  185. package/.history/src/core/scenarioManager_20240812203839.ts +94 -0
  186. package/.history/src/core/scenarioManager_20240812213437.ts +85 -0
  187. package/.history/src/core/scenarioManager_20240813225852.ts +85 -0
  188. package/.history/src/core/scenarioManager_20240823235010.ts +85 -0
  189. package/.history/src/core/scenarioManager_20240904002038.ts +94 -0
  190. package/.history/src/core/scenarioManager_20240904012411.ts +94 -0
  191. package/.history/src/core/scenarioManager_20240904012519.ts +94 -0
  192. package/.history/src/index_20240403231531.js +6 -0
  193. package/.history/src/index_20240429233436.js +8 -0
  194. package/.history/src/index_20240429233926.js +8 -0
  195. package/.history/src/index_20240429234401.js +7 -0
  196. package/.history/src/index_20240429234404.js +6 -0
  197. package/.history/src/resource/soundObject_20240419004314.ts +71 -0
  198. package/.history/src/resource/soundObject_20240815034420.ts +66 -0
  199. package/.history/src/resource/soundObject_20240815034836.ts +79 -0
  200. package/.history/src/resource/soundObject_20240815034919.ts +87 -0
  201. package/.history/src/resource/soundObject_20240815040724.ts +81 -0
  202. package/.history/src/resource/soundObject_20240815041022.ts +87 -0
  203. package/.history/src/resource/soundObject_20240815042103.ts +87 -0
  204. package/.history/src/resource/soundObject_20240823235929.ts +91 -0
  205. package/.history/src/resource/soundObject_20240824213129.ts +99 -0
  206. package/.history/src/resource/soundObject_20240824213611.ts +101 -0
  207. package/.history/src/resource/soundObject_20240824215734.ts +101 -0
  208. package/.history/src/resource/soundObject_20240825004926.ts +101 -0
  209. package/.history/src/resource/soundObject_20240825004947.ts +101 -0
  210. package/.history/src/utils/logger_20240812174230.ts +13 -0
  211. package/.history/src/utils/logger_20240823232736.ts +14 -0
  212. package/.history/src/utils/logger_20240824214930.js +14 -0
  213. package/.history/src/utils/store_20240812174230.ts +17 -0
  214. package/.history/src/utils/store_20240823232948.ts +29 -0
  215. package/.history/src/utils/store_20240824214020.js +17 -0
  216. package/.history/src/utils/store_20240824214955.js +29 -0
  217. package/.history/src/utils/waitUtil_20240812174230.ts +4 -0
  218. package/.history/src/utils/waitUtil_20240823232739.ts +4 -0
  219. package/.history/src/utils/waitUtil_20240824214024.js +4 -0
  220. package/.history/src/utils/waitUtil_20240824215009.js +4 -0
  221. package/.history/test/js/title_20240428215305.js +254 -0
  222. package/.history/test/js/title_20240429221911.js +227 -0
  223. package/.history/test/js/title_20240429222806.js +243 -0
  224. package/.history/test/js/title_20240429222854.js +263 -0
  225. package/.history/test/js/title_20240429222906.js +263 -0
  226. package/.history/test/js/title_20240429235639.js +263 -0
  227. package/.history/test/js/title_20240429235840.js +263 -0
  228. package/.history/test/js/title_20240430014721.js +262 -0
  229. package/.history/test/js/title_20240430014759.js +254 -0
  230. package/.history/test/js/title_20240430134612.js +285 -0
  231. package/.history/test/js/title_20240430141051.js +285 -0
  232. package/.history/test/js/title_20240430173745.js +245 -0
  233. package/.history/tsconfig_20240812174230.json +22 -0
  234. package/.history/tsconfig_20240824010157.json +19 -0
  235. package/.history/tsconfig_20240824220700.json +20 -0
  236. package/.history/tsconfig_20240825011301.json +20 -0
  237. package/.history/webpack.config_20240423002825.js +37 -0
  238. package/.history/webpack.config_20240430001157.js +38 -0
  239. package/.history/webpack.config_20240430001309.js +37 -0
  240. package/.history/webpack.config_20240430002112.js +37 -0
  241. package/CLAUDE.md +96 -0
  242. package/LICENSE +21 -0
  243. package/README.md +108 -39
  244. package/coverage/lcov-report/base.css +224 -0
  245. package/coverage/lcov-report/block-navigation.js +87 -0
  246. package/coverage/lcov-report/core/drawer.ts.html +1264 -0
  247. package/coverage/lcov-report/core/index.html +146 -0
  248. package/coverage/lcov-report/core/resourceManager.ts.html +136 -0
  249. package/coverage/lcov-report/core/scenarioManager.ts.html +373 -0
  250. package/coverage/lcov-report/favicon.png +0 -0
  251. package/coverage/lcov-report/index.html +146 -0
  252. package/coverage/lcov-report/prettify.css +1 -0
  253. package/coverage/lcov-report/prettify.js +2 -0
  254. package/coverage/lcov-report/resource/ImageObject.ts.html +433 -0
  255. package/coverage/lcov-report/resource/index.html +131 -0
  256. package/coverage/lcov-report/resource/soundObject.ts.html +346 -0
  257. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  258. package/coverage/lcov-report/sorter.js +196 -0
  259. package/coverage/lcov-report/utils/TextMeasurer.ts.html +520 -0
  260. package/coverage/lcov-report/utils/index.html +161 -0
  261. package/coverage/lcov-report/utils/logger.ts.html +142 -0
  262. package/coverage/lcov-report/utils/store.ts.html +151 -0
  263. package/coverage/lcov-report/utils/waitUtil.ts.html +97 -0
  264. package/coverage/lcov.info +882 -0
  265. package/dist/README.md +294 -0
  266. package/dist/engineConfig.json +10 -0
  267. package/dist/package.json +51 -0
  268. package/dist/parser/cli.js +61 -0
  269. package/dist/parser/parser.js +53 -0
  270. package/{src → dist/src}/core/drawer.js +0 -9
  271. package/dist/src/core/drawer.js.map +1 -0
  272. package/dist/src/core/index.js +969 -0
  273. package/{src → dist/src}/core/scenarioManager.js +5 -6
  274. package/dist/src/core/scenarioManager.js.map +1 -0
  275. package/{src → dist/src}/resource/soundObject.js +4 -2
  276. package/dist/src/resource/soundObject.js.map +1 -0
  277. package/dist/src/utils/fallbackTemplate.js +13 -0
  278. package/dist/src/utils/fallbackTemplate.js.map +1 -0
  279. package/dist/webtalekit-alpha-0.2.13.tgz +0 -0
  280. package/docs/event-system-specification.md +493 -0
  281. package/docs/glossary.html +833 -0
  282. package/docs/index.html +296 -0
  283. package/docs/tag-reference.html +1317 -0
  284. package/docs/ui-template-guide.html +1068 -0
  285. package/example/README.md +29 -0
  286. package/example/engineConfig.json +10 -0
  287. package/example/package-lock.json +5145 -0
  288. package/example/package.json +26 -0
  289. package/example/src/index.js +13 -0
  290. package/example/src/resource/background/beach.jpg +0 -0
  291. package/example/src/resource/background/city.jpg +0 -0
  292. package/example/src/resource/background/crossroad.jpg +0 -0
  293. package/example/src/resource/background/forest.jpg +0 -0
  294. package/example/src/resource/background/laboratory.jpg +0 -0
  295. package/example/src/resource/background/library.jpg +0 -0
  296. package/example/src/resource/background/living_room.jpg +0 -0
  297. package/example/src/resource/background/music_room.jpg +0 -0
  298. package/example/src/resource/background/stage.jpg +0 -0
  299. package/example/src/resource/background/sunset.jpg +0 -0
  300. package/example/src/resource/background/title_bg.png +0 -0
  301. package/example/src/resource/bgm/calm_music.wav +0 -0
  302. package/example/src/resource/bgm/doorbell.mp3 +0 -0
  303. package/example/src/resource/bgm/nc366476_Virtual_Voyage.mp3 +0 -0
  304. package/example/src/resource/bgm/title_theme.mp3 +0 -0
  305. package/example/src/resource/chara/dancer.png +0 -0
  306. package/example/src/resource/chara/guest.png +0 -0
  307. package/example/src/resource/chara/guide.png +0 -0
  308. package/example/src/resource/chara/scientist.png +0 -0
  309. package/example/src/resource/config.js +0 -0
  310. package/example/src/resource/se/doorbell.mp3 +0 -0
  311. package/example/src/resource/system/systemPicture/01_message/message.png +0 -0
  312. package/example/src/resource/system/systemPicture/02_button/button.png +0 -0
  313. package/example/src/resource/system/systemPicture/02_button/button2.png +0 -0
  314. package/example/src/resource/system/systemPicture/02_button/button3.png +0 -0
  315. package/example/src/resource/system/systemPicture/03_system_button/auto.png +0 -0
  316. package/example/src/resource/system/systemPicture/03_system_button/auto2.png +0 -0
  317. package/example/src/resource/system/systemPicture/03_system_button/close.png +0 -0
  318. package/example/src/resource/system/systemPicture/03_system_button/close2.png +0 -0
  319. package/example/src/resource/system/systemPicture/03_system_button/config.png +0 -0
  320. package/example/src/resource/system/systemPicture/03_system_button/config2.png +0 -0
  321. package/example/src/resource/system/systemPicture/03_system_button/load.png +0 -0
  322. package/example/src/resource/system/systemPicture/03_system_button/load2.png +0 -0
  323. package/example/src/resource/system/systemPicture/03_system_button/log.png +0 -0
  324. package/example/src/resource/system/systemPicture/03_system_button/log2.png +0 -0
  325. package/example/src/resource/system/systemPicture/03_system_button/menu.png +0 -0
  326. package/example/src/resource/system/systemPicture/03_system_button/menu2.png +0 -0
  327. package/example/src/resource/system/systemPicture/03_system_button/qload.png +0 -0
  328. package/example/src/resource/system/systemPicture/03_system_button/qload2.png +0 -0
  329. package/example/src/resource/system/systemPicture/03_system_button/qsave.png +0 -0
  330. package/example/src/resource/system/systemPicture/03_system_button/qsave2.png +0 -0
  331. package/example/src/resource/system/systemPicture/03_system_button/save.png +0 -0
  332. package/example/src/resource/system/systemPicture/03_system_button/save2.png +0 -0
  333. package/example/src/resource/system/systemPicture/03_system_button/screen.png +0 -0
  334. package/example/src/resource/system/systemPicture/03_system_button/screen2.png +0 -0
  335. package/example/src/resource/system/systemPicture/03_system_button/skip.png +0 -0
  336. package/example/src/resource/system/systemPicture/03_system_button/skip2.png +0 -0
  337. package/example/src/resource/system/systemPicture/03_system_button/title.png +0 -0
  338. package/example/src/resource/system/systemPicture/03_system_button/title2.png +0 -0
  339. package/example/src/resource/system/systemPicture//345/210/251/347/224/250/350/246/217/347/264/204.txt +0 -0
  340. package/example/src/resource/system/wait.gif +0 -0
  341. package/example/src/scene/animation.scene +28 -0
  342. package/example/src/scene/background.scene +29 -0
  343. package/example/src/scene/character.scene +26 -0
  344. package/example/src/scene/choice.scene +97 -0
  345. package/example/src/scene/dialog.scene +105 -0
  346. package/example/src/scene/effects.scene +38 -0
  347. package/example/src/scene/en/animation.scene +28 -0
  348. package/example/src/scene/en/background.scene +26 -0
  349. package/example/src/scene/en/character.scene +26 -0
  350. package/example/src/scene/en/choice.scene +32 -0
  351. package/example/src/scene/en/effects.scene +37 -0
  352. package/example/src/scene/en/sound.scene +26 -0
  353. package/example/src/scene/en/text.scene +26 -0
  354. package/example/src/scene/en/title.scene +39 -0
  355. package/example/src/scene/if_test.scene +37 -0
  356. package/example/src/scene/resource-error-test.scene +15 -0
  357. package/example/src/scene/save-load-test.scene +48 -0
  358. package/example/src/scene/sound.scene +26 -0
  359. package/example/src/scene/test_error.scene +21 -0
  360. package/example/src/scene/text.scene +34 -0
  361. package/example/src/scene/title.scene +51 -0
  362. package/example/src/screen/incoming.html +474 -0
  363. package/example/src/screen/title.html +135 -0
  364. package/example/src/template.html +16 -0
  365. package/example/test-results/.last-run.json +4 -0
  366. package/example/webpack.config.js +69 -0
  367. package/image.png +0 -0
  368. package/package.json +3 -1
  369. package/playwright-report/index.html +71 -0
  370. package/s-plan1-5Light-s-1.jpg +0 -0
  371. package/test-results/.last-run.json +6 -0
  372. package/tests/e2e/if-global-attribute.spec.js +90 -0
  373. package/tests/e2e/resource-error-handling.spec.js +58 -0
  374. package/tests/e2e/screenshots/before-error-check.png +0 -0
  375. package/tests/e2e/screenshots/choices.png +0 -0
  376. package/tests/e2e/screenshots/message-window-click-wait.png +0 -0
  377. package/src/core/drawer.js.map +0 -1
  378. package/src/core/scenarioManager.js.map +0 -1
  379. package/src/resource/soundObject.js.map +0 -1
  380. /package/{src → dist/src}/core/resourceManager.js +0 -0
  381. /package/{src → dist/src}/core/resourceManager.js.map +0 -0
  382. /package/{src → dist/src}/resource/ImageObject.js +0 -0
  383. /package/{src → dist/src}/resource/ImageObject.js.map +0 -0
  384. /package/{src → dist/src}/utils/logger.js +0 -0
  385. /package/{src → dist/src}/utils/logger.js.map +0 -0
  386. /package/{src → dist/src}/utils/store.js +0 -0
  387. /package/{src → dist/src}/utils/store.js.map +0 -0
  388. /package/{src → dist/src}/utils/waitUtil.js +0 -0
  389. /package/{src → dist/src}/utils/waitUtil.js.map +0 -0
@@ -0,0 +1,969 @@
1
+ import { Drawer } from './drawer'
2
+ import { ScenarioManager } from './scenarioManager'
3
+ import { ImageObject } from '../resource/ImageObject'
4
+ import { ResourceManager } from './resourceManager'
5
+ import { SoundObject } from '../resource/soundObject'
6
+ import engineConfig from '../../engineConfig.json'
7
+ import { sleep } from '../utils/waitUtil'
8
+ import { getDefaultDialogTemplate } from '../utils/fallbackTemplate'
9
+ import { generateStore } from '../utils/store'
10
+
11
+ export class Core {
12
+ constructor() {
13
+ // プロパティの初期化
14
+ this.bgm = null
15
+ this.isAuto = false
16
+ this.isNext = false
17
+ this.isSkip = false
18
+ this.onNextHandler = null
19
+ this.sceneFile = {}
20
+ this.sceneConfig = {}
21
+ this.commandList = {
22
+ text: this.textHandler,
23
+ choice: this.choiceHandler,
24
+ show: this.showHandler,
25
+ newpage: this.newpageHandler,
26
+ hide: this.hideHandler,
27
+ jump: this.jumpHandler,
28
+ sound: this.soundHandler,
29
+ say: this.sayHandler,
30
+ if: this.ifHandler,
31
+ call: this.callHandler,
32
+ moveto: this.moveToHandler,
33
+ route: this.routeHandler,
34
+ wait: this.waitHandler,
35
+ dialog: this.dialogHandler,
36
+ save: this.saveHandler,
37
+ load: this.loadHandler,
38
+ }
39
+ // gameContainerの初期化(HTMLのgameContainerを取得する)
40
+ this.gameContainer = document.getElementById('gameContainer')
41
+ // Drawerの初期化(canvasタグのサイズを設定する)
42
+ this.drawer = new Drawer(this.gameContainer)
43
+ // ScenarioManagerの初期化(変数の初期値設定)
44
+ this.scenarioManager = new ScenarioManager()
45
+ // ResourceManagerの初期化(引数にconfigを渡して、リソース管理配列を作る)
46
+ this.resourceManager = new ResourceManager(import(/* webpackIgnore: true */ '/src/resource/config.js')) // webpackIgnoreでバンドルを無視する
47
+ this.displayedImages = {}
48
+ this.usedSounds = {}
49
+ // ストレージの初期化
50
+ this.store = generateStore()
51
+ }
52
+
53
+ setConfig(config) {
54
+ // ゲームの設定情報をセットする
55
+ engineConfig = config
56
+ }
57
+
58
+ async start(initScene) {
59
+ // TODO: ブラウザ用のビルドの場合は、最初にクリックしてもらう
60
+ // titleタグの内容を書き換える
61
+ document.title = engineConfig.title
62
+ // sceneファイルを読み込む
63
+ await this.loadScene(initScene || 'title')
64
+ // 画面を表示する
65
+ await this.loadScreen(this.sceneConfig)
66
+ // 入力イベントを設定する
67
+ document.querySelector('#gameContainer').addEventListener('keydown', (e) => {
68
+ if (e.key === 'Enter') {
69
+ this.onNextHandler()
70
+ } else if (e.key === 'Control') {
71
+ this.drawer.isSkip = true
72
+ this.isNext = true
73
+ }
74
+ })
75
+ document.querySelector('#gameContainer').addEventListener('keyup', (e) => {
76
+ if (e.key === 'Control') {
77
+ this.drawer.isSkip = true
78
+ this.isNext = false
79
+ }
80
+ })
81
+ document.querySelector('#gameContainer').addEventListener('click', (e) => {
82
+ this.onNextHandler()
83
+ })
84
+
85
+ await this.textHandler('タップでスタート')
86
+ // BGMを再生する
87
+ this.soundHandler({
88
+ mode: 'bgm',
89
+ src: this.sceneConfig.bgm,
90
+ loop: true,
91
+ play: true,
92
+ })
93
+ // シナリオを実行する
94
+ while (this.scenarioManager.hasNext()) {
95
+ await this.runScenario()
96
+ }
97
+ }
98
+
99
+ async loadScene(sceneFileName) {
100
+ // sceneファイルを読み込む
101
+ this.sceneFile = await import(/* webpackChunkName: "[request]" */ `/src/js/${sceneFileName}.js`)
102
+ // sceneファイルの初期化処理を実行
103
+ if (this.sceneFile.init) {
104
+ this.sceneFile.init(this.getAPIForScript())
105
+ }
106
+ // シナリオの進行状況を初期化
107
+ this.scenarioManager.setScenario(this.sceneFile.scenario, sceneFileName)
108
+ this.sceneConfig = { ...this.sceneConfig, ...this.sceneFile.sceneConfig }
109
+ }
110
+
111
+ // ファイルの存在確認を行う関数
112
+ async checkResourceExists(url) {
113
+ try {
114
+ const response = await fetch(url, { method: 'HEAD' })
115
+ return response.ok
116
+ } catch (error) {
117
+ return false
118
+ }
119
+ }
120
+
121
+ // ファイルの存在確認を行う関数
122
+ async checkResourceExists(url) {
123
+ try {
124
+ const response = await fetch(url, { method: 'HEAD' })
125
+ return response.ok
126
+ } catch (error) {
127
+ return false
128
+ }
129
+ }
130
+
131
+ async loadScreen(sceneConfig, options = {}) {
132
+ const {
133
+ isDialog = false, // ダイアログモードかどうか
134
+ fallbackTemplate = null, // フォールバック用テンプレート
135
+ skipBackground = false, // 背景画像の読み込みをスキップ
136
+ } = options
137
+
138
+ // 画面名を設定する。
139
+ this.scenarioManager.progress.currentScene = sceneConfig.name
140
+ this.scenarioManager.setSceneName(sceneConfig.name)
141
+ // sceneConfig.templateを読み込んで、HTMLを表示する
142
+ // テンプレートの存在確認
143
+ if (!isDialog && !(await this.checkResourceExists(sceneConfig.template))) {
144
+ console.error(`Template file not found: ${sceneConfig.template}`)
145
+ throw new Error(`Template file not found: ${sceneConfig.template}`)
146
+ }
147
+
148
+ const htmlString = await (await fetch(sceneConfig.template)).text()
149
+ // 読み込んだhtmlからIDにmainを持つdivタグとStyleタグ以下を取り出して、gameContainerに表示する
150
+ let parser = new DOMParser()
151
+ let doc = parser.parseFromString(htmlString, 'text/html')
152
+
153
+ let mainDiv = isDialog ? doc.getElementById('dialogContainer') : doc.getElementById('main')
154
+
155
+ if (!mainDiv) {
156
+ // mainが見つからない場合は、フォールバックテンプレートを使用
157
+ if (fallbackTemplate) {
158
+ console.warn(`Main div not found in template, using fallback: ${fallbackTemplate}`)
159
+ mainDiv = doc.createElement('div')
160
+ const fallbackTemplateText = fallbackTemplate()
161
+ mainDiv.innerHTML = fallbackTemplateText.htmlString
162
+ // フォールバックテンプレートのスタイルを適用
163
+ const styleElement = doc.head.getElementsByTagName('style')[0] || doc.createElement('style')
164
+ styleElement.textContent = fallbackTemplateText.styleString || ''
165
+ doc.head.appendChild(styleElement)
166
+ } else {
167
+ throw new Error('Main div not found in template and no fallback provided.')
168
+ }
169
+ }
170
+ if (!this.gameContainer) {
171
+ throw new Error('Game container not found.')
172
+ }
173
+ // ゲーム進行用に必要な情報をセットする
174
+ if (!isDialog) {
175
+ // 既に読み込んだスタイルシートがあったら削除する
176
+ const styleTags = document.head.getElementsByTagName('style')
177
+ for (const styleTag of styleTags) {
178
+ document.head.removeChild(styleTag)
179
+ }
180
+ this.gameContainer.innerHTML = mainDiv.innerHTML
181
+ this.drawer.setScreen(this.gameContainer, engineConfig.resolution)
182
+ } else {
183
+ this.gameContainer.appendChild(mainDiv)
184
+ }
185
+ // Styleタグを取り出して、headタグに追加する
186
+ const styleElement = doc.head.getElementsByTagName('style')[0]
187
+ document.head.appendChild(styleElement)
188
+
189
+ if (!skipBackground) {
190
+ console.info(`background: ${await this.checkResourceExists(sceneConfig.background)}`)
191
+ // 背景画像の存在確認
192
+ if (!(await this.checkResourceExists(sceneConfig.background))) {
193
+ throw new Error(`Background image not found: ${sceneConfig.background}`)
194
+ } else {
195
+ // 背景画像を表示する
196
+ const background = await new ImageObject().setImageAsync(sceneConfig.background)
197
+ this.displayedImages['background'] = {
198
+ image: background,
199
+ size: {
200
+ width: this.gameContainer.clientWidth,
201
+ height: this.gameContainer.clientHeight,
202
+ },
203
+ }
204
+ }
205
+ this.drawer.show(this.displayedImages)
206
+ }
207
+ }
208
+
209
+ async runScenario() {
210
+ let scenarioObject = this.scenarioManager.next()
211
+ if (!scenarioObject) {
212
+ return
213
+ }
214
+ // シナリオオブジェクトのtypeプロパティに応じて、対応する関数を実行する
215
+ const commandType = scenarioObject.type || 'text'
216
+ const commandFunction = this.commandList[commandType]
217
+
218
+ // コマンドが存在しない場合のエラーハンドリング
219
+ if (!commandFunction) {
220
+ const errorMessage = `Error: Command type "${commandType}" is not defined`
221
+ throw new Error(errorMessage)
222
+ }
223
+
224
+ const boundFunction = commandFunction.bind(this)
225
+ scenarioObject = await this.httpHandler(scenarioObject)
226
+
227
+ // ifグローバル属性の処理
228
+ if (scenarioObject.if !== undefined) {
229
+ const condition = this.executeCode(`return ${scenarioObject.if}`)
230
+
231
+ // 条件がfalseの場合、このタグの処理をスキップ
232
+ if (!condition) {
233
+ return
234
+ }
235
+ }
236
+
237
+ await boundFunction(scenarioObject)
238
+ }
239
+
240
+ async textHandler(scenarioObject) {
241
+ // 文章だけの場合は、contentプロパティに配列として設定する
242
+ if (typeof scenarioObject === 'string') scenarioObject = { content: [scenarioObject] }
243
+ // httpレスポンスがある場合は、list.contentに追加して、表示対象に加える
244
+ if (scenarioObject.then || scenarioObject.error) {
245
+ scenarioObject.content = scenarioObject.content.concat(scenarioObject.then || scenarioObject.error)
246
+ }
247
+
248
+ // 名前が設定されている場合は、名前を表示する
249
+ if (scenarioObject.name) {
250
+ this.drawer.drawName(scenarioObject.name)
251
+ } else {
252
+ this.drawer.drawName('')
253
+ }
254
+
255
+ //prettier-ignore
256
+ this.onNextHandler = () => { this.drawer.isSkip = true }
257
+ this.drawer.clearText() // テキスト表示領域をクリア
258
+ // 表示する文章を1行ずつ表示する
259
+ for (const text of scenarioObject.content) {
260
+ if (typeof text === 'string') {
261
+ await this.drawer.drawText(this.expandVariable(text), scenarioObject.speed || 25)
262
+ } else {
263
+ if (text.type === 'br' || text.type === 'wait') {
264
+ if (text.type === 'br') this.drawer.drawLineBreak()
265
+ if (!text.nw) {
266
+ await this.waitHandler({ wait: text.time })
267
+ }
268
+ } else {
269
+ const container = this.drawer.createDecoratedElement(text)
270
+ await this.drawer.drawText(this.expandVariable(text.content[0]), text.speed || 25, container)
271
+ }
272
+ }
273
+ }
274
+ await this.waitHandler({ wait: scenarioObject.time })
275
+ this.drawer.isSkip = false
276
+ this.scenarioManager.setHistory(scenarioObject.content)
277
+ }
278
+
279
+ expandVariable(text) {
280
+ if (typeof text !== 'string') return text
281
+ return text.replace(/{{([^{}]+)}}/g, (match) => {
282
+ const expr = match.slice(2, -2)
283
+ const returnValue = this.executeCode(`return ${expr}`)
284
+ return typeof returnValue == 'object' ? JSON.stringify(returnValue) : returnValue
285
+ })
286
+ }
287
+
288
+ async waitHandler(line) {
289
+ // line.timeがある場合、line.waitに代入する
290
+ if (line.time) line.wait = line.time
291
+ //prettier-ignore
292
+ this.onNextHandler = () => { this.isNext = true }
293
+
294
+ // line.waitが数値に変換可能な文字列の場合、数値に変換
295
+ if (typeof line.wait === 'string' && !isNaN(Number(line.wait))) {
296
+ line.wait = Number(line.wait)
297
+ }
298
+ if (typeof line.wait === 'number') {
299
+ if (line.wait > 0 || this.isAuto) {
300
+ const waitTime = line.wait || 1500
301
+ // 指定された時間だけ待機
302
+ await sleep(waitTime)
303
+ }
304
+ } else {
305
+ // 改行ごとに入力待ち
306
+ await this.clickWait()
307
+ }
308
+ }
309
+
310
+ // クリック待ち処理
311
+ async clickWait() {
312
+ this.drawer.setVisibility('#waitCircle', true)
313
+ return new Promise((resolve) => {
314
+ const intervalId = setInterval(() => {
315
+ if (this.isNext) {
316
+ this.drawer.setVisibility('#waitCircle', false)
317
+ clearInterval(intervalId)
318
+ this.isNext = false
319
+ resolve(null)
320
+ }
321
+ }, 500)
322
+ })
323
+ }
324
+
325
+ async sayHandler(line) {
326
+ // say(name:string, pattern: string, voice: {playの引数}, ...text)
327
+ if (line.voice) await this.soundHandler({ path: line.voice, play: true })
328
+ await this.textHandler({ content: line.content, name: line.name, speed: line.speed || 25 })
329
+ this.scenarioManager.setHistory(line)
330
+ }
331
+
332
+ async choiceHandler(line) {
333
+ document.querySelector('#interactiveView').style.visibility = 'visible'
334
+ if (line.prompt) this.textHandler(line.prompt)
335
+ // ムスタッシュ構文があるときは、変数の展開
336
+ line.content.forEach((choice) => {
337
+ choice.label = this.expandVariable(choice.label)
338
+ })
339
+ const { selectId, onSelect: selectHandler } = await this.drawer.drawChoices(line)
340
+ if (selectHandler !== undefined) {
341
+ this.scenarioManager.addScenario(selectHandler)
342
+ }
343
+ this.scenarioManager.setHistory({ line, ...selectId })
344
+ document.querySelector('#interactiveView').style.visibility = 'hidden'
345
+ }
346
+
347
+ jumpHandler(line) {
348
+ // ジャンプ先が現在の行より小さいときは、今の行とジャンプ先の行の間で、sub=falseの行を抽出して、scenarioManagerに追加する
349
+ if (line.index < this.scenarioManager.getIndex()) {
350
+ // scenarioManagerからシナリオを取得
351
+ const scenario = this.scenarioManager.getScenario()
352
+ // 結合用に、ジャンプ先までのインデックスを取得
353
+ const noEditScenarioList = {
354
+ before: scenario.slice(0, line.index),
355
+ after: scenario.slice(this.scenarioManager.getIndex()),
356
+ }
357
+ // ジャンプ先のインデックスまでのシナリオを取得
358
+ const scenarioList = scenario.slice(line.index, this.scenarioManager.getIndex())
359
+ // sub=falseの行だけを取得
360
+ const subFalseScenario = scenarioList.filter((line) => !line.sub)
361
+ // scenarioManagerに追加
362
+ this.scenarioManager.setScenario([...noEditScenarioList.before, ...subFalseScenario, ...noEditScenarioList.after])
363
+ }
364
+ this.newpageHandler()
365
+ this.scenarioManager.setIndex(Number(line.index))
366
+ }
367
+
368
+ async showHandler(line) {
369
+ // ムスタッシュ構文があるときは、変数の展開
370
+ Object.keys(line).forEach((item) => {
371
+ line[item] = this.expandVariable(line[item])
372
+ })
373
+ // 表示する画像の情報を管理オブジェクトに追加
374
+ const modeList = { bg: 'background', cutin: '', chara: '', cg: 'background', effect: 'effect' }
375
+ const key = Object.keys(modeList).includes(line.mode) ? modeList[line.mode] : line.name || line.src.split('/').pop()
376
+ const baseLine = engineConfig.resolution.height / 2
377
+ const centerPoint = {
378
+ left: { x: engineConfig.resolution.width * 0.25, y: baseLine },
379
+ center: { x: engineConfig.resolution.width * 0.5, y: baseLine },
380
+ right: { x: engineConfig.resolution.width * 0.75, y: baseLine },
381
+ }
382
+ line.src = this.expandVariable(line.src) || line.name
383
+
384
+ const image = await this.getImageObject(line)
385
+ // 画像の表示位置を設定
386
+ let position = { x: line.x || 0, y: line.y || 0 }
387
+ // prettier-ignore
388
+ let size = line.width && line.height ? { width: line.width, height: line.height } : { width: image.getSize().width, height: image.getSize().height }
389
+
390
+ // line.modeが'cutin'の場合、center:middleのエイリアスを強制する
391
+ if (line.mode === 'cutin') {
392
+ line.pos = 'center:middle'
393
+ }
394
+
395
+ if (line.mode === 'cg') {
396
+ this.tempImages = { ...this.displayedImages }
397
+ this.displayedImages = { background: line.src }
398
+ size = { width: engineConfig.resolution.width, height: engineConfig.resolution.height }
399
+ }
400
+
401
+ if (line.pos) {
402
+ const pos = line.pos.split(':')
403
+ const baseLines = {
404
+ top: 0 + size.height,
405
+ middle: engineConfig.resolution.height / 2,
406
+ bottom: engineConfig.resolution.height - size.height,
407
+ }
408
+ // エイリアスが設定されている場合、画像の中心点を求めて、画像の表示位置を設定する
409
+ position.x = centerPoint[pos[0]].x - size.width / 2
410
+ if (pos[1] === 'middle') {
411
+ position.y = baseLines[pos[1]] - size.width / 2
412
+ } else if (pos[1]) {
413
+ position.y = baseLines[pos[1]]
414
+ } else {
415
+ position.y = baseLine / 2
416
+ }
417
+ }
418
+ this.displayedImages[key] = {
419
+ image,
420
+ pos: position,
421
+ size: size,
422
+ look: line.look,
423
+ entry: line.entry,
424
+ }
425
+
426
+ if (line.sepia) this.displayedImages[key].image.setSepia(line.sepia)
427
+ if (line.mono) this.displayedImages[key].image.setMonochrome(line.mono)
428
+ if (line.blur) this.displayedImages[key].image.setBlur(line.blur)
429
+ if (line.opacity) this.displayedImages[key].image.setOpacity(line.opacity)
430
+
431
+ if (line.transition === 'fade') {
432
+ // フェードイン効果で表示
433
+ await this.drawer.fadeIn(line.duration || 2000, await this.getImageObject(line), {
434
+ pos: position,
435
+ size,
436
+ look: line.look,
437
+ entry: line.entry,
438
+ })
439
+ this.drawer.show(this.displayedImages)
440
+ } else {
441
+ // 通常の表示処理
442
+ this.drawer.show(this.displayedImages)
443
+ }
444
+ }
445
+
446
+ async hideHandler(line) {
447
+ const targetImage = this.displayedImages[line.name]
448
+ if (line.mode === 'cg') {
449
+ this.displayedImages = { ...this.tempImages }
450
+ this.tempImages = {}
451
+ } else {
452
+ delete this.displayedImages[line.name]
453
+ }
454
+ this.drawer.show(this.displayedImages)
455
+ if (line.transition === 'fade') {
456
+ // フェードアウト効果で非表示
457
+ await this.drawer.fadeOut(line.duration || 1000, targetImage.image, {
458
+ pos: targetImage.pos,
459
+ size: targetImage.size,
460
+ look: targetImage.look,
461
+ })
462
+ }
463
+ }
464
+
465
+ async moveToHandler(line) {
466
+ const key = line.name
467
+ await this.drawer.moveTo(key, this.displayedImages, { x: line.x, y: line.y }, line.duration | 1)
468
+ }
469
+
470
+ async getImageObject(line) {
471
+ const name = line.name || line.src.split('/').pop()
472
+ let image
473
+
474
+ // ファイルの存在確認
475
+ if (!(await this.checkResourceExists(line.src))) {
476
+ console.error(`Image file not found: ${line.src}`)
477
+
478
+ // エラーメッセージを表示
479
+ await this.textHandler(`エラー: 画像ファイルが見つかりません: ${line.src}`)
480
+ // 空の画像オブジェクトを返す
481
+ return new ImageObject()
482
+ }
483
+
484
+ // 既にインスタンスがある場合は、それを使う
485
+ if (Object.hasOwn(this.displayedImages, name)) {
486
+ const targetImage = this.displayedImages[name]
487
+ const imageObject = targetImage ? targetImage.image : new ImageObject()
488
+ image = await imageObject.setImageAsync(line.src)
489
+ } else {
490
+ image = await new ImageObject().setImageAsync(line.src)
491
+ }
492
+ return image
493
+ }
494
+
495
+ async soundHandler(line) {
496
+ const soundObject = await this.getSoundObject(line)
497
+
498
+ if (line.mode === 'bgm') {
499
+ // BGMの場合、既存のBGMを停止して、新しいBGMをセットする
500
+ if (this.bgm && this.bgm.isPlaying) {
501
+ this.bgm.stop()
502
+ }
503
+ this.bgm = soundObject
504
+ this.bgm.play(true)
505
+ } else {
506
+ if ('play' in line) {
507
+ 'loop' in line ? soundObject.play(true) : soundObject.play()
508
+ } else if ('stop' in line) {
509
+ soundObject.stop()
510
+ } else if ('pause' in line) {
511
+ soundObject.pause()
512
+ }
513
+ }
514
+
515
+ // soundObjectを管理オブジェクトに追加
516
+ const key = line.name || line.src.split('/').pop()
517
+ this.usedSounds[key] = {
518
+ audio: soundObject,
519
+ }
520
+ }
521
+
522
+ async getSoundObject(line) {
523
+ const name = line.name || line.src.split('/').pop()
524
+ let resource
525
+
526
+ // ファイルの存在確認
527
+ if (!(await this.checkResourceExists(line.src))) {
528
+ console.error(`Sound file not found: ${line.src}`)
529
+
530
+ // エラーメッセージを表示
531
+ await this.textHandler(`エラー: 音声ファイルが見つかりません: ${line.src}`)
532
+ // 空のサウンドオブジェクトを返す
533
+ return new SoundObject()
534
+ }
535
+
536
+ // 既にインスタンスがある場合は、それを使う
537
+ if (Object.hasOwn(this.usedSounds, name)) {
538
+ const targetResource = this.usedSounds[name]
539
+ const soundObject = targetResource ? targetResource.audio : new SoundObject()
540
+ resource = await soundObject.setAudioAsync(line.src)
541
+ } else {
542
+ resource = await new SoundObject().setAudioAsync(line.src)
543
+ }
544
+ return resource
545
+ }
546
+
547
+ newpageHandler() {
548
+ this.displayedImages = {
549
+ background: {
550
+ image: this.getBackground(),
551
+ size: {
552
+ width: this.gameContainer.clientWidth,
553
+ height: this.gameContainer.clientHeight,
554
+ },
555
+ },
556
+ }
557
+ this.drawer.clear()
558
+ this.drawer.show(this.displayedImages)
559
+ }
560
+
561
+ async ifHandler(line) {
562
+ const isTrue = this.executeCode(`return ${line.condition}`)
563
+ const appendScenario = isTrue ? line.content[0].content : line.content[1].content
564
+ this.scenarioManager.addScenario(appendScenario)
565
+ }
566
+
567
+ async routeHandler(line) {
568
+ if (this.bgm.isPlaying) {
569
+ // BGMを停止する
570
+ this.soundHandler({
571
+ mode: 'bgm',
572
+ src: this.sceneConfig.bgm,
573
+ stop: true,
574
+ })
575
+ }
576
+ this.newpageHandler()
577
+ if (this.sceneFile.cleanUp) {
578
+ // 終了処理を実行する
579
+ this.sceneFile.cleanUp()
580
+ }
581
+ // sceneファイルを読み込む
582
+ await this.loadScene(line.to)
583
+ // 画面を表示する
584
+ await this.loadScreen(this.sceneConfig)
585
+ // BGMを再生する
586
+ this.soundHandler({
587
+ mode: 'bgm',
588
+ src: this.sceneConfig.bgm,
589
+ loop: true,
590
+ play: true,
591
+ })
592
+ }
593
+
594
+ // Sceneファイルに、ビルド時に実行処理を追加して、そこに処理をお願いしたほうがいいかも?
595
+ callHandler(line) {
596
+ this.executeCode(line.method)
597
+ }
598
+
599
+ async httpHandler(line) {
600
+ if (!(line.get || line.post || line.put || line.delete)) {
601
+ return line
602
+ }
603
+ // progress属性を処理する
604
+ // prettier-ignore
605
+ const progressText = line.content.filter((content) => content.type === 'progress')[0]
606
+ if (progressText) {
607
+ await this.textHandler({ content: [progressText.content][0], wait: 0 })
608
+ }
609
+ // get,post,put,delete属性を処理する
610
+ const headers = line.content
611
+ .filter((content) => content.type === 'header')[0]
612
+ .content.reduce(
613
+ (acc, header) => ({
614
+ ...acc,
615
+ [header.type]: header.content,
616
+ }),
617
+ {},
618
+ )
619
+ const body = line.content
620
+ .filter((content) => content.type === 'data')[0]
621
+ .content.reduce(
622
+ (acc, header) => ({
623
+ ...acc,
624
+ [header.type]: header.content,
625
+ }),
626
+ {},
627
+ )
628
+ const response = await fetch(line.get || line.post || line.put || line.delete, {
629
+ method: line.get ? 'GET' : line.post ? 'POST' : line.put ? 'PUT' : 'DELETE',
630
+ headers: headers,
631
+ body: JSON.stringify(body),
632
+ })
633
+ if (response.ok) {
634
+ const json = await response.json()
635
+ this.sceneFile.res = json
636
+ line.then = line.content.filter((content) => content.type === 'then')[0].content
637
+ } else {
638
+ this.sceneFile.res = json
639
+ line.error = line.content.filter((content) => content.type === 'error')[0].content
640
+ }
641
+ if (line.content) {
642
+ line.content = line.content.filter(
643
+ (content) =>
644
+ !(
645
+ content.type &&
646
+ (content.type === 'header' ||
647
+ content.type === 'data' ||
648
+ content.type === 'then' ||
649
+ content.type === 'error' ||
650
+ content.type === 'progress')
651
+ ),
652
+ )
653
+ }
654
+ return line
655
+ }
656
+
657
+ async dialogHandler(scenarioObject) {
658
+ let result = null
659
+ if (!scenarioObject || !scenarioObject.content) {
660
+ throw new Error('Invalid scenario object for dialog handler.')
661
+ }
662
+ // 既にあるダイアログがある場合は、閉じる
663
+ const existingDialog = document.querySelector('#dialogContainer')
664
+ if (existingDialog) {
665
+ existingDialog.close()
666
+ existingDialog.remove()
667
+ }
668
+ // ダイアログのテンプレートを読み込む
669
+ await this.loadScreen(scenarioObject, {
670
+ isDialog: true,
671
+ skipBackground: true,
672
+ skipBgm: true,
673
+ fallbackTemplate: getDefaultDialogTemplate,
674
+ })
675
+ // ダイアログ用のコンテナを取得
676
+ const dialogContainer = document.querySelector('#dialogContainer')
677
+ if (!dialogContainer) {
678
+ throw new Error('Dialog container not found.')
679
+ }
680
+ scenarioObject.content.forEach((content) => {
681
+ if (content.type === 'prompt') {
682
+ let prompt = content
683
+ // プロンプトの内容を設定
684
+
685
+ // ムスタッシュ構文があるときは、変数の展開
686
+ const promptElement = dialogContainer.querySelector('.dialog-prompt')
687
+ if (promptElement) {
688
+ promptElement.innerHTML = prompt.content.map((text) => this.expandVariable(text)).join('\n')
689
+ }
690
+ } else if (content.type === 'actions') {
691
+ // ボタンの追加
692
+ let actions = content.content
693
+
694
+ const buttonContainer = dialogContainer.querySelector('.dialog-buttons')
695
+ actions.forEach((action) => {
696
+ // ムスタッシュ構文があるときは、変数の展開
697
+ action.label = this.expandVariable(action.label)
698
+ // テンプレートのボタン取得
699
+ let button = buttonContainer.querySelector(`#dialog-button-${action.id}`)
700
+
701
+ if (!button) {
702
+ // 無い場合は、新しいボタンを作成
703
+ button = document.createElement('button')
704
+ button.id = `dialog-button-${action.id}`
705
+ button.classList.add('dialog-button')
706
+ button.innerText = action.label
707
+ buttonContainer.appendChild(button)
708
+ }
709
+ button.innerText = action.label
710
+ button.addEventListener('click', () => {
711
+ // 選択されたアクションを処理
712
+ this.scenarioManager.addScenario(action.content)
713
+ result = action.id // 選択されたアクションのIDを保存
714
+
715
+ // ダイアログを閉じる
716
+ dialogContainer.close()
717
+ })
718
+ })
719
+ }
720
+ })
721
+
722
+ dialogContainer.showModal() // ダイアログを表示
723
+ return new Promise((resolve) => {
724
+ dialogContainer.addEventListener('close', () => {
725
+ resolve(result)
726
+ })
727
+ })
728
+ }
729
+
730
+ setBackground(image) {
731
+ this.displayedImages['background'] = image
732
+ }
733
+
734
+ getBackground() {
735
+ return this.displayedImages['background'].image
736
+ }
737
+
738
+ executeCode(code) {
739
+ try {
740
+ const context = { ...this.sceneFile }
741
+ const func = new Function(...Object.keys(context), code)
742
+ return func.apply(null, Object.values(context))
743
+ } catch (error) {
744
+ console.error('Error executing code:', error)
745
+ }
746
+ }
747
+
748
+ // Scriptから安全にアクセスできるメソッドを定義
749
+ getAPIForScript() {
750
+ return {
751
+ drawer: {
752
+ drawName: this.drawer.drawName.bind(this.drawer),
753
+ drawText: this.drawer.drawText.bind(this.drawer),
754
+ drawChoices: this.drawer.drawChoices.bind(this.drawer),
755
+ clearText: this.drawer.clearText.bind(this.drawer),
756
+ show: this.drawer.show.bind(this.drawer),
757
+ moveTo: this.drawer.moveTo.bind(this.drawer),
758
+ fadeIn: this.drawer.fadeIn.bind(this.drawer),
759
+ fadeOut: this.drawer.fadeOut.bind(this.drawer),
760
+ },
761
+ sound: {
762
+ play: this.soundHandler.bind(this),
763
+ stop: (name) => this.soundHandler({ name, stop: true }),
764
+ pause: (name) => this.soundHandler({ name, pause: true }),
765
+ },
766
+ scenario: {
767
+ jump: this.jumpHandler.bind(this),
768
+ addScene: this.scenarioManager.addScenario.bind(this.scenarioManager),
769
+ getProgress: () => this.scenarioManager.progress,
770
+ setProgress: (progress) => (this.scenarioManager.progress = progress),
771
+ getIndex: () => this.scenarioManager.getIndex(),
772
+ setIndex: (index) => this.scenarioManager.setIndex(index),
773
+ hasNext: () => this.scenarioManager.hasNext(),
774
+ next: () => this.scenarioManager.next(),
775
+ getHistory: () => this.scenarioManager.getHistory(),
776
+ setHistory: (history) => this.scenarioManager.setHistory(history),
777
+ setScenario: (scenario) => this.scenarioManager.setScenario(scenario),
778
+ getScenario: () => this.scenarioManager.getScenario(),
779
+ getSceneName: () => this.scenarioManager.progress.currentScene,
780
+ setScreenName: (name) => (this.sceneConfig.name = name),
781
+ },
782
+ images: {
783
+ get: this.getImageObject.bind(this),
784
+ getAll: () => this.displayedImages,
785
+ set: (name, image) => (this.displayedImages[name] = image),
786
+ delete: (name) => delete this.displayedImages[name],
787
+ },
788
+ sounds: {
789
+ get: (name) => this.usedSounds[name],
790
+ getAll: () => this.usedSounds,
791
+ set: (name, sound) => (this.usedSounds[name] = sound),
792
+ delete: (name) => delete this.usedSounds[name],
793
+ load: this.getSoundObject.bind(this),
794
+ },
795
+ background: {
796
+ set: this.setBackground.bind(this),
797
+ get: this.getBackground.bind(this),
798
+ },
799
+ wait: this.waitHandler.bind(this),
800
+ clickWait: this.clickWait.bind(this),
801
+ core: {
802
+ text: this.textHandler.bind(this),
803
+ choice: this.choiceHandler.bind(this),
804
+ show: this.showHandler.bind(this),
805
+ newpage: this.newpageHandler.bind(this),
806
+ hide: this.hideHandler.bind(this),
807
+ jump: this.jumpHandler.bind(this),
808
+ sound: this.soundHandler.bind(this),
809
+ say: this.sayHandler.bind(this),
810
+ if: this.ifHandler.bind(this),
811
+ moveto: this.moveToHandler.bind(this),
812
+ route: this.routeHandler.bind(this),
813
+ wait: this.waitHandler.bind(this),
814
+ save: this.saveHandler.bind(this),
815
+ load: this.loadHandler.bind(this),
816
+ },
817
+ save: {
818
+ save: this.saveHandler.bind(this),
819
+ load: this.loadHandler.bind(this),
820
+ getSaveData: () => this.getSaveData(),
821
+ setSaveData: (data) => this.setSaveData(data),
822
+ getSaveList: () => this.getSaveList(),
823
+ deleteSave: (slot) => this.deleteSave(slot),
824
+ },
825
+ }
826
+ }
827
+
828
+ async saveHandler(line) {
829
+ const slot = line.slot || 'auto'
830
+ const name = line.name || `セーブ${slot}`
831
+
832
+ const saveData = {
833
+ slot: slot,
834
+ name: name,
835
+ timestamp: new Date().toISOString(),
836
+ scenarioManager: {
837
+ progress: JSON.parse(JSON.stringify(this.scenarioManager.progress)),
838
+ sceneName: this.scenarioManager.getSceneName() || this.sceneConfig.name,
839
+ currentIndex: this.scenarioManager.getIndex(),
840
+ history: this.scenarioManager.getHistory ? [...this.scenarioManager.getHistory()] : [],
841
+ },
842
+ sceneConfig: this.sceneConfig,
843
+ displayedImages: Object.keys(this.displayedImages).reduce((acc, key) => {
844
+ if (key !== 'background') {
845
+ acc[key] = {
846
+ src: this.displayedImages[key].image?.src || null,
847
+ pos: this.displayedImages[key].pos,
848
+ size: this.displayedImages[key].size,
849
+ look: this.displayedImages[key].look,
850
+ entry: this.displayedImages[key].entry,
851
+ }
852
+ }
853
+ return acc
854
+ }, {}),
855
+ backgroundImage: this.displayedImages.background?.image?.getImage()?.src || null,
856
+ usedSounds: Object.keys(this.usedSounds).reduce((acc, key) => {
857
+ acc[key] = {
858
+ src: this.usedSounds[key].audio?.src || null,
859
+ }
860
+ return acc
861
+ }, {}),
862
+ bgmSrc: this.bgm?.src || null,
863
+ }
864
+
865
+ this.store.set(`save_${slot}`, saveData)
866
+
867
+ if (line.message !== false) {
868
+ await this.textHandler(`ゲームをセーブしました: ${name}`)
869
+ }
870
+ }
871
+
872
+ async loadHandler(line) {
873
+ const slot = line.slot || 'auto'
874
+
875
+ const saveDataRaw = this.store.get ? this.store.get(`save_${slot}`) : this.store[`save_${slot}`]
876
+ if (!saveDataRaw) {
877
+ const errorMsg = `セーブデータが見つかりません: スロット${slot}`
878
+
879
+ if (line.message !== false) {
880
+ await this.textHandler(errorMsg)
881
+ }
882
+ return
883
+ }
884
+
885
+ // ディープコピーで循環参照を回避
886
+ const saveData = JSON.parse(JSON.stringify(saveDataRaw))
887
+
888
+ try {
889
+ const sceneName = saveData.scenarioManager.sceneName || saveData.sceneConfig.name
890
+ if (!sceneName) {
891
+ throw new Error('Scene name not found in save data')
892
+ }
893
+
894
+ // シーンとプログレスを復元
895
+ await this.loadScene(sceneName)
896
+ await this.loadScreen(saveData.sceneConfig, { skipBackground: true, skipBgm: true })
897
+
898
+ // 読んだところまで復元
899
+ this.scenarioManager.setSceneName(saveData.scenarioManager.sceneName)
900
+ this.scenarioManager.setIndex(saveData.scenarioManager.currentIndex)
901
+ this.scenarioManager.setHistory(saveData.scenarioManager.history || [])
902
+ this.scenarioManager.progress = { ...this.scenarioManager.progress, ...saveData.scenarioManager.progress }
903
+
904
+ // 画面の復元
905
+ this.displayedImages = {}
906
+ if (saveData.backgroundImage) {
907
+ const background = await new ImageObject().setImageAsync(saveData.backgroundImage)
908
+ this.displayedImages['background'] = {
909
+ image: background,
910
+ size: {
911
+ width: this.gameContainer.clientWidth,
912
+ height: this.gameContainer.clientHeight,
913
+ },
914
+ }
915
+ }
916
+
917
+ for (const [key, imageData] of Object.entries(saveData.displayedImages)) {
918
+ if (imageData.src) {
919
+ const image = await new ImageObject().setImageAsync(imageData.src)
920
+ this.displayedImages[key] = {
921
+ image: image,
922
+ pos: imageData.pos,
923
+ size: imageData.size,
924
+ look: imageData.look,
925
+ entry: imageData.entry,
926
+ }
927
+ }
928
+ }
929
+
930
+ // BGMの復元
931
+ if (saveData.bgmSrc) {
932
+ this.soundHandler({ mode: 'bgm', src: saveData.bgmSrc, loop: true, play: true })
933
+ }
934
+
935
+ this.drawer.show(this.displayedImages)
936
+
937
+ if (line.message !== false) {
938
+ await this.textHandler(`ゲームをロードしました: ${saveData.name}`)
939
+ }
940
+ } catch (error) {
941
+ const errorMsg = `ロードに失敗しました: ${error.message}`
942
+
943
+ if (line.message !== false) {
944
+ await this.textHandler(errorMsg)
945
+ }
946
+ }
947
+ }
948
+
949
+ getSaveData() {
950
+ const saveKeys = Object.keys(this.store).filter((key) => key.startsWith('save_'))
951
+ return saveKeys
952
+ .map((key) => this.store[key])
953
+ .sort((a, b) => {
954
+ return new Date(b.timestamp) - new Date(a.timestamp)
955
+ })
956
+ }
957
+
958
+ setSaveData(data) {
959
+ this.store.set(`save_${data.slot}`, data)
960
+ }
961
+
962
+ getSaveList() {
963
+ return this.getSaveData()
964
+ }
965
+
966
+ deleteSave(slot) {
967
+ delete this.store[`save_${slot}`]
968
+ }
969
+ }