mirror of
https://github.com/ad044/lainTSX.git
synced 2024-10-22 23:19:06 +00:00
Merge remote-tracking branch 'origin/master' into extraction-script
This commit is contained in:
commit
a6a408b97f
123 changed files with 6705 additions and 5843 deletions
207
package-lock.json
generated
207
package-lock.json
generated
|
@ -4384,11 +4384,6 @@
|
|||
"resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
|
||||
"integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="
|
||||
},
|
||||
"chardet": {
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
|
||||
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
|
||||
},
|
||||
"check-types": {
|
||||
"version": "11.1.2",
|
||||
"resolved": "https://registry.npmjs.org/check-types/-/check-types-11.1.2.tgz",
|
||||
|
@ -4476,19 +4471,6 @@
|
|||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="
|
||||
},
|
||||
"cli-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
|
||||
"integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
|
||||
"requires": {
|
||||
"restore-cursor": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"cli-width": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
|
||||
"integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw=="
|
||||
},
|
||||
"cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
|
@ -6886,16 +6868,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"external-editor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
|
||||
"integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
|
||||
"requires": {
|
||||
"chardet": "^0.7.0",
|
||||
"iconv-lite": "^0.4.24",
|
||||
"tmp": "^0.0.33"
|
||||
}
|
||||
},
|
||||
"extglob": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
|
||||
|
@ -7022,14 +6994,6 @@
|
|||
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
|
||||
"integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw=="
|
||||
},
|
||||
"figures": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
|
||||
"integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"file-entry-cache": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
|
||||
|
@ -8087,9 +8051,9 @@
|
|||
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw=="
|
||||
},
|
||||
"immer": {
|
||||
"version": "7.0.9",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-7.0.9.tgz",
|
||||
"integrity": "sha512-Vs/gxoM4DqNAYR7pugIxi0Xc8XAun/uy7AQu4fLLqaTBHxjOP9pJ266Q9MWA/ly4z6rAFZbvViOtihxUZ7O28A=="
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz",
|
||||
"integrity": "sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA=="
|
||||
},
|
||||
"import-cwd": {
|
||||
"version": "2.1.0",
|
||||
|
@ -8177,94 +8141,9 @@
|
|||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
|
||||
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "7.3.3",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
|
||||
"integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
|
||||
"requires": {
|
||||
"ansi-escapes": "^4.2.1",
|
||||
"chalk": "^4.1.0",
|
||||
"cli-cursor": "^3.1.0",
|
||||
"cli-width": "^3.0.0",
|
||||
"external-editor": "^3.0.3",
|
||||
"figures": "^3.0.0",
|
||||
"lodash": "^4.17.19",
|
||||
"mute-stream": "0.0.8",
|
||||
"run-async": "^2.4.0",
|
||||
"rxjs": "^6.6.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"through": "^2.3.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
||||
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
|
||||
},
|
||||
"internal-ip": {
|
||||
"version": "4.3.0",
|
||||
|
@ -11909,11 +11788,6 @@
|
|||
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
|
||||
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
|
||||
},
|
||||
"mute-stream": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.16",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.16.tgz",
|
||||
|
@ -12395,9 +12269,9 @@
|
|||
}
|
||||
},
|
||||
"open": {
|
||||
"version": "7.3.0",
|
||||
"resolved": "https://registry.npmjs.org/open/-/open-7.3.0.tgz",
|
||||
"integrity": "sha512-mgLwQIx2F/ye9SmbrUkurZCnkoXyXyu9EbHtJZrICjVAJfyMArdHp3KkixGdZx1ZHFPNIwl0DDM1dFFqXbTLZw==",
|
||||
"version": "7.4.2",
|
||||
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
|
||||
"integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
|
||||
"requires": {
|
||||
"is-docker": "^2.0.0",
|
||||
"is-wsl": "^2.1.1"
|
||||
|
@ -12453,11 +12327,6 @@
|
|||
"resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
|
||||
"integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc="
|
||||
},
|
||||
"os-tmpdir": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"p-each-series": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz",
|
||||
|
@ -14064,9 +13933,9 @@
|
|||
}
|
||||
},
|
||||
"react-dev-utils": {
|
||||
"version": "11.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.0.tgz",
|
||||
"integrity": "sha512-uIZTUZXB5tbiM/0auUkLVjWhZGM7DSI304iGunyhA9m985iIDVXd9I4z6MkNa9jeLzeUJbU9A7TUNrcbXAahxw==",
|
||||
"version": "11.0.3",
|
||||
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-11.0.3.tgz",
|
||||
"integrity": "sha512-4lEA5gF4OHrcJLMUV1t+4XbNDiJbsAWCH5Z2uqlTqW6dD7Cf5nEASkeXrCI/Mz83sI2o527oBIFKVMXtRf1Vtg==",
|
||||
"requires": {
|
||||
"@babel/code-frame": "7.10.4",
|
||||
"address": "1.1.2",
|
||||
|
@ -14081,13 +13950,13 @@
|
|||
"global-modules": "2.0.0",
|
||||
"globby": "11.0.1",
|
||||
"gzip-size": "5.1.1",
|
||||
"immer": "7.0.9",
|
||||
"inquirer": "7.3.3",
|
||||
"immer": "8.0.1",
|
||||
"is-root": "2.1.0",
|
||||
"loader-utils": "2.0.0",
|
||||
"open": "^7.0.2",
|
||||
"pkg-up": "3.1.0",
|
||||
"react-error-overlay": "^6.0.8",
|
||||
"prompts": "2.4.0",
|
||||
"react-error-overlay": "^6.0.9",
|
||||
"recursive-readdir": "2.2.2",
|
||||
"shell-quote": "1.7.2",
|
||||
"strip-ansi": "6.0.0",
|
||||
|
@ -14160,9 +14029,9 @@
|
|||
}
|
||||
},
|
||||
"react-error-overlay": {
|
||||
"version": "6.0.8",
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.8.tgz",
|
||||
"integrity": "sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw=="
|
||||
"version": "6.0.9",
|
||||
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz",
|
||||
"integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew=="
|
||||
},
|
||||
"react-is": {
|
||||
"version": "16.13.1",
|
||||
|
@ -14292,6 +14161,11 @@
|
|||
"utility-types": "^3.10.0"
|
||||
}
|
||||
},
|
||||
"react-use-gesture": {
|
||||
"version": "9.0.4",
|
||||
"resolved": "https://registry.npmjs.org/react-use-gesture/-/react-use-gesture-9.0.4.tgz",
|
||||
"integrity": "sha512-G0sbQY+HSm2gSVIlD+LE1unpVpG7YZRTr8TI72vo0Nu1lecJtvjbcY3ZLonEZLTtODJgLL6nBllMRXyy0bRSQA=="
|
||||
},
|
||||
"react-use-measure": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.0.2.tgz",
|
||||
|
@ -14785,15 +14659,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"restore-cursor": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
|
||||
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
|
||||
"requires": {
|
||||
"onetime": "^5.1.0",
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"ret": {
|
||||
"version": "0.1.15",
|
||||
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
|
||||
|
@ -14935,11 +14800,6 @@
|
|||
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.5.tgz",
|
||||
"integrity": "sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA=="
|
||||
},
|
||||
"run-async": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
|
||||
"integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ=="
|
||||
},
|
||||
"run-parallel": {
|
||||
"version": "1.1.10",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz",
|
||||
|
@ -14953,14 +14813,6 @@
|
|||
"aproba": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.6.3",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz",
|
||||
"integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==",
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
|
@ -16412,11 +16264,6 @@
|
|||
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
|
||||
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA=="
|
||||
},
|
||||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
},
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
||||
|
@ -16473,14 +16320,6 @@
|
|||
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
|
||||
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||
"requires": {
|
||||
"os-tmpdir": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"tmpl": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz",
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
"react-dom": "^16.13.1",
|
||||
"react-scripts": "^4.0.0",
|
||||
"react-three-fiber": "^4.2.20",
|
||||
"react-use-gesture": "^9.0.4",
|
||||
"three": "^0.119.1",
|
||||
"three-plain-animator": "^1.0.2",
|
||||
"typescript": "^3.7.5",
|
||||
|
@ -24,7 +25,7 @@
|
|||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!three/.*)/\"",
|
||||
"eject": "react-scripts eject",
|
||||
"extract": "node scripts/extract/extract.mjs"
|
||||
},
|
||||
|
|
|
@ -5,18 +5,12 @@
|
|||
<link rel="icon" type="image/png" href="icon.png" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<style>
|
||||
body {
|
||||
background-color: #000;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<noscript
|
||||
>do you actually believe i could rewrite this in plain html css or
|
||||
smoetihng</noscript
|
||||
>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r119/three.min.js"></script>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
const { getByText } = render(<App />);
|
||||
const linkElement = getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
71
src/App.tsx
71
src/App.tsx
|
@ -1,4 +1,10 @@
|
|||
import React, { Suspense, useEffect, useMemo } from "react";
|
||||
import React, {
|
||||
Suspense,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
import MainScene from "./scenes/MainScene";
|
||||
import "./static/css/page.css";
|
||||
import { Canvas } from "react-three-fiber";
|
||||
|
@ -13,8 +19,8 @@ import TaKScene from "./scenes/TaKScene";
|
|||
import ChangeDiscScene from "./scenes/ChangeDiscScene";
|
||||
import EndScene from "./scenes/EndScene";
|
||||
import IdleMediaScene from "./scenes/IdleMediaScene";
|
||||
import KeyPressHandler from "./components/KeyPressHandler";
|
||||
import Preloader from "./components/Preloader";
|
||||
import InputHandler from "./components/InputHandler";
|
||||
import mobileAndTabletCheck from "./utils/mobileAndTabletCheck";
|
||||
|
||||
const App = () => {
|
||||
const currentScene = useStore((state) => state.currentScene);
|
||||
|
@ -35,23 +41,72 @@ const App = () => {
|
|||
tak: <TaKScene />,
|
||||
change_disc: <ChangeDiscScene />,
|
||||
end: <EndScene />,
|
||||
null: <></>,
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
const [width, setWidth] = useState((window.screen.height / 1.8) * 1.3);
|
||||
const [height, setHeight] = useState(window.screen.height / 1.8);
|
||||
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
|
||||
const handleGameResize = useCallback((event) => {
|
||||
switch (event.key) {
|
||||
case "k":
|
||||
setWidth((prevWidth) => prevWidth * 1.1);
|
||||
setHeight((prevHeight) => prevHeight * 1.1);
|
||||
break;
|
||||
case "j":
|
||||
setWidth((prevWidth) => prevWidth / 1.1);
|
||||
setHeight((prevHeight) => prevHeight / 1.1);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleScreenResize = useCallback(() => {
|
||||
const isMobile = mobileAndTabletCheck();
|
||||
if (!isMobile) {
|
||||
const h = window.screen.height / 1.8;
|
||||
setWidth(h * 1.3);
|
||||
setHeight(h);
|
||||
setIsMobile(false);
|
||||
} else {
|
||||
const h = window.screen.height / 1.05;
|
||||
setHeight(h);
|
||||
setWidth(h * 1.3);
|
||||
setIsMobile(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isMobile) window.addEventListener("keydown", handleGameResize);
|
||||
|
||||
window.addEventListener("resize", handleScreenResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleGameResize);
|
||||
window.removeEventListener("resize", handleScreenResize);
|
||||
};
|
||||
}, [handleGameResize, handleScreenResize, isMobile]);
|
||||
|
||||
return (
|
||||
<div id="game-root" className="game">
|
||||
<span className="canvas">
|
||||
<Canvas concurrent>
|
||||
<KeyPressHandler />
|
||||
<div className="game" style={{ width: width, height: height }}>
|
||||
<Canvas
|
||||
concurrent
|
||||
gl={{ antialias: false }}
|
||||
pixelRatio={window.devicePixelRatio}
|
||||
className="main-canvas"
|
||||
>
|
||||
<Suspense fallback={null}>
|
||||
{/*<Preloader />*/}
|
||||
{dispatchScene[currentScene as keyof typeof dispatchScene]}
|
||||
<InputHandler isMobile={isMobile} />
|
||||
</Suspense>
|
||||
</Canvas>
|
||||
</span>
|
||||
{["media", "idle_media", "tak", "end"].includes(currentScene) && (
|
||||
<div style={{ marginTop: -height }}>
|
||||
<MediaPlayer />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
37
src/__tests__/helpers/media-helpers.test.ts
Normal file
37
src/__tests__/helpers/media-helpers.test.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import { findNodeFromWord } from "../../helpers/media-helpers";
|
||||
|
||||
it("Finds the next node with the same word", () => {
|
||||
expect(findNodeFromWord("father", "Cou041", "b").node.node_name).toEqual(
|
||||
"Lda151"
|
||||
);
|
||||
expect(findNodeFromWord("father", "Lda151", "b").node.node_name).toEqual(
|
||||
"Lda155"
|
||||
);
|
||||
expect(findNodeFromWord("father", "Lda155", "b").node.node_name).toEqual(
|
||||
"Lda164"
|
||||
);
|
||||
expect(findNodeFromWord("father", "Lda182", "b").node.node_name).toEqual(
|
||||
"Lda200"
|
||||
);
|
||||
expect(findNodeFromWord("father", "Lda229", "b").node.node_name).toEqual(
|
||||
"Cou041"
|
||||
);
|
||||
expect(findNodeFromWord("father", "Cou041", "b").node.node_name).toEqual(
|
||||
"Lda151"
|
||||
);
|
||||
expect(findNodeFromWord("chaos", "Lda154", "b").node.node_name).toEqual(
|
||||
"Tda056"
|
||||
);
|
||||
expect(findNodeFromWord("chaos", "Tda056", "b").node.node_name).toEqual(
|
||||
"Tda059"
|
||||
);
|
||||
expect(findNodeFromWord("prompt", "Lda154", "b").node.node_name).toEqual(
|
||||
"Tda072"
|
||||
);
|
||||
expect(findNodeFromWord("abuse", "Dc1012", "a").node.node_name).toEqual(
|
||||
"Lda005"
|
||||
);
|
||||
expect(findNodeFromWord("abuse", "Lda005", "a").node.node_name).toEqual(
|
||||
"Dc1012"
|
||||
);
|
||||
});
|
29
src/__tests__/helpers/name-selection-helpers.test.ts
Normal file
29
src/__tests__/helpers/name-selection-helpers.test.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import handleNameSelection from "../../helpers/name-selection-helpers";
|
||||
|
||||
it("Handles the logic for japanese characters", () => {
|
||||
// cant be first character check
|
||||
expect(handleNameSelection("", "ン")).toEqual(undefined);
|
||||
// if its not first, then fine
|
||||
expect(handleNameSelection("キ", "ン")).toEqual("キン");
|
||||
//「ー」 cannot be added to 「ッ」 and 「ン」or itself
|
||||
expect(handleNameSelection("キッ", "ー")).toEqual(undefined);
|
||||
expect(handleNameSelection("キン", "ー")).toEqual(undefined);
|
||||
expect(handleNameSelection("キー", "ー")).toEqual(undefined);
|
||||
// characters that can be followed by the lowercase characters
|
||||
expect(handleNameSelection("キ", "ャ")).toEqual("キャ");
|
||||
// cant be followed by lowercase character
|
||||
expect(handleNameSelection("ー", "ャ")).toEqual(undefined);
|
||||
// for 「ッ」, it can added to any character except itself
|
||||
expect(handleNameSelection("ャ", "ッ")).toEqual("ャッ");
|
||||
// cant be added
|
||||
expect(handleNameSelection("ッ", "ッ")).toEqual(undefined);
|
||||
// dakuten
|
||||
expect(handleNameSelection("カ", "゛")).toEqual("ガ");
|
||||
// cant be appended
|
||||
expect(handleNameSelection("ガ", "゛")).toEqual(undefined);
|
||||
// handakuten
|
||||
expect(handleNameSelection("ハ", "゜")).toEqual("パ");
|
||||
// cant be appended
|
||||
expect(handleNameSelection("キ", "゜")).toEqual(undefined);
|
||||
expect(handleNameSelection("パ", "゜")).toEqual(undefined);
|
||||
});
|
158
src/__tests__/helpers/node-finder.test.ts
Normal file
158
src/__tests__/helpers/node-finder.test.ts
Normal file
|
@ -0,0 +1,158 @@
|
|||
import { findNode, unknownNodeTemplate } from "../../helpers/node-helpers";
|
||||
import site_a from "../../resources/site_a.json";
|
||||
import gameProgress from "../../resources/initial_progress.json";
|
||||
|
||||
/*
|
||||
visual representation of the data we're working with
|
||||
|
||||
[null, "0517", null, null],
|
||||
[null, null, "0510", "0513"],
|
||||
["0506", null, null, null],
|
||||
|
|
||||
[null, null, null, "0422"], ["0422", "0417", null, null], [null, "0416", "0417", "0420"],
|
||||
[null, null, null, "0414"], - ["0414", null, null, "0413"], - ["0413", null, null, null],
|
||||
[null, null, null, null], [null, null, null, "0405"], ["0405", null, null, null],
|
||||
|
|
||||
[null, null, null, null] [null, null, null, null], [null, null, null, null],
|
||||
[null, null, null, null], [null, null, null, null], [null, null, null, null],
|
||||
[null, null, null, null], [null, null, null, null], [null, null, null, null],
|
||||
|
||||
*/
|
||||
|
||||
const middleMatrixIdx = 7;
|
||||
const leftMatrixIdx = 8;
|
||||
|
||||
it("Finds which node to go to", () => {
|
||||
// from unknown to left unknown
|
||||
expect(
|
||||
findNode(
|
||||
{
|
||||
...unknownNodeTemplate,
|
||||
matrixIndices: { matrixIdx: middleMatrixIdx, rowIdx: 2, colIdx: 3 },
|
||||
},
|
||||
"left",
|
||||
3,
|
||||
"a",
|
||||
gameProgress,
|
||||
true
|
||||
)
|
||||
).toEqual({
|
||||
node: "unknown",
|
||||
matrixIndices: { rowIdx: 2, colIdx: 3, matrixIdx: leftMatrixIdx },
|
||||
didMove: true,
|
||||
});
|
||||
|
||||
// from 0405 down
|
||||
expect(
|
||||
findNode(
|
||||
{
|
||||
...site_a["04"]["0405"],
|
||||
matrixIndices: { matrixIdx: middleMatrixIdx, rowIdx: 2, colIdx: 3 },
|
||||
},
|
||||
"down",
|
||||
4,
|
||||
"a",
|
||||
gameProgress,
|
||||
true
|
||||
)
|
||||
).toEqual({
|
||||
node: "unknown",
|
||||
matrixIndices: { rowIdx: 2, colIdx: 3, matrixIdx: middleMatrixIdx },
|
||||
didMove: true,
|
||||
});
|
||||
|
||||
// from 0422 (from left matrix) right
|
||||
expect(
|
||||
findNode(
|
||||
{
|
||||
...site_a["04"]["0422"],
|
||||
matrixIndices: { matrixIdx: 8, rowIdx: 0, colIdx: 3 },
|
||||
},
|
||||
"right",
|
||||
4,
|
||||
"a",
|
||||
gameProgress,
|
||||
true
|
||||
)
|
||||
).toEqual({
|
||||
node: "0413",
|
||||
matrixIndices: { rowIdx: 1, colIdx: 3, matrixIdx: 7 },
|
||||
didMove: true,
|
||||
});
|
||||
|
||||
// from 0422 left
|
||||
expect(
|
||||
findNode(
|
||||
{
|
||||
...site_a["04"]["0422"],
|
||||
matrixIndices: { matrixIdx: middleMatrixIdx, rowIdx: 0, colIdx: 0 },
|
||||
},
|
||||
"left",
|
||||
4,
|
||||
"a",
|
||||
gameProgress,
|
||||
true
|
||||
)
|
||||
).toEqual({
|
||||
node: "0422",
|
||||
matrixIndices: { rowIdx: 0, colIdx: 3, matrixIdx: 8 },
|
||||
didMove: true,
|
||||
});
|
||||
|
||||
// from 0422 up
|
||||
expect(
|
||||
findNode(
|
||||
{
|
||||
...site_a["04"]["0422"],
|
||||
matrixIndices: { matrixIdx: middleMatrixIdx, rowIdx: 0, colIdx: 0 },
|
||||
},
|
||||
"up",
|
||||
4,
|
||||
"a",
|
||||
gameProgress,
|
||||
true
|
||||
)
|
||||
).toEqual({
|
||||
node: "0506",
|
||||
matrixIndices: { rowIdx: 2, colIdx: 0, matrixIdx: 7 },
|
||||
didMove: true,
|
||||
});
|
||||
|
||||
// from 0422 right
|
||||
expect(
|
||||
findNode(
|
||||
{
|
||||
...site_a["04"]["0422"],
|
||||
matrixIndices: { matrixIdx: middleMatrixIdx, rowIdx: 0, colIdx: 0 },
|
||||
},
|
||||
"right",
|
||||
4,
|
||||
"a",
|
||||
gameProgress,
|
||||
true
|
||||
)
|
||||
).toEqual({
|
||||
node: "0417",
|
||||
matrixIndices: { rowIdx: 0, colIdx: 1, matrixIdx: 7 },
|
||||
didMove: false,
|
||||
});
|
||||
|
||||
// from 0414 up
|
||||
expect(
|
||||
findNode(
|
||||
{
|
||||
...site_a["04"]["0414"],
|
||||
matrixIndices: { matrixIdx: middleMatrixIdx, rowIdx: 1, colIdx: 0 },
|
||||
},
|
||||
"up",
|
||||
4,
|
||||
"a",
|
||||
gameProgress,
|
||||
true
|
||||
)
|
||||
).toEqual({
|
||||
node: "0422",
|
||||
matrixIndices: { rowIdx: 0, colIdx: 0, matrixIdx: 7 },
|
||||
didMove: false,
|
||||
});
|
||||
});
|
29
src/__tests__/helpers/node-helpers.test.ts
Normal file
29
src/__tests__/helpers/node-helpers.test.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { getNodeById, isNodeVisible } from "../../helpers/node-helpers";
|
||||
import site_a from "../../resources/site_a.json";
|
||||
import gameProgress from "../../resources/initial_progress.json";
|
||||
|
||||
it("Finds the node by it's id", () => {
|
||||
expect(getNodeById("0422", "a").node_name).toEqual("Tda028");
|
||||
expect(getNodeById("0000", "a").node_name).toEqual("Env001");
|
||||
expect(getNodeById("0616", "a").node_name).toEqual("Cou015");
|
||||
expect(getNodeById("0100", "b").node_name).toEqual("Sskn04#");
|
||||
expect(getNodeById("0101", "b").node_name).toEqual("Dc1025");
|
||||
});
|
||||
|
||||
const oneViewCount = { ...gameProgress, final_video_viewcount: 1 };
|
||||
const twoViewCount = { ...gameProgress, final_video_viewcount: 2 };
|
||||
const threeViewCount = { ...gameProgress, final_video_viewcount: 3 };
|
||||
const fourViewCount = { ...gameProgress, final_video_viewcount: 4 };
|
||||
|
||||
it("Checks if the node is visible", () => {
|
||||
expect(isNodeVisible(site_a["04"]["0422"], gameProgress)).toEqual(true);
|
||||
expect(isNodeVisible(site_a["04"]["0413"], gameProgress)).toEqual(true);
|
||||
expect(isNodeVisible(site_a["04"]["0406"], gameProgress)).toEqual(false);
|
||||
expect(isNodeVisible(site_a["04"]["0410"], gameProgress)).toEqual(false);
|
||||
expect(isNodeVisible(site_a["04"]["0406"], oneViewCount)).toEqual(true);
|
||||
expect(isNodeVisible(site_a["06"]["0612"], gameProgress)).toEqual(false);
|
||||
expect(isNodeVisible(site_a["06"]["0612"], oneViewCount)).toEqual(true);
|
||||
expect(isNodeVisible(site_a["06"]["0612"], twoViewCount)).toEqual(true);
|
||||
expect(isNodeVisible(site_a["08"]["0801"], fourViewCount)).toEqual(true);
|
||||
expect(isNodeVisible(site_a["08"]["0801"], threeViewCount)).toEqual(false);
|
||||
});
|
84
src/__tests__/input-handlers/handleBootSceneInput.test.ts
Normal file
84
src/__tests__/input-handlers/handleBootSceneInput.test.ts
Normal file
|
@ -0,0 +1,84 @@
|
|||
import * as eventTemplates from "../../core/eventTemplates";
|
||||
import { getBootSceneContext } from "../../store";
|
||||
import handleBootSceneInput from "../../core/input-handlers/handleBootSceneInput";
|
||||
import {
|
||||
enterLoadData,
|
||||
enterUserAuthorization,
|
||||
exitUserAuthorization,
|
||||
startNewGame,
|
||||
} from "../../core/eventTemplates";
|
||||
import { BootSubscene, MainMenuComponent } from "../../types/types";
|
||||
|
||||
it("Checks whether or not the boot scene input handler reacts appropriately for each input", () => {
|
||||
{
|
||||
// change main menu active component
|
||||
const spy = jest.spyOn(eventTemplates, "changeMainMenuComponent");
|
||||
const testContext = getBootSceneContext();
|
||||
handleBootSceneInput(testContext, "UP");
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
// select main menu component
|
||||
{
|
||||
const testContext = {
|
||||
...getBootSceneContext(),
|
||||
activeMainMenuComponent: "authorize_user" as MainMenuComponent,
|
||||
};
|
||||
expect(handleBootSceneInput(testContext, "CIRCLE")).toEqual(
|
||||
enterUserAuthorization
|
||||
);
|
||||
}
|
||||
{
|
||||
const testContext = {
|
||||
...getBootSceneContext(),
|
||||
activeMainMenuComponent: "load_data" as MainMenuComponent,
|
||||
};
|
||||
expect(handleBootSceneInput(testContext, "CIRCLE")).toEqual(enterLoadData);
|
||||
}
|
||||
{
|
||||
// change letter in authorize user scene
|
||||
const spy = jest.spyOn(eventTemplates, "updateAuthorizeUserLetterIdx");
|
||||
const testContext = {
|
||||
...getBootSceneContext(),
|
||||
subscene: "authorize_user" as BootSubscene,
|
||||
};
|
||||
|
||||
handleBootSceneInput(testContext, "RIGHT");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// start new game
|
||||
const testContext = {
|
||||
...getBootSceneContext(),
|
||||
subscene: "authorize_user" as BootSubscene,
|
||||
playerName: "チ",
|
||||
};
|
||||
|
||||
expect(handleBootSceneInput(testContext, "START")).toEqual(startNewGame);
|
||||
}
|
||||
{
|
||||
// delete last char if player name is not empty
|
||||
const spy = jest.spyOn(eventTemplates, "removePlayerNameLastChar");
|
||||
const testContext = {
|
||||
...getBootSceneContext(),
|
||||
subscene: "authorize_user" as BootSubscene,
|
||||
playerName: "チ",
|
||||
};
|
||||
|
||||
handleBootSceneInput(testContext, "X");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// go back to main menu if player name is empty
|
||||
const testContext = {
|
||||
...getBootSceneContext(),
|
||||
subscene: "authorize_user" as BootSubscene,
|
||||
playerName: "",
|
||||
};
|
||||
|
||||
expect(handleBootSceneInput(testContext, "X")).toEqual(
|
||||
exitUserAuthorization
|
||||
);
|
||||
}
|
||||
});
|
38
src/__tests__/input-handlers/handleEndSceneInput.test.ts
Normal file
38
src/__tests__/input-handlers/handleEndSceneInput.test.ts
Normal file
|
@ -0,0 +1,38 @@
|
|||
import * as eventTemplates from "../../core/eventTemplates";
|
||||
import { getEndSceneContext } from "../../store";
|
||||
import handleEndSceneInput from "../../core/input-handlers/handleEndSceneInput";
|
||||
import { EndComponent } from "../../types/types";
|
||||
|
||||
it("Checks whether or not the end scene input handler reacts appropriately for each input", () => {
|
||||
{
|
||||
// changing end active component
|
||||
const spy = jest.spyOn(eventTemplates, "changeEndComponent");
|
||||
const testContext = { ...getEndSceneContext(), selectionVisible: true };
|
||||
|
||||
handleEndSceneInput(testContext, "DOWN");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
// selecting end component
|
||||
{
|
||||
const spy = jest.spyOn(eventTemplates, "endGame");
|
||||
const testContext = { ...getEndSceneContext(), selectionVisible: true };
|
||||
|
||||
handleEndSceneInput(testContext, "CIRCLE");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
|
||||
{
|
||||
const spy = jest.spyOn(eventTemplates, "changeSite");
|
||||
const testContext = {
|
||||
...getEndSceneContext(),
|
||||
selectionVisible: true,
|
||||
activeEndComponent: "continue" as EndComponent,
|
||||
};
|
||||
|
||||
handleEndSceneInput(testContext, "CIRCLE");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
});
|
131
src/__tests__/input-handlers/handleMainSceneInput.test.ts
Normal file
131
src/__tests__/input-handlers/handleMainSceneInput.test.ts
Normal file
|
@ -0,0 +1,131 @@
|
|||
import { getMainSceneContext } from "../../store";
|
||||
import handleMainSceneInput from "../../core/input-handlers/handleMainSceneInput";
|
||||
import * as eventTemplates from "../../core/eventTemplates";
|
||||
import site_a from "../../resources/site_a.json";
|
||||
import {
|
||||
enterLevelSelection,
|
||||
pauseGame,
|
||||
ripNode,
|
||||
showAbout,
|
||||
throwNode,
|
||||
} from "../../core/eventTemplates";
|
||||
import { nodeToScene } from "../../helpers/node-helpers";
|
||||
import { PauseComponent } from "../../types/types";
|
||||
|
||||
const expectOr = (...tests: (() => void)[]) => {
|
||||
try {
|
||||
tests.shift()!();
|
||||
} catch (e) {
|
||||
if (tests.length) expectOr(...tests);
|
||||
else throw e;
|
||||
}
|
||||
};
|
||||
|
||||
it("Checks whether or not the main scene input handler reacts appropriately for each input", () => {
|
||||
{
|
||||
const spy = jest.spyOn(eventTemplates, "changeNode");
|
||||
const testContext = getMainSceneContext();
|
||||
handleMainSceneInput(testContext, "UP");
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// move vertically when utmost up node is currently selected
|
||||
const spy = jest.spyOn(eventTemplates, "siteMoveVertical");
|
||||
const testContext = {
|
||||
...getMainSceneContext(),
|
||||
activeNode: {
|
||||
...site_a["04"]["0422"],
|
||||
matrixIndices: { matrixIdx: 7, rowIdx: 0, colIdx: 0 },
|
||||
},
|
||||
};
|
||||
handleMainSceneInput(testContext, "UP");
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// move horizontally when utmost left node is currently selected
|
||||
const spy = jest.spyOn(eventTemplates, "siteMoveHorizontal");
|
||||
const testContext = getMainSceneContext();
|
||||
handleMainSceneInput(testContext, "LEFT");
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// play throw node/rip node animation and set the scene when the player selects a node
|
||||
const testContext = getMainSceneContext();
|
||||
|
||||
const output = handleMainSceneInput(testContext, "CIRCLE");
|
||||
expectOr(
|
||||
() =>
|
||||
expect(output).toEqual(
|
||||
ripNode({ currentScene: nodeToScene(testContext.activeNode)! })
|
||||
),
|
||||
() =>
|
||||
expect(output).toEqual(
|
||||
throwNode({ currentScene: nodeToScene(testContext.activeNode)! })
|
||||
)
|
||||
);
|
||||
}
|
||||
{
|
||||
// entering level selection
|
||||
const testContext = getMainSceneContext();
|
||||
|
||||
expect(handleMainSceneInput(testContext, "L2")).toEqual(
|
||||
enterLevelSelection({ selectedLevel: testContext.level })
|
||||
);
|
||||
}
|
||||
{
|
||||
// entering pause
|
||||
const testContext = getMainSceneContext();
|
||||
|
||||
expect(handleMainSceneInput(testContext, "TRIANGLE")).toEqual(
|
||||
pauseGame({ siteRot: [Math.PI / 2, testContext.siteRotY, 0] })
|
||||
);
|
||||
}
|
||||
{
|
||||
// changing level inside level selection
|
||||
const spy = jest.spyOn(eventTemplates, "changeSelectedLevel");
|
||||
|
||||
const testContext = {
|
||||
...getMainSceneContext(),
|
||||
subscene: "level_selection",
|
||||
};
|
||||
|
||||
handleMainSceneInput(testContext, "UP");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// selecting new level when currently below it
|
||||
|
||||
const spy = jest.spyOn(eventTemplates, "selectLevel");
|
||||
const testContext = {
|
||||
...getMainSceneContext(),
|
||||
selectedLevel: 10,
|
||||
subscene: "level_selection",
|
||||
};
|
||||
|
||||
handleMainSceneInput(testContext, "CIRCLE");
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// changing pause active component
|
||||
const spy = jest.spyOn(eventTemplates, "changePauseComponent");
|
||||
const testContext = {
|
||||
...getMainSceneContext(),
|
||||
subscene: "pause",
|
||||
};
|
||||
|
||||
handleMainSceneInput(testContext, "UP");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// selecting pause component
|
||||
const testContext = {
|
||||
...getMainSceneContext(),
|
||||
subscene: "pause",
|
||||
activePauseComponent: "about" as PauseComponent,
|
||||
};
|
||||
|
||||
expect(handleMainSceneInput(testContext, "CIRCLE")).toEqual(showAbout);
|
||||
}
|
||||
});
|
68
src/__tests__/input-handlers/handleMediaSceneInput.test.ts
Normal file
68
src/__tests__/input-handlers/handleMediaSceneInput.test.ts
Normal file
|
@ -0,0 +1,68 @@
|
|||
import * as eventTemplates from "../../core/eventTemplates";
|
||||
import { exitMedia } from "../../core/eventTemplates";
|
||||
import { getMediaSceneContext } from "../../store";
|
||||
import handleMediaSceneInput from "../../core/input-handlers/handleMediaSceneInput";
|
||||
import { LeftMediaComponent, MediaSide } from "../../types/types";
|
||||
|
||||
it("Checks whether or not the media scene input handler reacts appropriately for each input", () => {
|
||||
{
|
||||
// changing left side media active component
|
||||
const spy = jest.spyOn(eventTemplates, "changeLeftMediaComponent");
|
||||
const testContext = getMediaSceneContext();
|
||||
|
||||
handleMediaSceneInput(testContext, "DOWN");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// changing media side from left to right
|
||||
const spy = jest.spyOn(eventTemplates, "changeMediaSide");
|
||||
const testContext = getMediaSceneContext();
|
||||
|
||||
handleMediaSceneInput(testContext, "RIGHT");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// exit media
|
||||
const testContext = {
|
||||
...getMediaSceneContext(),
|
||||
activeMediaComponent: "exit" as LeftMediaComponent,
|
||||
};
|
||||
|
||||
expect(handleMediaSceneInput(testContext, "CIRCLE")).toEqual(exitMedia);
|
||||
}
|
||||
|
||||
{
|
||||
// play media
|
||||
const spy = jest.spyOn(eventTemplates, "playMedia");
|
||||
const testContext = getMediaSceneContext();
|
||||
handleMediaSceneInput(testContext, "CIRCLE");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// change right side media component
|
||||
const spy = jest.spyOn(eventTemplates, "changeRightMediaComponent");
|
||||
const testContext = {
|
||||
...getMediaSceneContext(),
|
||||
currentMediaSide: "right" as MediaSide,
|
||||
};
|
||||
|
||||
handleMediaSceneInput(testContext, "DOWN");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// change from right side to left
|
||||
const spy = jest.spyOn(eventTemplates, "changeMediaSide");
|
||||
const testContext = {
|
||||
...getMediaSceneContext(),
|
||||
currentMediaSide: "right" as MediaSide,
|
||||
};
|
||||
|
||||
handleMediaSceneInput(testContext, "LEFT");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
});
|
34
src/__tests__/input-handlers/handleSsknSceneInput.test.ts
Normal file
34
src/__tests__/input-handlers/handleSsknSceneInput.test.ts
Normal file
|
@ -0,0 +1,34 @@
|
|||
import * as eventTemplates from "../../core/eventTemplates";
|
||||
import { getSsknSceneContext } from "../../store";
|
||||
import handleSsknSceneInput from "../../core/input-handlers/handleSsknSceneInput";
|
||||
import { exitSskn } from "../../core/eventTemplates";
|
||||
import { SsknComponent } from "../../types/types";
|
||||
|
||||
it("Checks whether or not the sskn scene input handler reacts appropriately for each input", () => {
|
||||
{
|
||||
// changing sskn active component
|
||||
const spy = jest.spyOn(eventTemplates, "changeSsknComponent");
|
||||
const testContext = getSsknSceneContext();
|
||||
|
||||
handleSsknSceneInput(testContext, "DOWN");
|
||||
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// select ok
|
||||
const spy = jest.spyOn(eventTemplates, "upgradeSskn");
|
||||
const testContext = getSsknSceneContext();
|
||||
|
||||
handleSsknSceneInput(testContext, "CIRCLE");
|
||||
expect(spy).toHaveBeenCalled();
|
||||
}
|
||||
{
|
||||
// select cancel
|
||||
const testContext = {
|
||||
...getSsknSceneContext(),
|
||||
activeSsknComponent: "cancel" as SsknComponent,
|
||||
};
|
||||
|
||||
expect(handleSsknSceneInput(testContext, "CIRCLE")).toEqual(exitSskn);
|
||||
}
|
||||
});
|
9
src/__tests__/save-state.test.ts
Normal file
9
src/__tests__/save-state.test.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { getCurrentUserState } from "../store";
|
||||
|
||||
it("Checks if setting state on localStorage works", () => {
|
||||
const spy = jest.spyOn(Storage.prototype, "setItem");
|
||||
const saveState = JSON.stringify(getCurrentUserState());
|
||||
localStorage.setItem("lainSaveState", saveState);
|
||||
expect(spy).toHaveBeenCalledTimes(1);
|
||||
expect(localStorage.getItem("lainSaveState")).toEqual(saveState);
|
||||
});
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
import accelaBootSpriteSheet from "../../static/sprite/login_intro_accela_spritesheet.png";
|
||||
import makeMeSad from "../../static/sprite/make_me_sad.png";
|
||||
import accelaBootSpriteSheet from "../../static/sprites/boot/login_intro_accela_spritesheet.png";
|
||||
import makeMeSad from "../../static/sprites/boot/make_me_sad.png";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { PlainAnimator } from "three-plain-animator/lib/plain-animator";
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import React, {useEffect, useMemo, useRef, useState} from "react";
|
||||
import bootLof from "../../static/sprite/boot_lof.png";
|
||||
import bootBottomBarLeft from "../../static/sprite/boot_bottom_bar_left.png";
|
||||
import bootBottomBarRight from "../../static/sprite/boot_bottom_bar_right.png";
|
||||
import bootPurpleSquare from "../../static/sprite/boot_purple_square.png";
|
||||
import bootGraySquare from "../../static/sprite/boot_gray_square.png";
|
||||
import bootDangoText from "../../static/sprite/dango_text.png";
|
||||
import bootMisoShio from "../../static/sprite/miso_shio.png";
|
||||
import bootArrows from "../../static/sprite/boot_arrows.png";
|
||||
import bootStatusTexts from "../../static/sprite/boot_status_texts.png";
|
||||
import bootBackgroundText from "../../static/sprite/boot_background_text.png";
|
||||
import bootBackgroundDistortedTex from "../../static/sprite/distorted_text.png";
|
||||
import bootLof from "../../static/sprites/boot/boot_lof.png";
|
||||
import bootBottomBarLeft from "../../static/sprites/boot/boot_bottom_bar_left.png";
|
||||
import bootBottomBarRight from "../../static/sprites/boot/boot_bottom_bar_right.png";
|
||||
import bootPurpleSquare from "../../static/sprites/boot/boot_purple_square.png";
|
||||
import bootGraySquare from "../../static/sprites/boot/boot_gray_square.png";
|
||||
import bootDangoText from "../../static/sprites/boot/dango_text.png";
|
||||
import bootMisoShio from "../../static/sprites/boot/miso_shio.png";
|
||||
import bootArrows from "../../static/sprites/boot/boot_arrows.png";
|
||||
import bootStatusTexts from "../../static/sprites/boot/boot_status_texts.png";
|
||||
import bootBackgroundText from "../../static/sprites/boot/boot_background_text.png";
|
||||
import bootBackgroundDistortedTex from "../../static/sprites/boot/distorted_text.png";
|
||||
|
||||
import {useFrame, useLoader} from "react-three-fiber";
|
||||
import {a, useSpring} from "@react-spring/three";
|
||||
|
@ -18,6 +18,7 @@ import sleep from "../../utils/sleep";
|
|||
|
||||
type BootAnimationProps = {
|
||||
visible: boolean;
|
||||
mainMenuVisible: boolean;
|
||||
activeSubScene: string;
|
||||
};
|
||||
|
||||
|
@ -134,19 +135,21 @@ const BootAnimation = (props: BootAnimationProps) => {
|
|||
|
||||
await sleep(100);
|
||||
currentBootStatusTextTex.offset.y = 0.79;
|
||||
})();
|
||||
}
|
||||
}, [bootBackgroundTextTex, currentBootStatusTextTex.offset, props.visible]);
|
||||
|
||||
await sleep(1700);
|
||||
useEffect(() => {
|
||||
if (props.mainMenuVisible) {
|
||||
currentBootStatusTextTex.offset.x = 0.5;
|
||||
currentBootStatusTextTex.offset.y = 0.005;
|
||||
setBootOpacity(0);
|
||||
setGraySquarePosY(0);
|
||||
setLofPosX(1.3);
|
||||
setLofPosY(1);
|
||||
|
||||
setBackgroundFloatingTextShown(true);
|
||||
})();
|
||||
}
|
||||
}, [bootBackgroundTextTex, currentBootStatusTextTex.offset, props.visible]);
|
||||
}, [currentBootStatusTextTex.offset, props.mainMenuVisible]);
|
||||
|
||||
const [bootOpacity, setBootOpacity] = useState(1);
|
||||
const [graySquarePosY, setGraySquarePosY] = useState(-0.8);
|
||||
|
@ -196,7 +199,7 @@ const BootAnimation = (props: BootAnimationProps) => {
|
|||
opacity={animationState.graySquareOpacity}
|
||||
/>
|
||||
</a.sprite>
|
||||
{props.activeSubScene !== "authorize_user" ? (
|
||||
{props.activeSubScene !== "authorize_user" && (
|
||||
<>
|
||||
{/*we have two of each to create looping effect*/}
|
||||
<a.sprite
|
||||
|
@ -315,8 +318,6 @@ const BootAnimation = (props: BootAnimationProps) => {
|
|||
/>
|
||||
</sprite>
|
||||
</>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</group>
|
||||
);
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
import React, { useEffect, useMemo, useRef } from "react";
|
||||
import authorizeHeaderUnderline from "../../static/sprite/authorize_header_underline.png";
|
||||
import authorizeGlass from "../../static/sprite/authorize_glass.png";
|
||||
import authorizeGlassUnderline from "../../static/sprite/authorize_glass_underline.png";
|
||||
import authorizeOrangeSquare from "../../static/sprite/authorize_orange_square.png";
|
||||
import authorizeStartToFinish from "../../static/sprite/authorize_start_to_finish.png";
|
||||
import authorizeInactiveLetters from "../../static/sprite/authorize_inactive_letters.png";
|
||||
import authorizeActiveLetters from "../../static/sprite/authorize_active_letters.png";
|
||||
import authorizeHeaderUnderline from "../../static/sprites/boot/authorize_header_underline.png";
|
||||
import authorizeGlass from "../../static/sprites/boot/authorize_glass.png";
|
||||
import authorizeGlassUnderline from "../../static/sprites/boot/authorize_glass_underline.png";
|
||||
import authorizeOrangeSquare from "../../static/sprites/boot/authorize_orange_square.png";
|
||||
import authorizeStartToFinish from "../../static/sprites/boot/authorize_start_to_finish.png";
|
||||
import authorizeInactiveLetters from "../../static/sprites/boot/authorize_inactive_letters.png";
|
||||
import authorizeActiveLetters from "../../static/sprites/boot/authorize_active_letters.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { OrbitControls } from "@react-three/drei";
|
||||
import { useStore } from "../../store";
|
||||
import usePrevious from "../../hooks/usePrevious";
|
||||
import StaticJpCharacter from "../TextRenderer/StaticJpCharacter";
|
||||
|
||||
type BootAuthorizeUserProps = {
|
||||
|
@ -44,78 +42,32 @@ const BootAuthorizeUser = (props: BootAuthorizeUserProps) => {
|
|||
authorizeActiveLetters
|
||||
);
|
||||
|
||||
const letterIdx = useStore((state) => state.authorizeUserLetterIdx);
|
||||
const subscene = useStore((state) => state.bootSubscene);
|
||||
const prevData = usePrevious({ letterIdx, subscene });
|
||||
const authorizeUserMatrixIndices = useStore(
|
||||
(state) => state.authorizeUserMatrixIndices
|
||||
);
|
||||
|
||||
const bgLettersRef = useRef<THREE.Object3D>();
|
||||
const activeLetterRef = useRef<THREE.Mesh>();
|
||||
|
||||
const activeLetterMap = useMemo(() => {
|
||||
activeLettersTex.wrapT = activeLettersTex.wrapS = THREE.RepeatWrapping;
|
||||
activeLettersTex.repeat.set(0.06, 0.2);
|
||||
activeLettersTex.offset.x = 0;
|
||||
activeLettersTex.offset.y = -0.2;
|
||||
activeLettersTex.offset.x = 0.0775 * authorizeUserMatrixIndices.colIdx;
|
||||
activeLettersTex.offset.y = -0.2 - 0.2 * authorizeUserMatrixIndices.rowIdx;
|
||||
return activeLettersTex;
|
||||
}, [activeLettersTex]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
prevData?.subscene === "main_menu" &&
|
||||
subscene === "authorize_user" &&
|
||||
activeLetterRef
|
||||
) {
|
||||
activeLetterMap.offset.x = 0;
|
||||
activeLetterMap.offset.y = -0.2;
|
||||
}
|
||||
}, [subscene, prevData?.subscene, activeLetterMap.offset]);
|
||||
}, [
|
||||
activeLettersTex,
|
||||
authorizeUserMatrixIndices.colIdx,
|
||||
authorizeUserMatrixIndices.rowIdx,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (bgLettersRef.current) {
|
||||
//down
|
||||
if (prevData!.letterIdx + 13 === letterIdx) {
|
||||
bgLettersRef.current.position.y += 0.25;
|
||||
activeLetterMap.offset.y -= 0.2;
|
||||
// down skip
|
||||
} else if (letterIdx === prevData!.letterIdx + 26) {
|
||||
bgLettersRef.current.position.y += 0.5;
|
||||
activeLetterMap.offset.y -= 0.4;
|
||||
} else if (letterIdx === prevData!.letterIdx + 52) {
|
||||
bgLettersRef.current.position.y += 1;
|
||||
activeLetterMap.offset.y -= 0.8;
|
||||
bgLettersRef.current.position.y =
|
||||
-0.7 + 0.25 * authorizeUserMatrixIndices.rowIdx;
|
||||
bgLettersRef.current.position.x =
|
||||
3.35 - 0.3 * authorizeUserMatrixIndices.colIdx;
|
||||
}
|
||||
// up
|
||||
else if (letterIdx === prevData!.letterIdx - 13) {
|
||||
bgLettersRef.current.position.y -= 0.25;
|
||||
activeLetterMap.offset.y += 0.2;
|
||||
// up skip
|
||||
} else if (letterIdx === prevData!.letterIdx - 26) {
|
||||
bgLettersRef.current.position.y -= 0.5;
|
||||
activeLetterMap.offset.y += 0.4;
|
||||
} else if (letterIdx === prevData!.letterIdx - 52) {
|
||||
bgLettersRef.current.position.y -= 1;
|
||||
activeLetterMap.offset.y += 0.8;
|
||||
}
|
||||
// left
|
||||
else if (letterIdx === prevData!.letterIdx - 1) {
|
||||
bgLettersRef.current.position.x += 0.3;
|
||||
activeLetterMap.offset.x -= 0.0775;
|
||||
}
|
||||
// left skip
|
||||
else if (letterIdx === prevData!.letterIdx - 2) {
|
||||
bgLettersRef.current.position.x += 0.6;
|
||||
activeLetterMap.offset.x -= 0.155;
|
||||
}
|
||||
// right
|
||||
else if (letterIdx === prevData!.letterIdx + 1) {
|
||||
bgLettersRef.current.position.x -= 0.3;
|
||||
activeLetterMap.offset.x += 0.0775;
|
||||
} else if (letterIdx === prevData!.letterIdx + 2) {
|
||||
bgLettersRef.current.position.x -= 0.6;
|
||||
activeLetterMap.offset.x += 0.155;
|
||||
}
|
||||
}
|
||||
}, [activeLetterMap.offset, letterIdx, prevData]);
|
||||
}, [authorizeUserMatrixIndices.colIdx, authorizeUserMatrixIndices.rowIdx]);
|
||||
|
||||
const playerName = useStore((state) => state.playerName.split(""));
|
||||
|
||||
|
@ -160,8 +112,9 @@ const BootAuthorizeUser = (props: BootAuthorizeUserProps) => {
|
|||
</sprite>
|
||||
<sprite
|
||||
scale={[0.2, 0.2, 0]}
|
||||
position={[-0.2, -0.3, 0]}
|
||||
position={[-0.19, -0.3, 0]}
|
||||
renderOrder={3}
|
||||
visible={!(playerName.length === 8)}
|
||||
>
|
||||
<spriteMaterial
|
||||
map={authorizeOrangeSquareTex}
|
||||
|
@ -170,8 +123,15 @@ const BootAuthorizeUser = (props: BootAuthorizeUserProps) => {
|
|||
depthTest={false}
|
||||
/>
|
||||
</sprite>
|
||||
|
||||
<group position={[playerName.length * -0.25 - 0.2, -0.27, 0]}>
|
||||
<group
|
||||
position={[
|
||||
(playerName.length === 8 ? 0.2 : 0) +
|
||||
playerName.length * -0.2 -
|
||||
0.2,
|
||||
-0.29,
|
||||
0,
|
||||
]}
|
||||
>
|
||||
{playerName.map((char, idx) => (
|
||||
<StaticJpCharacter char={char} charIdx={idx} key={idx} />
|
||||
))}
|
||||
|
@ -189,11 +149,10 @@ const BootAuthorizeUser = (props: BootAuthorizeUserProps) => {
|
|||
/>
|
||||
</sprite>
|
||||
|
||||
<OrbitControls />
|
||||
<group position={[-1.15, 0.4, 0.3]} rotation={[-0.8, 0, -0.3]}>
|
||||
<mesh
|
||||
scale={[4, 1.28, 0]}
|
||||
position={[3.35, -0.7, 0]}
|
||||
position={[1.25, -0.45, 0]}
|
||||
ref={bgLettersRef}
|
||||
>
|
||||
<planeBufferGeometry attach="geometry" />
|
||||
|
@ -201,7 +160,6 @@ const BootAuthorizeUser = (props: BootAuthorizeUserProps) => {
|
|||
map={authorizeInactiveLettersTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
side={THREE.DoubleSide}
|
||||
/>
|
||||
</mesh>
|
||||
<mesh
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React from "react";
|
||||
import loadDataUnderline from "../../static/sprite/load_data_header_underline.png";
|
||||
import loadDataUnderline from "../../static/sprites/boot/load_data_header_underline.png";
|
||||
import * as THREE from "three";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import Prompt from "../Prompt";
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import React, { useMemo } from "react";
|
||||
import { a, useSpring } from "@react-spring/three";
|
||||
import authorizeActive from "../../static/sprite/authorize_user_active.png";
|
||||
import authorizeInactive from "../../static/sprite/authorize_user_inactive.png";
|
||||
import loadDataActive from "../../static/sprite/load_data_active.png";
|
||||
import loadDataInactive from "../../static/sprite/load_data_inactive.png";
|
||||
import authorizeActive from "../../static/sprites/boot/authorize_user_active.png";
|
||||
import authorizeInactive from "../../static/sprites/boot/authorize_user_inactive.png";
|
||||
import loadDataActive from "../../static/sprites/boot/load_data_active.png";
|
||||
import loadDataInactive from "../../static/sprites/boot/load_data_inactive.png";
|
||||
import authorizeUserHeader from "../../static/sprites/boot/authorize_user_scene_header.png";
|
||||
import loadDataHeader from "../../static/sprites/boot/load_data_header.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import authorizeUserHeader from "../../static/sprite/authorize_user_scene_header.png";
|
||||
import loadDataHeader from "../../static/sprite/load_data_header.png";
|
||||
import { useStore } from "../../store";
|
||||
|
||||
type BootMainMenuProps = {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react";
|
||||
import * as THREE from "three";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import mainCylinder from "../../static/sprite/end_cylinder_1.png";
|
||||
import mainCylinder from "../../static/sprites/end/end_cylinder_1.png";
|
||||
|
||||
const EndCylinder = () => {
|
||||
const mainCylinderTex = useLoader(THREE.TextureLoader, mainCylinder);
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
import React, { useRef, useState } from "react";
|
||||
import middleSpritesheet from "../../static/sprite/end_middle_spritesheet.png";
|
||||
import middleLain from "../../static/sprite/end_middle_lain.png";
|
||||
import circleSpritesheet from "../../static/sprite/end_circle_spritesheet.png";
|
||||
import endText from "../../static/sprite/end_end_text.png";
|
||||
import continueText from "../../static/sprite/end_continue_text.png";
|
||||
import React, { memo, useRef, useState } from "react";
|
||||
import middleSpritesheet from "../../static/sprites/end/end_middle_spritesheet.png";
|
||||
import middleLain from "../../static/sprites/end/end_middle_lain.png";
|
||||
import circleSpritesheet from "../../static/sprites/end/end_circle_spritesheet.png";
|
||||
import endText from "../../static/sprites/end/end_end_text.png";
|
||||
import continueText from "../../static/sprites/end/end_continue_text.png";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { PlainAnimator } from "three-plain-animator/lib/plain-animator";
|
||||
import { a, useSpring } from "@react-spring/three";
|
||||
import { useStore } from "../../store";
|
||||
|
||||
const EndSelectionScreen = () => {
|
||||
type EndSelectionScreenProps = {
|
||||
visible: boolean;
|
||||
};
|
||||
|
||||
const EndSelectionScreen = memo((props: EndSelectionScreenProps) => {
|
||||
const middleSpritesheetTex: any = useLoader(
|
||||
THREE.TextureLoader,
|
||||
middleSpritesheet
|
||||
|
@ -63,7 +67,7 @@ const EndSelectionScreen = () => {
|
|||
const lainOpacity = lainOpacityToggle.to([0, 1], [0, 0.5]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<group visible={props.visible}>
|
||||
<sprite position={[-3.5, 0, -3]} scale={[10, 0.8, 0]}>
|
||||
<spriteMaterial attach="material" map={middleSpritesheetTex} />
|
||||
</sprite>
|
||||
|
@ -93,8 +97,8 @@ const EndSelectionScreen = () => {
|
|||
opacity={lainOpacity}
|
||||
/>
|
||||
</sprite>
|
||||
</>
|
||||
</group>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default EndSelectionScreen;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useRef } from "react";
|
||||
import * as THREE from "three";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import secondCylinder from "../../static/sprite/end_cylinder_2.png";
|
||||
import secondCylinder from "../../static/sprites/end/end_cylinder_2.png";
|
||||
|
||||
type EndSphereProps = {
|
||||
position: number[];
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, { useEffect, useMemo, useRef } from "react";
|
||||
import gateText from "../../static/sprite/gate_pass.png";
|
||||
import gateTextUnderline from "../../static/sprite/gate_pass_underline.png";
|
||||
import gateTextAccessPass from "../../static/sprite/you_got_an_access_pass.png";
|
||||
import changeSiteEnable from "../../static/sprite/change_site_enable.png";
|
||||
import gateLeftThing from "../../static/sprite/left_gate_thing.png";
|
||||
import gateRightThing from "../../static/sprite/right_gate_thing.png";
|
||||
import gateText from "../../static/sprites/gate/gate_pass.png";
|
||||
import gateTextUnderline from "../../static/sprites/gate/gate_pass_underline.png";
|
||||
import gateTextAccessPass from "../../static/sprites/gate/you_got_an_access_pass.png";
|
||||
import changeSiteEnable from "../../static/sprites/gate/change_site_enable.png";
|
||||
import gateLeftThing from "../../static/sprites/gate/left_gate_thing.png";
|
||||
import gateRightThing from "../../static/sprites/gate/right_gate_thing.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
|
||||
|
@ -14,7 +14,7 @@ type GateMiddleProps = {
|
|||
};
|
||||
|
||||
const GateHUD = (props: GateMiddleProps) => {
|
||||
const wordFont = useLoader(THREE.FontLoader, "/3d_fonts/MediaWord.blob");
|
||||
const wordFont = useLoader(THREE.FontLoader, "/3d-fonts/MediaWord.blob");
|
||||
const config = useMemo(
|
||||
() => ({
|
||||
font: wordFont,
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import BlueZero from "./GateMiddleObject/BlueZero";
|
||||
import BlueOne from "./GateMiddleObject/BlueOne";
|
||||
import { a, useSpring, useSprings } from "@react-spring/three";
|
||||
import blue_digit_positions from "../../resources/blue_digit_positions.json";
|
||||
import Mirror from "./GateMiddleObject/Mirror";
|
||||
import BlueDigit from "./GateMiddleObject/BlueDigit";
|
||||
|
||||
type GateMiddleObjectProps = {
|
||||
intro: boolean;
|
||||
|
@ -16,14 +15,12 @@ const GateMiddleObject = (props: GateMiddleObjectProps) => {
|
|||
const [springs, set] = useSprings(44, (intIdx) => {
|
||||
const idx = intIdx.toString();
|
||||
return {
|
||||
type: blue_digit_positions[idx as keyof typeof blue_digit_positions].type,
|
||||
posX:
|
||||
blue_digit_positions[idx as keyof typeof blue_digit_positions]
|
||||
.initial_x,
|
||||
posY:
|
||||
blue_digit_positions[idx as keyof typeof blue_digit_positions]
|
||||
.initial_y,
|
||||
visibility: false,
|
||||
config: { duration: 150 },
|
||||
};
|
||||
});
|
||||
|
@ -40,7 +37,6 @@ const GateMiddleObject = (props: GateMiddleObjectProps) => {
|
|||
.final_y,
|
||||
delay:
|
||||
blue_digit_positions[idx as keyof typeof blue_digit_positions].delay,
|
||||
visibility: true,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -62,23 +58,18 @@ const GateMiddleObject = (props: GateMiddleObjectProps) => {
|
|||
position-z={middleObjectGroupState.posZ}
|
||||
visible={props.intro}
|
||||
>
|
||||
{springs.map((item, idx) =>
|
||||
item.type.get() === 1 ? (
|
||||
<BlueOne
|
||||
{springs.map((item, idx) => (
|
||||
<BlueDigit
|
||||
type={
|
||||
blue_digit_positions[
|
||||
idx.toString() as keyof typeof blue_digit_positions
|
||||
].type
|
||||
}
|
||||
posX={item.posX}
|
||||
posY={item.posY}
|
||||
key={idx}
|
||||
visibility={item.visibility}
|
||||
/>
|
||||
) : (
|
||||
<BlueZero
|
||||
posX={item.posX}
|
||||
posY={item.posY}
|
||||
key={idx}
|
||||
visibility={item.visibility}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
))}
|
||||
</a.group>
|
||||
<Mirror
|
||||
visible={props.gateLvl === 1 ? !props.intro : props.gateLvl > 0}
|
||||
|
|
|
@ -1,29 +1,41 @@
|
|||
import React, { useEffect, useMemo, useRef } from "react";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import gateBlueBinarySingularZero from "../../../static/sprite/blue_binary_singular_zero.png";
|
||||
import gateBlueBinarySingularOne from "../../../static/sprites/gate/blue_binary_singular_one.png";
|
||||
import { a, SpringValue } from "@react-spring/three";
|
||||
import gateBlueBinarySingularZero from "../../../static/sprites/gate/blue_binary_singular_zero.png";
|
||||
|
||||
type BlueZeroProps = {
|
||||
type BlueDigitProps = {
|
||||
type: number;
|
||||
posX: SpringValue<number>;
|
||||
posY: SpringValue<number>;
|
||||
visibility: SpringValue<boolean>;
|
||||
};
|
||||
|
||||
const BlueZero = (props: BlueZeroProps) => {
|
||||
const BlueDigit = (props: BlueDigitProps) => {
|
||||
const gateBlueBinarySingularOneTex = useLoader(
|
||||
THREE.TextureLoader,
|
||||
gateBlueBinarySingularOne
|
||||
);
|
||||
const gateBlueBinarySingularZeroTex = useLoader(
|
||||
THREE.TextureLoader,
|
||||
gateBlueBinarySingularZero
|
||||
);
|
||||
|
||||
const objRef = useRef<THREE.Mesh>();
|
||||
const matRef = useRef<THREE.ShaderMaterial>();
|
||||
|
||||
const uniforms = useMemo(
|
||||
() => ({
|
||||
zeroTex: { type: "t", value: gateBlueBinarySingularZeroTex },
|
||||
tex: {
|
||||
type: "t",
|
||||
value:
|
||||
props.type === 1
|
||||
? gateBlueBinarySingularOneTex
|
||||
: gateBlueBinarySingularZeroTex,
|
||||
},
|
||||
brightnessMultiplier: { value: 1.5 },
|
||||
}),
|
||||
[gateBlueBinarySingularZeroTex]
|
||||
[gateBlueBinarySingularOneTex, gateBlueBinarySingularZeroTex, props.type]
|
||||
);
|
||||
|
||||
const vertexShader = `
|
||||
|
@ -35,14 +47,13 @@ const BlueZero = (props: BlueZeroProps) => {
|
|||
}
|
||||
`;
|
||||
|
||||
const fragmentShaderZero = `
|
||||
uniform sampler2D zeroTex;
|
||||
const fragmentShader = `
|
||||
uniform sampler2D tex;
|
||||
uniform float brightnessMultiplier;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = texture2D(zeroTex, vUv) * brightnessMultiplier;
|
||||
gl_FragColor = texture2D(tex, vUv) * brightnessMultiplier;
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -50,21 +61,26 @@ const BlueZero = (props: BlueZeroProps) => {
|
|||
setTimeout(() => {
|
||||
if (matRef.current) {
|
||||
matRef.current.uniforms.brightnessMultiplier.value = 3.5;
|
||||
matRef.current.uniformsNeedUpdate = true;
|
||||
}
|
||||
}, 1400);
|
||||
setTimeout(() => {
|
||||
if (objRef.current) objRef.current.visible = true;
|
||||
}, 150);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<a.mesh
|
||||
scale={[0.08, 0.1, 0]}
|
||||
scale={[props.type === 1 ? 0.04 : 0.08, 0.1, 0]}
|
||||
position-x={props.posX}
|
||||
position-y={props.posY}
|
||||
renderOrder={5}
|
||||
visible={props.visibility}
|
||||
visible={false}
|
||||
ref={objRef}
|
||||
>
|
||||
<planeBufferGeometry attach="geometry"></planeBufferGeometry>
|
||||
<planeBufferGeometry attach="geometry" />
|
||||
<shaderMaterial
|
||||
fragmentShader={fragmentShaderZero}
|
||||
fragmentShader={fragmentShader}
|
||||
vertexShader={vertexShader}
|
||||
uniforms={uniforms}
|
||||
attach="material"
|
||||
|
@ -76,4 +92,4 @@ const BlueZero = (props: BlueZeroProps) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default BlueZero;
|
||||
export default BlueDigit;
|
|
@ -1,77 +0,0 @@
|
|||
import React, { useEffect, useMemo, useRef } from "react";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import gateBlueBinarySingularOne from "../../../static/sprite/blue_binary_singular_one.png";
|
||||
import { a, SpringValue } from "@react-spring/three";
|
||||
|
||||
type BlueOneProps = {
|
||||
posX: SpringValue<number>;
|
||||
posY: SpringValue<number>;
|
||||
visibility: SpringValue<boolean>;
|
||||
};
|
||||
|
||||
const BlueOne = (props: BlueOneProps) => {
|
||||
const gateBlueBinarySingularOneTex = useLoader(
|
||||
THREE.TextureLoader,
|
||||
gateBlueBinarySingularOne
|
||||
);
|
||||
|
||||
const matRef = useRef<THREE.ShaderMaterial>();
|
||||
|
||||
const uniforms = useMemo(
|
||||
() => ({
|
||||
oneTex: { type: "t", value: gateBlueBinarySingularOneTex },
|
||||
brightnessMultiplier: { value: 1.5 },
|
||||
}),
|
||||
[gateBlueBinarySingularOneTex]
|
||||
);
|
||||
|
||||
const vertexShader = `
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const fragmentShaderOne = `
|
||||
uniform sampler2D oneTex;
|
||||
uniform float brightnessMultiplier;
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = texture2D(oneTex, vUv) * brightnessMultiplier;
|
||||
}
|
||||
`;
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => {
|
||||
if (matRef.current)
|
||||
matRef.current.uniforms.brightnessMultiplier.value = 3.5;
|
||||
}, 1400);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<a.mesh
|
||||
scale={[0.04, 0.1, 0]}
|
||||
position-x={props.posX}
|
||||
position-y={props.posY}
|
||||
renderOrder={5}
|
||||
visible={props.visibility}
|
||||
>
|
||||
<planeBufferGeometry attach="geometry"></planeBufferGeometry>
|
||||
<shaderMaterial
|
||||
fragmentShader={fragmentShaderOne}
|
||||
vertexShader={vertexShader}
|
||||
uniforms={uniforms}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
ref={matRef}
|
||||
/>
|
||||
</a.mesh>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlueOne;
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useMemo, useRef } from "react";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import mirrorTexture from "../../../static/sprite/gate_object_texture.png";
|
||||
import mirrorTexture from "../../../static/sprites/gate/gate_object_texture.png";
|
||||
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
||||
|
||||
type GLTFResult = GLTF & {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useMemo, useRef } from "react";
|
||||
import blueBinary from "../../static/sprite/blue_binary.png";
|
||||
import blueBinary from "../../static/sprites/gate/blue_binary.png";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
|
||||
|
@ -85,7 +85,7 @@ const GateSide = () => {
|
|||
scale={[3, 1.5, 0]}
|
||||
renderOrder={1}
|
||||
>
|
||||
<planeBufferGeometry attach="geometry"></planeBufferGeometry>
|
||||
<planeBufferGeometry attach="geometry" />
|
||||
<shaderMaterial
|
||||
attach="material"
|
||||
uniforms={uniforms}
|
||||
|
@ -101,7 +101,7 @@ const GateSide = () => {
|
|||
scale={[-3, 1.5, 0]}
|
||||
renderOrder={1}
|
||||
>
|
||||
<planeBufferGeometry attach="geometry"></planeBufferGeometry>
|
||||
<planeBufferGeometry attach="geometry" />
|
||||
<shaderMaterial
|
||||
attach="material"
|
||||
uniforms={uniforms}
|
||||
|
|
84
src/components/IdleManager.tsx
Normal file
84
src/components/IdleManager.tsx
Normal file
|
@ -0,0 +1,84 @@
|
|||
import { useFrame } from "react-three-fiber";
|
||||
import { playAudio, useStore } from "../store";
|
||||
import * as audio from "../static/audio/sfx";
|
||||
import {
|
||||
playIdleAudio,
|
||||
playIdleVideo,
|
||||
playLainIdleAnim,
|
||||
} from "../core/eventTemplates";
|
||||
import {
|
||||
getRandomIdleLainAnim,
|
||||
getRandomIdleMedia,
|
||||
} from "../helpers/idle-helpers";
|
||||
import handleEvent from "../core/handleEvent";
|
||||
import { useEffect } from "react";
|
||||
|
||||
type IdleManagerProps = {
|
||||
lainIdleTimerRef: any;
|
||||
idleSceneTimerRef: any;
|
||||
};
|
||||
|
||||
const IdleManager = (props: IdleManagerProps) => {
|
||||
const mainSubscene = useStore((state) => state.mainSubscene);
|
||||
const scene = useStore((state) => state.currentScene);
|
||||
|
||||
useEffect(() => {
|
||||
if (scene !== "main") {
|
||||
props.idleSceneTimerRef.current = -1;
|
||||
}
|
||||
}, [props.idleSceneTimerRef, scene]);
|
||||
|
||||
useFrame(() => {
|
||||
const now = Date.now();
|
||||
if (
|
||||
props.lainIdleTimerRef.current !== -1 &&
|
||||
props.idleSceneTimerRef.current !== -1 &&
|
||||
mainSubscene !== "pause" &&
|
||||
mainSubscene !== "level_selection" &&
|
||||
scene === "main"
|
||||
) {
|
||||
if (now > props.lainIdleTimerRef.current + 10000) {
|
||||
// after one idle animation plays, the second comes sooner than it would after a regular keypress
|
||||
props.lainIdleTimerRef.current = now - 2500;
|
||||
|
||||
const [idleLainAnim, duration] = getRandomIdleLainAnim();
|
||||
|
||||
const event = playLainIdleAnim({
|
||||
lainMoveState: idleLainAnim,
|
||||
duration: duration,
|
||||
});
|
||||
|
||||
if (event) handleEvent(event);
|
||||
}
|
||||
if (now > props.idleSceneTimerRef.current + 30000) {
|
||||
// put it on lock until the next action, since while the idle media plays, the
|
||||
// Date.now() value keeps increasing, which can result in another idle media playing right after one finishes
|
||||
// one way to work around this would be to modify the value depending on the last played idle media's duration
|
||||
// but i'm way too lazy for that
|
||||
props.idleSceneTimerRef.current = -1;
|
||||
|
||||
playAudio(audio.sound32);
|
||||
|
||||
const data = getRandomIdleMedia();
|
||||
|
||||
const { type, nodeName, images, media } = data;
|
||||
let event;
|
||||
if (type === "audio" && images && nodeName) {
|
||||
event = playIdleAudio({
|
||||
idleNodeName: nodeName,
|
||||
idleImages: images,
|
||||
idleMedia: media,
|
||||
});
|
||||
} else if (type === "video") {
|
||||
event = playIdleVideo({ idleMedia: media });
|
||||
}
|
||||
|
||||
if (event) handleEvent(event);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default IdleManager;
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { useStore } from "../store";
|
||||
import { a, useSpring } from "@react-spring/three";
|
||||
import dummy from "../static/sprite/dummy.png";
|
||||
import dummy from "../static/sprites/dummy.png";
|
||||
import * as THREE from "three";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
|
||||
|
@ -31,13 +31,7 @@ const Images = () => {
|
|||
const textureLoader = useMemo(() => new THREE.TextureLoader(), []);
|
||||
|
||||
useEffect(() => {
|
||||
let images;
|
||||
if (currentScene === "media" || currentScene === "tak") {
|
||||
images = nodeImages;
|
||||
} else if (currentScene === "idle_media") {
|
||||
images = idleNodeImages;
|
||||
}
|
||||
|
||||
const images = currentScene === "idle_media" ? idleNodeImages : nodeImages;
|
||||
if (images) {
|
||||
// checking the length of the img arr doesn't work in some cases
|
||||
// since the amount of images varies from 1 to 3.
|
||||
|
@ -63,24 +57,27 @@ const Images = () => {
|
|||
}, [currentScene, activeSite, idleNodeImages, nodeImages]);
|
||||
|
||||
useEffect(() => {
|
||||
const loadNewImage = (imgIdx: number) => {
|
||||
setImageScaleY(0);
|
||||
let timer: ReturnType<typeof setTimeout>;
|
||||
|
||||
setTimeout(() => {
|
||||
textureLoader.load(sceneImages[imgIdx].default, setActiveImage);
|
||||
setImageScaleY(3.75);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
(async () => {
|
||||
if (mediaPercentageElapsed === 0 && sceneImages[0]) {
|
||||
textureLoader.load(sceneImages[0].default, setActiveImage);
|
||||
} else if (mediaPercentageElapsed === 35 && sceneImages[1]) {
|
||||
loadNewImage(1);
|
||||
setImageScaleY(0);
|
||||
timer = setTimeout(() => {
|
||||
textureLoader.load(sceneImages[1].default, setActiveImage);
|
||||
setImageScaleY(3.75);
|
||||
}, 300);
|
||||
} else if (mediaPercentageElapsed === 70 && sceneImages[2]) {
|
||||
loadNewImage(2);
|
||||
setImageScaleY(0);
|
||||
timer = setTimeout(() => {
|
||||
textureLoader.load(sceneImages[1].default, setActiveImage);
|
||||
setImageScaleY(3.75);
|
||||
}, 300);
|
||||
}
|
||||
})();
|
||||
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}, [mediaPercentageElapsed, sceneImages, textureLoader]);
|
||||
|
||||
return (
|
||||
|
|
277
src/components/InputHandler.tsx
Normal file
277
src/components/InputHandler.tsx
Normal file
|
@ -0,0 +1,277 @@
|
|||
import React, { useCallback, useEffect, useRef } from "react";
|
||||
import {
|
||||
getBootSceneContext,
|
||||
getEndSceneContext,
|
||||
getMainSceneContext,
|
||||
getMediaSceneContext,
|
||||
getSsknSceneContext,
|
||||
useStore,
|
||||
} from "../store";
|
||||
import getKeyPress from "../utils/getKeyPress";
|
||||
import handleMediaSceneInput from "../core/input-handlers/handleMediaSceneInput";
|
||||
import handleSsknSceneInput from "../core/input-handlers/handleSsknSceneInput";
|
||||
import handleMainSceneInput from "../core/input-handlers/handleMainSceneInput";
|
||||
import handleBootSceneInput from "../core/input-handlers/handleBootSceneInput";
|
||||
import handleEndSceneInput from "../core/input-handlers/handleEndSceneInput";
|
||||
import handleEvent from "../core/handleEvent";
|
||||
import { GameEvent } from "../types/types";
|
||||
import { MouseEvent, useLoader } from "react-three-fiber";
|
||||
import circleButton from "../static/sprites/controller/circle.png";
|
||||
import squareButton from "../static/sprites/controller/square.png";
|
||||
import triangleButton from "../static/sprites/controller/triangle.png";
|
||||
import crossButton from "../static/sprites/controller/cross.png";
|
||||
import startButton from "../static/sprites/controller/start.png";
|
||||
import l2Button from "../static/sprites/controller/l2.png";
|
||||
import * as THREE from "three";
|
||||
import { useGesture } from "react-use-gesture";
|
||||
import IdleManager from "./IdleManager";
|
||||
|
||||
type InputHandlerProps = {
|
||||
isMobile: boolean;
|
||||
};
|
||||
|
||||
const InputHandler = (props: InputHandlerProps) => {
|
||||
const scene = useStore((state) => state.currentScene);
|
||||
const inputCooldown = useStore((state) => state.inputCooldown);
|
||||
|
||||
const circleButtonTex = useLoader(THREE.TextureLoader, circleButton);
|
||||
const crossButtonTex = useLoader(THREE.TextureLoader, crossButton);
|
||||
const squareButtonTex = useLoader(THREE.TextureLoader, squareButton);
|
||||
const triangleButtonTex = useLoader(THREE.TextureLoader, triangleButton);
|
||||
const startButtonTex = useLoader(THREE.TextureLoader, startButton);
|
||||
const l2ButtonTex = useLoader(THREE.TextureLoader, l2Button);
|
||||
|
||||
const timeSinceLastKeyPress = useRef(-1);
|
||||
|
||||
const lainIdleTimerRef = useRef(-1);
|
||||
const idleSceneTimerRef = useRef(-1);
|
||||
|
||||
const handleKeyPress = useCallback(
|
||||
(keyPress: string) => {
|
||||
const now = Date.now();
|
||||
|
||||
if (
|
||||
now > timeSinceLastKeyPress.current + inputCooldown &&
|
||||
inputCooldown !== -1
|
||||
) {
|
||||
if (scene === "main") {
|
||||
timeSinceLastKeyPress.current = now;
|
||||
lainIdleTimerRef.current = now;
|
||||
idleSceneTimerRef.current = now;
|
||||
}
|
||||
|
||||
const sceneFns = (() => {
|
||||
switch (scene) {
|
||||
case "main":
|
||||
return {
|
||||
contextProvider: getMainSceneContext,
|
||||
keyPressHandler: handleMainSceneInput,
|
||||
};
|
||||
case "media":
|
||||
return {
|
||||
contextProvider: getMediaSceneContext,
|
||||
keyPressHandler: handleMediaSceneInput,
|
||||
};
|
||||
case "sskn":
|
||||
return {
|
||||
contextProvider: getSsknSceneContext,
|
||||
keyPressHandler: handleSsknSceneInput,
|
||||
};
|
||||
case "boot":
|
||||
return {
|
||||
contextProvider: getBootSceneContext,
|
||||
keyPressHandler: handleBootSceneInput,
|
||||
};
|
||||
case "end":
|
||||
return {
|
||||
contextProvider: getEndSceneContext,
|
||||
keyPressHandler: handleEndSceneInput,
|
||||
};
|
||||
case "gate":
|
||||
case "polytan":
|
||||
useStore.setState({ currentScene: "main" });
|
||||
break;
|
||||
case "idle_media":
|
||||
useStore.setState({
|
||||
currentScene: "main",
|
||||
idleStarting: false,
|
||||
intro: false,
|
||||
inputCooldown: -1,
|
||||
});
|
||||
break;
|
||||
}
|
||||
})();
|
||||
|
||||
if (sceneFns) {
|
||||
const { contextProvider, keyPressHandler } = sceneFns;
|
||||
|
||||
const ctx = contextProvider();
|
||||
const event: GameEvent | undefined = keyPressHandler(
|
||||
ctx as any,
|
||||
keyPress
|
||||
);
|
||||
if (event) handleEvent(event);
|
||||
}
|
||||
}
|
||||
},
|
||||
[inputCooldown, scene]
|
||||
);
|
||||
|
||||
const bind = useGesture(
|
||||
{
|
||||
onDragEnd: ({ axis, direction: xy }) => {
|
||||
if (axis === "x") {
|
||||
if (xy[0] > 0) handleKeyPress("RIGHT");
|
||||
else handleKeyPress("LEFT");
|
||||
} else {
|
||||
if (xy[1] > 0) handleKeyPress("DOWN");
|
||||
else handleKeyPress("UP");
|
||||
}
|
||||
},
|
||||
},
|
||||
{ drag: { delay: true } }
|
||||
);
|
||||
|
||||
const firedRef = useRef(false);
|
||||
|
||||
const handleKeyBoardEvent = useCallback(
|
||||
(event) => {
|
||||
if (!firedRef.current) {
|
||||
firedRef.current = true;
|
||||
const key = getKeyPress(event.key);
|
||||
|
||||
if (key) handleKeyPress(key);
|
||||
}
|
||||
},
|
||||
[handleKeyPress]
|
||||
);
|
||||
|
||||
const handleVirtualButtonPress = useCallback(
|
||||
(event: MouseEvent) => {
|
||||
handleKeyPress(event.object.name);
|
||||
},
|
||||
[handleKeyPress]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("keydown", handleKeyBoardEvent);
|
||||
|
||||
window.addEventListener("keyup", () => {
|
||||
firedRef.current = false;
|
||||
});
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeyBoardEvent);
|
||||
window.removeEventListener("keyup", () => {
|
||||
firedRef.current = false;
|
||||
});
|
||||
};
|
||||
}, [handleKeyBoardEvent]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{props.isMobile && (
|
||||
<>
|
||||
<sprite scale={[10, 10, 0]} renderOrder={99999} {...bind()}>
|
||||
<spriteMaterial attach="material" opacity={0} depthTest={false} />
|
||||
</sprite>
|
||||
|
||||
<sprite
|
||||
scale={[1.5, 1.5, 0]}
|
||||
position={[-4, 3, 0]}
|
||||
renderOrder={99999}
|
||||
onClick={handleVirtualButtonPress}
|
||||
name={"L2"}
|
||||
>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={l2ButtonTex}
|
||||
depthTest={false}
|
||||
opacity={0.8}
|
||||
/>
|
||||
</sprite>
|
||||
|
||||
<sprite
|
||||
scale={[1.5, 1.5, 0]}
|
||||
position={[4, 3, 0]}
|
||||
renderOrder={99999}
|
||||
onClick={handleVirtualButtonPress}
|
||||
name={"START"}
|
||||
>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={startButtonTex}
|
||||
depthTest={false}
|
||||
opacity={0.8}
|
||||
/>
|
||||
</sprite>
|
||||
|
||||
<group
|
||||
scale={[0.8, 0.8, 0]}
|
||||
position={[3.5, -2.3, 0]}
|
||||
renderOrder={9999}
|
||||
>
|
||||
<sprite
|
||||
scale={[1.5, 1.5, 0]}
|
||||
position={[1, 0, 0]}
|
||||
onClick={handleVirtualButtonPress}
|
||||
name={"CIRCLE"}
|
||||
>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={circleButtonTex}
|
||||
depthTest={false}
|
||||
opacity={0.8}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite
|
||||
scale={[1.5, 1.5, 0]}
|
||||
position={[0, -1, 0]}
|
||||
onClick={handleVirtualButtonPress}
|
||||
name={"CROSS"}
|
||||
>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={crossButtonTex}
|
||||
depthTest={false}
|
||||
opacity={0.8}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite
|
||||
scale={[1.5, 1.5, 0]}
|
||||
position={[0, 1, 0]}
|
||||
onClick={handleVirtualButtonPress}
|
||||
name={"TRIANGLE"}
|
||||
>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={triangleButtonTex}
|
||||
depthTest={false}
|
||||
opacity={0.8}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite
|
||||
scale={[1.5, 1.5, 0]}
|
||||
position={[-1, 0, 0]}
|
||||
onClick={handleVirtualButtonPress}
|
||||
name={"square"}
|
||||
>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={squareButtonTex}
|
||||
depthTest={false}
|
||||
opacity={0.8}
|
||||
/>
|
||||
</sprite>
|
||||
</group>
|
||||
</>
|
||||
)}
|
||||
<IdleManager
|
||||
lainIdleTimerRef={lainIdleTimerRef}
|
||||
idleSceneTimerRef={idleSceneTimerRef}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default InputHandler;
|
|
@ -1,163 +0,0 @@
|
|||
import { useCallback, useEffect, useRef } from "react";
|
||||
import {
|
||||
BootSceneContext,
|
||||
EndSceneContext,
|
||||
getBootSceneContext,
|
||||
getEndSceneContext,
|
||||
getMainSceneContext,
|
||||
getMediaSceneContext,
|
||||
getSsknSceneContext,
|
||||
MainSceneContext,
|
||||
MediaSceneContext,
|
||||
playAudio,
|
||||
SsknSceneContext,
|
||||
useStore,
|
||||
} from "../store";
|
||||
import { getKeyCodeAssociation } from "../utils/keyPressUtils";
|
||||
import handleMediaSceneKeyPress from "../core/scene-keypress-handlers/handleMediaSceneKeyPress";
|
||||
import handleSsknSceneKeyPress from "../core/scene-keypress-handlers/handleSsknSceneKeyPress";
|
||||
import handleMainSceneKeyPress from "../core/scene-keypress-handlers/handleMainSceneKeyPress";
|
||||
import handleBootSceneKeyPress from "../core/scene-keypress-handlers/handleBootSceneKeyPress";
|
||||
import { useFrame } from "react-three-fiber";
|
||||
import { getRandomIdleLainAnim } from "../utils/idle-utils";
|
||||
import * as audio from "../static/sfx";
|
||||
import handleEndSceneKeyPress from "../core/scene-keypress-handlers/handleEndSceneKeyPress";
|
||||
import handleMediaSceneEvent from "../core/scene-event-handlers/handleMediaSceneEvent";
|
||||
import handleSsknSceneEvent from "../core/scene-event-handlers/handleSsknSceneEvent";
|
||||
import handleBootSceneEvent from "../core/scene-event-handlers/handleBootSceneEvent";
|
||||
import handleEndSceneEvent from "../core/scene-event-handlers/handleEndSceneEvent";
|
||||
import handleEvent from "../core/scene-event-handlers/handleEvent";
|
||||
|
||||
const KeyPressHandler = () => {
|
||||
const scene = useStore((state) => state.currentScene);
|
||||
const mainSubscene = useStore((state) => state.mainSubscene);
|
||||
const inputCooldown = useStore((state) => state.inputCooldown);
|
||||
|
||||
const setLainMoveState = useStore((state) => state.setLainMoveState);
|
||||
|
||||
const timeSinceLastKeyPress = useRef(-1);
|
||||
const lainIdleCounter = useRef(-1);
|
||||
const idleSceneCounter = useRef(-1);
|
||||
|
||||
useFrame(() => {
|
||||
const now = Date.now();
|
||||
if (
|
||||
lainIdleCounter.current > -1 &&
|
||||
idleSceneCounter.current > -1 &&
|
||||
mainSubscene !== "pause" &&
|
||||
mainSubscene !== "level_selection" &&
|
||||
scene === "main"
|
||||
) {
|
||||
if (now > lainIdleCounter.current + 10000) {
|
||||
setLainMoveState(getRandomIdleLainAnim());
|
||||
// after one idle animation plays, the second comes sooner than it would after a regular keypress
|
||||
lainIdleCounter.current = now - 2500;
|
||||
}
|
||||
if (now > idleSceneCounter.current + 30000) {
|
||||
// put it on lock until the next action, since while the idle media plays, the
|
||||
// Date.now() value keeps increasing, which can result in another idle media playing right after one finishes
|
||||
// one way to work around this would be to modify the value depending on the last played idle media's duration
|
||||
// but i'm way too lazy for that
|
||||
idleSceneCounter.current = -1;
|
||||
|
||||
// idleManager(getRandomIdleMedia());
|
||||
playAudio(audio.sound32);
|
||||
|
||||
setTimeout(() => {
|
||||
// useStore.setState({ event: "play_idle_media" });
|
||||
}, 1200);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (scene !== "main") idleSceneCounter.current = -1;
|
||||
}, [scene]);
|
||||
|
||||
const handleKeyPress = useCallback(
|
||||
(event) => {
|
||||
const { keyCode } = event;
|
||||
|
||||
const keyPress = getKeyCodeAssociation(keyCode);
|
||||
|
||||
const now = Date.now();
|
||||
|
||||
if (
|
||||
keyPress
|
||||
// !inputCooldown &&
|
||||
// now > timeSinceLastKeyPress.current + 1500
|
||||
) {
|
||||
if (scene === "main") {
|
||||
lainIdleCounter.current = now;
|
||||
idleSceneCounter.current = now;
|
||||
timeSinceLastKeyPress.current = now;
|
||||
}
|
||||
|
||||
const sceneFns = (() => {
|
||||
switch (scene) {
|
||||
case "main":
|
||||
return {
|
||||
contextProvider: getMainSceneContext,
|
||||
keyPressHandler: handleMainSceneKeyPress,
|
||||
};
|
||||
case "media":
|
||||
return {
|
||||
contextProvider: getMediaSceneContext,
|
||||
keyPressHandler: handleMediaSceneKeyPress,
|
||||
};
|
||||
// case "sskn":
|
||||
// return {
|
||||
// contextProvider: getSsknSceneContext,
|
||||
// keyPressHandler: handleSsknSceneKeyPress,
|
||||
// eventHandler: handleSsknSceneEvent,
|
||||
// };
|
||||
// case "boot":
|
||||
// return {
|
||||
// contextProvider: getBootSceneContext,
|
||||
// keyPressHandler: handleBootSceneKeyPress,
|
||||
// eventHandler: handleBootSceneEvent,
|
||||
// };
|
||||
// case "end":
|
||||
// return {
|
||||
// contextProvider: getEndSceneContext,
|
||||
// keyPressHandler: handleEndSceneKeyPress,
|
||||
// eventHandler: handleEndSceneEvent,
|
||||
// };
|
||||
// case "gate":
|
||||
// case "polytan":
|
||||
// useStore.setState({ currentScene: "main" });
|
||||
// break;
|
||||
// case "idle_media":
|
||||
// useStore.setState({
|
||||
// currentScene: "main",
|
||||
// idleStarting: false,
|
||||
// });
|
||||
// break;
|
||||
}
|
||||
})();
|
||||
|
||||
if (sceneFns) {
|
||||
const { contextProvider, keyPressHandler } = sceneFns;
|
||||
|
||||
const ctx = contextProvider(keyPress);
|
||||
const event = keyPressHandler(ctx as any) as any;
|
||||
if (event) handleEvent(event);
|
||||
// if (event) eventHandler(event.event, event.mutations);
|
||||
}
|
||||
}
|
||||
},
|
||||
[inputCooldown, scene]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("keydown", handleKeyPress);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeyPress);
|
||||
};
|
||||
}, [handleKeyPress]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default KeyPressHandler;
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useMemo, useRef } from "react";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import takIntro from "../static/sprite/tak_intro.png";
|
||||
import takOutro from "../static/sprite/tak_outro.png";
|
||||
import mouth1 from "../static/sprite/mouth_1.png";
|
||||
import mouth2 from "../static/sprite/mouth_2.png";
|
||||
import mouth3 from "../static/sprite/mouth_3.png";
|
||||
import mouth4 from "../static/sprite/mouth_4.png";
|
||||
import takIntro from "../static/sprites/lain/lain_speak_intro.png";
|
||||
import takOutro from "../static/sprites/lain/lain_speak_outro.png";
|
||||
import mouth1 from "../static/sprites/lain/mouth_1.png";
|
||||
import mouth2 from "../static/sprites/lain/mouth_2.png";
|
||||
import mouth3 from "../static/sprites/lain/mouth_3.png";
|
||||
import mouth4 from "../static/sprites/lain/mouth_4.png";
|
||||
import { useStore } from "../store";
|
||||
import { LainConstructor } from "./MainScene/Lain";
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React, { useState } from "react";
|
||||
import loadingSpritesheet from "../static/sprite/loading_spritesheet.png";
|
||||
import lifeInstinct from "../static/sprite/life_instinct_function_os.png";
|
||||
import React, { memo, useState } from "react";
|
||||
import loadingSpritesheet from "../static/sprites/loading/loading_spritesheet.png";
|
||||
import lifeInstinct from "../static/sprites/loading/life_instinct_function_os.png";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { PlainAnimator } from "three-plain-animator/lib/plain-animator";
|
||||
|
||||
const Loading = () => {
|
||||
const Loading = memo(() => {
|
||||
const loadingTex: any = useLoader(THREE.TextureLoader, loadingSpritesheet);
|
||||
const lifeInstinctTex = useLoader(THREE.TextureLoader, lifeInstinct);
|
||||
|
||||
|
@ -21,14 +21,29 @@ const Loading = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<sprite scale={[0.35, 0.6, 0.35]} position={[0, 0.2, 0]}>
|
||||
<spriteMaterial attach="material" map={loadingTex} />
|
||||
<sprite scale={[5, 5, 5]} renderOrder={999}>
|
||||
<spriteMaterial attach="material" color={0x000000} depthTest={false} />
|
||||
</sprite>
|
||||
<sprite scale={[0.4, 0.6, 0.4]} position={[0, -0.5, 0]}>
|
||||
<spriteMaterial attach="material" map={lifeInstinctTex} />
|
||||
<sprite
|
||||
scale={[0.35, 0.6, 0.35]}
|
||||
position={[0, 0.2, 0]}
|
||||
renderOrder={1000}
|
||||
>
|
||||
<spriteMaterial attach="material" map={loadingTex} depthTest={false} />
|
||||
</sprite>
|
||||
<sprite
|
||||
scale={[0.4, 0.6, 0.4]}
|
||||
position={[0, -0.5, 0]}
|
||||
renderOrder={1000}
|
||||
>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={lifeInstinctTex}
|
||||
depthTest={false}
|
||||
/>
|
||||
</sprite>
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default Loading;
|
||||
|
|
|
@ -1,35 +1,15 @@
|
|||
import React, { memo, useEffect, useRef } from "react";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import bigHud from "../../static/sprite/big_hud.png";
|
||||
import longHud from "../../static/sprite/long_hud.png";
|
||||
import boringHud from "../../static/sprite/long_hud_boring.png";
|
||||
import bigHud from "../../static/sprites/main/big_hud.png";
|
||||
import longHud from "../../static/sprites/main/long_hud.png";
|
||||
import boringHud from "../../static/sprites/main/boring_hud.png";
|
||||
import { useStore } from "../../store";
|
||||
import lerp from "../../utils/lerp";
|
||||
import GreenTextRenderer from "../TextRenderer/GreenTextRenderer";
|
||||
import usePrevious from "../../hooks/usePrevious";
|
||||
import { getNodeHud } from "../../utils/node-utils";
|
||||
|
||||
export type HUDType = {
|
||||
mirrored: number;
|
||||
long: {
|
||||
position: number[];
|
||||
initial_position: number[];
|
||||
};
|
||||
boring: {
|
||||
position: number[];
|
||||
initial_position: number[];
|
||||
};
|
||||
big: {
|
||||
position: number[];
|
||||
initial_position: number[];
|
||||
};
|
||||
big_text: number[];
|
||||
medium_text: {
|
||||
position: number[];
|
||||
initial_position: number[];
|
||||
};
|
||||
};
|
||||
import { getNodeHud } from "../../helpers/node-helpers";
|
||||
import { HUDData } from "../../types/types";
|
||||
|
||||
const HUD = memo(() => {
|
||||
const activeRef = useRef(true);
|
||||
|
@ -45,18 +25,6 @@ const HUD = memo(() => {
|
|||
const scene = useStore((state) => state.currentScene);
|
||||
const prevData = usePrevious({ siteRotY, activeLevel, subscene, scene });
|
||||
|
||||
const lerpObject = (
|
||||
obj: THREE.Object3D,
|
||||
posX: number,
|
||||
initialPosX: number
|
||||
) => {
|
||||
obj.position.x = lerp(
|
||||
obj.position.x,
|
||||
activeRef.current ? posX : initialPosX,
|
||||
0.12
|
||||
);
|
||||
};
|
||||
|
||||
// this part is imperative because it performs a lot better than having a toggleable spring.
|
||||
useFrame(() => {
|
||||
if (
|
||||
|
@ -66,25 +34,30 @@ const HUD = memo(() => {
|
|||
greenTextRef.current
|
||||
) {
|
||||
const hud = currentHudRef.current;
|
||||
lerpObject(
|
||||
longHudRef.current,
|
||||
hud.long.position[0],
|
||||
hud.long.initial_position[0]
|
||||
|
||||
longHudRef.current.position.x = lerp(
|
||||
longHudRef.current.position.x,
|
||||
activeRef.current ? hud.long.position[0] : hud.long.initial_position[0],
|
||||
0.12
|
||||
);
|
||||
lerpObject(
|
||||
boringHudRef.current,
|
||||
hud.boring.position[0],
|
||||
hud.boring.initial_position[0]
|
||||
boringHudRef.current.position.x = lerp(
|
||||
boringHudRef.current.position.x,
|
||||
activeRef.current
|
||||
? hud.boring.position[0]
|
||||
: hud.boring.initial_position[0],
|
||||
0.12
|
||||
);
|
||||
lerpObject(
|
||||
bigHudRef.current,
|
||||
hud.big.position[0],
|
||||
hud.big.initial_position[0]
|
||||
bigHudRef.current.position.x = lerp(
|
||||
bigHudRef.current.position.x,
|
||||
activeRef.current ? hud.big.position[0] : hud.big.initial_position[0],
|
||||
0.12
|
||||
);
|
||||
lerpObject(
|
||||
greenTextRef.current,
|
||||
hud.medium_text.position[0],
|
||||
hud.medium_text.initial_position[0]
|
||||
greenTextRef.current.position.x = lerp(
|
||||
greenTextRef.current.position.x,
|
||||
activeRef.current
|
||||
? hud.medium_text.position[0]
|
||||
: hud.medium_text.initial_position[0],
|
||||
0.12
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -102,7 +75,7 @@ const HUD = memo(() => {
|
|||
bigHudRef.current!.scale.x = Math.abs(bigHudRef.current!.scale.x);
|
||||
};
|
||||
|
||||
const setPos = (hud: HUDType, pos: string) => {
|
||||
const setPos = (hud: HUDData, pos: string) => {
|
||||
longHudRef.current!.position.set(
|
||||
...(hud.long[pos as keyof typeof hud.long] as [number, number, number])
|
||||
);
|
||||
|
@ -130,11 +103,12 @@ const HUD = memo(() => {
|
|||
if (
|
||||
!(scene === "main" && prevData?.scene === "main") ||
|
||||
(subscene === "site" && prevData?.subscene === "pause") ||
|
||||
(subscene === "site" && prevData?.subscene === "not_found") ||
|
||||
subscene === "pause"
|
||||
) {
|
||||
// set to final pos instantly
|
||||
setPos(hud, "position");
|
||||
if (hud.mirrored) mirror();
|
||||
else unMirror();
|
||||
} else {
|
||||
if (
|
||||
prevData?.siteRotY !== siteRotY ||
|
||||
|
@ -149,11 +123,10 @@ const HUD = memo(() => {
|
|||
() => {
|
||||
// set to initial pos instantly while its hidden
|
||||
setPos(hud, "initial_position");
|
||||
if (hud.mirrored) {
|
||||
mirror();
|
||||
} else {
|
||||
unMirror();
|
||||
}
|
||||
|
||||
if (hud.mirrored) mirror();
|
||||
else unMirror();
|
||||
|
||||
currentHudRef.current = hud;
|
||||
activeRef.current = true;
|
||||
},
|
||||
|
|
|
@ -2,35 +2,35 @@ import React, { Suspense, useEffect, useMemo, useRef, useState } from "react";
|
|||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { PlainSingularAnimator } from "three-plain-animator/lib/plain-singular-animator";
|
||||
import moveDownSpriteSheet from "../../static/sprite/jump_down.png";
|
||||
import moveUpSpriteSheet from "../../static/sprite/jump_up.png";
|
||||
import moveLeftSpriteSheet from "../../static/sprite/move_left.png";
|
||||
import moveRightSpriteSheet from "../../static/sprite/move_right.png";
|
||||
import standingSpriteSheet from "../../static/sprite/standing.png";
|
||||
import introSpriteSheet from "../../static/sprite/intro.png";
|
||||
import throwNodeSpriteSheet from "../../static/sprite/throw_node.png";
|
||||
import ripMiddleRingSpriteSheet from "../../static/sprite/rip_middle_ring.png";
|
||||
import knockSpriteSheet from "../../static/sprite/knock.png";
|
||||
import knockAndFallSpriteSheet from "../../static/sprite/knock_and_fall.png";
|
||||
import touchAndScareSpriteSheet from "../../static/sprite/touch_node_and_get_scared.png";
|
||||
import ripNodeSpriteSheet from "../../static/sprite/rip_node.png";
|
||||
import touchSleeveSpriteSheet from "../../static/sprite/touch_sleeve.png";
|
||||
import prayerSpriteSheet from "../../static/sprite/prayer.png";
|
||||
import thinkingSpriteSheet from "../../static/sprite/thinking.png";
|
||||
import stretchSpriteSheet from "../../static/sprite/stretch.png";
|
||||
import stretch2SpriteSheet from "../../static/sprite/stretch_2.png";
|
||||
import spinSpriteSheet from "../../static/sprite/spin.png";
|
||||
import scratchHeadSpriteSheet from "../../static/sprite/scratch_head.png";
|
||||
import blushSpriteSheet from "../../static/sprite/blush.png";
|
||||
import handsBehindHeadSpriteSheet from "../../static/sprite/hands_behind_head.png";
|
||||
import handsOnHipsSpriteSheet from "../../static/sprite/hands_on_hips.png";
|
||||
import handsOnHips2SpriteSheet from "../../static/sprite/hands_on_hips_2.png";
|
||||
import handsTogetherSpriteSheet from "../../static/sprite/hands_together.png";
|
||||
import leanForwardSpriteSheet from "../../static/sprite/lean_forward.png";
|
||||
import leanLeftSpriteSheet from "../../static/sprite/lean_left.png";
|
||||
import leanRightSpriteSheet from "../../static/sprite/lean_right.png";
|
||||
import lookAroundSpriteSheet from "../../static/sprite/look_around.png";
|
||||
import playWithHairSpriteSheet from "../../static/sprite/play_with_hair.png";
|
||||
import moveDownSpriteSheet from "../../static/sprites/lain/jump_down.png";
|
||||
import moveUpSpriteSheet from "../../static/sprites/lain/jump_up.png";
|
||||
import moveLeftSpriteSheet from "../../static/sprites/lain/move_left.png";
|
||||
import moveRightSpriteSheet from "../../static/sprites/lain/move_right.png";
|
||||
import standingSpriteSheet from "../../static/sprites/lain/standing.png";
|
||||
import introSpriteSheet from "../../static/sprites/lain/intro.png";
|
||||
import throwNodeSpriteSheet from "../../static/sprites/lain/throw_node.png";
|
||||
import ripMiddleRingSpriteSheet from "../../static/sprites/lain/rip_middle_ring.png";
|
||||
import knockSpriteSheet from "../../static/sprites/lain/knock.png";
|
||||
import knockAndFallSpriteSheet from "../../static/sprites/lain/knock_and_fall.png";
|
||||
import touchAndScareSpriteSheet from "../../static/sprites/lain/touch_node_and_get_scared.png";
|
||||
import ripNodeSpriteSheet from "../../static/sprites/lain/rip_node.png";
|
||||
import touchSleeveSpriteSheet from "../../static/sprites/lain/touch_sleeve.png";
|
||||
import prayerSpriteSheet from "../../static/sprites/lain/prayer.png";
|
||||
import thinkingSpriteSheet from "../../static/sprites/lain/thinking.png";
|
||||
import stretchSpriteSheet from "../../static/sprites/lain/stretch.png";
|
||||
import stretch2SpriteSheet from "../../static/sprites/lain/stretch_2.png";
|
||||
import spinSpriteSheet from "../../static/sprites/lain/spin.png";
|
||||
import scratchHeadSpriteSheet from "../../static/sprites/lain/scratch_head.png";
|
||||
import blushSpriteSheet from "../../static/sprites/lain/blush.png";
|
||||
import handsBehindHeadSpriteSheet from "../../static/sprites/lain/hands_behind_head.png";
|
||||
import handsOnHipsSpriteSheet from "../../static/sprites/lain/hands_on_hips.png";
|
||||
import handsOnHips2SpriteSheet from "../../static/sprites/lain/hands_on_hips_2.png";
|
||||
import handsTogetherSpriteSheet from "../../static/sprites/lain/hands_together.png";
|
||||
import leanForwardSpriteSheet from "../../static/sprites/lain/lean_forward.png";
|
||||
import leanLeftSpriteSheet from "../../static/sprites/lain/lean_left.png";
|
||||
import leanRightSpriteSheet from "../../static/sprites/lain/lean_right.png";
|
||||
import lookAroundSpriteSheet from "../../static/sprites/lain/look_around.png";
|
||||
import playWithHairSpriteSheet from "../../static/sprites/lain/play_with_hair.png";
|
||||
|
||||
import { useStore } from "../../store";
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useEffect, useRef } from "react";
|
||||
import level_selection_font from "../../static/sprite/select_level_font.png";
|
||||
import verticalHud from "../../static/sprite/select_level_hud_vertical.png";
|
||||
import horizontalHud from "../../static/sprite/select_level_hud_horizontal.png";
|
||||
import levelSelectionText from "../../static/sprite/select_level_text.png";
|
||||
import upArrow from "../../static/sprite/select_level_up_arrow.png";
|
||||
import downArrow from "../../static/sprite/select_level_down_arrow.png";
|
||||
import upArrowActive from "../../static/sprite/select_level_up_arrow_active.png";
|
||||
import downArrowActive from "../../static/sprite/select_level_down_arrow_active.png";
|
||||
import level_selection_font from "../../static/sprites/main/select_level_font.png";
|
||||
import verticalHud from "../../static/sprites/main/select_level_hud_vertical.png";
|
||||
import horizontalHud from "../../static/sprites/main/select_level_hud_horizontal.png";
|
||||
import levelSelectionText from "../../static/sprites/main/select_level_text.png";
|
||||
import upArrow from "../../static/sprites/main/select_level_up_arrow.png";
|
||||
import downArrow from "../../static/sprites/main/select_level_down_arrow.png";
|
||||
import upArrowActive from "../../static/sprites/main/select_level_up_arrow_active.png";
|
||||
import downArrowActive from "../../static/sprites/main/select_level_down_arrow_active.png";
|
||||
import { useStore } from "../../store";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
|
@ -124,7 +124,7 @@ const LevelSelection = () => {
|
|||
]);
|
||||
|
||||
return (
|
||||
<group>
|
||||
<>
|
||||
<a.group position-y={pos.vertPosY} renderOrder={5}>
|
||||
<mesh
|
||||
scale={[0.3, 0.4, 0]}
|
||||
|
@ -212,7 +212,7 @@ const LevelSelection = () => {
|
|||
depthTest={false}
|
||||
/>
|
||||
</a.sprite>
|
||||
</group>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import middleRingTexture from "../../../static/sprite/middle_ring_tex.png";
|
||||
import middleRingTexture from "../../../static/sprites/main/middle_ring_tex.png";
|
||||
import * as THREE from "three";
|
||||
import { a, useSpring } from "@react-spring/three";
|
||||
import { useStore } from "../../../store";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useMemo } from "react";
|
||||
import middleRingTexture from "../../../static/sprite/middle_ring_tex.png";
|
||||
import middleRingTexture from "../../../static/sprites/main/middle_ring_tex.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { a, useSpring } from "@react-spring/three";
|
||||
|
|
|
@ -3,28 +3,9 @@ import * as THREE from "three";
|
|||
import PauseSquare from "./PauseSquare";
|
||||
import PauseBigLetter from "../../TextRenderer/PauseBigLetter";
|
||||
import { useStore } from "../../../store";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import usePrevious from "../../../hooks/usePrevious";
|
||||
|
||||
const Pause = () => {
|
||||
const exit = useStore((state) => state.pauseExitAnimation);
|
||||
const [showActiveComponent, setShowActiveComponent] = useState(false);
|
||||
const [animation, setAnimation] = useState(false);
|
||||
const [intro, setIntro] = useState(true);
|
||||
|
||||
const wordFont = useLoader(THREE.FontLoader, "/3d_fonts/MediaWord.blob");
|
||||
|
||||
const config = useMemo(
|
||||
() => ({
|
||||
font: wordFont,
|
||||
size: 2.5,
|
||||
}),
|
||||
[wordFont]
|
||||
);
|
||||
|
||||
const activeComponent = useStore((state) =>
|
||||
showActiveComponent ? state.activePauseComponent : ""
|
||||
);
|
||||
|
||||
const generateSqaureGeom = useCallback((row: number, square: number) => {
|
||||
const geometry = new THREE.PlaneBufferGeometry();
|
||||
const uvAttribute = geometry.attributes.uv;
|
||||
|
@ -48,306 +29,169 @@ const Pause = () => {
|
|||
[generateSqaureGeom]
|
||||
);
|
||||
|
||||
const subscene = useStore((state) => state.mainSubscene);
|
||||
const letterLocs = useMemo(
|
||||
() => ({
|
||||
"05": { letter: "E" },
|
||||
"11": { letter: "S" },
|
||||
"33": { letter: "C" },
|
||||
"45": { letter: "A" },
|
||||
"51": { letter: "L" },
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
const subscene = useStore((state) => state.mainSubscene);
|
||||
const prevData = usePrevious({ subscene });
|
||||
const setInputCooldown = useStore((state) => state.setInputCooldown);
|
||||
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [finished, setFinished] = useState(false);
|
||||
const [exit, setExit] = useState(false);
|
||||
|
||||
const activeComponent = useStore(
|
||||
useCallback((state) => (finished ? state.activePauseComponent : ""), [
|
||||
finished,
|
||||
])
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setAnimation(false);
|
||||
setIntro(true);
|
||||
setShowActiveComponent(false);
|
||||
if (subscene === "pause") {
|
||||
setTimeout(() => {
|
||||
setTimeout(() => {
|
||||
setAnimation(true);
|
||||
}, 1000);
|
||||
setTimeout(() => {
|
||||
setShowActiveComponent(true);
|
||||
setIntro(false);
|
||||
setInputCooldown(false);
|
||||
}, 3500);
|
||||
}, 3400);
|
||||
setTimeout(() => setVisible(true), 4400);
|
||||
setTimeout(() => setFinished(true), 7300);
|
||||
setTimeout(() => setInputCooldown(1000), 7600);
|
||||
}
|
||||
}, [setInputCooldown, subscene]);
|
||||
|
||||
if (prevData?.subscene === "pause" && subscene === "site") {
|
||||
setExit(true);
|
||||
setTimeout(() => {
|
||||
setVisible(false);
|
||||
setFinished(false);
|
||||
setExit(false);
|
||||
}, 1200);
|
||||
}
|
||||
}, [prevData?.subscene, setInputCooldown, subscene]);
|
||||
|
||||
const whenActive = useCallback((rowIdx: number, colIdx: number) => {
|
||||
switch (rowIdx) {
|
||||
case 5:
|
||||
if (colIdx > 1 && colIdx < 5) return "load";
|
||||
break;
|
||||
case 4:
|
||||
if (colIdx > 5 && colIdx < 7) return "about";
|
||||
break;
|
||||
case 3:
|
||||
if (colIdx > 3 && colIdx < 7) return "change";
|
||||
break;
|
||||
case 1:
|
||||
if (colIdx > 1 && colIdx < 5) return "save";
|
||||
break;
|
||||
case 0:
|
||||
if (colIdx > 4 && colIdx < 7) return "exit";
|
||||
break;
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{animation && (
|
||||
<>
|
||||
<group position={[-0.85, -0.7, 0]} scale={[0.85, 0.85, 0]}>
|
||||
{[0, 1, 2, 3, 2, 1, 0].map((row: number, rowIdx: number) =>
|
||||
[0, 1, 2, 3, 4, 5, 6].map((col: number) => {
|
||||
if (rowIdx === 5 && col > 0 && col < 5) {
|
||||
return col === 1 ? (
|
||||
<React.Fragment key={`Lfragment`}>
|
||||
{visible && (
|
||||
<group position={[-0.9, -0.7, 0]} scale={[0.85, 0.85, 0]}>
|
||||
{[0, 1, 2, 3, 2, 1, 0].map((r: number, rowIdx: number) =>
|
||||
[0, 1, 2, 3, 4, 5, 6].map((c: number, colIdx: number) => {
|
||||
const key = `${rowIdx}${colIdx}`;
|
||||
|
||||
const letter = letterLocs[key as keyof typeof letterLocs];
|
||||
if (letter)
|
||||
return (
|
||||
<React.Fragment key={`${key}fragment`}>
|
||||
<PauseBigLetter
|
||||
color={"white"}
|
||||
letter={"L"}
|
||||
letterIdx={col}
|
||||
position={[0.35, 1.8, 0]}
|
||||
scale={[0.25, 0.25, 0.25]}
|
||||
active={!(activeComponent === "load")}
|
||||
key={"whiteL"}
|
||||
letter={letter.letter}
|
||||
letterIdx={0}
|
||||
position={[colIdx / 2.8, rowIdx / 2.8, 0]}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
intro={intro}
|
||||
colIdx={colIdx}
|
||||
mainLetter={true}
|
||||
active={
|
||||
letter.letter ===
|
||||
activeComponent.charAt(0).toUpperCase()
|
||||
}
|
||||
introFinished={finished}
|
||||
exit={exit}
|
||||
/>
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
geometry={squareGeoms[r][c]}
|
||||
colIdx={colIdx}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
key={"whiteLsquare"}
|
||||
shouldDisappear={true}
|
||||
intro={intro}
|
||||
letter={letter.letter}
|
||||
introFinished={finished}
|
||||
exit={exit}
|
||||
/>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
active={!(activeComponent === "load")}
|
||||
key={`${rowIdx}${col}L`}
|
||||
intro={intro}
|
||||
/>
|
||||
);
|
||||
} else if (rowIdx === 4 && col > 4 && col < 7) {
|
||||
return col === 5 ? (
|
||||
<React.Fragment key={"AFragment"}>
|
||||
<PauseBigLetter
|
||||
color={"white"}
|
||||
letter={"A"}
|
||||
letterIdx={col}
|
||||
position={[1.78, 1.43, 0]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
active={!(activeComponent === "about")}
|
||||
key={"whiteA"}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
intro={intro}
|
||||
/>
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
key={"whiteAsquare"}
|
||||
shouldDisappear={true}
|
||||
intro={intro}
|
||||
/>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
active={!(activeComponent === "about")}
|
||||
key={`${rowIdx}${col}A`}
|
||||
intro={intro}
|
||||
/>
|
||||
);
|
||||
} else if (rowIdx === 3 && col > 2 && col < 7) {
|
||||
return col === 3 ? (
|
||||
<React.Fragment key={"CFragment"}>
|
||||
<PauseBigLetter
|
||||
color={"white"}
|
||||
letter={"C"}
|
||||
letterIdx={col}
|
||||
position={[1.05, 1.07, 0]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
active={!(activeComponent === "change")}
|
||||
key={"whiteC"}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
intro={intro}
|
||||
/>
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
key={"whiteCsquare"}
|
||||
shouldDisappear={true}
|
||||
intro={intro}
|
||||
/>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
active={!(activeComponent === "change")}
|
||||
key={`${rowIdx}${col}C`}
|
||||
intro={intro}
|
||||
/>
|
||||
);
|
||||
} else if (rowIdx === 1 && col > 0 && col < 5) {
|
||||
return col === 1 ? (
|
||||
<React.Fragment key={"Sfragment"}>
|
||||
<PauseBigLetter
|
||||
color={"white"}
|
||||
letter={"S"}
|
||||
letterIdx={col}
|
||||
position={[0.35, 0.35, 0]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
active={!(activeComponent === "save")}
|
||||
key={"whiteS"}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
intro={intro}
|
||||
/>
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
key={"whiteSsquare"}
|
||||
shouldDisappear={true}
|
||||
intro={intro}
|
||||
/>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
active={!(activeComponent === "save")}
|
||||
key={`${rowIdx}${col}S`}
|
||||
intro={intro}
|
||||
/>
|
||||
);
|
||||
} else if (rowIdx === 0 && col > 4 && col < 7) {
|
||||
return col === 5 ? (
|
||||
<React.Fragment key={"Efragment"}>
|
||||
<PauseBigLetter
|
||||
color={"white"}
|
||||
letter={"E"}
|
||||
letterIdx={col}
|
||||
position={[1.78, 0, 0]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
active={!(activeComponent === "exit")}
|
||||
key={"whiteE"}
|
||||
rowIdx={1}
|
||||
colIdx={col}
|
||||
intro={intro}
|
||||
/>
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
key={"whiteEsquare"}
|
||||
shouldDisappear={true}
|
||||
intro={intro}
|
||||
/>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
active={!(activeComponent === "exit")}
|
||||
key={`${rowIdx}${col}E`}
|
||||
intro={intro}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
else
|
||||
return (
|
||||
<PauseSquare
|
||||
geometry={squareGeoms[row][col]}
|
||||
geometry={squareGeoms[r][c]}
|
||||
colIdx={colIdx}
|
||||
rowIdx={rowIdx}
|
||||
colIdx={col}
|
||||
key={`${rowIdx}${col}r`}
|
||||
active={true}
|
||||
intro={intro}
|
||||
key={key}
|
||||
active={activeComponent === whenActive(rowIdx, colIdx)}
|
||||
introFinished={finished}
|
||||
exit={exit}
|
||||
/>
|
||||
);
|
||||
}
|
||||
})
|
||||
)}
|
||||
{"Load".split("").map((letter, idx) => (
|
||||
|
||||
<>
|
||||
{"oad".split("").map((letter, idx) => (
|
||||
<PauseBigLetter
|
||||
color={idx > 0 ? "yellow" : "orange"}
|
||||
letter={letter}
|
||||
letterIdx={idx}
|
||||
key={idx}
|
||||
position={[0.35 + idx / 2.8, 1.8, 0]}
|
||||
scale={[0.25, 0.25, 0.25]}
|
||||
position={[2 / 2.8 + idx / 2.8, 5 / 2.8, 0]}
|
||||
active={activeComponent === "load"}
|
||||
/>
|
||||
))}
|
||||
{"About".split("").map((letter, idx) => (
|
||||
{"bout".split("").map((letter, idx) => (
|
||||
<PauseBigLetter
|
||||
color={idx > 0 ? "yellow" : "orange"}
|
||||
letter={letter}
|
||||
letterIdx={idx}
|
||||
position={[1.78 + idx / 2.8, 1.43, 0]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
position={[6 / 2.8 + idx / 2.8, 4 / 2.8, 0]}
|
||||
active={activeComponent === "about"}
|
||||
key={idx}
|
||||
/>
|
||||
))}
|
||||
{"Change".split("").map((letter, idx) => (
|
||||
|
||||
{"hange".split("").map((letter, idx) => (
|
||||
<PauseBigLetter
|
||||
color={idx > 0 ? "yellow" : "orange"}
|
||||
letter={letter}
|
||||
letterIdx={idx}
|
||||
position={[1.05 + idx / 2.8, 1.07, 0]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
position={[4 / 2.8 + idx / 2.8, 3 / 2.8, 0]}
|
||||
active={activeComponent === "change"}
|
||||
key={idx}
|
||||
/>
|
||||
))}
|
||||
{"Save".split("").map((letter, idx) => (
|
||||
|
||||
{"ave".split("").map((letter, idx) => (
|
||||
<PauseBigLetter
|
||||
color={idx > 0 ? "yellow" : "orange"}
|
||||
letter={letter}
|
||||
letterIdx={idx}
|
||||
position={[0.35 + idx / 2.8, 0.35, 0]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
position={[2 / 2.8 + idx / 2.8, 1 / 2.8, 0]}
|
||||
active={activeComponent === "save"}
|
||||
key={idx}
|
||||
/>
|
||||
))}
|
||||
{"Exit".split("").map((letter, idx) => (
|
||||
{"xit".split("").map((letter, idx) => (
|
||||
<PauseBigLetter
|
||||
color={idx > 0 ? "yellow" : "orange"}
|
||||
letter={letter}
|
||||
letterIdx={idx}
|
||||
position={[1.78 + idx / 2.8, 0, 0]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
position={[6 / 2.8 + idx / 2.8, 0, 0]}
|
||||
key={idx}
|
||||
active={activeComponent === "exit"}
|
||||
/>
|
||||
))}
|
||||
<group visible={!exit}>
|
||||
<sprite
|
||||
position={[0.5, -0.8, 0]}
|
||||
scale={[3, 1, 0]}
|
||||
renderOrder={100}
|
||||
>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
color={0x000000}
|
||||
opacity={0.8}
|
||||
depthTest={false}
|
||||
/>
|
||||
</sprite>
|
||||
<mesh
|
||||
scale={[0.08, 0.07, 0]}
|
||||
position={[-0.2, -0.6, 0]}
|
||||
renderOrder={101}
|
||||
>
|
||||
<textGeometry
|
||||
attach="geometry"
|
||||
args={["Application Version 1.0", config]}
|
||||
/>
|
||||
<meshBasicMaterial
|
||||
attach="material"
|
||||
color={0x00ba7c}
|
||||
transparent={true}
|
||||
depthTest={false}
|
||||
/>
|
||||
</mesh>
|
||||
</group>
|
||||
</group>
|
||||
</>
|
||||
</group>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -1,25 +1,47 @@
|
|||
import React, { useMemo, memo } from "react";
|
||||
import * as THREE from "three";
|
||||
import React, { memo, useMemo } from "react";
|
||||
import pauseGrayBoxes from "../../../static/sprites/main/pause_gray_boxes.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import pauseGrayBoxes from "../../../static/sprite/pause_gray_boxes.png";
|
||||
import * as THREE from "three";
|
||||
import { a, useSpring } from "@react-spring/three";
|
||||
import { useStore } from "../../../store";
|
||||
|
||||
type PauseSquareProps = {
|
||||
geometry: THREE.PlaneBufferGeometry;
|
||||
colIdx: number;
|
||||
rowIdx: number;
|
||||
geometry: THREE.PlaneBufferGeometry;
|
||||
letter?: string;
|
||||
active?: boolean;
|
||||
shouldDisappear?: boolean;
|
||||
intro?: boolean;
|
||||
introFinished?: boolean;
|
||||
exit?: boolean;
|
||||
};
|
||||
|
||||
const PauseSquare = memo((props: PauseSquareProps) => {
|
||||
const exitAnimation = useStore((state) => state.pauseExitAnimation);
|
||||
const squareTex = useLoader(THREE.TextureLoader, pauseGrayBoxes);
|
||||
|
||||
const grayBoxesTex = useLoader(THREE.TextureLoader, pauseGrayBoxes);
|
||||
const introSpring = useSpring({
|
||||
from: {
|
||||
posX: 1.05,
|
||||
posY: 1.07,
|
||||
rotZ: -1,
|
||||
rotX: Math.PI,
|
||||
rotY: Math.PI,
|
||||
},
|
||||
to: async (next) => {
|
||||
await next({
|
||||
posX: props.colIdx / 2.8,
|
||||
posY: props.rowIdx / 2.8,
|
||||
rotZ: 0,
|
||||
config: { duration: 500 },
|
||||
});
|
||||
await next({
|
||||
rotX: 0,
|
||||
rotY: props.letter ? Math.PI / 2 : 0,
|
||||
delay: (props.rowIdx + props.colIdx) * 100,
|
||||
config: { duration: 200 },
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const getExitAnimValue = useMemo(() => {
|
||||
const exitAnimValue = useMemo(() => {
|
||||
let col, row;
|
||||
if (props.colIdx < 3) col = -1;
|
||||
else if (props.colIdx > 3) col = 1;
|
||||
|
@ -29,55 +51,37 @@ const PauseSquare = memo((props: PauseSquareProps) => {
|
|||
else if (props.rowIdx > 3) row = 1;
|
||||
else row = 0;
|
||||
|
||||
return { row, col };
|
||||
return { row: row * 2.2, col: col * 2.2 };
|
||||
}, [props.colIdx, props.rowIdx]);
|
||||
|
||||
const initialState = useSpring({
|
||||
posX: props.colIdx / 2.8 + getExitAnimValue.col * (exitAnimation ? 2.2 : 0),
|
||||
posY: props.rowIdx / 2.8 + getExitAnimValue.row * (exitAnimation ? 2.2 : 0),
|
||||
rotX: props.active ? (exitAnimation ? Math.PI / 2 : 0) : -Math.PI,
|
||||
rotY: props.active ? (exitAnimation ? Math.PI / 2 : 0) : Math.PI / 2,
|
||||
rotZ: 0,
|
||||
from: { posX: 1.05, posY: 1.07, rotZ: -1 },
|
||||
const spring = useSpring({
|
||||
posX: props.colIdx / 2.8 + (props.exit ? exitAnimValue.col : 0),
|
||||
posY: props.rowIdx / 2.8 + (props.exit ? exitAnimValue.row : 0),
|
||||
rotY: props.active || props.exit ? Math.PI / 2 : 0,
|
||||
rotX: props.active ? Math.PI : 0,
|
||||
config: { duration: 500 },
|
||||
});
|
||||
|
||||
const shadowState = useSpring({
|
||||
posX: props.colIdx / 2.8 + getExitAnimValue.col * (exitAnimation ? 2.2 : 0),
|
||||
posY: props.rowIdx / 2.8 + getExitAnimValue.row * (exitAnimation ? 2.2 : 0),
|
||||
rotX: exitAnimation ? Math.PI / 2 : 0,
|
||||
rotY: exitAnimation ? Math.PI / 2 : 0,
|
||||
from: { posX: 1.05, posY: 1.07, rotZ: -1 },
|
||||
config: { duration: 500 },
|
||||
});
|
||||
|
||||
const introState = useSpring({
|
||||
rotX: 0,
|
||||
rotY: props.shouldDisappear ? Math.PI / 2 : 0,
|
||||
from: { rotX: Math.PI, rotY: Math.PI },
|
||||
delay: (props.rowIdx + props.colIdx) * 100 + 500,
|
||||
config: { duration: 200 },
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<a.mesh
|
||||
position-x={props.introFinished ? spring.posX : introSpring.posX}
|
||||
position-y={props.introFinished ? spring.posY : introSpring.posY}
|
||||
rotation-z={props.introFinished ? 0 : introSpring.rotZ}
|
||||
rotation-x={props.introFinished ? spring.rotX : introSpring.rotX}
|
||||
rotation-y={
|
||||
!props.letter && props.introFinished ? spring.rotY : introSpring.rotY
|
||||
}
|
||||
geometry={props.geometry}
|
||||
position-x={initialState.posX}
|
||||
position-y={initialState.posY}
|
||||
scale={[
|
||||
props.colIdx > 3 ? -0.25 : 0.25,
|
||||
props.rowIdx <= 3 ? -0.25 : 0.25,
|
||||
0,
|
||||
]}
|
||||
rotation-x={props.intro ? introState.rotX : initialState.rotX}
|
||||
rotation-y={props.intro ? introState.rotY : initialState.rotY}
|
||||
rotation-z={initialState.rotZ}
|
||||
renderOrder={100}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
attach="material"
|
||||
map={grayBoxesTex}
|
||||
map={squareTex}
|
||||
side={
|
||||
(props.colIdx > 3 && props.rowIdx <= 3) ||
|
||||
(props.colIdx <= 3 && props.rowIdx > 3)
|
||||
|
@ -88,26 +92,6 @@ const PauseSquare = memo((props: PauseSquareProps) => {
|
|||
depthTest={false}
|
||||
/>
|
||||
</a.mesh>
|
||||
<group scale={[0.9, 0.9, 0]} position={[0.1, 0.1, 0]}>
|
||||
<a.mesh
|
||||
geometry={props.geometry}
|
||||
position-x={shadowState.posX}
|
||||
position-y={shadowState.posY}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
rotation-x={shadowState.rotX}
|
||||
rotation-y={shadowState.rotY}
|
||||
rotation-z={initialState.rotZ}
|
||||
renderOrder={99}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
attach="material"
|
||||
side={THREE.DoubleSide}
|
||||
transparent={true}
|
||||
color={0x1d1d2d}
|
||||
/>
|
||||
</a.mesh>
|
||||
</group>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useRef } from "react";
|
||||
import aboutBg from "../../../static/sprite/about_background.png";
|
||||
import aboutBg from "../../../static/sprites/main/about_background.png";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { useStore } from "../../../store";
|
||||
|
@ -10,8 +10,6 @@ const About = () => {
|
|||
const aboutBgTex = useLoader(THREE.TextureLoader, aboutBg);
|
||||
|
||||
const bgRef = useRef<THREE.Sprite>();
|
||||
// todo im not sure where the other bg file is located,
|
||||
// the one here is just the text, in the original game there's another one
|
||||
|
||||
useFrame(() => {
|
||||
if (bgRef.current) {
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
import React, { memo } from "react";
|
||||
import notFound from "../../../static/sprite/not_found.png";
|
||||
import notFoundLof from "../../../static/sprite/not_found_lof.png";
|
||||
import notFound from "../../../static/sprites/main/not_found.png";
|
||||
import notFoundLof from "../../../static/sprites/main/not_found_lof.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { useStore } from "../../../store";
|
||||
|
||||
const NotFound = memo(() => {
|
||||
const notFoundTex = useLoader(THREE.TextureLoader, notFound);
|
||||
const notFoundLofTex = useLoader(THREE.TextureLoader, notFoundLof);
|
||||
|
||||
const wordNotFound = useStore((state) => state.wordNotFound);
|
||||
|
||||
return (
|
||||
<group visible={false}>
|
||||
<group visible={wordNotFound}>
|
||||
<sprite scale={[1, 0.25, 0]} renderOrder={106} position={[-1, -0.05, 0]}>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { memo } from "react";
|
||||
import headerContainer from "../../../static/sprite/prompt_question_container.png";
|
||||
import headerContainer from "../../../static/sprites/prompt/prompt_question_container.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import StaticOrangeLetter from "../../TextRenderer/StaticOrangeLetter";
|
||||
|
|
|
@ -2,8 +2,8 @@ import React, { memo, useEffect, useState } from "react";
|
|||
import Node from "./Node";
|
||||
import node_positions from "../../../resources/node_positions.json";
|
||||
import { useStore } from "../../../store";
|
||||
import { NodeData, SiteData } from "./Site";
|
||||
import usePrevious from "../../../hooks/usePrevious";
|
||||
import {NodeData, SiteData} from "../../../types/types";
|
||||
|
||||
type ActiveLevelNodesProps = {
|
||||
visibleNodes: SiteData;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import React, { memo, useMemo } from "react";
|
||||
import * as THREE from "three";
|
||||
import lofTexture from "../../../static/sprite/gray_ring_lof.png";
|
||||
import holeTexture from "../../../static/sprite/hole.png";
|
||||
import lifeTexture from "../../../static/sprite/life.png";
|
||||
import lofTexture from "../../../static/sprites/main/gray_ring_lof.png";
|
||||
import holeTexture from "../../../static/sprites/main/hole.png";
|
||||
import lifeTexture from "../../../static/sprites/main/life.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
|
||||
type GrayRingProps = {
|
||||
|
|
|
@ -2,20 +2,20 @@ import React, { memo, useMemo } from "react";
|
|||
import { useLoader } from "react-three-fiber";
|
||||
import { a } from "@react-spring/three";
|
||||
import * as THREE from "three";
|
||||
import Cou from "../../../static/sprite/Cou.png";
|
||||
import CouViewed from "../../../static/sprite/Cou_viewed.png";
|
||||
import Dc from "../../../static/sprite/Dc.png";
|
||||
import DcViewed from "../../../static/sprite/Dc_viewed.png";
|
||||
import Sskn from "../../../static/sprite/SSkn.png";
|
||||
import SsknViewed from "../../../static/sprite/SSkn_viewed.png";
|
||||
import Tda from "../../../static/sprite/Tda.png";
|
||||
import TdaViewed from "../../../static/sprite/Tda_viewed.png";
|
||||
import Dia from "../../../static/sprite/Dia.png";
|
||||
import DiaViewed from "../../../static/sprite/Dia_viewed.png";
|
||||
import Lda from "../../../static/sprite/Lda.png";
|
||||
import LdaViewed from "../../../static/sprite/Lda_viewed.png";
|
||||
import MULTI from "../../../static/sprite/MULTI.png";
|
||||
import MULTIViewed from "../../../static/sprite/MULTI_viewed.png";
|
||||
import Cou from "../../../static/sprites/nodes/Cou.png";
|
||||
import CouViewed from "../../../static/sprites/nodes/Cou_viewed.png";
|
||||
import Dc from "../../../static/sprites/nodes/Dc.png";
|
||||
import DcViewed from "../../../static/sprites/nodes/Dc_viewed.png";
|
||||
import Sskn from "../../../static/sprites/nodes/SSkn.png";
|
||||
import SsknViewed from "../../../static/sprites/nodes/SSkn_viewed.png";
|
||||
import Tda from "../../../static/sprites/nodes/Tda.png";
|
||||
import TdaViewed from "../../../static/sprites/nodes/Tda_viewed.png";
|
||||
import Dia from "../../../static/sprites/nodes/Dia.png";
|
||||
import DiaViewed from "../../../static/sprites/nodes/Dia_viewed.png";
|
||||
import Lda from "../../../static/sprites/nodes/Lda.png";
|
||||
import LdaViewed from "../../../static/sprites/nodes/Lda_viewed.png";
|
||||
import MULTI from "../../../static/sprites/nodes/MULTI.png";
|
||||
import MULTIViewed from "../../../static/sprites/nodes/MULTI_viewed.png";
|
||||
import level_y_values from "../../../resources/level_y_values.json";
|
||||
|
||||
type NodeContructorProps = {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, { memo, useEffect, useState } from "react";
|
||||
import node_positions from "../../../resources/node_positions.json";
|
||||
import { useStore } from "../../../store";
|
||||
import { SiteData } from "./Site";
|
||||
import InactiveLevelNode from "./InactiveLevelNode";
|
||||
import usePrevious from "../../../hooks/usePrevious";
|
||||
import { generateInactiveNodes } from "../../../utils/node-utils";
|
||||
import { generateInactiveNodes } from "../../../helpers/node-helpers";
|
||||
import {SiteData} from "../../../types/types";
|
||||
|
||||
type ActiveLevelNodesProps = {
|
||||
visibleNodes: SiteData;
|
||||
|
|
21
src/components/MainScene/Site/MainSceneBackground.tsx
Normal file
21
src/components/MainScene/Site/MainSceneBackground.tsx
Normal file
|
@ -0,0 +1,21 @@
|
|||
import React, { memo } from "react";
|
||||
import mainSceneBg from "../../../static/sprites/main/main_scene_background.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
|
||||
const MainSceneBackground = memo(() => {
|
||||
const mainSceneBgTex = useLoader(THREE.TextureLoader, mainSceneBg);
|
||||
|
||||
return (
|
||||
<mesh renderOrder={-5} scale={[5, 1, 0]}>
|
||||
<planeBufferGeometry attach="geometry" />
|
||||
<meshBasicMaterial
|
||||
attach="material"
|
||||
map={mainSceneBgTex}
|
||||
depthTest={false}
|
||||
/>
|
||||
</mesh>
|
||||
);
|
||||
});
|
||||
|
||||
export default MainSceneBackground;
|
|
@ -2,27 +2,27 @@ import React, { memo, useEffect, useMemo, useRef } from "react";
|
|||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import { a, useSpring } from "@react-spring/three";
|
||||
import * as THREE from "three";
|
||||
import Cou from "../../../static/sprite/Cou.png";
|
||||
import CouActive from "../../../static/sprite/Cou_active.png";
|
||||
import CouViewed from "../../../static/sprite/Cou_viewed.png";
|
||||
import Dc from "../../../static/sprite/Dc.png";
|
||||
import DcActive from "../../../static/sprite/Dc_active.png";
|
||||
import DcViewed from "../../../static/sprite/Dc_viewed.png";
|
||||
import Sskn from "../../../static/sprite/SSkn.png";
|
||||
import SsknActive from "../../../static/sprite/SSkn_active.png";
|
||||
import SsknViewed from "../../../static/sprite/SSkn_viewed.png";
|
||||
import Tda from "../../../static/sprite/Tda.png";
|
||||
import TdaActive from "../../../static/sprite/Tda_active.png";
|
||||
import TdaViewed from "../../../static/sprite/Tda_viewed.png";
|
||||
import Dia from "../../../static/sprite/Dia.png";
|
||||
import DiaActive from "../../../static/sprite/Dia_active.png";
|
||||
import DiaViewed from "../../../static/sprite/Dia_viewed.png";
|
||||
import Lda from "../../../static/sprite/Lda.png";
|
||||
import LdaActive from "../../../static/sprite/Lda_active.png";
|
||||
import LdaViewed from "../../../static/sprite/Lda_viewed.png";
|
||||
import MULTI from "../../../static/sprite/MULTI.png";
|
||||
import MULTIActive from "../../../static/sprite/MULTI_active.png";
|
||||
import MULTIViewed from "../../../static/sprite/MULTI_viewed.png";
|
||||
import Cou from "../../../static/sprites/nodes/Cou.png";
|
||||
import CouActive from "../../../static/sprites/nodes/Cou_active.png";
|
||||
import CouViewed from "../../../static/sprites/nodes/Cou_viewed.png";
|
||||
import Dc from "../../../static/sprites/nodes/Dc.png";
|
||||
import DcActive from "../../../static/sprites/nodes/Dc_active.png";
|
||||
import DcViewed from "../../../static/sprites/nodes/Dc_viewed.png";
|
||||
import Sskn from "../../../static/sprites/nodes/SSkn.png";
|
||||
import SsknActive from "../../../static/sprites/nodes/SSkn_active.png";
|
||||
import SsknViewed from "../../../static/sprites/nodes/SSkn_viewed.png";
|
||||
import Tda from "../../../static/sprites/nodes/Tda.png";
|
||||
import TdaActive from "../../../static/sprites/nodes/Tda_active.png";
|
||||
import TdaViewed from "../../../static/sprites/nodes/Tda_viewed.png";
|
||||
import Dia from "../../../static/sprites/nodes/Dia.png";
|
||||
import DiaActive from "../../../static/sprites/nodes/Dia_active.png";
|
||||
import DiaViewed from "../../../static/sprites/nodes/Dia_viewed.png";
|
||||
import Lda from "../../../static/sprites/nodes/Lda.png";
|
||||
import LdaActive from "../../../static/sprites/nodes/Lda_active.png";
|
||||
import LdaViewed from "../../../static/sprites/nodes/Lda_viewed.png";
|
||||
import MULTI from "../../../static/sprites/nodes/MULTI.png";
|
||||
import MULTIActive from "../../../static/sprites/nodes/MULTI_active.png";
|
||||
import MULTIViewed from "../../../static/sprites/nodes/MULTI_viewed.png";
|
||||
import level_y_values from "../../../resources/level_y_values.json";
|
||||
import { useStore } from "../../../store";
|
||||
|
||||
|
|
|
@ -2,20 +2,20 @@ import React, { useEffect, useMemo, useRef } from "react";
|
|||
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
||||
import * as THREE from "three";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import Cou from "../../../../../static/sprite/Cou.png";
|
||||
import CouGold from "../../../../../static/sprite/Cou_gold.png";
|
||||
import Dc from "../../../../../static/sprite/Dc.png";
|
||||
import DcGold from "../../../../../static/sprite/Dc_gold.png";
|
||||
import Sskn from "../../../../../static/sprite/SSkn.png";
|
||||
import SsknGold from "../../../../../static/sprite/SSkn_gold.png";
|
||||
import Tda from "../../../../../static/sprite/Tda.png";
|
||||
import TdaGold from "../../../../../static/sprite/Tda_gold.png";
|
||||
import Dia from "../../../../../static/sprite/Dia.png";
|
||||
import DiaGold from "../../../../../static/sprite/Dia_gold.png";
|
||||
import Lda from "../../../../../static/sprite/Lda.png";
|
||||
import LdaGold from "../../../../../static/sprite/Lda_gold.png";
|
||||
import MULTI from "../../../../../static/sprite/MULTI.png";
|
||||
import MULTIGold from "../../../../../static/sprite/MULTI_gold.png";
|
||||
import Cou from "../../../../../static/sprites/nodes/Cou.png";
|
||||
import CouGold from "../../../../../static/sprites/nodes/Cou_gold.png";
|
||||
import Dc from "../../../../../static/sprites/nodes/Dc.png";
|
||||
import DcGold from "../../../../../static/sprites/nodes/Dc_gold.png";
|
||||
import Sskn from "../../../../../static/sprites/nodes/SSkn.png";
|
||||
import SsknGold from "../../../../../static/sprites/nodes/SSkn_gold.png";
|
||||
import Tda from "../../../../../static/sprites/nodes/Tda.png";
|
||||
import TdaGold from "../../../../../static/sprites/nodes/Tda_gold.png";
|
||||
import Dia from "../../../../../static/sprites/nodes/Dia.png";
|
||||
import DiaGold from "../../../../../static/sprites/nodes/Dia_gold.png";
|
||||
import Lda from "../../../../../static/sprites/nodes/Lda.png";
|
||||
import LdaGold from "../../../../../static/sprites/nodes/Lda_gold.png";
|
||||
import MULTI from "../../../../../static/sprites/nodes/MULTI.png";
|
||||
import MULTIGold from "../../../../../static/sprites/nodes/MULTI_gold.png";
|
||||
import { useStore } from "../../../../../store";
|
||||
|
||||
type GLTFResult = GLTF & {
|
||||
|
@ -35,9 +35,7 @@ type GoldNodeProps = {
|
|||
const GoldNode = (props: GoldNodeProps) => {
|
||||
const { nodes } = useLoader<GLTFResult>(GLTFLoader, "models/gold_node.glb");
|
||||
|
||||
const activeNodeName = useStore(
|
||||
(state) => state.activeNode.node_name
|
||||
);
|
||||
const activeNodeName = useStore((state) => state.activeNode.node_name);
|
||||
|
||||
const tex = useMemo(() => {
|
||||
if (activeNodeName.includes("S")) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useRef } from "react";
|
||||
import MULTI from "../../../../../static/sprite/MULTI.png";
|
||||
import MULTI from "../../../../../static/sprites/nodes/MULTI.png";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React, { memo, useEffect, useMemo, useRef } from "react";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import siteATex from "../../../static/sprite/site_a.png";
|
||||
import siteBTex from "../../../static/sprite/site_b.png";
|
||||
import siteLevelTex from "../../../static/sprite/site_levels.png";
|
||||
import siteATex from "../../../static/sprites/main/site_a.png";
|
||||
import siteBTex from "../../../static/sprites/main/site_b.png";
|
||||
import siteLevelTex from "../../../static/sprites/main/site_levels.png";
|
||||
|
||||
type PurpleRingProps = {
|
||||
purpleRingPosY: number;
|
||||
|
|
|
@ -8,38 +8,9 @@ import InactiveLevelNodes from "./InactiveLevelNodes";
|
|||
import site_a from "../../../resources/site_a.json";
|
||||
import site_b from "../../../resources/site_b.json";
|
||||
import level_y_values from "../../../resources/level_y_values.json";
|
||||
import { filterInvisibleNodes } from "../../../utils/node-utils";
|
||||
import { filterInvisibleNodes } from "../../../helpers/node-helpers";
|
||||
import Loading from "../../Loading";
|
||||
|
||||
export type NodeData = {
|
||||
id: string;
|
||||
image_table_indices: { 1: string; 2: string; 3: string };
|
||||
triggers_final_video: number;
|
||||
required_final_video_viewcount: number;
|
||||
media_file: string;
|
||||
node_name: string;
|
||||
site: string;
|
||||
type: number;
|
||||
title: string;
|
||||
unlocked_by: string;
|
||||
upgrade_requirement: number;
|
||||
words: { 1: string; 2: string; 3: string };
|
||||
matrixIndices?: {
|
||||
matrixIdx: number;
|
||||
rowIdx: number;
|
||||
colIdx: number;
|
||||
};
|
||||
is_viewed?: number;
|
||||
};
|
||||
|
||||
export type Level = {
|
||||
[key: string]: NodeData;
|
||||
};
|
||||
|
||||
export type SiteData = {
|
||||
[key: string]: Level;
|
||||
};
|
||||
|
||||
type SiteProps = {
|
||||
introFinished: boolean;
|
||||
};
|
||||
|
@ -96,7 +67,7 @@ const Site = (props: SiteProps) => {
|
|||
);
|
||||
|
||||
return (
|
||||
<Suspense fallback={<Loading />}>
|
||||
<Suspense fallback={props.introFinished ? <Loading /> : null}>
|
||||
<a.group rotation-x={rotXState.x}>
|
||||
<a.group rotation-y={rotYState.y} position-y={posState.y}>
|
||||
<ActiveLevelNodes visibleNodes={visibleNodes} />
|
||||
|
|
79
src/components/MainScene/Starfield/IntroStar.tsx
Normal file
79
src/components/MainScene/Starfield/IntroStar.tsx
Normal file
|
@ -0,0 +1,79 @@
|
|||
import React, { useMemo, useRef } from "react";
|
||||
import { a } from "@react-spring/three";
|
||||
import * as THREE from "three";
|
||||
import { useFrame } from "react-three-fiber";
|
||||
|
||||
type IntroStarProps = {
|
||||
position: number[];
|
||||
color: string;
|
||||
};
|
||||
|
||||
const IntroStar = (props: IntroStarProps) => {
|
||||
const uniforms = useMemo(
|
||||
() => ({
|
||||
color1: {
|
||||
value: new THREE.Color("white"),
|
||||
},
|
||||
color2: {
|
||||
value: new THREE.Color(props.color),
|
||||
},
|
||||
}),
|
||||
[props.color]
|
||||
);
|
||||
|
||||
const vertexShader = `
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const fragmentShader = `
|
||||
uniform vec3 color1;
|
||||
uniform vec3 color2;
|
||||
uniform float alpha;
|
||||
|
||||
varying vec2 vUv;
|
||||
|
||||
void main() {
|
||||
float alpha = smoothstep(0.0, 1.0, vUv.y);
|
||||
float colorMix = smoothstep(1.0, 2.0, 1.8);
|
||||
|
||||
gl_FragColor = vec4(mix(color1, color2, colorMix), alpha) * 0.8;
|
||||
}
|
||||
`;
|
||||
|
||||
const starRef = useRef<THREE.Object3D>();
|
||||
|
||||
const amp = useRef(Math.random() / 10);
|
||||
|
||||
useFrame(() => {
|
||||
if (starRef.current && starRef.current.visible) {
|
||||
starRef.current.position.y += 0.25 + amp.current;
|
||||
if (starRef.current.position.y > 40) starRef.current.visible = false;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<mesh
|
||||
position={props.position as [number, number, number]}
|
||||
scale={[0.01, 2, 0.01]}
|
||||
renderOrder={-1}
|
||||
ref={starRef}
|
||||
>
|
||||
<boxBufferGeometry attach="geometry" args={[1, 1, 1]} />
|
||||
<a.shaderMaterial
|
||||
attach="material"
|
||||
fragmentShader={fragmentShader}
|
||||
vertexShader={vertexShader}
|
||||
transparent={true}
|
||||
depthWrite={false}
|
||||
uniforms={uniforms}
|
||||
/>
|
||||
</mesh>
|
||||
);
|
||||
};
|
||||
|
||||
export default IntroStar;
|
|
@ -1,26 +1,27 @@
|
|||
import React, { useRef } from "react";
|
||||
import React, { useMemo, useRef } from "react";
|
||||
import { a } from "@react-spring/three";
|
||||
import * as THREE from "three";
|
||||
import { useFrame } from "react-three-fiber";
|
||||
import lerp from "../../../utils/lerp";
|
||||
|
||||
type StarProps = {
|
||||
position: number[];
|
||||
color: string;
|
||||
introStar?: boolean;
|
||||
shouldIntro?: boolean;
|
||||
shouldIntro: boolean;
|
||||
};
|
||||
|
||||
const Star = (props: StarProps) => {
|
||||
const uniformConstructor = (col: string) => {
|
||||
return {
|
||||
const uniforms = useMemo(
|
||||
() => ({
|
||||
color1: {
|
||||
value: new THREE.Color("white"),
|
||||
},
|
||||
color2: {
|
||||
value: new THREE.Color(col),
|
||||
value: new THREE.Color(props.color),
|
||||
},
|
||||
};
|
||||
};
|
||||
}),
|
||||
[props.color]
|
||||
);
|
||||
|
||||
const vertexShader = `
|
||||
varying vec2 vUv;
|
||||
|
@ -54,17 +55,11 @@ const Star = (props: StarProps) => {
|
|||
|
||||
useFrame(() => {
|
||||
if (starRef.current) {
|
||||
if (props.introStar) {
|
||||
starRef.current.position.y += 0.25 + amp.current;
|
||||
} else {
|
||||
if (starRef.current.position.y > 4) {
|
||||
starRef.current.position.y = props.position[1];
|
||||
}
|
||||
starRef.current.position.y += 0.01 + amp.current + introAmpRef.current;
|
||||
if (introAmpRef.current > 0) {
|
||||
introAmpRef.current -= 0.004;
|
||||
}
|
||||
}
|
||||
introAmpRef.current = lerp(introAmpRef.current, 0, 0.01);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -82,7 +77,7 @@ const Star = (props: StarProps) => {
|
|||
vertexShader={vertexShader}
|
||||
transparent={true}
|
||||
depthWrite={false}
|
||||
uniforms={uniformConstructor(props.color)}
|
||||
uniforms={uniforms}
|
||||
/>
|
||||
</mesh>
|
||||
);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { memo, useEffect, useMemo, useState } from "react";
|
||||
import React, { memo, useMemo } from "react";
|
||||
import Star from "./Star";
|
||||
import IntroStar from "./IntroStar";
|
||||
|
||||
type StarfieldProps = {
|
||||
shouldIntro: boolean;
|
||||
|
@ -34,17 +35,11 @@ const Starfield = memo((props: StarfieldProps) => {
|
|||
].map((x) =>
|
||||
Array.from({ length: x }, () => [
|
||||
lcgInstance() / 1000000050,
|
||||
lcgInstance() / 100000099 - 15,
|
||||
lcgInstance() / 100000059 + 5,
|
||||
lcgInstance() / 1000000050,
|
||||
])
|
||||
);
|
||||
|
||||
const [introVisible, setIntroVisible] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
setTimeout(() => setIntroVisible(false), 3200);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<group position={[0, -1, 2]} visible={props.mainVisible}>
|
||||
|
@ -101,20 +96,18 @@ const Starfield = memo((props: StarfieldProps) => {
|
|||
))}
|
||||
</group>
|
||||
</group>
|
||||
{introVisible && props.shouldIntro ? (
|
||||
{props.shouldIntro && (
|
||||
<group position={[-2, -15, -30]} rotation={[Math.PI / 3, 0, 0]}>
|
||||
{posesBlueFromBottom.map((poses, idx) => (
|
||||
<Star position={poses} color={"blue"} key={idx} introStar={true} />
|
||||
<IntroStar position={poses} color={"blue"} key={idx} />
|
||||
))}
|
||||
{posesWhiteFromBottom.map((poses, idx) => (
|
||||
<Star position={poses} color={"white"} key={idx} introStar={true} />
|
||||
<IntroStar position={poses} color={"white"} key={idx} />
|
||||
))}
|
||||
{posesCyanFromBottom.map((poses, idx) => (
|
||||
<Star position={poses} color={"cyan"} key={idx} introStar={true} />
|
||||
<IntroStar position={poses} color={"cyan"} key={idx} />
|
||||
))}
|
||||
</group>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { memo, useMemo, useRef } from "react";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import orbSprite from "../../static/sprite/orb.png";
|
||||
import orbSprite from "../../static/sprites/main/orb.png";
|
||||
import { useStore } from "../../store";
|
||||
|
||||
type YellowOrbProps = {
|
||||
|
|
|
@ -59,7 +59,7 @@ const MediaPlayer = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<video width="800" height="600" id="media" ref={videoRef} controls>
|
||||
<video width="800" height="600" id="media" ref={videoRef}>
|
||||
<track id={"track"} ref={trackRef} kind="captions" default />
|
||||
</video>
|
||||
<div id={"subtitle-container"}>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { MutableRefObject } from "react";
|
||||
import audioVisualizerOrangeOrb from "../../../static/sprite/audio_visual_orb_orange.png";
|
||||
import audioVisualizerYellowOrb from "../../../static/sprite/audio_visual_orb_yellow.png";
|
||||
import audioVisualizerOrangeOrb from "../../../static/sprites/media/audio_visual_orb_orange.png";
|
||||
import audioVisualizerYellowOrb from "../../../static/sprites/media/audio_visual_orb_yellow.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { memo, useState } from "react";
|
||||
import * as THREE from "three";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import lofSpriteSheet from "../../static/sprite/lof_spritesheet.png";
|
||||
import lofSpriteSheet from "../../static/sprites/media/lof_spritesheet.png";
|
||||
import { PlainAnimator } from "three-plain-animator/lib/plain-animator";
|
||||
|
||||
const Lof = memo(() => {
|
||||
|
|
|
@ -1,177 +0,0 @@
|
|||
import React, { useMemo, useRef } from "react";
|
||||
import { useStore } from "../../store";
|
||||
import loadingBarContainer from "../../static/sprite/media_loading_bar_container.png";
|
||||
import loadingBar from "../../static/sprite/media_loading_bar.png";
|
||||
import loadingBar10Perc from "../../static/sprite/media_loading_bar_10perc.png";
|
||||
import loadingBar20Perc from "../../static/sprite/media_loading_bar_20perc.png";
|
||||
import loadingBar30Perc from "../../static/sprite/media_loading_bar_30perc.png";
|
||||
import loadingBar40Perc from "../../static/sprite/media_loading_bar_40perc.png";
|
||||
import loadingBar50Perc from "../../static/sprite/media_loading_bar_50perc.png";
|
||||
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
|
||||
const MediaLoadingBar = () => {
|
||||
const mediaPercentageElapsed = useStore(
|
||||
(state) => state.mediaPercentageElapsed
|
||||
);
|
||||
const loadingBarContainerTex = useLoader(
|
||||
THREE.TextureLoader,
|
||||
loadingBarContainer
|
||||
);
|
||||
const loadingBarTex = useLoader(THREE.TextureLoader, loadingBar);
|
||||
const loadingBar10PercTex = useLoader(THREE.TextureLoader, loadingBar10Perc);
|
||||
const loadingBar20PercTex = useLoader(THREE.TextureLoader, loadingBar20Perc);
|
||||
const loadingBar30PercTex = useLoader(THREE.TextureLoader, loadingBar30Perc);
|
||||
const loadingBar40PercTex = useLoader(THREE.TextureLoader, loadingBar40Perc);
|
||||
const loadingBar50PercTex = useLoader(THREE.TextureLoader, loadingBar50Perc);
|
||||
|
||||
// the additions here are very linear, but just +ing the values wouldn't work
|
||||
// since in case the video were to get rewinded the bar wouldn't react properly
|
||||
// doing it declaratively like this fixes that concern
|
||||
const loadingBarState = useMemo(() => {
|
||||
const mediaPercentageDispatch = {
|
||||
0: {
|
||||
scaleX: 0,
|
||||
texture: loadingBar10PercTex,
|
||||
offsetX: 0,
|
||||
},
|
||||
5: {
|
||||
scaleX: 0.25,
|
||||
texture: loadingBar10PercTex,
|
||||
offsetX: 0,
|
||||
},
|
||||
10: { scaleX: 0.5, texture: loadingBar20PercTex, offsetX: 0.145 },
|
||||
15: { scaleX: 0.75, texture: loadingBar30PercTex, offsetX: 0.25 },
|
||||
20: {
|
||||
scaleX: 1,
|
||||
texture: loadingBar40PercTex,
|
||||
offsetX: 0.4,
|
||||
},
|
||||
25: {
|
||||
scaleX: 1.25,
|
||||
texture: loadingBar50PercTex,
|
||||
offsetX: 0.55,
|
||||
},
|
||||
30: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 0.8,
|
||||
},
|
||||
35: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 1.05,
|
||||
},
|
||||
40: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 1.3,
|
||||
},
|
||||
45: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 1.55,
|
||||
},
|
||||
50: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 1.8,
|
||||
},
|
||||
55: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 2.05,
|
||||
},
|
||||
60: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 2.3,
|
||||
},
|
||||
65: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 2.55,
|
||||
},
|
||||
70: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 2.8,
|
||||
},
|
||||
75: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 3.05,
|
||||
},
|
||||
80: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 3.3,
|
||||
},
|
||||
85: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 3.55,
|
||||
},
|
||||
90: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 3.65,
|
||||
},
|
||||
95: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 3.85,
|
||||
},
|
||||
100: {
|
||||
scaleX: 1.5,
|
||||
texture: loadingBarTex,
|
||||
offsetX: 3.95,
|
||||
},
|
||||
};
|
||||
return mediaPercentageDispatch[
|
||||
mediaPercentageElapsed as keyof typeof mediaPercentageDispatch
|
||||
];
|
||||
}, [
|
||||
loadingBar10PercTex,
|
||||
loadingBar20PercTex,
|
||||
loadingBar30PercTex,
|
||||
loadingBar40PercTex,
|
||||
loadingBar50PercTex,
|
||||
loadingBarTex,
|
||||
mediaPercentageElapsed,
|
||||
]);
|
||||
|
||||
const loadingBarMatRef = useRef<THREE.Material>();
|
||||
useFrame(() => {
|
||||
if (loadingBarMatRef) {
|
||||
loadingBarMatRef.current!.needsUpdate = true;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<sprite scale={[5.2, 0.5, 1]} position={[2.15, 3.005, 0]}>
|
||||
<spriteMaterial attach="material" map={loadingBarContainerTex} />
|
||||
</sprite>
|
||||
<mesh
|
||||
scale={[loadingBarState ? loadingBarState.scaleX : 0, 0.195, 1]}
|
||||
position={[
|
||||
loadingBarState ? -0.2 + loadingBarState.offsetX : -0.2,
|
||||
2.945,
|
||||
0,
|
||||
]}
|
||||
>
|
||||
<planeBufferGeometry attach="geometry" />
|
||||
<meshBasicMaterial
|
||||
ref={loadingBarMatRef}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
map={loadingBarState ? loadingBarState.texture : null}
|
||||
/>
|
||||
</mesh>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MediaLoadingBar;
|
177
src/components/MediaScene/MediaProgressBar.tsx
Normal file
177
src/components/MediaScene/MediaProgressBar.tsx
Normal file
|
@ -0,0 +1,177 @@
|
|||
import React, { useMemo, useRef } from "react";
|
||||
import { useStore } from "../../store";
|
||||
import progressBarContainer from "../../static/sprites/media/media_loading_bar_container.png";
|
||||
import progressBar from "../../static/sprites/progressbar/progress_bar0.png";
|
||||
import progressBar1 from "../../static/sprites/progressbar/progress_bar1.png";
|
||||
import progressBar2 from "../../static/sprites/progressbar/progress_bar2.png";
|
||||
import progressBar3 from "../../static/sprites/progressbar/progress_bar3.png";
|
||||
import progressBar4 from "../../static/sprites/progressbar/progress_bar4.png";
|
||||
import progressBar5 from "../../static/sprites/progressbar/progress_bar5.png";
|
||||
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
|
||||
const MediaProgressBar = () => {
|
||||
const mediaPercentageElapsed = useStore(
|
||||
(state) => state.mediaPercentageElapsed
|
||||
);
|
||||
const progressBarContainerTex = useLoader(
|
||||
THREE.TextureLoader,
|
||||
progressBarContainer
|
||||
);
|
||||
const progressBarTex = useLoader(THREE.TextureLoader, progressBar);
|
||||
const progressBar1Tex = useLoader(THREE.TextureLoader, progressBar1);
|
||||
const progressBar2Tex = useLoader(THREE.TextureLoader, progressBar2);
|
||||
const progressBar3Tex = useLoader(THREE.TextureLoader, progressBar3);
|
||||
const progressBar4Tex = useLoader(THREE.TextureLoader, progressBar4);
|
||||
const progressBar5Tex = useLoader(THREE.TextureLoader, progressBar5);
|
||||
|
||||
// the additions here are very linear, but just +ing the values wouldn't work
|
||||
// since in case the video were to get rewinded the bar wouldn't react properly
|
||||
// doing it declaratively like this fixes that concern
|
||||
const progressBarState = useMemo(() => {
|
||||
const mediaPercentageDispatch = {
|
||||
0: {
|
||||
scaleX: 0,
|
||||
texture: progressBar1Tex,
|
||||
offsetX: 0,
|
||||
},
|
||||
5: {
|
||||
scaleX: 0.25,
|
||||
texture: progressBar1Tex,
|
||||
offsetX: 0,
|
||||
},
|
||||
10: { scaleX: 0.5, texture: progressBar2Tex, offsetX: 0.145 },
|
||||
15: { scaleX: 0.75, texture: progressBar3Tex, offsetX: 0.25 },
|
||||
20: {
|
||||
scaleX: 1,
|
||||
texture: progressBar4Tex,
|
||||
offsetX: 0.4,
|
||||
},
|
||||
25: {
|
||||
scaleX: 1.25,
|
||||
texture: progressBar5Tex,
|
||||
offsetX: 0.55,
|
||||
},
|
||||
30: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 0.8,
|
||||
},
|
||||
35: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 1.05,
|
||||
},
|
||||
40: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 1.3,
|
||||
},
|
||||
45: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 1.55,
|
||||
},
|
||||
50: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 1.8,
|
||||
},
|
||||
55: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 2.05,
|
||||
},
|
||||
60: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 2.3,
|
||||
},
|
||||
65: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 2.55,
|
||||
},
|
||||
70: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 2.8,
|
||||
},
|
||||
75: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 3.05,
|
||||
},
|
||||
80: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 3.3,
|
||||
},
|
||||
85: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 3.55,
|
||||
},
|
||||
90: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 3.65,
|
||||
},
|
||||
95: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 3.85,
|
||||
},
|
||||
100: {
|
||||
scaleX: 1.5,
|
||||
texture: progressBarTex,
|
||||
offsetX: 3.95,
|
||||
},
|
||||
};
|
||||
return mediaPercentageDispatch[
|
||||
mediaPercentageElapsed as keyof typeof mediaPercentageDispatch
|
||||
];
|
||||
}, [
|
||||
progressBar1Tex,
|
||||
progressBar2Tex,
|
||||
progressBar3Tex,
|
||||
progressBar4Tex,
|
||||
progressBar5Tex,
|
||||
progressBarTex,
|
||||
mediaPercentageElapsed,
|
||||
]);
|
||||
|
||||
const progressBarMatRef = useRef<THREE.Material>();
|
||||
useFrame(() => {
|
||||
if (progressBarMatRef) {
|
||||
progressBarMatRef.current!.needsUpdate = true;
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<sprite scale={[5.2, 0.5, 1]} position={[2.15, 3.005, 0]}>
|
||||
<spriteMaterial attach="material" map={progressBarContainerTex} />
|
||||
</sprite>
|
||||
<mesh
|
||||
scale={[progressBarState ? progressBarState.scaleX : 0, 0.195, 1]}
|
||||
position={[
|
||||
progressBarState ? -0.2 + progressBarState.offsetX : -0.2,
|
||||
2.945,
|
||||
0,
|
||||
]}
|
||||
>
|
||||
<planeBufferGeometry attach="geometry" />
|
||||
<meshBasicMaterial
|
||||
ref={progressBarMatRef}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
map={progressBarState ? progressBarState.texture : null}
|
||||
/>
|
||||
</mesh>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MediaProgressBar;
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react";
|
||||
import * as THREE from "three";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import mediaNodeNameContainer from "../../static/sprite/media_node_name_container.png";
|
||||
import mediaNodeNameContainer from "../../static/sprites/media/media_node_name_container.png";
|
||||
|
||||
const NodeNameContainer = () => {
|
||||
const mediaNodeNameContainerTex = useLoader(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import grayTextureFile from "../../../../static/sprite/gray_box.png";
|
||||
import darkGrayTextureFile from "../../../../static/sprite/dark_gray_box.png";
|
||||
import grayTextureFile from "../../../../static/sprites/media/gray_box.png";
|
||||
import darkGrayTextureFile from "../../../../static/sprites/media/dark_gray_box.png";
|
||||
import React, {memo, useRef} from "react";
|
||||
import { ShapeProps } from "../LeftSide";
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import grayTextureFile from "../../../../static/sprite/gray_box.png";
|
||||
import darkGrayTextureFile from "../../../../static/sprite/dark_gray_box.png";
|
||||
import grayTextureFile from "../../../../static/sprites/media/gray_box.png";
|
||||
import darkGrayTextureFile from "../../../../static/sprites/media/dark_gray_box.png";
|
||||
import React, { memo, useRef } from "react";
|
||||
import { ShapeProps } from "../LeftSide";
|
||||
import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useMemo } from "react";
|
||||
import * as THREE from "three";
|
||||
import wordInactiveTexture from "../../../../static/sprite/word_background.png";
|
||||
import wordActiveTexture from "../../../../static/sprite/word_background_active.png";
|
||||
import wordInactiveTexture from "../../../../static/sprites/media/word_background.png";
|
||||
import wordActiveTexture from "../../../../static/sprites/media/word_background_active.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import { a, SpringValue } from "@react-spring/three";
|
||||
|
||||
|
@ -13,7 +13,7 @@ type WordProps = {
|
|||
};
|
||||
|
||||
const Word = (props: WordProps) => {
|
||||
const wordFont = useLoader(THREE.FontLoader, "/3d_fonts/MediaWord.blob");
|
||||
const wordFont = useLoader(THREE.FontLoader, "/3d-fonts/MediaWord.blob");
|
||||
const config = useMemo(
|
||||
() => ({
|
||||
font: wordFont,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import React, { useEffect, useMemo, useRef } from "react";
|
||||
import header from "../../static/sprite/polytan_header.png";
|
||||
import background from "../../static/sprite/polytan_background.png";
|
||||
import leftArmHud from "../../static/sprite/poly_larm_hud.png";
|
||||
import rightArmHud from "../../static/sprite/poly_rarm_hud.png";
|
||||
import rightLegHud from "../../static/sprite/poly_rleg_hud.png";
|
||||
import leftLegHud from "../../static/sprite/poly_lleg_hud.png";
|
||||
import headHud from "../../static/sprite/poly_head_hud.png";
|
||||
import bodyHud from "../../static/sprite/poly_body_hud.png";
|
||||
import header from "../../static/sprites/polytan/polytan_header.png";
|
||||
import background from "../../static/sprites/polytan/polytan_background.png";
|
||||
import leftArmHud from "../../static/sprites/polytan/poly_larm_hud.png";
|
||||
import rightArmHud from "../../static/sprites/polytan/poly_rarm_hud.png";
|
||||
import rightLegHud from "../../static/sprites/polytan/poly_rleg_hud.png";
|
||||
import leftLegHud from "../../static/sprites/polytan/poly_lleg_hud.png";
|
||||
import headHud from "../../static/sprites/polytan/poly_head_hud.png";
|
||||
import bodyHud from "../../static/sprites/polytan/poly_body_hud.png";
|
||||
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
|
@ -21,7 +21,7 @@ const PolytanBackground = () => {
|
|||
const headHudTex = useLoader(THREE.TextureLoader, headHud);
|
||||
const bodyHudTex = useLoader(THREE.TextureLoader, bodyHud);
|
||||
|
||||
const wordFont = useLoader(THREE.FontLoader, "/3d_fonts/MediaWord.blob");
|
||||
const wordFont = useLoader(THREE.FontLoader, "/3d-fonts/MediaWord.blob");
|
||||
|
||||
const config = useMemo(
|
||||
() => ({
|
||||
|
|
|
@ -1,26 +1,16 @@
|
|||
import React from "react";
|
||||
import body from "../../static/sprite/body.png";
|
||||
import head from "../../static/sprite/head.png";
|
||||
import leftLeg from "../../static/sprite/left_leg.png";
|
||||
import leftArm from "../../static/sprite/left_arm.png";
|
||||
import rightArm from "../../static/sprite/right_arm.png";
|
||||
import rightLeg from "../../static/sprite/right_leg.png";
|
||||
import skeleton from "../../static/sprite/polytan_skeleton.png";
|
||||
import React, { memo } from "react";
|
||||
import body from "../../static/sprites/polytan/body.png";
|
||||
import head from "../../static/sprites/polytan/head.png";
|
||||
import leftLeg from "../../static/sprites/polytan/left_leg.png";
|
||||
import leftArm from "../../static/sprites/polytan/left_arm.png";
|
||||
import rightArm from "../../static/sprites/polytan/right_arm.png";
|
||||
import rightLeg from "../../static/sprites/polytan/right_leg.png";
|
||||
import skeleton from "../../static/sprites/polytan/polytan_skeleton.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { useStore } from "../../store";
|
||||
|
||||
type PolytanBearProps = {
|
||||
unlockedParts: {
|
||||
body: boolean;
|
||||
head: boolean;
|
||||
leftArm: boolean;
|
||||
rightArm: boolean;
|
||||
leftLeg: boolean;
|
||||
rightLeg: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
const PolytanBear = (props: PolytanBearProps) => {
|
||||
const PolytanBear = memo(() => {
|
||||
const skeletonTex = useLoader(THREE.TextureLoader, skeleton);
|
||||
const headTex = useLoader(THREE.TextureLoader, head);
|
||||
const bodyTex = useLoader(THREE.TextureLoader, body);
|
||||
|
@ -29,6 +19,8 @@ const PolytanBear = (props: PolytanBearProps) => {
|
|||
const rightArmTex = useLoader(THREE.TextureLoader, rightArm);
|
||||
const rightLegTex = useLoader(THREE.TextureLoader, rightLeg);
|
||||
|
||||
const unlockedParts = useStore((state) => state.polytanUnlockedParts);
|
||||
|
||||
return (
|
||||
<>
|
||||
<sprite scale={[4, 5, 0]} position={[0, -0.4, 0]}>
|
||||
|
@ -39,7 +31,7 @@ const PolytanBear = (props: PolytanBearProps) => {
|
|||
<spriteMaterial
|
||||
attach="material"
|
||||
map={bodyTex}
|
||||
visible={props.unlockedParts.body}
|
||||
visible={unlockedParts.body}
|
||||
/>
|
||||
</sprite>
|
||||
|
||||
|
@ -47,39 +39,39 @@ const PolytanBear = (props: PolytanBearProps) => {
|
|||
<spriteMaterial
|
||||
attach="material"
|
||||
map={headTex}
|
||||
visible={props.unlockedParts.head}
|
||||
visible={unlockedParts.head}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite scale={[1.9, 1, 0]} position={[1, -2.2, 0]}>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={leftLegTex}
|
||||
visible={props.unlockedParts.leftLeg}
|
||||
visible={unlockedParts.leftLeg}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite scale={[1.5, 1.9, 0]} position={[1.2, -0.4, 0]}>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={leftArmTex}
|
||||
visible={props.unlockedParts.leftArm}
|
||||
visible={unlockedParts.leftArm}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite scale={[1.6, 2, 0]} position={[-1.2, -1.2, 0]}>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={rightArmTex}
|
||||
visible={props.unlockedParts.rightArm}
|
||||
visible={unlockedParts.rightArm}
|
||||
/>
|
||||
</sprite>
|
||||
<sprite scale={[1.9, 1, 0]} position={[-1, -2.2, 0]}>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
map={rightLegTex}
|
||||
visible={props.unlockedParts.rightLeg}
|
||||
visible={unlockedParts.rightLeg}
|
||||
/>
|
||||
</sprite>
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default PolytanBear;
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
import introSpriteSheet from "../static/sprite/intro.png";
|
||||
import moveDownSpriteSheet from "../static/sprite/jump_down.png";
|
||||
import moveUpSpriteSheet from "../static/sprite/jump_up.png";
|
||||
import standingSpriteSheet from "../static/sprite/standing.png";
|
||||
import moveLeftSpriteSheet from "../static/sprite/move_left.png";
|
||||
import moveRightSpriteSheet from "../static/sprite/move_right.png";
|
||||
import bigHudSpriteSheet from "../static/sprite/big_hud.png";
|
||||
import longHudSpriteSheet from "../static/sprite/long_hud.png";
|
||||
import boringHudSpriteSheet from "../static/sprite/long_hud_boring.png";
|
||||
import throwNodeSpriteSheet from "../static/sprite/throw_node.png";
|
||||
import ripMiddleRingSpriteSheet from "../static/sprite/rip_middle_ring.png";
|
||||
import ripNodeSpriteSheet from "../static/sprite/rip_node.png";
|
||||
import prayerSpriteSheet from "../static/sprite/prayer.png";
|
||||
import knockSpriteSheet from "../static/sprite/knock.png";
|
||||
import knockAndFallSpriteSheet from "../static/sprite/knock_and_fall.png";
|
||||
import touchAndScareSpriteSheet from "../static/sprite/touch_node_and_get_scared.png";
|
||||
import touchSleeveSpriteSheet from "../static/sprite/touch_sleeve.png";
|
||||
import thinkingSpriteSheet from "../static/sprite/thinking.png";
|
||||
import stretchSpriteSheet from "../static/sprite/stretch.png";
|
||||
import stretch2SpriteSheet from "../static/sprite/stretch_2.png";
|
||||
import spinSpriteSheet from "../static/sprite/spin.png";
|
||||
import scratchHeadSpriteSheet from "../static/sprite/scratch_head.png";
|
||||
import blushSpriteSheet from "../static/sprite/blush.png";
|
||||
import handsBehindHeadSpriteSheet from "../static/sprite/hands_behind_head.png";
|
||||
import handsOnHipsSpriteSheet from "../static/sprite/hands_on_hips.png";
|
||||
import handsOnHips2SpriteSheet from "../static/sprite/hands_on_hips_2.png";
|
||||
import handsTogetherSpriteSheet from "../static/sprite/hands_together.png";
|
||||
import leanForwardSpriteSheet from "../static/sprite/lean_forward.png";
|
||||
import leanLeftSpriteSheet from "../static/sprite/lean_left.png";
|
||||
import leanRightSpriteSheet from "../static/sprite/lean_right.png";
|
||||
import lookAroundSpriteSheet from "../static/sprite/look_around.png";
|
||||
import playWithHairSpriteSheet from "../static/sprite/play_with_hair.png";
|
||||
import introSpriteSheet from "../static/sprites/lain/intro.png";
|
||||
import moveDownSpriteSheet from "../static/sprites/lain/jump_down.png";
|
||||
import moveUpSpriteSheet from "../static/sprites/lain/jump_up.png";
|
||||
import standingSpriteSheet from "../static/sprites/lain/standing.png";
|
||||
import moveLeftSpriteSheet from "../static/sprites/lain/move_left.png";
|
||||
import moveRightSpriteSheet from "../static/sprites/lain/move_right.png";
|
||||
import bigHudSpriteSheet from "../static/sprites/big_hud.png";
|
||||
import longHudSpriteSheet from "../static/sprites/long_hud.png";
|
||||
import boringHudSpriteSheet from "../static/sprites/long_hud_boring.png";
|
||||
import throwNodeSpriteSheet from "../static/sprites/lain/throw_node.png";
|
||||
import ripMiddleRingSpriteSheet from "../static/sprites/lain/rip_middle_ring.png";
|
||||
import ripNodeSpriteSheet from "../static/sprites/lain/rip_node.png";
|
||||
import prayerSpriteSheet from "../static/sprites/lain/prayer.png";
|
||||
import knockSpriteSheet from "../static/sprites/lain/knock.png";
|
||||
import knockAndFallSpriteSheet from "../static/sprites/lain/knock_and_fall.png";
|
||||
import touchAndScareSpriteSheet from "../static/sprites/lain/touch_node_and_get_scared.png";
|
||||
import touchSleeveSpriteSheet from "../static/sprites/lain/touch_sleeve.png";
|
||||
import thinkingSpriteSheet from "../static/sprites/lain/thinking.png";
|
||||
import stretchSpriteSheet from "../static/sprites/lain/stretch.png";
|
||||
import stretch2SpriteSheet from "../static/sprites/lain/stretch_2.png";
|
||||
import spinSpriteSheet from "../static/sprites/lain/spin.png";
|
||||
import scratchHeadSpriteSheet from "../static/sprites/lain/scratch_head.png";
|
||||
import blushSpriteSheet from "../static/sprites/lain/blush.png";
|
||||
import handsBehindHeadSpriteSheet from "../static/sprites/lain/hands_behind_head.png";
|
||||
import handsOnHipsSpriteSheet from "../static/sprites/lain/hands_on_hips.png";
|
||||
import handsOnHips2SpriteSheet from "../static/sprites/lain/hands_on_hips_2.png";
|
||||
import handsTogetherSpriteSheet from "../static/sprites/lain/hands_together.png";
|
||||
import leanForwardSpriteSheet from "../static/sprites/lain/lean_forward.png";
|
||||
import leanLeftSpriteSheet from "../static/sprites/lain/lean_left.png";
|
||||
import leanRightSpriteSheet from "../static/sprites/lain/lean_right.png";
|
||||
import lookAroundSpriteSheet from "../static/sprites/lain/look_around.png";
|
||||
import playWithHairSpriteSheet from "../static/sprites/lain/play_with_hair.png";
|
||||
|
||||
import * as THREE from "three";
|
||||
import { useLoader, useThree } from "react-three-fiber";
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import React, { memo } from "react";
|
||||
import answerContainer from "../static/sprite/prompt_answer_container.png";
|
||||
import questionContainer from "../static/sprite/prompt_question_container.png";
|
||||
import yes from "../static/sprite/prompt_yes.png";
|
||||
import no from "../static/sprite/prompt_no.png";
|
||||
import question from "../static/sprite/prompt_question.png";
|
||||
import answerContainer from "../static/sprites/prompt/prompt_answer_container.png";
|
||||
import questionContainer from "../static/sprites/prompt/prompt_question_container.png";
|
||||
import yes from "../static/sprites/prompt/prompt_yes.png";
|
||||
import no from "../static/sprites/prompt/prompt_no.png";
|
||||
import question from "../static/sprites/prompt/prompt_question.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { useStore } from "../store";
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import React, { memo } from "react";
|
||||
import ssknBackground from "../../static/sprite/sskn_background.png";
|
||||
import ssknBackgroundText from "../../static/sprite/sskn_background_text.png";
|
||||
import ssknBackground from "../../static/sprites/sskn/sskn_background.png";
|
||||
import ssknBackgroundText from "../../static/sprites/sskn/sskn_background_text.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import ssknTopLabel from "../../static/sprite/sskn_top_label.png";
|
||||
import ssknDango from "../../static/sprite/sskn_dango.png";
|
||||
import ssknTopLabel from "../../static/sprites/sskn/sskn_top_label.png";
|
||||
import ssknDango from "../../static/sprites/sskn/sskn_dango.png";
|
||||
|
||||
const SsknBackground = memo(() => {
|
||||
const ssknBackgroundTex = useLoader(THREE.TextureLoader, ssknBackground);
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import React, { memo } from "react";
|
||||
import ssknOk from "../../static/sprite/sskn_ok.png";
|
||||
import ssknOkInactive from "../../static/sprite/sskn_ok_inactive.png";
|
||||
import ssknCancel from "../../static/sprite/sskn_cancel.png";
|
||||
import ssknCancelInactive from "../../static/sprite/sskn_cancel_inactive.png";
|
||||
import ssknUpgrade from "../../static/sprite/sskn_upgrade.png";
|
||||
import ssknArrow from "../../static/sprite/sskn_arrow.png";
|
||||
import ssknTextWrapper from "../../static/sprite/sskn_text_wrapper.png";
|
||||
import ssknTextWrapperInactive from "../../static/sprite/sskn_text_wrapper_inactive.png";
|
||||
import ssknLine from "../../static/sprite/sskn_line.png";
|
||||
import ssknOk from "../../static/sprites/sskn/sskn_ok.png";
|
||||
import ssknOkInactive from "../../static/sprites/sskn/sskn_ok_inactive.png";
|
||||
import ssknCancel from "../../static/sprites/sskn/sskn_cancel.png";
|
||||
import ssknCancelInactive from "../../static/sprites/sskn/sskn_cancel_inactive.png";
|
||||
import ssknUpgrade from "../../static/sprites/sskn/sskn_upgrade.png";
|
||||
import ssknArrow from "../../static/sprites/sskn/sskn_arrow.png";
|
||||
import ssknTextWrapper from "../../static/sprites/sskn/sskn_text_wrapper.png";
|
||||
import ssknTextWrapperInactive from "../../static/sprites/sskn/sskn_text_wrapper_inactive.png";
|
||||
import ssknLine from "../../static/sprites/sskn/sskn_line.png";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import SsknLoadingBar from "./SsknLoadingBar";
|
||||
import SsknProgressBar from "./SsknProgressBar";
|
||||
import { useStore } from "../../store";
|
||||
|
||||
const SsknHUD = memo(() => {
|
||||
|
@ -37,7 +37,7 @@ const SsknHUD = memo(() => {
|
|||
return (
|
||||
<>
|
||||
{loading ? (
|
||||
<SsknLoadingBar />
|
||||
<SsknProgressBar />
|
||||
) : (
|
||||
<group>
|
||||
<sprite position={[2.8, -2, 0]} scale={[1, 0.5, 0]}>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { memo, useRef } from "react";
|
||||
import ssknIcon from "../../static/sprite/SSkn_icon.png";
|
||||
import ssknIcon from "../../static/sprites/sskn/SSkn_icon.png";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
import React, { useRef } from "react";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import ssknLoadingBarContainer from "../../static/sprite/SSkn_loading_bar.png";
|
||||
import loadingBar10Perc from "../../static/sprite/media_loading_bar_10perc.png";
|
||||
import loadingBar20Perc from "../../static/sprite/media_loading_bar_20perc.png";
|
||||
import loadingBar30Perc from "../../static/sprite/media_loading_bar_30perc.png";
|
||||
import loadingBar40Perc from "../../static/sprite/media_loading_bar_40perc.png";
|
||||
import loadingBar50Perc from "../../static/sprite/media_loading_bar_50perc.png";
|
||||
import loadingBar from "../../static/sprite/media_loading_bar.png";
|
||||
|
||||
const SsknLoadingBar = () => {
|
||||
const ssknLoadingBarContainerTex = useLoader(
|
||||
THREE.TextureLoader,
|
||||
ssknLoadingBarContainer
|
||||
);
|
||||
|
||||
const loadingBarTex = useLoader(THREE.TextureLoader, loadingBar);
|
||||
const loadingBar10PercTex = useLoader(THREE.TextureLoader, loadingBar10Perc);
|
||||
const loadingBar20PercTex = useLoader(THREE.TextureLoader, loadingBar20Perc);
|
||||
const loadingBar30PercTex = useLoader(THREE.TextureLoader, loadingBar30Perc);
|
||||
const loadingBar40PercTex = useLoader(THREE.TextureLoader, loadingBar40Perc);
|
||||
const loadingBar50PercTex = useLoader(THREE.TextureLoader, loadingBar50Perc);
|
||||
|
||||
const loadingBarRef = useRef<THREE.Object3D>();
|
||||
const loadingBarMatRef = useRef<THREE.SpriteMaterial>();
|
||||
const percentageElapsed = useRef(0);
|
||||
const last = useRef(0);
|
||||
|
||||
useFrame(() => {
|
||||
const now = Date.now();
|
||||
|
||||
if (
|
||||
now > last.current + 200 &&
|
||||
loadingBarRef.current &&
|
||||
loadingBarMatRef.current
|
||||
) {
|
||||
percentageElapsed.current += 5;
|
||||
switch (percentageElapsed.current) {
|
||||
case 5:
|
||||
loadingBarRef.current.scale.x = 0.25;
|
||||
loadingBarMatRef.current.map = loadingBar10PercTex;
|
||||
break;
|
||||
case 10:
|
||||
loadingBarRef.current.scale.x += 0.25;
|
||||
loadingBarRef.current.position.x += 0.1;
|
||||
loadingBarMatRef.current.map = loadingBar20PercTex;
|
||||
break;
|
||||
case 15:
|
||||
loadingBarRef.current.scale.x += 0.25;
|
||||
loadingBarRef.current.position.x += 0.1;
|
||||
loadingBarMatRef.current.map = loadingBar30PercTex;
|
||||
break;
|
||||
case 20:
|
||||
loadingBarRef.current.scale.x += 0.25;
|
||||
loadingBarRef.current.position.x += 0.1;
|
||||
loadingBarMatRef.current.map = loadingBar40PercTex;
|
||||
break;
|
||||
case 25:
|
||||
loadingBarRef.current.scale.x += 0.25;
|
||||
loadingBarRef.current.position.x += 0.1;
|
||||
loadingBarMatRef.current.map = loadingBar50PercTex;
|
||||
break;
|
||||
default:
|
||||
if (loadingBarRef.current.position.x < 4.1) {
|
||||
loadingBarMatRef.current.map = loadingBarTex;
|
||||
loadingBarRef.current.position.x += 0.2;
|
||||
}
|
||||
}
|
||||
last.current = now;
|
||||
}
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<sprite scale={[5.5, 0.3, 0]} position={[2, -2.7, 0]} renderOrder={4}>
|
||||
<spriteMaterial attach="material" map={ssknLoadingBarContainerTex} />
|
||||
</sprite>
|
||||
<sprite
|
||||
scale={[0.2, 0.15, 0]}
|
||||
position={[-0.5, -2.68, 0]}
|
||||
renderOrder={4}
|
||||
ref={loadingBarRef}
|
||||
>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
ref={loadingBarMatRef}
|
||||
map={loadingBar10PercTex}
|
||||
opacity={0.8}
|
||||
/>
|
||||
</sprite>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SsknLoadingBar;
|
95
src/components/SsknScene/SsknProgressBar.tsx
Normal file
95
src/components/SsknScene/SsknProgressBar.tsx
Normal file
|
@ -0,0 +1,95 @@
|
|||
import React, { useRef } from "react";
|
||||
import { useFrame, useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import ssknProgressBarContainer from "../../static/sprites/sskn/sskn_progress_bar.png";
|
||||
import progressBar1 from "../../static/sprites/progressbar/progress_bar1.png";
|
||||
import progressBar2 from "../../static/sprites/progressbar/progress_bar2.png";
|
||||
import progressBar3 from "../../static/sprites/progressbar/progress_bar3.png";
|
||||
import progressBar4 from "../../static/sprites/progressbar/progress_bar4.png";
|
||||
import progressBar5 from "../../static/sprites/progressbar/progress_bar5.png";
|
||||
import progressBar from "../../static/sprites/progressbar/progress_bar0.png";
|
||||
|
||||
const SsknProgressBar = () => {
|
||||
const ssknProgressBarContainerTex = useLoader(
|
||||
THREE.TextureLoader,
|
||||
ssknProgressBarContainer
|
||||
);
|
||||
|
||||
const progressBarTex = useLoader(THREE.TextureLoader, progressBar);
|
||||
const progressBar1Tex = useLoader(THREE.TextureLoader, progressBar1);
|
||||
const progressBar2Tex = useLoader(THREE.TextureLoader, progressBar2);
|
||||
const progressBar3Tex = useLoader(THREE.TextureLoader, progressBar3);
|
||||
const progressBar4Tex = useLoader(THREE.TextureLoader, progressBar4);
|
||||
const progressBar5Tex = useLoader(THREE.TextureLoader, progressBar5);
|
||||
|
||||
const progressBarRef = useRef<THREE.Object3D>();
|
||||
const progressBarMatRef = useRef<THREE.SpriteMaterial>();
|
||||
const percentageElapsed = useRef(0);
|
||||
const last = useRef(0);
|
||||
|
||||
useFrame(() => {
|
||||
const now = Date.now();
|
||||
|
||||
if (
|
||||
now > last.current + 200 &&
|
||||
progressBarRef.current &&
|
||||
progressBarMatRef.current
|
||||
) {
|
||||
percentageElapsed.current += 5;
|
||||
switch (percentageElapsed.current) {
|
||||
case 5:
|
||||
progressBarRef.current.scale.x = 0.25;
|
||||
progressBarMatRef.current.map = progressBar1Tex;
|
||||
break;
|
||||
case 10:
|
||||
progressBarRef.current.scale.x += 0.25;
|
||||
progressBarRef.current.position.x += 0.1;
|
||||
progressBarMatRef.current.map = progressBar2Tex;
|
||||
break;
|
||||
case 15:
|
||||
progressBarRef.current.scale.x += 0.25;
|
||||
progressBarRef.current.position.x += 0.1;
|
||||
progressBarMatRef.current.map = progressBar3Tex;
|
||||
break;
|
||||
case 20:
|
||||
progressBarRef.current.scale.x += 0.25;
|
||||
progressBarRef.current.position.x += 0.1;
|
||||
progressBarMatRef.current.map = progressBar4Tex;
|
||||
break;
|
||||
case 25:
|
||||
progressBarRef.current.scale.x += 0.25;
|
||||
progressBarRef.current.position.x += 0.1;
|
||||
progressBarMatRef.current.map = progressBar5Tex;
|
||||
break;
|
||||
default:
|
||||
if (progressBarRef.current.position.x < 4.1) {
|
||||
progressBarMatRef.current.map = progressBarTex;
|
||||
progressBarRef.current.position.x += 0.2;
|
||||
}
|
||||
}
|
||||
last.current = now;
|
||||
}
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<sprite scale={[5.5, 0.3, 0]} position={[2, -2.7, 0]} renderOrder={4}>
|
||||
<spriteMaterial attach="material" map={ssknProgressBarContainerTex} />
|
||||
</sprite>
|
||||
<sprite
|
||||
scale={[0.2, 0.15, 0]}
|
||||
position={[-0.5, -2.68, 0]}
|
||||
renderOrder={4}
|
||||
ref={progressBarRef}
|
||||
>
|
||||
<spriteMaterial
|
||||
attach="material"
|
||||
ref={progressBarMatRef}
|
||||
map={progressBar1Tex}
|
||||
opacity={0.8}
|
||||
/>
|
||||
</sprite>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SsknProgressBar;
|
|
@ -1,14 +1,14 @@
|
|||
import React from "react";
|
||||
import statusContainer from "../static/sprite/status_container.png";
|
||||
import loadSuccessfulImg from "../static/sprite/load_successful.png";
|
||||
import loadFailImg from "../static/sprite/load_fail.png";
|
||||
import saveSuccessfulImg from "../static/sprite/save_successful.png";
|
||||
import React, { memo } from "react";
|
||||
import statusContainer from "../static/sprites/status/status_container.png";
|
||||
import loadSuccessfulImg from "../static/sprites/status/load_successful.png";
|
||||
import loadFailImg from "../static/sprites/status/load_fail.png";
|
||||
import saveSuccessfulImg from "../static/sprites/status/save_successful.png";
|
||||
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import { useStore } from "../store";
|
||||
|
||||
const Status = () => {
|
||||
const Status = memo(() => {
|
||||
const loadSuccessful = useStore((state) => state.loadSuccessful);
|
||||
const saveSuccessful = useStore((state) => state.saveSuccessful);
|
||||
|
||||
|
@ -62,6 +62,6 @@ const Status = () => {
|
|||
</sprite>
|
||||
</group>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export default Status;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import orangeFont from "../../static/sprite/orange_font_texture.png";
|
||||
import yellowFont from "../../static/sprite/yellow_font_texture.png";
|
||||
import orangeFont from "../../static/sprites/fonts/orange_font_texture.png";
|
||||
import yellowFont from "../../static/sprites/fonts/yellow_font_texture.png";
|
||||
import * as THREE from "three";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import orange_font_json from "../../resources/font_data/big_font.json";
|
||||
|
@ -80,7 +80,7 @@ const BigLetter = memo((props: { letter: string; letterIdx: number }) => {
|
|||
|
||||
const subscene = useStore((state) => state.mainSubscene);
|
||||
const scene = useStore((state) => state.currentScene);
|
||||
const prevData = usePrevious({ scene, subscene });
|
||||
const prevData = usePrevious({ scene, subscene, activeNode });
|
||||
const [lastMediaLeftComponent, setLastMediaLeftComponent] = useState("play");
|
||||
|
||||
const [shrinkState, set] = useSpring(() => ({
|
||||
|
@ -91,8 +91,13 @@ const BigLetter = memo((props: { letter: string; letterIdx: number }) => {
|
|||
useEffect(() => {
|
||||
if (
|
||||
subscene === "pause" ||
|
||||
(subscene === "site" && prevData?.subscene === "not_found") ||
|
||||
(subscene === "site" && prevData?.subscene === "pause")
|
||||
(subscene === "site" && prevData?.subscene === "pause") ||
|
||||
(activeNode === prevData?.activeNode &&
|
||||
!(
|
||||
subscene === "level_selection" ||
|
||||
color === "orange" ||
|
||||
scene === "media"
|
||||
))
|
||||
)
|
||||
return;
|
||||
if (scene === "main" && prevData?.scene === "main") {
|
||||
|
@ -124,6 +129,7 @@ const BigLetter = memo((props: { letter: string; letterIdx: number }) => {
|
|||
lastMediaLeftComponent,
|
||||
prevData?.scene,
|
||||
prevData?.subscene,
|
||||
prevData?.activeNode,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useLoader } from "react-three-fiber";
|
||||
import * as THREE from "three";
|
||||
import greenFont from "../../static/sprite/white_and_green_texture.png";
|
||||
import greenFont from "../../static/sprites/fonts/white_and_green_texture.png";
|
||||
import medium_font_json from "../../resources/font_data/medium_font.json";
|
||||
import { a } from "@react-spring/three";
|
||||
import React, { memo, useMemo } from "react";
|
||||
|
|
|
@ -3,7 +3,7 @@ import { useStore } from "../../store";
|
|||
import { a, useTrail } from "@react-spring/three";
|
||||
import BigLetter from "./BigLetter";
|
||||
import usePrevious from "../../hooks/usePrevious";
|
||||
import { getNodeHud } from "../../utils/node-utils";
|
||||
import { getNodeHud } from "../../helpers/node-helpers";
|
||||
|
||||
const MainYellowTextAnimator = (props: { visible?: boolean }) => {
|
||||
const activeNode = useStore((state) => state.activeNode);
|
||||
|
|
|
@ -1,41 +1,27 @@
|
|||
import orangeFont from "../../static/sprite/orange_font_texture.png";
|
||||
import yellowFont from "../../static/sprite/yellow_font_texture.png";
|
||||
import whiteFont from "../../static/sprite/white_and_green_texture.png";
|
||||
import orangeFont from "../../static/sprites/fonts/orange_font_texture.png";
|
||||
import yellowFont from "../../static/sprites/fonts/yellow_font_texture.png";
|
||||
import whiteFont from "../../static/sprites/fonts/white_and_green_texture.png";
|
||||
import * as THREE from "three";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import orange_font_json from "../../resources/font_data/big_font.json";
|
||||
import { a, useSpring } from "@react-spring/three";
|
||||
import React, { useMemo, memo } from "react";
|
||||
import { useStore } from "../../store";
|
||||
|
||||
const PauseBigLetter = memo(
|
||||
(props: {
|
||||
color: string;
|
||||
letter: string;
|
||||
letterIdx: number;
|
||||
position: number[];
|
||||
scale: number[];
|
||||
active?: boolean;
|
||||
rowIdx?: number;
|
||||
colIdx?: number;
|
||||
intro?: boolean;
|
||||
mainLetter?: boolean;
|
||||
active?: boolean;
|
||||
introFinished?: boolean;
|
||||
exit?: boolean;
|
||||
}) => {
|
||||
const exitAnimation = useStore(
|
||||
(state) => state.pauseExitAnimation
|
||||
);
|
||||
|
||||
const tex = useMemo(() => {
|
||||
switch (props.color) {
|
||||
case "white":
|
||||
return whiteFont;
|
||||
case "yellow":
|
||||
return yellowFont;
|
||||
default:
|
||||
return orangeFont;
|
||||
}
|
||||
}, [props.color]);
|
||||
|
||||
const colorTexture: THREE.Texture = useLoader(THREE.TextureLoader, tex);
|
||||
const whiteFontTex = useLoader(THREE.TextureLoader, whiteFont);
|
||||
const orangeFontTex = useLoader(THREE.TextureLoader, orangeFont);
|
||||
const yellowFontTex = useLoader(THREE.TextureLoader, yellowFont);
|
||||
|
||||
const lineYOffset = useMemo(() => {
|
||||
const lineOne = "ABCDEFGHIJKLMNOPQ";
|
||||
|
@ -93,64 +79,133 @@ const PauseBigLetter = memo(
|
|||
return geometry;
|
||||
}, [letterData, lineYOffset]);
|
||||
|
||||
const exitAnimValue = useMemo(() => {
|
||||
let col = 0;
|
||||
let row = 0;
|
||||
if (props.colIdx && props.rowIdx) {
|
||||
if (props.colIdx < 3) col = -1;
|
||||
else if (props.colIdx > 3) col = 1;
|
||||
|
||||
if (props.rowIdx < 3) row = -1;
|
||||
else if (props.rowIdx > 3) row = 1;
|
||||
|
||||
return { row, col };
|
||||
}
|
||||
}, [props.colIdx, props.rowIdx]);
|
||||
|
||||
const initialState = useSpring({
|
||||
posX:
|
||||
props.position[0] +
|
||||
(exitAnimValue ? exitAnimValue.col * (exitAnimation ? 2.2 : 0) : 0),
|
||||
posY:
|
||||
-letterData[4] / 50 +
|
||||
props.position[1] +
|
||||
(exitAnimValue ? exitAnimValue.row * (exitAnimation ? 2.2 : 0) : 0),
|
||||
rotX: props.active ? (exitAnimation ? Math.PI / 2 : 0) : -Math.PI,
|
||||
rotY: props.active ? (exitAnimation ? Math.PI / 2 : 0) : Math.PI / 2,
|
||||
const mainLetterIntroSpring = useSpring({
|
||||
from: {
|
||||
rotX: Math.PI,
|
||||
rotY: Math.PI / 2,
|
||||
},
|
||||
to: { rotY: 0, rotX: 0 },
|
||||
delay: (props.rowIdx! + props.colIdx!) * 100 + 500,
|
||||
config: { duration: 500 },
|
||||
});
|
||||
|
||||
const introState = useSpring({
|
||||
rotX: 0,
|
||||
rotY: 0,
|
||||
from: { rotX: Math.PI, rotY: Math.PI * 2 },
|
||||
delay: (props.rowIdx! + props.colIdx!) * 100 + 500,
|
||||
config: { duration: 200 },
|
||||
const exitAnimValue = useMemo(() => {
|
||||
let col, row;
|
||||
if (props.colIdx! < 3) col = -1;
|
||||
else if (props.colIdx! > 3) col = 1;
|
||||
else col = 0;
|
||||
|
||||
if (props.rowIdx! < 3) row = -1;
|
||||
else if (props.rowIdx! > 3) row = 1;
|
||||
else row = 0;
|
||||
|
||||
return { row: row * 2.2, col: col * 2.2 };
|
||||
}, [props.colIdx, props.rowIdx]);
|
||||
|
||||
const mainLetterSpring = useSpring({
|
||||
orangeRotY: props.active ? 0 : Math.PI / 2,
|
||||
orangeRotX: props.active ? 0 : Math.PI,
|
||||
whiteRotY: props.active || props.exit ? Math.PI / 2 : 0,
|
||||
whiteRotX: props.active || props.exit ? Math.PI : 0,
|
||||
posX: props.colIdx
|
||||
? props.colIdx / 2.8 + (props.exit ? exitAnimValue.col : 0)
|
||||
: props.position[0],
|
||||
posY: props.rowIdx
|
||||
? props.rowIdx / 2.8 + (props.exit ? exitAnimValue.row : 0)
|
||||
: -letterData[4] / 50 + props.position[1],
|
||||
config: { duration: 500 },
|
||||
});
|
||||
|
||||
const nonMainLetterSpring = useSpring({
|
||||
rotY: props.active ? 0 : Math.PI / 2,
|
||||
rotX: props.active ? 0 : Math.PI,
|
||||
config: { duration: 500 },
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
{props.mainLetter ? (
|
||||
<>
|
||||
<a.mesh
|
||||
position={[
|
||||
props.position[0],
|
||||
-letterData[4] / 50 + props.position[1],
|
||||
props.position[2],
|
||||
]}
|
||||
position-x={initialState.posX}
|
||||
position-y={initialState.posY}
|
||||
scale={props.scale as [number, number, number]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
geometry={geom}
|
||||
rotation-x={props.intro ? introState.rotX : initialState.rotX}
|
||||
rotation-y={props.intro ? introState.rotY : initialState.rotY}
|
||||
rotation-x={
|
||||
props.introFinished
|
||||
? mainLetterSpring.orangeRotX
|
||||
: mainLetterIntroSpring.rotX
|
||||
}
|
||||
rotation-y={
|
||||
props.introFinished
|
||||
? mainLetterSpring.orangeRotY
|
||||
: mainLetterIntroSpring.rotY
|
||||
}
|
||||
position-x={mainLetterSpring.posX}
|
||||
position-y={mainLetterSpring.posY}
|
||||
renderOrder={100}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
map={colorTexture}
|
||||
map={props.introFinished ? orangeFontTex : whiteFontTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
side={THREE.FrontSide}
|
||||
depthTest={false}
|
||||
/>
|
||||
</a.mesh>
|
||||
<a.mesh
|
||||
position={[
|
||||
props.position[0],
|
||||
-letterData[4] / 50 + props.position[1],
|
||||
props.position[2],
|
||||
]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
geometry={geom}
|
||||
position-x={mainLetterSpring.posX}
|
||||
position-y={mainLetterSpring.posY}
|
||||
rotation-x={
|
||||
props.introFinished ? mainLetterSpring.whiteRotX : Math.PI
|
||||
}
|
||||
rotation-y={
|
||||
props.introFinished ? mainLetterSpring.whiteRotY : Math.PI / 2
|
||||
}
|
||||
renderOrder={100}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
map={whiteFontTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
side={THREE.FrontSide}
|
||||
depthTest={false}
|
||||
/>
|
||||
</a.mesh>
|
||||
</>
|
||||
) : (
|
||||
<a.mesh
|
||||
position={[
|
||||
props.position[0],
|
||||
-letterData[4] / 50 + props.position[1],
|
||||
props.position[2],
|
||||
]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
geometry={geom}
|
||||
rotation-x={nonMainLetterSpring.rotX}
|
||||
rotation-y={nonMainLetterSpring.rotY}
|
||||
renderOrder={100}
|
||||
>
|
||||
<meshBasicMaterial
|
||||
map={yellowFontTex}
|
||||
attach="material"
|
||||
transparent={true}
|
||||
side={THREE.FrontSide}
|
||||
depthTest={false}
|
||||
/>
|
||||
</a.mesh>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import orangeFont from "../../static/sprite/orange_jp_font.png";
|
||||
import orangeFont from "../../static/sprites/fonts/orange_jp_font.png";
|
||||
import * as THREE from "three";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import jp_font_json from "../../resources/font_data/jp_font.json";
|
||||
|
@ -34,8 +34,8 @@ const StaticJpCharacter = memo((props: { char: string; charIdx: number }) => {
|
|||
|
||||
return (
|
||||
<mesh
|
||||
position={[props.charIdx / 4, 0, 0]}
|
||||
scale={[0.25, 0.25, 0]}
|
||||
position={[props.charIdx / 5, 0, 0]}
|
||||
scale={[0.2, 0.2, 0]}
|
||||
geometry={geom}
|
||||
renderOrder={205}
|
||||
>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import orangeFont from "../../static/sprite/orange_font_texture.png";
|
||||
import orangeFont from "../../static/sprites/fonts/orange_font_texture.png";
|
||||
import * as THREE from "three";
|
||||
import { useLoader } from "react-three-fiber";
|
||||
import orange_font_json from "../../resources/font_data/big_font.json";
|
||||
|
|
|
@ -1,13 +1,32 @@
|
|||
import { NodeData } from "../components/MainScene/Site/Site";
|
||||
import * as audio from "../static/sfx";
|
||||
import * as audio from "../static/audio/sfx";
|
||||
import {
|
||||
nodeExplodeAnimation,
|
||||
nodeKnockAndFallAnimation,
|
||||
nodeKnockAnimation,
|
||||
nodeRipAnimation,
|
||||
nodeThrowAnimation,
|
||||
} from "../utils/node-animations";
|
||||
import { playAudio } from "../store";
|
||||
} from "../helpers/node-animation-helpers";
|
||||
import { playMediaElement, resetMediaElement } from "../helpers/media-helpers";
|
||||
import {
|
||||
ActiveSite,
|
||||
AuthorizeUserMatrixIndices,
|
||||
EndComponent,
|
||||
GameScene,
|
||||
LeftMediaComponent,
|
||||
MediaComponent,
|
||||
MediaSide,
|
||||
NodeData,
|
||||
PromptComponent,
|
||||
RightMediaComponent,
|
||||
SiteSaveState,
|
||||
SsknComponent,
|
||||
UserSaveState,
|
||||
} from "../types/types";
|
||||
import { saveUserProgress, useStore } from "../store";
|
||||
|
||||
const setNodeViewed = useStore.getState().setNodeViewed;
|
||||
const resetMediaScene = useStore.getState().resetMediaScene;
|
||||
const loadUserSaveState = useStore.getState().loadUserSaveState;
|
||||
|
||||
export const siteMoveHorizontal = (calculatedState: {
|
||||
lainMoveAnimation: string;
|
||||
|
@ -19,15 +38,13 @@ export const siteMoveHorizontal = (calculatedState: {
|
|||
mutation: {
|
||||
lainMoveState: calculatedState.lainMoveAnimation,
|
||||
siteRot: calculatedState.siteRot,
|
||||
inputCooldown: true,
|
||||
inputCooldown: 5500,
|
||||
},
|
||||
delay: 0,
|
||||
},
|
||||
{
|
||||
mutation: {
|
||||
activeNode: calculatedState.activeNode,
|
||||
lainMoveState: "standing",
|
||||
inputCooldown: false,
|
||||
},
|
||||
delay: 3900,
|
||||
},
|
||||
|
@ -45,37 +62,36 @@ export const siteMoveVertical = (calculatedState: {
|
|||
mutation: {
|
||||
lainMoveState: calculatedState.lainMoveAnimation,
|
||||
activeLevel: calculatedState.activeLevel,
|
||||
inputCooldown: true,
|
||||
inputCooldown: 5500,
|
||||
},
|
||||
delay: 0,
|
||||
},
|
||||
{
|
||||
mutation: {
|
||||
activeNode: calculatedState.activeNode,
|
||||
lainMoveState: "standing",
|
||||
inputCooldown: false,
|
||||
},
|
||||
delay: 3900,
|
||||
},
|
||||
],
|
||||
audio: [
|
||||
{ sfx: [audio.sound13], delay: 0 },
|
||||
{ sfx: [audio.sound13] },
|
||||
{ sfx: [audio.sound10, audio.sound9], delay: 1300 },
|
||||
{ sfx: [audio.sound8], delay: 2700 },
|
||||
],
|
||||
});
|
||||
|
||||
export const changeNode = (calculatedState: { activeNode: NodeData }) => ({
|
||||
state: [{ mutation: { activeNode: calculatedState.activeNode }, delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
||||
});
|
||||
|
||||
export const throwNode = (calculatedState: { currentScene: string }) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: { lainMoveState: "throw_node", inputCooldown: true },
|
||||
delay: 0,
|
||||
mutation: { activeNode: calculatedState.activeNode, inputCooldown: 1500 },
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound1] }],
|
||||
});
|
||||
|
||||
export const throwNode = (calculatedState: { currentScene: GameScene }) => ({
|
||||
state: [
|
||||
{ mutation: { lainMoveState: "throw_node", inputCooldown: -1 } },
|
||||
{
|
||||
mutation: {
|
||||
currentScene: calculatedState.currentScene,
|
||||
|
@ -87,18 +103,15 @@ export const throwNode = (calculatedState: { currentScene: string }) => ({
|
|||
],
|
||||
effects: [nodeThrowAnimation],
|
||||
audio: [
|
||||
{ sfx: [audio.sound0], delay: 0 },
|
||||
{ sfx: [audio.sound0] },
|
||||
{ sfx: [audio.sound12], delay: 1600 },
|
||||
{ sfx: [audio.sound13, audio.sound14], delay: 2800 },
|
||||
],
|
||||
});
|
||||
|
||||
export const ripNode = (calculatedState: { currentScene: string }) => ({
|
||||
export const ripNode = (calculatedState: { currentScene: GameScene }) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: { lainMoveState: "rip_node", inputCooldown: true },
|
||||
delay: 0,
|
||||
},
|
||||
{ mutation: { lainMoveState: "rip_node", inputCooldown: -1 } },
|
||||
{
|
||||
mutation: {
|
||||
currentScene: calculatedState.currentScene,
|
||||
|
@ -110,7 +123,7 @@ export const ripNode = (calculatedState: { currentScene: string }) => ({
|
|||
],
|
||||
effects: [nodeRipAnimation],
|
||||
audio: [
|
||||
{ sfx: [audio.sound0], delay: 0 },
|
||||
{ sfx: [audio.sound0] },
|
||||
{ sfx: [audio.sound12], delay: 1600 },
|
||||
{ sfx: [audio.sound13, audio.sound15], delay: 4000 },
|
||||
],
|
||||
|
@ -121,18 +134,17 @@ export const explodeNode = {
|
|||
{
|
||||
mutation: {
|
||||
lainMoveState: "touch_node_and_get_scared",
|
||||
inputCooldown: true,
|
||||
inputCooldown: 3800,
|
||||
},
|
||||
delay: 0,
|
||||
},
|
||||
{
|
||||
mutation: { lainMoveState: "standing", inputCooldown: false },
|
||||
mutation: { lainMoveState: "standing" },
|
||||
delay: 3800,
|
||||
},
|
||||
],
|
||||
effects: [nodeExplodeAnimation],
|
||||
audio: [
|
||||
{ sfx: [audio.sound0], delay: 0 },
|
||||
{ sfx: [audio.sound0] },
|
||||
{ sfx: [audio.sound17], delay: 2400 },
|
||||
{ sfx: [audio.sound33], delay: 3150 },
|
||||
],
|
||||
|
@ -140,33 +152,24 @@ export const explodeNode = {
|
|||
|
||||
export const knockNode = {
|
||||
state: [
|
||||
{ mutation: { lainMoveState: "knock", inputCooldown: true }, delay: 0 },
|
||||
{ mutation: { lainMoveState: "knock", inputCooldown: 3500 } },
|
||||
{
|
||||
mutation: { lainMoveState: "standing", inputCooldown: false },
|
||||
delay: 2900,
|
||||
mutation: { lainMoveState: "standing" },
|
||||
delay: 3500,
|
||||
},
|
||||
],
|
||||
effects: [nodeKnockAnimation],
|
||||
audio: [
|
||||
{ sfx: [audio.sound0], delay: 0 },
|
||||
{ sfx: [audio.sound18], delay: 1200 },
|
||||
],
|
||||
audio: [{ sfx: [audio.sound0] }, { sfx: [audio.sound18], delay: 1200 }],
|
||||
};
|
||||
|
||||
export const knockNodeAndFall = {
|
||||
state: [
|
||||
{
|
||||
mutation: { lainMoveState: "knock_and_fall", inputCooldown: true },
|
||||
delay: 0,
|
||||
},
|
||||
{
|
||||
mutation: { lainMoveState: "standing", inputCooldown: false },
|
||||
delay: 7500,
|
||||
},
|
||||
{ mutation: { lainMoveState: "knock_and_fall", inputCooldown: 6000 } },
|
||||
{ mutation: { lainMoveState: "standing" }, delay: 6000 },
|
||||
],
|
||||
effects: [nodeKnockAndFallAnimation],
|
||||
audio: [
|
||||
{ sfx: [audio.sound0], delay: 0 },
|
||||
{ sfx: [audio.sound0] },
|
||||
{ sfx: [audio.sound18], delay: 1200 },
|
||||
{ sfx: [audio.sound19], delay: 2300 },
|
||||
{ sfx: [audio.sound33], delay: 3150 },
|
||||
|
@ -181,23 +184,28 @@ export const enterLevelSelection = (calculatedState: {
|
|||
mutation: {
|
||||
selectedLevel: calculatedState.selectedLevel,
|
||||
mainSubscene: "level_selection",
|
||||
inputCooldown: 1500,
|
||||
},
|
||||
delay: 0,
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound1] }],
|
||||
});
|
||||
|
||||
export const exitLevelSelection = {
|
||||
state: [{ mutation: { mainSubscene: "site" }, delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
||||
state: [{ mutation: { mainSubscene: "site", inputCooldown: 1500 } }],
|
||||
audio: [{ sfx: [audio.sound1] }],
|
||||
};
|
||||
|
||||
export const changeSelectedLevel = (calculatedState: {
|
||||
selectedLevel: number;
|
||||
}) => ({
|
||||
state: [
|
||||
{ mutation: { selectedLevel: calculatedState.selectedLevel }, delay: 0 },
|
||||
{
|
||||
mutation: {
|
||||
selectedLevel: calculatedState.selectedLevel,
|
||||
inputCooldown: 100,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
|
@ -212,15 +220,13 @@ export const selectLevel = (calculatedState: {
|
|||
lainMoveState: calculatedState.lainMoveState,
|
||||
activeLevel: calculatedState.activeLevel,
|
||||
mainSubscene: "site",
|
||||
inputCooldown: true,
|
||||
inputCooldown: 5500,
|
||||
},
|
||||
delay: 0,
|
||||
},
|
||||
{
|
||||
mutation: {
|
||||
activeNode: calculatedState.activeNode,
|
||||
lainMoveState: "standing",
|
||||
inputCooldown: false,
|
||||
},
|
||||
delay: 3900,
|
||||
},
|
||||
|
@ -238,19 +244,15 @@ export const pauseGame = (calculatedState: { siteRot: number[] }) => ({
|
|||
lainMoveState: "rip_middle_ring",
|
||||
pauseExitAnimation: false,
|
||||
mainSubscene: "pause",
|
||||
inputCooldown: true,
|
||||
inputCooldown: -1,
|
||||
},
|
||||
delay: 0,
|
||||
},
|
||||
{
|
||||
mutation: { siteRot: calculatedState.siteRot },
|
||||
delay: 3600,
|
||||
},
|
||||
],
|
||||
audio: [
|
||||
{ sfx: [audio.sound7], delay: 0 },
|
||||
{ sfx: [audio.sound23], delay: 3600 },
|
||||
],
|
||||
audio: [{ sfx: [audio.sound7] }, { sfx: [audio.sound23], delay: 3600 }],
|
||||
});
|
||||
|
||||
export const changePauseComponent = (calculatedState: {
|
||||
|
@ -258,29 +260,31 @@ export const changePauseComponent = (calculatedState: {
|
|||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: { activePauseComponent: calculatedState.activePauseComponent },
|
||||
delay: 0,
|
||||
mutation: {
|
||||
activePauseComponent: calculatedState.activePauseComponent,
|
||||
inputCooldown: 700,
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound1] }],
|
||||
});
|
||||
|
||||
export const showPermissionDenied = {
|
||||
state: [
|
||||
{ mutation: { permissionDenied: true }, delay: 0 },
|
||||
{ mutation: { permissionDenied: true, inputCooldown: 1200 } },
|
||||
{ mutation: { permissionDenied: false }, delay: 1200 },
|
||||
],
|
||||
audio: [{ sfx: [audio.sound0], delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound0] }],
|
||||
};
|
||||
|
||||
export const displayPrompt = {
|
||||
state: [{ mutation: { promptVisible: true }, delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound0], delay: 0 }],
|
||||
state: [{ mutation: { promptVisible: true, inputCooldown: 0 } }],
|
||||
audio: [{ sfx: [audio.sound0] }],
|
||||
};
|
||||
|
||||
export const showAbout = {
|
||||
state: [{ mutation: { showingAbout: true }, delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound0], delay: 0 }],
|
||||
state: [{ mutation: { showingAbout: true } }],
|
||||
audio: [{ sfx: [audio.sound0] }],
|
||||
};
|
||||
|
||||
export const exitPause = (calculatedState: { siteRot: number[] }) => ({
|
||||
|
@ -288,103 +292,125 @@ export const exitPause = (calculatedState: { siteRot: number[] }) => ({
|
|||
{
|
||||
mutation: {
|
||||
siteRot: calculatedState.siteRot,
|
||||
pauseExitAnimation: true,
|
||||
activePauseComponent: "change",
|
||||
inputCooldown: true,
|
||||
inputCooldown: 1400,
|
||||
mainSubscene: "site",
|
||||
activePauseComponent: "",
|
||||
},
|
||||
delay: 0,
|
||||
},
|
||||
{
|
||||
mutation: {
|
||||
mainSubscene: "site",
|
||||
activePauseComponent: "change",
|
||||
inputCooldown: false,
|
||||
lainMoveState: "standing",
|
||||
},
|
||||
delay: 1200,
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound0], delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound0] }],
|
||||
});
|
||||
|
||||
export const exitAbout = {
|
||||
state: [{ mutation: { showingAbout: false }, delay: 0 }],
|
||||
state: [{ mutation: { showingAbout: false, inputCooldown: 0 } }],
|
||||
};
|
||||
|
||||
export const changePromptComponent = (calculatedState: {
|
||||
activePromptComponent: "yes" | "no";
|
||||
activePromptComponent: PromptComponent;
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
activePromptComponent: calculatedState.activePromptComponent,
|
||||
inputCooldown: 100,
|
||||
},
|
||||
delay: 0,
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound1] }],
|
||||
});
|
||||
|
||||
export const exitPrompt = {
|
||||
state: [
|
||||
{
|
||||
mutation: { activePromptComponent: "no", promptVisible: false },
|
||||
delay: 0,
|
||||
mutation: {
|
||||
activePromptComponent: "no",
|
||||
promptVisible: false,
|
||||
inputCooldown: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound28], delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound28] }],
|
||||
};
|
||||
|
||||
// todo actually save
|
||||
export const saveGame = () => ({
|
||||
export const saveGame = (calculatedState: {
|
||||
userSaveState: UserSaveState;
|
||||
}) => ({
|
||||
state: [
|
||||
{ mutation: { saveSuccessful: true, inputCooldown: 1200 } },
|
||||
{
|
||||
mutation: { saveSuccessful: true },
|
||||
delay: 0,
|
||||
mutation: {
|
||||
saveSuccessful: undefined,
|
||||
promptVisible: false,
|
||||
activePromptComponent: "no",
|
||||
},
|
||||
{
|
||||
mutation: { saveSuccessful: undefined },
|
||||
delay: 1200,
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound28], delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound28] }],
|
||||
effects: [() => saveUserProgress(calculatedState.userSaveState)],
|
||||
});
|
||||
|
||||
// todo actually load
|
||||
export const loadGame = () => ({
|
||||
export const loadGameFail = {
|
||||
state: [
|
||||
{
|
||||
mutation: { loadSuccessful: true },
|
||||
delay: 0,
|
||||
mutation: {
|
||||
loadSuccessful: false,
|
||||
inputCooldown: 1200,
|
||||
},
|
||||
},
|
||||
{ mutation: { loadSuccessful: undefined }, delay: 1200 },
|
||||
],
|
||||
audio: [{ sfx: [audio.sound28] }],
|
||||
};
|
||||
|
||||
export const loadGame = (calculatedState: {
|
||||
userSaveState: UserSaveState;
|
||||
}) => ({
|
||||
state: [
|
||||
{ mutation: { loadSuccessful: true, inputCooldown: 1200 } },
|
||||
{
|
||||
mutation: { loadSuccessful: undefined },
|
||||
mutation: {
|
||||
loadSuccessful: undefined,
|
||||
currentScene: "null",
|
||||
mainSubscene: "site",
|
||||
lainMoveState: "standing",
|
||||
promptVisible: false,
|
||||
activePromptComponent: "no",
|
||||
activePauseComponent: "change",
|
||||
},
|
||||
delay: 1200,
|
||||
},
|
||||
{
|
||||
mutation: { currentScene: "main", intro: true },
|
||||
delay: 1300,
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound28] }],
|
||||
effects: [
|
||||
() =>
|
||||
setTimeout(() => loadUserSaveState(calculatedState.userSaveState), 1200),
|
||||
],
|
||||
audio: [{ sfx: [audio.sound28], delay: 0 }],
|
||||
});
|
||||
|
||||
export const changeSite = (calculatedState: {
|
||||
newActiveSite: "a" | "b";
|
||||
newActiveSite: ActiveSite;
|
||||
newActiveNode: NodeData;
|
||||
newActiveLevel: string;
|
||||
newSiteRot: number[];
|
||||
newSiteSaveState: {
|
||||
a: {
|
||||
activeNode: NodeData;
|
||||
siteRot: number[];
|
||||
activeLevel: string;
|
||||
};
|
||||
b: {
|
||||
activeNode: NodeData;
|
||||
siteRot: number[];
|
||||
activeLevel: string;
|
||||
};
|
||||
};
|
||||
newSiteSaveState: SiteSaveState;
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
intro: true,
|
||||
currentScene: "change_disc",
|
||||
lainMoveState: "standing",
|
||||
promptVisible: false,
|
||||
|
@ -397,26 +423,338 @@ export const changeSite = (calculatedState: {
|
|||
activeLevel: calculatedState.newActiveLevel,
|
||||
// save state
|
||||
siteSaveState: calculatedState.newSiteSaveState,
|
||||
inputCooldown: -1,
|
||||
},
|
||||
delay: 0,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const changeLeftMediaComponent = (calculatedState: {
|
||||
activeComponent: "play" | "exit";
|
||||
activeComponent: LeftMediaComponent;
|
||||
}) => ({
|
||||
state: [
|
||||
{ mutation: { activeMediaComponent: calculatedState.activeComponent } },
|
||||
{
|
||||
mutation: {
|
||||
activeMediaComponent: calculatedState.activeComponent,
|
||||
inputCooldown: 1200,
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound1], delay: 0 }],
|
||||
audio: [{ sfx: [audio.sound1] }],
|
||||
});
|
||||
|
||||
export const changeMediaSide = (calculatedState: {
|
||||
activeMediaComponent: "fstWord" | "sndWord" | "thirdWord" | "exit" | "play";
|
||||
activeMediaComponent: MediaComponent;
|
||||
lastActiveMediaComponents: {
|
||||
left: "play" | "exit";
|
||||
right: "fstWord" | "sndWord" | "thirdWord";
|
||||
left: LeftMediaComponent;
|
||||
right: RightMediaComponent;
|
||||
};
|
||||
currentMediaSide: MediaSide;
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
activeMediaComponent: calculatedState.activeMediaComponent,
|
||||
lastActiveMediaComponents: calculatedState.lastActiveMediaComponents,
|
||||
currentMediaSide: calculatedState.currentMediaSide,
|
||||
inputCooldown: 0,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const playMedia = (calculatedState: { activeNode: NodeData }) => ({
|
||||
state: [{ mutation: { mediaPercentageElapsed: 0, inputCooldown: 500 } }],
|
||||
effects: [
|
||||
playMediaElement,
|
||||
() =>
|
||||
setNodeViewed(calculatedState.activeNode.node_name, {
|
||||
is_viewed: 1,
|
||||
is_visible: 1,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export const exitMedia = {
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
currentScene: "main",
|
||||
inputCooldown: -1,
|
||||
},
|
||||
},
|
||||
],
|
||||
effects: [resetMediaElement, resetMediaScene],
|
||||
};
|
||||
|
||||
export const changeRightMediaComponent = (calculatedState: {
|
||||
wordPosStateIdx: number;
|
||||
activeComponent: RightMediaComponent;
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
activeMediaComponent: calculatedState.activeComponent,
|
||||
mediaWordPosStateIdx: calculatedState.wordPosStateIdx,
|
||||
inputCooldown: 300,
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound1] }],
|
||||
});
|
||||
|
||||
export const wordNotFound = {
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
currentScene: "main",
|
||||
wordNotFound: true,
|
||||
inputCooldown: 300,
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound30] }],
|
||||
effects: [resetMediaElement, resetMediaScene],
|
||||
};
|
||||
|
||||
export const hideWordNotFound = {
|
||||
state: [{ mutation: { wordNotFound: false, inputCooldown: 0 } }],
|
||||
};
|
||||
|
||||
export const selectWord = (calculatedState: {
|
||||
activeLevel: string;
|
||||
activeNode: NodeData;
|
||||
siteRot: number[];
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
activeLevel: calculatedState.activeLevel,
|
||||
siteRot: calculatedState.siteRot,
|
||||
activeNode: calculatedState.activeNode,
|
||||
wordSelected: true,
|
||||
currentScene: "main",
|
||||
inputCooldown: -1,
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound29] }],
|
||||
effects: [resetMediaElement, resetMediaScene],
|
||||
});
|
||||
|
||||
export const changeSsknComponent = (calculatedState: {
|
||||
activeSsknComponent: SsknComponent;
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
activeSsknComponent: calculatedState.activeSsknComponent,
|
||||
inputCooldown: 100,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const upgradeSskn = (calculatedState: { activeNode: NodeData }) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
ssknLoading: true,
|
||||
inputCooldown: -1,
|
||||
},
|
||||
},
|
||||
{ mutation: { currentScene: "main" }, delay: 6000 },
|
||||
],
|
||||
effects: [
|
||||
() =>
|
||||
setNodeViewed(calculatedState.activeNode.node_name, {
|
||||
is_viewed: 1,
|
||||
is_visible: 0,
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export const exitSskn = {
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
currentScene: "main",
|
||||
ssknLoading: false,
|
||||
activeSsknComponent: "ok",
|
||||
inputCooldown: -1,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const changeEndComponent = (calculatedState: {
|
||||
activeEndComponent: EndComponent;
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
activeEndComponent: calculatedState.activeEndComponent,
|
||||
inputCooldown: 100,
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound1] }],
|
||||
});
|
||||
|
||||
export const endGame = (calculatedState: { userSaveState: UserSaveState }) => ({
|
||||
state: [{ mutation: { currentScene: "boot", inputCooldown: -1 } }],
|
||||
audio: [{ sfx: [audio.sound0] }],
|
||||
effects: [() => saveUserProgress(calculatedState.userSaveState)],
|
||||
});
|
||||
|
||||
export const changeMainMenuComponent = (calculatedState: {
|
||||
activeMainMenuComponent: "authorize_user" | "load_data";
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
activeMainMenuComponent: calculatedState.activeMainMenuComponent,
|
||||
inputCooldown: 200,
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound1] }],
|
||||
});
|
||||
|
||||
export const exitLoadData = {
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
bootSubscene: "main_menu",
|
||||
promptVisible: false,
|
||||
activePromptComponent: "no",
|
||||
inputCooldown: 500,
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound29] }],
|
||||
};
|
||||
|
||||
export const enterLoadData = {
|
||||
state: [
|
||||
{ mutation: { bootSubscene: "load_data", inputCooldown: 500 } },
|
||||
{ mutation: { promptVisible: true }, delay: 500 },
|
||||
],
|
||||
audio: [{ sfx: [audio.sound0] }],
|
||||
};
|
||||
|
||||
export const enterUserAuthorization = {
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
bootSubscene: "authorize_user",
|
||||
inputCooldown: 500,
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound0] }],
|
||||
};
|
||||
|
||||
export const exitUserAuthorization = {
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
playerName: "",
|
||||
bootSubscene: "main_menu",
|
||||
inputCooldown: 500,
|
||||
authorizeUserMatrixIndices: { rowIdx: 1, colIdx: 7 },
|
||||
},
|
||||
},
|
||||
],
|
||||
audio: [{ sfx: [audio.sound29] }],
|
||||
};
|
||||
|
||||
export const startNewGame = {
|
||||
state: [
|
||||
{ mutation: { currentScene: "main", intro: true, inputCooldown: -1 } },
|
||||
],
|
||||
};
|
||||
|
||||
export const updatePlayerName = (calculatedState: { playerName: string }) => ({
|
||||
state: [{ mutation: { playerName: calculatedState.playerName } }],
|
||||
audio: [{ sfx: [audio.sound0] }],
|
||||
});
|
||||
|
||||
export const removePlayerNameLastChar = (calculatedState: {
|
||||
playerName: string;
|
||||
}) => ({
|
||||
state: [{ mutation: { playerName: calculatedState.playerName } }],
|
||||
audio: [{ sfx: [audio.sound29] }],
|
||||
});
|
||||
|
||||
export const failUpdatePlayerName = { audio: [{ sfx: [audio.sound0] }] };
|
||||
|
||||
export const updateAuthorizeUserLetterMatrixIndices = (calculatedState: {
|
||||
authorizeUserLetterMatrixIndices: AuthorizeUserMatrixIndices;
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
inputCooldown: 300,
|
||||
authorizeUserMatrixIndices:
|
||||
calculatedState.authorizeUserLetterMatrixIndices,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const playIdleVideo = (calculatedState: { idleMedia: string }) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
idleStarting: true,
|
||||
idleMedia: calculatedState.idleMedia,
|
||||
idleImages: undefined,
|
||||
idleNodeName: undefined,
|
||||
inputCooldown: -1,
|
||||
},
|
||||
},
|
||||
{ mutation: { currentScene: "idle_media" }, delay: 1200 },
|
||||
],
|
||||
});
|
||||
|
||||
export const playIdleAudio = (calculatedState: {
|
||||
idleMedia: string;
|
||||
idleImages: { "1": string; "2": string; "3": string };
|
||||
idleNodeName: string;
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
idleStarting: true,
|
||||
inputCooldown: -1,
|
||||
idleMedia: calculatedState.idleMedia,
|
||||
idleImages: calculatedState.idleImages,
|
||||
idleNodeName: calculatedState.idleNodeName,
|
||||
},
|
||||
},
|
||||
{ mutation: { currentScene: "idle_media" }, delay: 1200 },
|
||||
],
|
||||
});
|
||||
|
||||
export const playLainIdleAnim = (calculatedState: {
|
||||
lainMoveState: string;
|
||||
duration: number;
|
||||
}) => ({
|
||||
state: [
|
||||
{
|
||||
mutation: {
|
||||
lainMoveState: calculatedState.lainMoveState,
|
||||
canLainMove: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
mutation: { lainMoveState: "standing", canLainMove: true },
|
||||
delay: calculatedState.duration,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export const resetInputCooldown = {
|
||||
state: [{ mutation: { inputCooldown: 0 } }],
|
||||
};
|
||||
currentMediaSide: "right" | "left";
|
||||
}) => ({});
|
||||
|
|
29
src/core/handleEvent.ts
Normal file
29
src/core/handleEvent.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { playAudio, useStore } from "../store";
|
||||
import sleep from "../utils/sleep";
|
||||
import { GameEvent } from "../types/types";
|
||||
|
||||
// the async/await here might be misleading for some, it functions as a setTimeout that fires
|
||||
// multiple async calls without stopping the execution, which is what we want.
|
||||
const handleEvent = (event: GameEvent) => {
|
||||
const setState = useStore.setState;
|
||||
|
||||
const { state, effects, audio } = event;
|
||||
|
||||
if (state)
|
||||
state.forEach(async (mutationData) => {
|
||||
const { delay, mutation } = mutationData;
|
||||
if (delay) await sleep(delay);
|
||||
setState(mutation);
|
||||
});
|
||||
|
||||
if (effects) effects.forEach((effect) => effect());
|
||||
|
||||
if (audio)
|
||||
audio.forEach(async (audio) => {
|
||||
const { delay, sfx } = audio;
|
||||
if (delay) await sleep(delay);
|
||||
sfx.forEach((soundEffect) => playAudio(soundEffect));
|
||||
});
|
||||
};
|
||||
|
||||
export default handleEvent;
|
123
src/core/input-handlers/handleBootSceneInput.ts
Normal file
123
src/core/input-handlers/handleBootSceneInput.ts
Normal file
|
@ -0,0 +1,123 @@
|
|||
import authorize_user_letters from "../../resources/authorize_user_letters.json";
|
||||
import {
|
||||
handleNameSelection,
|
||||
handleUserAuthorizationMove,
|
||||
} from "../../helpers/name-selection-helpers";
|
||||
import {
|
||||
changeMainMenuComponent,
|
||||
changePromptComponent,
|
||||
enterLoadData,
|
||||
enterUserAuthorization,
|
||||
exitLoadData,
|
||||
exitUserAuthorization,
|
||||
failUpdatePlayerName,
|
||||
loadGame,
|
||||
loadGameFail,
|
||||
removePlayerNameLastChar,
|
||||
startNewGame,
|
||||
updateAuthorizeUserLetterMatrixIndices,
|
||||
updatePlayerName,
|
||||
} from "../eventTemplates";
|
||||
import { BootSceneContext, GameEvent } from "../../types/types";
|
||||
|
||||
const handleBootSceneInput = (
|
||||
bootSceneContext: BootSceneContext,
|
||||
keyPress: string
|
||||
): GameEvent | undefined => {
|
||||
const {
|
||||
subscene,
|
||||
activeMainMenuComponent,
|
||||
activePromptComponent,
|
||||
promptVisible,
|
||||
playerName,
|
||||
authorizeUserMatrixIndices,
|
||||
} = bootSceneContext;
|
||||
|
||||
if (promptVisible) {
|
||||
switch (keyPress) {
|
||||
case "LEFT":
|
||||
return changePromptComponent({ activePromptComponent: "yes" });
|
||||
case "RIGHT":
|
||||
return changePromptComponent({ activePromptComponent: "no" });
|
||||
case "CIRCLE":
|
||||
switch (activePromptComponent) {
|
||||
case "no":
|
||||
return exitLoadData;
|
||||
case "yes":
|
||||
const stateToLoad = localStorage.getItem("lainSaveState");
|
||||
|
||||
if (stateToLoad)
|
||||
return loadGame({
|
||||
userSaveState: JSON.parse(stateToLoad),
|
||||
});
|
||||
else return loadGameFail;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (subscene) {
|
||||
case "main_menu":
|
||||
switch (keyPress) {
|
||||
case "UP":
|
||||
case "DOWN":
|
||||
const newComponent =
|
||||
keyPress === "UP" ? "authorize_user" : "load_data";
|
||||
return changeMainMenuComponent({
|
||||
activeMainMenuComponent: newComponent,
|
||||
});
|
||||
case "CIRCLE":
|
||||
switch (activeMainMenuComponent) {
|
||||
case "authorize_user":
|
||||
return enterUserAuthorization;
|
||||
case "load_data":
|
||||
return enterLoadData;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "authorize_user":
|
||||
switch (keyPress) {
|
||||
case "START":
|
||||
if (playerName.length > 0) return startNewGame;
|
||||
return;
|
||||
case "CROSS":
|
||||
if (playerName.length > 0) {
|
||||
return removePlayerNameLastChar({
|
||||
playerName: playerName.slice(0, -1),
|
||||
});
|
||||
} else {
|
||||
return exitUserAuthorization;
|
||||
}
|
||||
case "LEFT":
|
||||
case "UP":
|
||||
case "DOWN":
|
||||
case "RIGHT":
|
||||
const direction = keyPress.toLowerCase();
|
||||
const newMatrixIndices = handleUserAuthorizationMove(
|
||||
authorizeUserMatrixIndices,
|
||||
direction
|
||||
);
|
||||
|
||||
if (newMatrixIndices)
|
||||
return updateAuthorizeUserLetterMatrixIndices({
|
||||
authorizeUserLetterMatrixIndices: newMatrixIndices,
|
||||
});
|
||||
break;
|
||||
case "CIRCLE":
|
||||
const chosenCharacter =
|
||||
authorize_user_letters.matrix[authorizeUserMatrixIndices.rowIdx][
|
||||
authorizeUserMatrixIndices.colIdx
|
||||
];
|
||||
|
||||
if (chosenCharacter) {
|
||||
const newName = handleNameSelection(playerName, chosenCharacter);
|
||||
|
||||
if (newName && newName.length > 8) return;
|
||||
if (newName !== undefined)
|
||||
return updatePlayerName({ playerName: newName });
|
||||
else return failUpdatePlayerName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default handleBootSceneInput;
|
52
src/core/input-handlers/handleEndSceneInput.ts
Normal file
52
src/core/input-handlers/handleEndSceneInput.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { changeEndComponent, changeSite, endGame } from "../eventTemplates";
|
||||
import { EndSceneContext, GameEvent } from "../../types/types";
|
||||
import { getCurrentUserState } from "../../store";
|
||||
|
||||
const handleEndSceneInput = (
|
||||
endSceneContext: EndSceneContext,
|
||||
keyPress: string
|
||||
): GameEvent | undefined => {
|
||||
const {
|
||||
selectionVisible,
|
||||
activeEndComponent,
|
||||
siteSaveState,
|
||||
activeNode,
|
||||
activeLevel,
|
||||
siteRot,
|
||||
} = endSceneContext;
|
||||
|
||||
if (selectionVisible) {
|
||||
switch (keyPress) {
|
||||
case "UP":
|
||||
case "DOWN":
|
||||
const newComponent = keyPress === "UP" ? "end" : "continue";
|
||||
return changeEndComponent({ activeEndComponent: newComponent });
|
||||
case "CIRCLE":
|
||||
switch (activeEndComponent) {
|
||||
case "end":
|
||||
return endGame({ userSaveState: getCurrentUserState() });
|
||||
case "continue":
|
||||
const siteToLoad = "a";
|
||||
const stateToLoad = siteSaveState[siteToLoad];
|
||||
|
||||
const newSiteSaveState = {
|
||||
...siteSaveState,
|
||||
b: {
|
||||
activeNode: activeNode,
|
||||
siteRot: [0, siteRot[1], 0],
|
||||
activeLevel: activeLevel.toString().padStart(2, "0"),
|
||||
},
|
||||
};
|
||||
return changeSite({
|
||||
newActiveSite: siteToLoad,
|
||||
newActiveNode: stateToLoad.activeNode,
|
||||
newSiteRot: stateToLoad.siteRot,
|
||||
newActiveLevel: stateToLoad.activeLevel,
|
||||
newSiteSaveState: newSiteSaveState,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default handleEndSceneInput;
|
|
@ -2,9 +2,9 @@ import {
|
|||
findNode,
|
||||
getNodeById,
|
||||
isNodeVisible,
|
||||
nodeToScene,
|
||||
unknownNodeTemplate,
|
||||
} from "../../utils/node-utils";
|
||||
import { MainSceneContext } from "../../store";
|
||||
} from "../../helpers/node-helpers";
|
||||
import {
|
||||
changeNode,
|
||||
changePauseComponent,
|
||||
|
@ -18,19 +18,29 @@ import {
|
|||
exitPause,
|
||||
exitPrompt,
|
||||
explodeNode,
|
||||
hideWordNotFound,
|
||||
knockNode,
|
||||
knockNodeAndFall,
|
||||
loadGame,
|
||||
loadGameFail,
|
||||
pauseGame,
|
||||
resetInputCooldown,
|
||||
ripNode,
|
||||
saveGame,
|
||||
selectLevel,
|
||||
showAbout,
|
||||
showPermissionDenied,
|
||||
siteMoveHorizontal,
|
||||
siteMoveVertical,
|
||||
throwNode,
|
||||
} from "../eventTemplates";
|
||||
import { GameEvent, MainSceneContext } from "../../types/types";
|
||||
import { getCurrentUserState } from "../../store";
|
||||
|
||||
const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
||||
const handleMainSceneInput = (
|
||||
mainSceneContext: MainSceneContext,
|
||||
keyPress: string
|
||||
): GameEvent | undefined => {
|
||||
const {
|
||||
subscene,
|
||||
selectedLevel,
|
||||
|
@ -40,13 +50,12 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
siteRotY,
|
||||
activeNode,
|
||||
level,
|
||||
keyPress,
|
||||
ssknLvl,
|
||||
showingAbout,
|
||||
promptVisible,
|
||||
activePromptComponent,
|
||||
gateLvl,
|
||||
siteSaveState,
|
||||
wordNotFound,
|
||||
canLainMove,
|
||||
} = mainSceneContext;
|
||||
|
||||
if (promptVisible) {
|
||||
|
@ -61,7 +70,7 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
return exitPrompt;
|
||||
case "yes":
|
||||
switch (activePauseComponent) {
|
||||
case "change":
|
||||
case "change": {
|
||||
const siteToLoad = activeSite === "a" ? "b" : "a";
|
||||
const stateToLoad = siteSaveState[siteToLoad];
|
||||
|
||||
|
@ -73,8 +82,6 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
activeLevel: level.toString().padStart(2, "0"),
|
||||
},
|
||||
};
|
||||
console.log(newSiteSaveState);
|
||||
|
||||
return changeSite({
|
||||
newActiveSite: siteToLoad,
|
||||
newActiveNode: stateToLoad.activeNode,
|
||||
|
@ -82,24 +89,32 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
newActiveLevel: stateToLoad.activeLevel,
|
||||
newSiteSaveState: newSiteSaveState,
|
||||
});
|
||||
}
|
||||
case "save":
|
||||
return saveGame();
|
||||
case "load":
|
||||
return loadGame();
|
||||
return saveGame({ userSaveState: getCurrentUserState() });
|
||||
case "load": {
|
||||
const stateToLoad = localStorage.getItem("lainSaveState");
|
||||
|
||||
if (stateToLoad)
|
||||
return loadGame({
|
||||
userSaveState: JSON.parse(stateToLoad),
|
||||
});
|
||||
else return loadGameFail;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (subscene) {
|
||||
case "site":
|
||||
if (wordNotFound) return hideWordNotFound;
|
||||
switch (keyPress) {
|
||||
case "LEFT":
|
||||
case "RIGHT": {
|
||||
const direction = keyPress.toLowerCase();
|
||||
const nodeData = findNode(
|
||||
activeNode.id,
|
||||
activeNode,
|
||||
direction,
|
||||
activeNode.matrixIndices!,
|
||||
level,
|
||||
activeSite,
|
||||
gameProgress,
|
||||
|
@ -124,6 +139,7 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
};
|
||||
|
||||
if (nodeData.didMove) {
|
||||
if (!canLainMove) return resetInputCooldown;
|
||||
return siteMoveHorizontal({
|
||||
lainMoveAnimation: lainMoveAnimation,
|
||||
siteRot: newSiteRot,
|
||||
|
@ -137,10 +153,16 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
case "DOWN": {
|
||||
const direction = keyPress.toLowerCase();
|
||||
|
||||
const upperLimit = activeSite === "a" ? 22 : 13;
|
||||
if (
|
||||
(direction === "up" && level === upperLimit) ||
|
||||
(direction === "down" && level === 1)
|
||||
)
|
||||
return;
|
||||
|
||||
const nodeData = findNode(
|
||||
activeNode.id,
|
||||
activeNode,
|
||||
direction,
|
||||
activeNode.matrixIndices!,
|
||||
level,
|
||||
activeSite,
|
||||
gameProgress,
|
||||
|
@ -160,19 +182,19 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
matrixIndices: nodeData.matrixIndices,
|
||||
};
|
||||
|
||||
if (nodeData.didMove)
|
||||
if (nodeData.didMove) {
|
||||
if (!canLainMove) return resetInputCooldown;
|
||||
return siteMoveVertical({
|
||||
lainMoveAnimation: lainMoveAnimation,
|
||||
activeLevel: newLevel,
|
||||
activeNode: newNode,
|
||||
});
|
||||
else return changeNode({ activeNode: newNode });
|
||||
} else return changeNode({ activeNode: newNode });
|
||||
}
|
||||
case "CIRCLE":
|
||||
const eventAnimation =
|
||||
Math.random() < 0.4 ? "rip_node" : "throw_node";
|
||||
if (!canLainMove) return resetInputCooldown;
|
||||
|
||||
const nodeType = activeNode.type;
|
||||
const eventAnimation = Math.random() < 0.4 ? throwNode : ripNode;
|
||||
|
||||
if (
|
||||
activeNode.id === "" ||
|
||||
|
@ -180,53 +202,18 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
)
|
||||
return;
|
||||
|
||||
if (activeNode.upgrade_requirement > ssknLvl) {
|
||||
const rejectEvents = [explodeNode, knockNode, knockNodeAndFall];
|
||||
if (activeNode.upgrade_requirement > gameProgress.sskn_level) {
|
||||
const rejectEvents = [knockNodeAndFall, knockNode, explodeNode];
|
||||
return rejectEvents[Math.floor(Math.random() * 3)];
|
||||
}
|
||||
|
||||
switch (nodeType) {
|
||||
case 0:
|
||||
case 2:
|
||||
case 4:
|
||||
case 3:
|
||||
case 5:
|
||||
return {
|
||||
event: `${eventAnimation}_media`,
|
||||
mutations: { scene: "media" },
|
||||
};
|
||||
case 6:
|
||||
if (activeNode.node_name.substr(0, 3) === "TaK") {
|
||||
return {
|
||||
event: `${eventAnimation}_tak`,
|
||||
mutations: { scene: "tak" },
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
event: `${eventAnimation}_media`,
|
||||
mutations: { scene: "media" },
|
||||
};
|
||||
}
|
||||
case 8:
|
||||
return {
|
||||
event: `${eventAnimation}_gate`,
|
||||
mutations: { scene: "gate" },
|
||||
};
|
||||
case 7:
|
||||
return {
|
||||
event: `${eventAnimation}_sskn`,
|
||||
mutations: { scene: "sskn" },
|
||||
};
|
||||
case 9:
|
||||
return {
|
||||
event: `${eventAnimation}_polytan`,
|
||||
mutations: { scene: "polytan" },
|
||||
};
|
||||
}
|
||||
const newScene = nodeToScene(activeNode);
|
||||
if (newScene) return eventAnimation({ currentScene: newScene });
|
||||
break;
|
||||
case "L2":
|
||||
return enterLevelSelection({ selectedLevel: level });
|
||||
case "TRIANGLE":
|
||||
if (!canLainMove) return resetInputCooldown;
|
||||
return pauseGame({ siteRot: [Math.PI / 2, siteRotY, 0] });
|
||||
}
|
||||
break;
|
||||
|
@ -241,19 +228,28 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
if (selectedLevel - 1 >= 1)
|
||||
return changeSelectedLevel({ selectedLevel: selectedLevel - 1 });
|
||||
break;
|
||||
case "X":
|
||||
case "CROSS":
|
||||
return exitLevelSelection;
|
||||
|
||||
case "CIRCLE":
|
||||
if (!canLainMove) return resetInputCooldown;
|
||||
|
||||
if (level === selectedLevel) return;
|
||||
|
||||
const direction = selectedLevel > level ? "up" : "down";
|
||||
|
||||
const rowIdx = direction === "up" ? 2 : 0;
|
||||
const newStartingPoint = {
|
||||
...activeNode,
|
||||
matrixIndices: {
|
||||
matrixIdx: activeNode.matrixIndices!.matrixIdx,
|
||||
rowIdx: direction === "up" ? 2 : 0,
|
||||
colIdx: 0,
|
||||
},
|
||||
};
|
||||
|
||||
const nodeData = findNode(
|
||||
activeNode.id,
|
||||
newStartingPoint,
|
||||
direction,
|
||||
{ ...activeNode.matrixIndices!, rowIdx: rowIdx },
|
||||
selectedLevel,
|
||||
activeSite,
|
||||
gameProgress,
|
||||
|
@ -284,13 +280,12 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
switch (keyPress) {
|
||||
case "UP":
|
||||
case "DOWN":
|
||||
const direction = keyPress.toLowerCase();
|
||||
const components = ["load", "about", "change", "save", "exit"];
|
||||
|
||||
const newComponent =
|
||||
components[
|
||||
components.indexOf(activePauseComponent) +
|
||||
(direction === "up" ? -1 : 1)
|
||||
(keyPress === "UP" ? -1 : 1)
|
||||
];
|
||||
|
||||
if (newComponent)
|
||||
|
@ -308,7 +303,10 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
case "load":
|
||||
return displayPrompt;
|
||||
case "change":
|
||||
if (activePauseComponent === "change" && gateLvl > 4)
|
||||
if (
|
||||
activePauseComponent === "change" &&
|
||||
gameProgress.gate_level > 4
|
||||
)
|
||||
return showPermissionDenied;
|
||||
else return displayPrompt;
|
||||
}
|
||||
|
@ -318,4 +316,4 @@ const handleMainSceneKeyPress = (mainSceneContext: MainSceneContext) => {
|
|||
}
|
||||
};
|
||||
|
||||
export default handleMainSceneKeyPress;
|
||||
export default handleMainSceneInput;
|
|
@ -1,10 +1,25 @@
|
|||
import { findNodeFromWord } from "../../utils/media-utils";
|
||||
import { MediaSceneContext } from "../../store";
|
||||
import { changeLeftMediaComponent, changeMediaSide } from "../eventTemplates";
|
||||
import { findNodeFromWord } from "../../helpers/media-helpers";
|
||||
import {
|
||||
changeLeftMediaComponent,
|
||||
changeMediaSide,
|
||||
changeRightMediaComponent,
|
||||
exitMedia,
|
||||
playMedia,
|
||||
selectWord,
|
||||
wordNotFound,
|
||||
} from "../eventTemplates";
|
||||
import { isNodeVisible } from "../../helpers/node-helpers";
|
||||
import {
|
||||
GameEvent,
|
||||
MediaSceneContext,
|
||||
RightMediaComponent,
|
||||
} from "../../types/types";
|
||||
|
||||
const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
||||
const handleMediaSceneInput = (
|
||||
mediaSceneContext: MediaSceneContext,
|
||||
keyPress: string
|
||||
): GameEvent | undefined => {
|
||||
const {
|
||||
keyPress,
|
||||
activeMediaComponent,
|
||||
wordPosStateIdx,
|
||||
activeNode,
|
||||
|
@ -19,11 +34,13 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
|||
switch (keyPress) {
|
||||
case "UP":
|
||||
case "DOWN": {
|
||||
const direction = keyPress.toLowerCase();
|
||||
const newComponent = direction === "up" ? "play" : "exit";
|
||||
const newComponent = keyPress === "UP" ? "play" : "exit";
|
||||
|
||||
return changeLeftMediaComponent({ activeComponent: newComponent });
|
||||
}
|
||||
case "RIGHT": {
|
||||
if (!activeNode.media_file.includes("XA")) return;
|
||||
|
||||
return changeMediaSide({
|
||||
activeMediaComponent: lastActiveMediaComponents.right,
|
||||
lastActiveMediaComponents: {
|
||||
|
@ -36,14 +53,9 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
|||
case "CIRCLE":
|
||||
switch (activeMediaComponent) {
|
||||
case "play":
|
||||
return {
|
||||
event: "media_play_select",
|
||||
node: activeNode,
|
||||
};
|
||||
return playMedia({ activeNode: activeNode });
|
||||
case "exit":
|
||||
return {
|
||||
event: "media_play_select",
|
||||
};
|
||||
return exitMedia;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -54,6 +66,7 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
|||
wordPosStateIdx - 1 < 1 ? 6 : wordPosStateIdx - 1;
|
||||
const newComponent = (() => {
|
||||
switch (activeMediaComponent) {
|
||||
default:
|
||||
case "fstWord":
|
||||
return "thirdWord";
|
||||
case "sndWord":
|
||||
|
@ -62,17 +75,17 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
|||
return "sndWord";
|
||||
}
|
||||
})();
|
||||
return {
|
||||
event: "media_rightside_up",
|
||||
newActiveComponent: newComponent,
|
||||
return changeRightMediaComponent({
|
||||
activeComponent: newComponent,
|
||||
wordPosStateIdx: newWordPosStateIdx,
|
||||
};
|
||||
});
|
||||
}
|
||||
case "DOWN": {
|
||||
const newWordPosStateIdx =
|
||||
wordPosStateIdx + 1 > 6 ? 1 : wordPosStateIdx + 1;
|
||||
const newComponent = (() => {
|
||||
switch (activeMediaComponent) {
|
||||
default:
|
||||
case "fstWord":
|
||||
return "sndWord";
|
||||
case "sndWord":
|
||||
|
@ -82,11 +95,10 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
|||
}
|
||||
})();
|
||||
|
||||
return {
|
||||
event: "media_rightside_down",
|
||||
newActiveComponent: newComponent,
|
||||
return changeRightMediaComponent({
|
||||
activeComponent: newComponent,
|
||||
wordPosStateIdx: newWordPosStateIdx,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
case "LEFT":
|
||||
|
@ -94,29 +106,39 @@ const handleMediaSceneKeyPress = (mediaSceneContext: MediaSceneContext) => {
|
|||
activeMediaComponent: lastActiveMediaComponents.left,
|
||||
lastActiveMediaComponents: {
|
||||
...lastActiveMediaComponents,
|
||||
right: activeMediaComponent as
|
||||
| "fstWord"
|
||||
| "sndWord"
|
||||
| "thirdWord",
|
||||
right: activeMediaComponent as RightMediaComponent,
|
||||
},
|
||||
currentMediaSide: "left",
|
||||
});
|
||||
|
||||
case "CIRCLE":
|
||||
const data = findNodeFromWord(
|
||||
activeMediaComponent,
|
||||
activeNode,
|
||||
activeSite,
|
||||
gameProgress
|
||||
);
|
||||
|
||||
if (data) {
|
||||
return { event: `media_word_select`, ...data };
|
||||
} else {
|
||||
return { event: `word_node_not_found` };
|
||||
const wordIdx = (() => {
|
||||
switch (activeMediaComponent as RightMediaComponent) {
|
||||
case "fstWord":
|
||||
return 1;
|
||||
case "sndWord":
|
||||
return 2;
|
||||
case "thirdWord":
|
||||
return 3;
|
||||
}
|
||||
})();
|
||||
|
||||
const nodeName = activeNode.node_name;
|
||||
const wordToFind = activeNode.words[wordIdx];
|
||||
|
||||
const data = findNodeFromWord(wordToFind, nodeName, activeSite);
|
||||
|
||||
const { node, level, siteRotY } = { ...data };
|
||||
|
||||
if (!isNodeVisible(node, gameProgress)) return wordNotFound;
|
||||
|
||||
return selectWord({
|
||||
activeNode: node,
|
||||
activeLevel: level,
|
||||
siteRot: [0, siteRotY, 0],
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default handleMediaSceneKeyPress;
|
||||
export default handleMediaSceneInput;
|
26
src/core/input-handlers/handleSsknSceneInput.ts
Normal file
26
src/core/input-handlers/handleSsknSceneInput.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { changeSsknComponent, exitSskn, upgradeSskn } from "../eventTemplates";
|
||||
import { GameEvent, SsknSceneContext } from "../../types/types";
|
||||
|
||||
const handleSsknSceneInput = (
|
||||
ssknSceneContext: SsknSceneContext,
|
||||
keyPress: string
|
||||
): GameEvent | undefined => {
|
||||
const { activeSsknComponent, activeNode } = ssknSceneContext;
|
||||
|
||||
switch (keyPress) {
|
||||
case "UP":
|
||||
case "DOWN":
|
||||
const direction = keyPress.toLowerCase();
|
||||
const newComponent = direction === "up" ? "ok" : "cancel";
|
||||
return changeSsknComponent({ activeSsknComponent: newComponent });
|
||||
case "CIRCLE":
|
||||
switch (activeSsknComponent) {
|
||||
case "ok":
|
||||
return upgradeSskn({ activeNode: activeNode });
|
||||
case "cancel":
|
||||
return exitSskn;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default handleSsknSceneInput;
|
|
@ -1,84 +0,0 @@
|
|||
import { playAudio, useStore } from "../../store";
|
||||
import * as audio from "../../static/sfx";
|
||||
|
||||
const handleBootSceneEvent = (eventState: any) => {
|
||||
const setState = useStore.setState;
|
||||
|
||||
switch (eventState.event) {
|
||||
case "main_menu_up":
|
||||
setState({ activeMainMenuComponent: "authorize_user" });
|
||||
playAudio(audio.sound1);
|
||||
break;
|
||||
case "main_menu_down":
|
||||
setState({ activeMainMenuComponent: "load_data" });
|
||||
playAudio(audio.sound1);
|
||||
break;
|
||||
case "main_menu_load_data_select":
|
||||
setState({ bootSubscene: "load_data" });
|
||||
playAudio(audio.sound0);
|
||||
|
||||
setTimeout(() => setState({ promptVisible: true }), 500);
|
||||
break;
|
||||
case "main_menu_authorize_user_select":
|
||||
setState({ authorizeUserLetterIdx: 0, bootSubscene: "authorize_user" });
|
||||
playAudio(audio.sound0);
|
||||
break;
|
||||
case "authorize_user_up":
|
||||
case "authorize_user_down":
|
||||
case "authorize_user_left":
|
||||
case "authorize_user_right":
|
||||
setState({
|
||||
authorizeUserLetterIdx: eventState.authorizeUserLetterIdx,
|
||||
});
|
||||
break;
|
||||
case "authorize_user_back":
|
||||
setState({
|
||||
playerName: "",
|
||||
bootSubscene: "main_menu",
|
||||
});
|
||||
playAudio(audio.sound29);
|
||||
break;
|
||||
case "update_player_name":
|
||||
setState({
|
||||
playerName: eventState.playerName,
|
||||
});
|
||||
playAudio(audio.sound0);
|
||||
break;
|
||||
case "update_player_name_denied":
|
||||
playAudio(audio.sound0);
|
||||
break;
|
||||
case "remove_last_char":
|
||||
setState({ playerName: eventState.playerName });
|
||||
playAudio(audio.sound29);
|
||||
break;
|
||||
case "load_data_no":
|
||||
setState({
|
||||
bootSubscene: "main_menu",
|
||||
promptVisible: false,
|
||||
activePromptComponent: "no",
|
||||
});
|
||||
playAudio(audio.sound29);
|
||||
break;
|
||||
case "load_data_yes":
|
||||
// todo check if data exists
|
||||
setState({ loadSuccessful: true });
|
||||
playAudio(audio.sound28);
|
||||
|
||||
//todo actually load
|
||||
setTimeout(() => setState({ loadSuccessful: undefined }), 1200);
|
||||
break;
|
||||
case "prompt_left":
|
||||
setState({ activePromptComponent: "yes" });
|
||||
playAudio(audio.sound1);
|
||||
break;
|
||||
case "prompt_right":
|
||||
setState({ activePromptComponent: "no" });
|
||||
playAudio(audio.sound1);
|
||||
break;
|
||||
case "start_new_game":
|
||||
setState({ currentScene: "main", intro: true });
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
export default handleBootSceneEvent;
|
|
@ -1,20 +0,0 @@
|
|||
import { useStore } from "../../store";
|
||||
|
||||
const handleEndSceneEvent = (eventState: any) => {
|
||||
const setState = useStore.setState;
|
||||
switch (eventState.event) {
|
||||
case "end_selection_up":
|
||||
setState({ activeEndComponent: "end" });
|
||||
break;
|
||||
case "end_selection_down":
|
||||
setState({ activeEndComponent: "continue" });
|
||||
break;
|
||||
case "end_continue_select":
|
||||
setState({ currentScene: "change_disc", intro: true });
|
||||
break;
|
||||
case "end_end_select":
|
||||
setState({ currentScene: "boot" });
|
||||
}
|
||||
};
|
||||
|
||||
export default handleEndSceneEvent;
|
|
@ -1,47 +0,0 @@
|
|||
import { playAudio, useStore } from "../../store";
|
||||
import sleep from "../../utils/sleep";
|
||||
|
||||
type Mutation = {
|
||||
mutation: Object;
|
||||
delay: number;
|
||||
};
|
||||
|
||||
type EventAudio = {
|
||||
sfx: HTMLAudioElement[];
|
||||
delay: number;
|
||||
};
|
||||
|
||||
type Event = {
|
||||
state: Mutation[];
|
||||
audio?: EventAudio[];
|
||||
effects?: (() => void)[];
|
||||
};
|
||||
|
||||
// the async/await here might be misleading for some, it functions as a setTimeout that fires
|
||||
// multiple async calls without stopping the execution, which is what we want.
|
||||
const handleEvent = (event: Event) => {
|
||||
const now = performance.now();
|
||||
const setState = useStore.setState;
|
||||
|
||||
const { state, audio, effects } = event;
|
||||
|
||||
state.forEach(async (mutationData) => {
|
||||
const { delay, mutation } = mutationData;
|
||||
if (delay) await sleep(delay);
|
||||
setState(mutation);
|
||||
});
|
||||
|
||||
if (effects) effects.forEach((effect) => effect());
|
||||
|
||||
if (audio) {
|
||||
audio.forEach(async (audio) => {
|
||||
const { delay, sfx } = audio;
|
||||
if (delay) await sleep(delay);
|
||||
sfx.forEach((soundEffect) => playAudio(soundEffect));
|
||||
});
|
||||
}
|
||||
|
||||
// console.log(performance.now() - now);
|
||||
};
|
||||
|
||||
export default handleEvent;
|
|
@ -1,84 +0,0 @@
|
|||
import { playAudio, useStore } from "../../store";
|
||||
import * as audio from "../../static/sfx";
|
||||
|
||||
const handleMediaSceneEvent = (eventState: any) => {
|
||||
const setState = useStore.setState;
|
||||
|
||||
const setNodeViewed = useStore.getState().setNodeViewed;
|
||||
const updateLeftSide = useStore.getState().updateLeftSide;
|
||||
const updateRightSide = useStore.getState().updateRightSide;
|
||||
|
||||
const setPercentageElapsed = useStore.getState().setPercentageElapsed;
|
||||
|
||||
const playMedia = () => {
|
||||
const mediaElement = document.getElementById("media") as HTMLMediaElement;
|
||||
|
||||
if (mediaElement && mediaElement.paused) {
|
||||
setPercentageElapsed(0);
|
||||
|
||||
mediaElement.play();
|
||||
}
|
||||
};
|
||||
|
||||
const exitMedia = () => {
|
||||
const mediaElement = document.getElementById("media") as HTMLMediaElement;
|
||||
if (mediaElement) {
|
||||
mediaElement.pause();
|
||||
mediaElement.currentTime = 0;
|
||||
}
|
||||
};
|
||||
|
||||
switch (eventState.event) {
|
||||
case "media_rightside_down":
|
||||
case "media_rightside_up":
|
||||
setState({
|
||||
activeMediaComponent: eventState.newActiveComponent,
|
||||
mediaWordPosStateIdx: eventState.wordPosStateIdx,
|
||||
});
|
||||
playAudio(audio.sound1);
|
||||
break;
|
||||
case "media_leftside_right":
|
||||
updateLeftSide(
|
||||
eventState.newActiveComponent,
|
||||
eventState.lastActiveComponent
|
||||
);
|
||||
break;
|
||||
case "media_rightside_left":
|
||||
updateRightSide(
|
||||
eventState.newActiveComponent,
|
||||
eventState.lastActiveComponent
|
||||
);
|
||||
break;
|
||||
case "media_play_select":
|
||||
setNodeViewed(eventState.node.node_name, {
|
||||
is_viewed: 1,
|
||||
is_visible: 1,
|
||||
});
|
||||
playMedia();
|
||||
break;
|
||||
case "media_exit_select":
|
||||
exitMedia();
|
||||
playAudio(audio.sound29);
|
||||
break;
|
||||
case "media_word_select":
|
||||
exitMedia();
|
||||
playAudio(audio.sound29);
|
||||
setState({
|
||||
wordSelected: true,
|
||||
activeLevel: eventState.level,
|
||||
siteRot: [0, eventState.siteRotY, 0],
|
||||
activeNode: eventState.node,
|
||||
currentScene: "main",
|
||||
});
|
||||
break;
|
||||
case "word_node_not_found":
|
||||
exitMedia();
|
||||
playAudio(audio.sound30);
|
||||
setState({
|
||||
mainSubscene: "not_found",
|
||||
currentScene: "main",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default handleMediaSceneEvent;
|
|
@ -1,41 +0,0 @@
|
|||
import { useStore } from "../../store";
|
||||
|
||||
const handleSsknSceneEvent = (eventState: any) => {
|
||||
const setState = useStore.setState;
|
||||
|
||||
const setNodeViewed = useStore.getState().setNodeViewed;
|
||||
|
||||
switch (eventState.event) {
|
||||
case "sskn_cancel_up":
|
||||
setState({
|
||||
activeSsknComponent: "ok",
|
||||
});
|
||||
break;
|
||||
case "sskn_ok_down":
|
||||
setState({
|
||||
activeSsknComponent: "cancel",
|
||||
});
|
||||
break;
|
||||
case "sskn_ok_select":
|
||||
setState({
|
||||
ssknLoading: true,
|
||||
});
|
||||
setNodeViewed(eventState.node.node_name, {
|
||||
is_viewed: 1,
|
||||
is_visible: 0,
|
||||
});
|
||||
// incrementSsknLvl();
|
||||
|
||||
setTimeout(() => setState({ currentScene: "main" }), 6000);
|
||||
|
||||
break;
|
||||
case "sskn_cancel_select":
|
||||
setState({
|
||||
ssknLoading: false,
|
||||
currentScene: "main",
|
||||
activeSsknComponent: "ok",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default handleSsknSceneEvent;
|
|
@ -1,189 +0,0 @@
|
|||
import authorize_user_letters from "../../resources/authorize_user_letters.json";
|
||||
import handleNameSelection from "../../utils/handleNameSelection";
|
||||
import { BootSceneContext } from "../../store";
|
||||
|
||||
const handleBootSceneKeyPress = (bootSceneContext: BootSceneContext) => {
|
||||
const {
|
||||
keyPress,
|
||||
subscene,
|
||||
activeMainMenuComponent,
|
||||
activePromptComponent,
|
||||
promptVisible,
|
||||
authorizeUserLetterIdx,
|
||||
playerName,
|
||||
} = bootSceneContext;
|
||||
|
||||
if (promptVisible) {
|
||||
switch (keyPress) {
|
||||
case "LEFT":
|
||||
return { event: "prompt_left" };
|
||||
case "RIGHT":
|
||||
return { event: "prompt_right" };
|
||||
case "CIRCLE":
|
||||
switch (activePromptComponent) {
|
||||
case "no":
|
||||
return { event: "load_data_no" };
|
||||
case "yes":
|
||||
return {
|
||||
event: "load_data_yes",
|
||||
};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (subscene) {
|
||||
case "main_menu":
|
||||
switch (keyPress) {
|
||||
case "UP":
|
||||
case "DOWN":
|
||||
return { event: `main_menu_${keyPress.toLowerCase()}` };
|
||||
case "CIRCLE":
|
||||
return { event: `main_menu_${activeMainMenuComponent}_select` };
|
||||
}
|
||||
break;
|
||||
case "authorize_user":
|
||||
switch (keyPress) {
|
||||
case "START":
|
||||
if (playerName.length > 0) {
|
||||
return {
|
||||
event: "start_new_game",
|
||||
};
|
||||
}
|
||||
break;
|
||||
case "X":
|
||||
if (playerName.length > 0) {
|
||||
return {
|
||||
event: "remove_last_char",
|
||||
playerName: playerName.slice(0, -1),
|
||||
};
|
||||
} else {
|
||||
return { event: "authorize_user_back" };
|
||||
}
|
||||
case "LEFT":
|
||||
// if utmost left, break
|
||||
if (
|
||||
[0, 13, 26, 39, 52].includes(authorizeUserLetterIdx) ||
|
||||
authorizeUserLetterIdx === 15
|
||||
)
|
||||
break;
|
||||
// skip
|
||||
else if (
|
||||
authorizeUserLetterIdx === 41 ||
|
||||
authorizeUserLetterIdx === 17 ||
|
||||
authorizeUserLetterIdx === 30 ||
|
||||
authorizeUserLetterIdx === 43 ||
|
||||
authorizeUserLetterIdx === 19 ||
|
||||
authorizeUserLetterIdx === 45
|
||||
) {
|
||||
return {
|
||||
event: "authorize_user_left",
|
||||
authorizeUserLetterIdx: authorizeUserLetterIdx - 2,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
event: "authorize_user_left",
|
||||
authorizeUserLetterIdx: authorizeUserLetterIdx - 1,
|
||||
};
|
||||
}
|
||||
case "RIGHT":
|
||||
// if utmost right, break
|
||||
if ([12, 25, 38, 51, 64].includes(authorizeUserLetterIdx)) break;
|
||||
// skip empty
|
||||
else if (
|
||||
authorizeUserLetterIdx === 39 ||
|
||||
authorizeUserLetterIdx === 41 ||
|
||||
authorizeUserLetterIdx === 28 ||
|
||||
authorizeUserLetterIdx === 15 ||
|
||||
authorizeUserLetterIdx === 43 ||
|
||||
authorizeUserLetterIdx === 17
|
||||
) {
|
||||
return {
|
||||
event: "authorize_user_right",
|
||||
authorizeUserLetterIdx: authorizeUserLetterIdx + 2,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
event: "authorize_user_right",
|
||||
authorizeUserLetterIdx: authorizeUserLetterIdx + 1,
|
||||
};
|
||||
}
|
||||
case "DOWN":
|
||||
// if utmost down, break
|
||||
if (
|
||||
Array.from(new Array(13), (x, i) => i + 52).includes(
|
||||
authorizeUserLetterIdx
|
||||
)
|
||||
) {
|
||||
break;
|
||||
// skip empty
|
||||
} else if (
|
||||
authorizeUserLetterIdx === 0 ||
|
||||
authorizeUserLetterIdx === 1 ||
|
||||
authorizeUserLetterIdx === 52 ||
|
||||
authorizeUserLetterIdx === 27 ||
|
||||
authorizeUserLetterIdx === 31 ||
|
||||
authorizeUserLetterIdx === 5
|
||||
) {
|
||||
return {
|
||||
event: "authorize_user_down",
|
||||
authorizeUserLetterIdx: authorizeUserLetterIdx + 26,
|
||||
};
|
||||
} else if (authorizeUserLetterIdx === 3) {
|
||||
return {
|
||||
event: "authorize_user_down",
|
||||
authorizeUserLetterIdx: authorizeUserLetterIdx + 52,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
event: "authorize_user_down",
|
||||
authorizeUserLetterIdx: authorizeUserLetterIdx + 13,
|
||||
};
|
||||
}
|
||||
case "UP":
|
||||
// if utmost up, break
|
||||
if (
|
||||
Array.from(new Array(13), (x, i) => i).includes(
|
||||
authorizeUserLetterIdx
|
||||
)
|
||||
) {
|
||||
break;
|
||||
// skip empty
|
||||
} else if (
|
||||
authorizeUserLetterIdx === 26 ||
|
||||
authorizeUserLetterIdx === 27 ||
|
||||
authorizeUserLetterIdx === 53 ||
|
||||
authorizeUserLetterIdx === 31 ||
|
||||
authorizeUserLetterIdx === 57
|
||||
) {
|
||||
return {
|
||||
event: "authorize_user_up",
|
||||
authorizeUserLetterIdx: authorizeUserLetterIdx - 26,
|
||||
};
|
||||
} else if (authorizeUserLetterIdx === 55) {
|
||||
return {
|
||||
event: "authorize_user_up",
|
||||
authorizeUserLetterIdx: authorizeUserLetterIdx - 52,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
event: "authorize_user_up",
|
||||
authorizeUserLetterIdx: authorizeUserLetterIdx - 13,
|
||||
};
|
||||
}
|
||||
case "CIRCLE":
|
||||
const chosenCharacter =
|
||||
authorize_user_letters[
|
||||
authorizeUserLetterIdx.toString() as keyof typeof authorize_user_letters
|
||||
];
|
||||
|
||||
const newName = handleNameSelection(playerName, chosenCharacter);
|
||||
|
||||
if (newName !== undefined)
|
||||
return { event: "update_player_name", playerName: newName };
|
||||
else return { event: "update_player_name_denied" };
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default handleBootSceneKeyPress;
|
|
@ -1,17 +0,0 @@
|
|||
import { EndSceneContext } from "../../store";
|
||||
|
||||
const handleEndSceneKeyPress = (endSceneContext: EndSceneContext) => {
|
||||
const { keyPress, selectionVisible, activeEndComponent } = endSceneContext;
|
||||
|
||||
if (selectionVisible) {
|
||||
switch (keyPress) {
|
||||
case "UP":
|
||||
case "DOWN":
|
||||
return { event: `end_selection_${keyPress.toLowerCase()}` };
|
||||
case "CIRCLE":
|
||||
return { event: `end_${activeEndComponent}_select` };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default handleEndSceneKeyPress;
|
|
@ -1,26 +0,0 @@
|
|||
import { SsknSceneContext } from "../../store";
|
||||
|
||||
const handleSsknSceneKeyPress = (ssknSceneContext: SsknSceneContext) => {
|
||||
const { keyPress, activeSsknComponent, activeNode } = ssknSceneContext;
|
||||
|
||||
switch (keyPress) {
|
||||
case "UP":
|
||||
case "DOWN":
|
||||
return {
|
||||
event: `sskn_${activeSsknComponent}_${keyPress.toLowerCase()}`,
|
||||
};
|
||||
case "CIRCLE":
|
||||
if (activeSsknComponent === "ok") {
|
||||
return {
|
||||
event: `sskn_ok_select`,
|
||||
node: activeNode,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
event: `sskn_cancel_select`,
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default handleSsknSceneKeyPress;
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue