{"id":343102,"date":"2022-12-25T03:00:43","date_gmt":"2022-12-25T03:00:43","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=343102"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=343102","title":{"rendered":"<span>\u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0431\u0430\u0437\u044b \u0434\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0432 \u0434\u0443\u0445\u0435 Dune 2\/2000 \u043d\u0430 Three.js, Vue3 + TS<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/347\/ba9\/d56\/347ba9d56682e757ce145dbd206cd288.jpg\" alt=\"\u041e\u043b\u0434\u044b \u0437\u0434\u0435\u0441\u044c? )\" title=\"\u041e\u043b\u0434\u044b \u0437\u0434\u0435\u0441\u044c? )\" width=\"1600\" height=\"1093\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/347\/ba9\/d56\/347ba9d56682e757ce145dbd206cd288.jpg\" data-blurred=\"true\"\/><figcaption>\u041e\u043b\u0434\u044b \u0437\u0434\u0435\u0441\u044c? )<\/figcaption><\/figure>\n<p>\u0421\u0430\u043c\u043e\u0439 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u043c\u043e\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435\u0439 \u0434\u043b\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 \u0431\u044b\u043b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 \u043e\u0442\u0447\u0435\u0442 <a href=\"https:\/\/habr.com\/ru\/post\/556238\/\" rel=\"noopener noreferrer nofollow\"><u>\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e FPS<\/u><\/a>. \u0421\u0443\u0434\u044f \u043f\u043e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043b\u044e\u0434\u0435\u0439 \u0437\u0430\u0448\u043b\u043e \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u043e \u0441\u044b\u0433\u0440\u0430\u0442\u044c, \u044f \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0432 \u043b\u0438\u0447\u043a\u0443 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u0435\u0449\u0435 \u043e\u0434\u043d\u0443 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u043a\u0440\u0430\u0444\u0442\u043e\u0432\u043e\u0433\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e \u0433\u0435\u0439\u043c\u0434\u0435\u0432\u0430 \u043d\u0430 javascript \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0432 \u0434\u0443\u0445\u0435 \u043a\u0443\u043b\u044c\u0442\u043e\u0432\u043e\u0439 Dune \u0438\u0437 \u0434\u0435\u0442\u0441\u0442\u0432\u0430. \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u0443\u043f\u0435\u0440\u0441\u044f \u0432 \u043d\u0438\u0437\u043a\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0435\u0439\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0437\u0430\u0441\u043a\u0443\u0447\u0430\u043b, \u0443\u0436\u0435 \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0434 \u043a\u0430\u043a \u0437\u0430\u0431\u0440\u043e\u0441\u0438\u043b \u044d\u0442\u043e \u0434\u0435\u043b\u043e. \u041d\u043e \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b, \u0441\u0435\u0439\u0447\u0430\u0441 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0438 \u0434\u0435\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0445\u043e\u0447\u0443, \u043f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e, \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443 \u0434\u043b\u044f \u0441\u0435\u0431\u044f, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0432 \u0438 \u043e \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0442\u0435\u0435 \u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043b\u044f \u043a\u043e\u0433\u043e-\u0442\u043e \u043e\u043a\u0430\u0436\u0443\u0442\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c\u0438 \u043c\u043e\u0438 \u0443\u0441\u0438\u043b\u0438\u044f. \u0421\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u043e\u0431\u044a\u0435\u043c\u043d\u043e\u0439, \u0434\u043e\u0442\u043e\u0448\u043d\u043e\u0439 \u0438 \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e\u0439 \u043a\u0430\u043a \u043f\u0435\u0440\u0432\u0430\u044f \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u0448\u0443\u0442\u0435\u0440\u0430, \u0437\u0430\u0442\u043e \u0441\u0430\u043c \u043a\u043e\u0434 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u0442\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u0435\u043a \u0438\u0437 Vue3 \u0438 TypeScript. \u0412\u043e \u043c\u043d\u043e\u0433\u043e, \u044d\u0442\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442 \u0438\u0434\u0435\u0438 \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u0435\u0440\u0432\u043e\u0439, \u0441 \u0442\u0435\u043c \u043e\u0442\u043b\u0438\u0447\u0438\u0435\u043c, \u0447\u0442\u043e \u043c\u044b \u043f\u0438\u043b\u0438\u043c \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e, \u0430 \u043d\u0435 \u0448\u0443\u0442\u0435\u0440 \u043e\u0442 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043b\u0438\u0446\u0430. \u042f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u0442\u043e \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0443\u0436\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u043e \u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e \u0432 \u043f\u0435\u0440\u0432\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0431\u0435\u0433\u043b\u043e \u043f\u043e\u043a\u0430\u0436\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u00ab\u043d\u043e\u0432\u044b\u0435 \u0444\u0438\u0447\u0438\u00bb.<\/p>\n<p><a href=\"https:\/\/dune-three.vercel.app\/\" rel=\"noopener noreferrer nofollow\"><u>\u0414\u0435\u043c\u043e-\u0441\u0442\u0435\u043d\u0434<\/u><\/a>.<\/p>\n<p><a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\" rel=\"noopener noreferrer nofollow\"><u>\u0420\u0435\u043f\u043e<\/u><\/a>.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u00ab\u043a\u0440\u0430\u0442\u043a\u0430\u044f \u043e\u0431\u0437\u043e\u0440\u043d\u0430\u044f \u044d\u043a\u0441\u043a\u0443\u0440\u0441\u0438\u044f\u00bb \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u0432\u0430\u0436\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u0430\u043c, \u043c\u043e\u0434\u0443\u043b\u044f\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<p><strong>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/strong><\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043a\u043e\u0434 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0432 \u0441\u0432\u043e\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0432 \u043e\u0431\u0449\u0435\u043c \u0438 \u0446\u0435\u043b\u043e\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442 \u043b\u044e\u0431\u043e\u0439 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043d\u0430 \u0441\u0445\u043e\u0436\u0438\u0445 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u0445. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u00ab\u0441\u0430\u043c\u044b\u043c \u043f\u0435\u0440\u0432\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c\u00bb \u0432\u0441\u0435 \u0442\u0430\u043a\u0436\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0430\u0439\u043b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043a\u043e\u0434\u0443 \u0441\u043f\u0438\u0441\u043a\u0438 \u0432\u0441\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0438\u043c\u0435\u043d \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u0446\u0432\u0435\u0442\u043e\u0432-\u0442\u0435\u043a\u0441\u0442\u0443\u0440, \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0433\u0435\u0439\u043c\u043f\u043b\u0435\u044f, \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u044b \u0442\u0435\u043a\u0441\u0442\u043e\u0432: <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/utils\/constants.ts\" rel=\"noopener noreferrer nofollow\"><u>@\/src\/utils\/constants.ts<\/u><\/a><\/p>\n<p><strong>\u041a\u043e\u043d\u0442\u0440\u043e\u043b<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/e59\/4ef\/285\/e594ef285c906fe97a91b874d0b27d7b.jpg\" alt=\"\u041f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c\" title=\"\u041f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c\" width=\"1600\" height=\"1093\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e59\/4ef\/285\/e594ef285c906fe97a91b874d0b27d7b.jpg\" data-blurred=\"true\"\/><figcaption>\u041f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c<\/figcaption><\/figure>\n<p>\u0422\u043e \u0447\u0442\u043e, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0432\u043f\u043e\u043b\u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043a\u043e\u043c\u0443-\u0442\u043e \u00ab\u043f\u043e\u0434\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u00bb \u2014 \u044d\u0442\u043e \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <a href=\"https:\/\/threejs.org\/examples\/?q=control#misc_controls_map\" rel=\"noopener noreferrer nofollow\"><u>MapControl<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u0435\u0442 \u00ab\u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u00bb \u043f\u043e\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u0436\u0430\u0442\u043e\u0439 \u043a\u043b\u0430\u0432\u0438\u0448\u0435 Tab, \u0430 \u043f\u0440\u0438 \u0437\u0430\u0436\u0430\u0442\u043e\u043c Space \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0432 \u00ab\u0433\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u0439 \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c\u00bb. \u0412\u0441\u0435 \u044d\u0442\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u0421\u0446\u0435\u043d\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u00ab\u0432\u0441\u0435\u0433\u043e \u043e\u0434\u0438\u043d \u0434\u0438\u0432\u00bb \u2014 \u0434\u043b\u044f Three, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430 \u0438\u0433\u0440\u044b.\u00a0 <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/components\/Scene\/Scene.vue\" rel=\"noopener noreferrer nofollow\"><u>@\/src\/components\/Scene\/Scene.vue<\/u><\/a>.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/00c\/e42\/41b\/00ce4241b6e6171d9862e5f174e56a8b.jpg\" alt=\"\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c\" title=\"\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c\" width=\"1600\" height=\"1093\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/00c\/e42\/41b\/00ce4241b6e6171d9862e5f174e56a8b.jpg\" data-blurred=\"true\"\/><figcaption>\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c<\/figcaption><\/figure>\n<p><strong>\u041c\u043e\u0434\u0443\u043b\u0438<\/strong><\/p>\n<p>\u0414\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u0431\u0430\u0437\u044b \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 [\u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 \u0448\u0443\u0442\u0435\u0440\u0430] \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0432\u044b\u0431\u043e\u0440 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0434\u0435\u0441\u044c \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b. \u0418 \u00ab\u0441\u0430\u043c\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c\u00bb \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/models\/modules.ts\" rel=\"noopener noreferrer nofollow\">\u0444\u0430\u0439\u043b<\/a> \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0438\u0433\u0440\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u0439. \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043e\u043d \u0441 \u0441\u0430\u043c\u043e\u0439 \u0441\u0430\u043a\u0440\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0449\u0438 \u0432\u043e \u0432\u0441\u0435\u0439 \u043a\u0443\u0445\u043d\u0435 \u2014 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u00ab\u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430\u00bb \u2014 \u043e\u0431\u0449\u0435\u0433\u043e \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435.<\/p>\n<pre><code class=\"typescript\">\/\/ \u0412 @\/src\/models\/modules.ts: \/\/ Main object export interface ISelf {  \/\/ Utils  helper: Helper; \/\/ \"\u043d\u0430\u0448\u0435 \u0432\u0441\u0435\" - \u043d\u0430\u0431\u043e\u0440 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443, \u043e\u0431\u0441\u0447\u0435\u0442\u044b \u0438 \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c - \"\u044d\u043a\u043e\u043d\u043e\u043c\u044f\u0449\u0438\u0439 \u043f\u0430\u043c\u044f\u0442\u044c\" ))  assets: Assets; \/\/ \u043c\u043e\u0434\u0443\u043b\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0449\u0438\u0439 \u0432\u0441\u0435 \u0430\u0441\u0441\u0435\u0442\u044b - \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b, \u043e\u0431\u044a\u0435\u043a\u0442\u044b-\u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0437\u0432\u0443\u043a\u0438  events: Events; \/\/ \u0448\u0438\u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439  audio: AudioBus; \/\/ \u0430\u0443\u0434\u0438\u043e\u043c\u0438\u043a\u0448\u0435\u0440   \/\/ Core  store: Store&lt;State>;  scene: Scene;  listener: AudioListener;  render: () => void; } <\/code><\/pre>\n<p>\u0412\u043e\u0442 \u044d\u0442\u043e\u0442 \u0430\u0440\u0445\u0438\u0432\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0431\u044b\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e \u043e\u0431\u043e\u0439\u0434\u0435\u043d \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u0415\u0441\u043b\u0438 \u043a\u0440\u0430\u0442\u043a\u043e, \u0442\u043e \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u043c\u044b \u00ab\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0438 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0430\u043d\u0438\u043c\u0438\u0440\u0443\u0435\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435\u00bb \u2014 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435\u043c\u0443 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u0446\u0435\u043d\u044b. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e \u0447\u0442\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043b\u044e\u0431\u044b\u043c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c \u043c\u043e\u0434\u0443\u043b\u044f\u043c \u043a\u043e \u0432\u0441\u0435\u043c \u0432\u0430\u0436\u043d\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0438, \u0447\u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u0432\u043e \u0432\u0441\u0435\u043c \u044d\u0442\u043e\u043c \u2014 \u043c\u043e\u0436\u0435\u043c \u00ab\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c\u00bb \u0440\u0430\u0434\u0438 \u043b\u0443\u0447\u0448\u0435\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0435\u043c\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443. \u041d\u0430 js \u0432 \u0448\u0443\u0442\u0435\u0440\u0435 \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u043e\u0442 \u0442\u0430\u043a, \u0432 \u00ab\u0441\u0446\u0435\u043d\u0435\u00bb Scene.vue:<\/p>\n<pre><code class=\"javascript\">\/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u201c\u043c\u0438\u0440\u0430\u201d (\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0439\u0448\u0438\u0439 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438-\u043e\u0431\u044a\u0435\u043a\u0442\u044b) this.world = new World(); this.world.init(this);<\/code><\/pre>\n<p>\u0413\u0434\u0435 <code>World<\/code> \u0438 \u043b\u044e\u0431\u044b\u0435 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u0435\u0442 \u0438 \u0430\u043d\u0438\u043c\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435:<\/p>\n<pre><code class=\"javascript\">function Module() {   this.init = (     scope,     texture1,     material1,     \/\/ ...   ) => {};     this.animate = (scope) => {}; }  export default Module;<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041d\u0430 ts, \u0432 \u0421\u0446\u0435\u043d\u0435:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">&lt;template>   &lt;div id=\"scene\" class=\"scene\" :class=\"isSelection &amp;&amp; 'scene--selection'\" \/> &lt;\/template>  &lt;script lang=\"ts\"> \/\/ ...  \/\/ Types import type { ISelf } from '@\/models\/modules'; \/\/ ...  export default defineComponent({   name: 'Scene',    setup() {     const store = useStore(key);      \/\/ Core      let container: HTMLElement;      let camera: PerspectiveCamera = new THREE.PerspectiveCamera();     let listener: AudioListener = new THREE.AudioListener();      let scene: Scene = new THREE.Scene();      let renderer: WebGLRenderer = new THREE.WebGLRenderer({       antialias: true,     });      \/\/ Helpers     let helper: Helper = new Helper();     let assets: Assets = new Assets();     let events: Events = new Events();     let audio: AudioBus = new AudioBus();      \/\/ Modules     let world = new World();     \/\/ Functions     let init: () => void;     let animate: () => void;     let render: () => void;      \/\/ Store getters     const isPause = computed(() => store.getters['layout\/isPause']);     \/\/ ..          \/\/ ...      \/\/ Go!     init = () => {       \/\/ Core       container = document.getElementById('scene') as HTMLElement;        \/\/ ...        \/\/ Modules       \/\/ ...       world.init(self);        \/\/ First render       \/\/ ...       render();     };      \/\/ ...      animate = () => {       if (!isPause.value) {         world.animate(self);          render();       }        \/\/ ...        requestAnimationFrame(animate);     };       render = () => {       renderer.render(scene, camera);       \/\/ console.log('Renderer info: ', renderer.info.memory.geometries, renderer.info.memory.textures, renderer.info.render);        \/\/ ...     };      \/\/ This is self )     let self: ISelf = {       \/\/ Utils       helper,       assets,       events,       audio,        \/\/ Core       store,       scene,       listener,       render,     };      \/\/ ...      onMounted(() => {       init();       animate();        \/\/ audio.toggle(isPause.value);     });      \/\/ ...   }, }); &lt;\/script><\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>TS \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u00ab\u043f\u0440\u044f\u043c\u043e \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0435 \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u044b\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b\u00bb, \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u044f\u0432\u043d\u043e \u0438 \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432\u044b\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441. \u0412\u043e\u0442 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u0438\u043c \u00ab\u043f\u0443\u0442\u044c \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u00bb \u043e\u0442 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438, \u043a \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>\u0412 @\/src\/models\/modules.ts:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ Interfaces \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/  \/\/ \u0421\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0431\u0435\u0437 \u043a\u043e\u043f\u0438\u0439 - \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0410\u0442\u043c\u043e\u0441\u0444\u0435\u0440\u0430 export interface ISimpleModule {  init(self: ISelf): void; }  \/\/ \u041c\u043e\u0434\u0443\u043b\u0438 interface IModule extends ISimpleModule {  isCanAdd(self: ISelf, vector: Vector3, name?: Names): boolean;  add(self: ISelf, vector: Vector3, name?: Names): void;  remove(self: ISelf, items: string[], name?: Names): void; }  \/\/ A\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 interface IAnimatedModule extends IModule {  animate(self: ISelf): void; }  \/\/ \u041c\u043e\u0434\u0443\u043b\u0438 \u0441 \u043a\u043e\u043f\u0438\u044f\u043c\u0438 interface IModules extends IModule {  initItem(self: ISelf, item: TObject, isStart: boolean): void; }  \/\/ \u0410\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0441 \u043a\u043e\u043f\u0438\u044f\u043c\u0438 interface IAnimatedModules extends IAnimatedModule {  initItem(self: ISelf, item: TObject, isStart: boolean): void; }  \/\/ Abstract \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/  \/\/ \u0421\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0431\u0435\u0437 \u043a\u043e\u043f\u0438\u0439 - \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0410\u0442\u043c\u043e\u0441\u0444\u0435\u0440\u0430 export abstract class SimpleModule implements ISimpleModule {  constructor(public name: Names) {    this.name = name;  }   \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f  public abstract init(self: ISelf): void; }  \/\/ \u041e\u0431\u0435\u0440\u0442\u043a\u0438 \u0438 \u043c\u043e\u0434\u0443\u043b\u0438 abstract class Module extends SimpleModule implements IModule {  constructor(public name: Names) {    super(name);  }   \/\/ \u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442?  public abstract isCanAdd(self: ISelf, vector: Vector3, name?: Names): boolean;   \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0435\u0434\u0438\u043d\u0438\u0446\u0443  public abstract add(self: ISelf, vector: Vector3, name?: Names): void;   \/\/ \u0423\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b  public abstract remove(self: ISelf, items: string[], name?: Names): void; }  \/\/ \u0410\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c export abstract class AnimatedModule extends Module implements IAnimatedModule {  constructor(public name: Names) {    super(name);  }   \/\/ \u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f  public abstract animate(self: ISelf): void; }  \/\/  \u041c\u043e\u0434\u0443\u043b\u0438 abstract class Modules extends Module implements IModules {  constructor(public name: Names) {    super(name);  }   \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0435\u0434\u0438\u043d\u0438\u0446\u0443  public abstract initItem(self: ISelf, item: TObject, isStart: boolean): void; }  \/\/ \u0410\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 abstract class AnimatedModules extends Modules implements IAnimatedModules {  constructor(public name: Names) {    super(name);  }   \/\/ \u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f  public abstract animate(self: ISelf): void; }  \/\/ Real \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/  \/\/ \u041e\u0431\u0435\u0440\u0442\u043a\u0438 export class Wrapper extends AnimatedModule implements IAnimatedModule {  constructor(public name: Names) {    super(name);  }   public init(self: ISelf): void {    console.log('modules.ts', 'Wrapper', 'init ', this.name, self);  }   \/\/ \u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442?  public isCanAdd(self: ISelf, vector: Vector3, name?: Names): boolean {    console.log('modules.ts', 'Wrapper', 'isCanAdd ', vector, name);    return false;  }   \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442  public add(self: ISelf, vector: Vector3, name?: Names): void {    console.log('modules.ts', 'Wrapper', 'add ', vector, name);  }   \/\/ \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b  public remove(self: ISelf, items: string[], name?: Names): void {    console.log('modules.ts', 'Wrapper', 'remove ', items, name);  }   public animate(self: ISelf): void {    console.log('modules.ts', 'Wrapper', 'animate ', this.name, self);  } }  \/\/ \u0421\u0442\u0440\u043e\u0435\u043d\u0438\u044f export class Builds extends Modules implements IModules {  constructor(public name: Names) {    super(name);  }   public init(self: ISelf): void {    console.log('modules.ts', 'Builds', 'init ', this.name, self);  }   public initItem(self: ISelf, item: TObject, isStart: boolean): void {    console.log(      'modules.ts',      'Builds',      'initItem ',      this.name,      self,      item,      isStart,    );  }   \/\/ \u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442?  public isCanAdd(self: ISelf, vector: Vector3): boolean {    return self.helper.isCanAddItemHelper(self, vector, this.name);  }   \/\/ \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b  public remove(self: ISelf, items: string[]): void {    self.helper.sellHelper(self, items, this.name);  }   \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442  public add(self: ISelf, vector: Vector3): void {    self.helper.addItemHelper(self, this, vector);  } }<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u0421\u0442\u0440\u043e\u0435\u043d\u0438\u0439 \u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0434\u0432\u0430 \u0435\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f \u2014 \u043a\u043e\u0433\u0434\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0443\u044e \u0433\u0435\u043e\u043c\u0435\u0442\u0440\u0438\u044e \u0438 \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u043e\u0434\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c:<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0431\u0435\u0437 \u043c\u043e\u0434\u0435\u043b\u0435\u0439:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">export class StaticSimpleBuilds extends Builds {  public geometry!: BoxBufferGeometry;  public material!: MeshStandardMaterial;   constructor(public name: Names) {    super(name);  }   \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430  public initItem(self: ISelf, item: TObject, isStart: boolean): void {    self.helper.initItemHelper(      self,      this.name,      this.geometry,      this.material,      item,      isStart,    );  }   public init(self: ISelf): void {    \/\/ \u0424\u043e\u0440\u043c\u0430    this.geometry = getGeometryByName(this.name);     \/\/ \u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b    this.material = new THREE.MeshStandardMaterial({      color: Colors[this.name as keyof typeof Colors],      map: self.assets.getTexture(this.name), \/\/ \u0422\u0435\u043a\u0441\u0442\u0443\u0440\u0430    });     \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f    self.helper.initModulesHelper(self, this);  } } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u0421\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f c \u043c\u043e\u0434\u0435\u043b\u044c\u044e:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">export class StaticModelsBuilds extends Builds {  public model!: GLTF;   constructor(public name: Names) {    super(name);  }   \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430  public initItem(self: ISelf, item: TObject, isStart: boolean): void {    self.helper.initItemFromModelHelper(      self,      this.name,      this.model,      item,      isStart,    );  }   public init(self: ISelf): void {    \/\/ \u041c\u043e\u0434\u0435\u043b\u044c    self.assets.GLTFLoader.load(      `.\/images\/models\/${this.name}.glb`,      (model: GLTF) => {        \/\/ \u041f\u0440\u0435\u043b\u043e\u0430\u0434\u0435\u0440        self.helper.loaderDispatchHelper(self.store, `${this.name}IsLoaded`);        this.model = self.helper.traverseHelper(self, model, this.name);         \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f        self.helper.initModulesHelper(self, this);        self.render();      },    );  } } <\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435 \u0432\u0441\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u043e\u0431\u0441\u0447\u0435\u0442\u044b-\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438 \u0434\u0430\u0436\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u043f\u0443\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0435\u043d\u044b \u0432 \u043a\u043b\u0430\u0441\u0441\u043e\u0432\u043e\u043c \u043c\u043e\u0434\u0443\u043b\u0435-\u043f\u043e\u043c\u043e\u0449\u043d\u0438\u043a\u0435 <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/utils\/helper.ts\" rel=\"noopener noreferrer nofollow\"><u>Helper<\/u><\/a> (\u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0441\u0442\u0438 \u0440\u0430\u0434\u0438 \u2014 \u043a\u0440\u043e\u043c\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u043e\u0439-\u0430\u0442\u043e\u043c\u0430\u0440\u043d\u043e\u0439 <code>getGeometryByName<\/code> \u0438\u0437 <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/utils\/utilities.ts\" rel=\"noopener noreferrer nofollow\"><u>\u043d\u0430\u0431\u043e\u0440\u0430 \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0445 \u0443\u0442\u0438\u043b\u0438\u0442<\/u><\/a>). \u041f\u0440\u043e\u0431\u0440\u043e\u0441 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u043c \u0438\u0437 \u043b\u044e\u0431\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430 \u043b\u043e\u0433\u0438\u043a\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u0441\u0430\u043c\u043e\u0439 \u0441\u0446\u0435\u043d\u043e\u0439 (\u043a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u043d\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 Three), \u0441 \u043c\u043e\u0434\u0443\u043b\u044f\u043c\u0438 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0446\u0430 \u0438\u043b\u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u043e\u0432-\u0430\u0441\u0441\u0435\u0442\u043e\u0432, \u0448\u0438\u043d\u043e\u0439 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438 \u0430\u0443\u0434\u0438\u043e\u0448\u0438\u043d\u043e\u0439.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u043c\u0435\u0442\u044c \u0434\u0432\u0435 \u00ab\u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u044e\u0449\u0438\u0435 \u043e\u0431\u0435\u0440\u0442\u043a\u0438\u00bb \u2014 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0430\u043c <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/components\/Scene\/World.ts\" rel=\"noopener noreferrer nofollow\"><u>World<\/u><\/a>, \u0435\u0433\u043e \u00ab\u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439\u00bb \u0442\u0438\u043f <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/components\/Scene\/Wolrd\/Builds.ts\" rel=\"noopener noreferrer nofollow\"><u>Build<\/u><\/a>, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0432\u0441\u0435 \u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f. \u0410 <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/tree\/master\/src\/components\/Scene\/Wolrd\/Builds\" rel=\"noopener noreferrer nofollow\"><u>\u0432\u0441\u0435 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u043d\u0438\u0437\u043e\u0432\u044b\u0435 \u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f<\/u><\/a> \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u043e\u0442 \u0442\u0430\u043a\u0438\u043c\u0438 \u0432\u043e\u0442 \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u043a\u043b\u0430\u0441\u0441\u0430\u043c\u0438:<\/p>\n<pre><code class=\"typescript\">\/\/ Constants import { Names } from '@\/utils\/constants';  \/\/ Modules import { ModuleType } from '@\/models\/modules';  export default class ModuleName extends ModuleType {  constructor() {    super(Names.modulename);  } } <\/code><\/pre>\n<p>\u041e\u0433\u043e! \u0412\u043e\u0442 \u0432 \u044d\u0442\u043e\u043c \u043c\u0435\u0441\u0442\u0435 \u043c\u044b \u0432\u044b\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0434\u0438\u043a\u0430\u043b\u044c\u043d\u043e \u0436\u0438\u0440\u043d\u044e\u0447\u0438\u0439 \u043f\u043b\u044e\u0441 \u0442\u0430\u0439\u043f\u0441\u043a\u0440\u0438\u043f\u0442\u0443! \u0412\u0435\u0434\u044c \u0435\u0441\u043b\u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u043b\u0430\u043f\u0448\u0435\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0439 \u0445\u0430\u043e\u0442\u0438\u0447\u043d\u044b\u0439 \u043a\u043e\u0434 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0432 \u043f\u0435\u0440\u0432\u043e\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0435 (<a href=\"https:\/\/github.com\/ushliypakostnik\/robot-game\/blob\/master\/src\/components\/Three\/Scene\/Enemies.js\" rel=\"noopener noreferrer nofollow\">\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440<\/a>) \u2014 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0440\u0430\u0436\u0430\u0435\u0442.)<\/p>\n<p><strong>\u0421\u0435\u0442\u043a\u0430<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/f89\/f71\/3e1\/f89f713e13af0b5dbd2f33cc5ec3781f.jpg\" alt=\"\u0418\u0433\u0440\u043e\u0432\u043e\u0439 \u0441\u0442\u043e\u043b\" title=\"\u0418\u0433\u0440\u043e\u0432\u043e\u0439 \u0441\u0442\u043e\u043b\" width=\"1600\" height=\"1093\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f89\/f71\/3e1\/f89f713e13af0b5dbd2f33cc5ec3781f.jpg\" data-blurred=\"true\"\/><figcaption>\u0418\u0433\u0440\u043e\u0432\u043e\u0439 \u0441\u0442\u043e\u043b<\/figcaption><\/figure>\n<p>\u0412 \u0448\u0443\u0442\u0435\u0440\u0435 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0441\u043d\u043e\u0432\u044b \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0433\u043e \u043c\u0438\u0440\u0430 \u2014 \u043f\u043e\u043b\u0430 \u0438 \u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0439, \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043c\u0435\u0441\u0442 \u0437\u0430\u0440\u0435\u0437\u0435\u0440\u0432\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043c\u0435\u043b\u043a\u0438\u0445 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b glb-\u043c\u043e\u0434\u0435\u043b\u044c \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e \u043c\u0438\u0440\u0430 \u2014 \u0442\u0435\u043a\u0443\u0449\u0438\u043c \u0443\u0440\u043e\u0432\u043d\u0435\u043c-\u043b\u043e\u043a\u0430\u0446\u0438\u0435\u0439. \u0417\u0434\u0435\u0441\u044c \u0436\u0435 \u0441\u0430\u043c\u043e \u0441\u043e\u0431\u043e\u0439 \u043d\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u00ab\u0441\u0435\u0442\u043a\u0438\u00bb, \u00ab\u0434\u043e\u0441\u043a\u0438\u00bb \u2014 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0439.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/f21\/a8e\/5de\/f21a8e5dec0f736589e560178524942b.jpg\" width=\"1600\" height=\"1093\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f21\/a8e\/5de\/f21a8e5dec0f736589e560178524942b.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<p><strong>\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435<\/strong><\/p>\n<p>\u041f\u043e\u043d\u044f\u0442\u043d\u043e \u0447\u0442\u043e \u043d\u0430 \u043d\u0443\u0436\u043d\u043e \u0443\u043c\u0435\u0442\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0432\u0435 \u0432\u0435\u0449\u0438 \u2014 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0438\u0440\u0430 \u0438 \u0438\u0433\u0440\u044b \u2014 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435-\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430, \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 \u0438 \u0432\u0441\u0435\u0445 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0438 \u0436\u0435\u043b\u0430\u043d\u0438\u0438. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u044d\u0442\u043e \u0447\u0430\u0441\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438 \u0432 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u0432\u0435\u0431-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430\u0445 \u0438 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u043e\u0432\u0441\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0435\u0433\u043e \u00ab\u043f\u0435\u0440\u0441\u0438\u0441\u0442\u043e\u0440\u0430\u00bb.\u00a0 \u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u043a \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0443 \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0435\u043c\u0443 \u0447\u0430\u0441\u0442\u0438 <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/store\/index.ts#L45\" rel=\"noopener noreferrer nofollow\"><u>\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0445\u043e\u0442\u0438\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c<\/u><\/a>.<\/p>\n<p>\u042f \u0432\u044b\u0434\u0435\u043b\u0438\u043b \u0434\u0432\u0430 \u043c\u043e\u0434\u0443\u043b\u044f \u2014 <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/store\/modules\/layout.ts\" rel=\"noopener noreferrer nofollow\"><u>\u00ab\u043b\u0435\u0439\u0430\u0443\u0442\u00bb<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0433\u0435\u0439\u043c\u043b\u0435\u044f \u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f (\u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u043b \u2014 \u0444\u043b\u0430\u0433\u0430 <code>isDesignPanel<\/code> \u0432 \u043d\u0435\u043c \u0431\u044b\u0442\u044c \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u2014 \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0439 \u043f\u0430\u043d\u0435\u043b\u044c\u044e \u043a\u043e\u043d\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u2014 \u043f\u0430\u043d\u0435\u043b\u044c \u00ab\u0437\u0430\u043b\u0438\u043f\u043d\u0435\u0442\u00bb \u043f\u043e\u043a\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043d\u043e\u0432\u0430 \u043d\u0430\u0436\u0430\u0442 \u0442\u0430\u0431), \u0438 <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/store\/modules\/objects.ts\" rel=\"noopener noreferrer nofollow\"><u>\u00ab\u043e\u0431\u044a\u0435\u043a\u0442\u044b\u00bb<\/u><\/a> \u2014 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0441\u0435\u0442\u043a\u0435 \u0438 \u043b\u044e\u0431\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u0445.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/5e1\/9f5\/0bd\/5e19f50bd583fa1d3ef5facded587da6.png\" width=\"1121\" height=\"669\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5e1\/9f5\/0bd\/5e19f50bd583fa1d3ef5facded587da6.png\"\/><figcaption><\/figcaption><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/fb8\/918\/dd6\/fb8918dd68b41add4adc01c0ca04c2fc.png\" width=\"768\" height=\"408\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/fb8\/918\/dd6\/fb8918dd68b41add4adc01c0ca04c2fc.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0441\u0435\u0442\u043a\u0438 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u0430\u0436\u043d\u044b\u0439 \u0444\u043b\u0430\u0433 <code>isStart<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u0435\u043d \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c \u0441\u0442\u0430\u0440\u0442\u043e\u0432\u044b\u0439 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0438\u0433\u0440\u044b. \u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u043c\u043e\u0434\u0443\u043b\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0435\u043c \u00ab\u0437\u0430 \u043e\u0431\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0438 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435\u00bb <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/components\/Scene\/Wolrd\/Atmosphere\/Atmosphere.ts\" rel=\"noopener noreferrer nofollow\">Atmosphere.ts<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0430\u043d\u0434\u043e\u043c\u043d\u043e \u0433\u0435\u043d\u0435\u0440\u0438\u0442 \u0433\u043e\u0440\u044b \u0438\u0437 \u0441\u0442\u043e\u043b\u0431\u0438\u043a\u043e\u0432 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u00ab\u0441 \u0447\u0438\u0441\u0442\u043e\u0433\u043e \u043b\u0438\u0441\u0442\u0430\u00bb \u0438\u043b\u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0438\u0445 \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432\u043e \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445:<\/p>\n<details class=\"spoiler\">\n<summary>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u0433\u043e\u0440 \u0437\u0430\u043d\u043e\u0432\u043e \u0438\u043b\u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ ...  this._positions = []; if (self.store.getters['objects\/isStart']) {  this._objects = [];   \/\/ \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u043c \u0433\u043e\u0440\u044b \u0437\u0430\u043d\u043e\u0432\u043e  for (let n = 0; n &lt; DESIGN.ATMOSPHERE_ELEMENTS[Names.stones]; ++n) {    this._meshes = new THREE.Group();     this._position = getUniqueRandomPosition(      this._positions,      0,      0,      10,      DESIGN.SIZE \/ DESIGN.CELL \/ 12.5,      false,    );    this._positions.push(this._position);     \/\/ ...     this._objects.push({      name: Names.stones,      id: '',      data: this._object,    });     self.scene.add(this._meshes);  }   \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435  self.store.dispatch('objects\/saveObjects', {    name: Names.stones,    objects: this._objects,  }); } else {  \/\/ \u0412\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0433\u043e\u0440\u044b \u0438\u0437 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430  this._objects = [...self.store.getters['objects\/objects'][Names.stones]];   this._objects.forEach((group) => {    this._meshes = new THREE.Group();     group.data.forEach((stone: TStone) => {      this._position = { x: stone.x, z: stone.z };      this._height = stone.h;       self.helper.geometry = new THREE.BoxBufferGeometry(        DESIGN.CELL,        DESIGN.CELL * this._height,        DESIGN.CELL,      );       this._mesh = new THREE.Mesh(        self.helper.geometry,        self.helper.material,      );      this._mesh.position.set(        this._position.x * DESIGN.CELL,        OBJECTS.sand.positionY,        this._position.z * DESIGN.CELL,      );      this._mesh.name = Names.stones;       this._meshes.add(this._mesh);    });    self.scene.add(this._meshes);  }); }  \/\/ ...<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443 \u00ab\u041d\u0430\u0447\u0430\u0442\u044c \u0441\u043d\u0430\u0447\u0430\u043b\u0430\u00bb \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u041f\u0430\u0443\u0437\u044b (\u043f\u043e Esc \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043d\u0435 PointerLockControls \u2014 \u0441\u043c. \u0441\u0442\u0430\u0442\u044c\u044e \u043e \u0448\u0443\u0442\u0435\u0440\u0435) \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u0442 \u0442\u0430\u043a\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430 \u043e\u0431\u0435\u0449\u0430\u043d\u0438\u0439 \u0441 <code>window.location.reload(true);<\/code> \u0432 \u0441\u0430\u043c\u043e\u043c \u043a\u043e\u043d\u0446\u0435. \u041f\u043e\u043d\u044f\u0442\u043d\u043e \u0447\u0442\u043e \u043e\u043d\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0431\u0440\u043e\u0441 \u0432\u0441\u0435\u0445 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449 \u043a\u0440\u043e\u043c\u0435 \u043c\u043e\u0434\u0443\u043b\u044f <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/store\/modules\/preloader.ts\" rel=\"noopener noreferrer nofollow\">\u043f\u0440\u0435\u043b\u043e\u0430\u0434\u0435\u0440\u0430<\/a> \u043d\u0430 \u0434\u0435\u0444\u043e\u043b\u0442:<\/p>\n<pre><code class=\"swift\">\/\/ \u041f\u043e\u043c\u043e\u0449\u043d\u0438\u043a \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 export const restartDispatchHelper = (store: Store&lt;State>): void => {   store     .dispatch('layout\/setField', {       field: 'isReload',       value: true,     })     .then(() => {       store         .dispatch('game\/reload')         .then(() => {           store             .dispatch('objects\/reload')             .then(() => {               store                 .dispatch('layout\/reload')                 .then(() => {                   \/\/ eslint-disable-next-line @typescript-eslint\/ban-ts-comment                   \/\/ @ts-ignore                   window.location.reload(true);                 })                 .catch((error) => {                   console.log(error);                 });             })             .catch((error) => {               console.log(error);             });         })         .catch((error) => {           console.log(error);         });     })     .catch((error) => {       console.log(error);     }); };<\/code><\/pre>\n<p><strong>\u0412\u044b\u0432\u043e\u0434<\/strong><\/p>\n<p>\u042f \u043f\u043e\u043b\u0443\u0447\u0438\u043b \u043c\u0430\u0441\u0441\u0443 \u0443\u0434\u043e\u0432\u043e\u043b\u044c\u0441\u0442\u0432\u0438\u044f \u043e\u0442 \u044d\u0442\u043e\u0439 \u043f\u043e\u043f\u044b\u0442\u043a\u0438. \u0421 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u043a\u043e\u0433\u0434\u0430 \u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043b \u0447\u0442\u043e \u043c\u043d\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0434\u0430\u043b\u044c\u0448\u0435 \u00ab\u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0442\u0430\u043d\u0447\u0438\u043a\u0438 \u0435\u0437\u0434\u0438\u0442\u044c \u0438 \u0441\u0442\u0440\u0435\u043b\u044f\u0442\u044c, \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c\u00bb, \u00ab\u0434\u044b\u043c\u0438\u0442\u0441\u044f \u0438 \u0432\u0437\u0440\u044b\u0432\u0430\u0442\u044c\u0441\u044f\u00bb \u2014 \u043f\u0440\u0438\u0443\u043d\u044b\u043b \u0438 \u00ab\u0437\u0430\u0441\u0443\u0448\u0438\u043b \u0432\u0435\u0441\u043b\u0430\u00bb, \u00ab\u043f\u043e\u0434\u043d\u044f\u043b \u043b\u0430\u043f\u043a\u0438\u00bb. \u041e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0443\u0436\u0435 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u0438 \u043e\u043d\u0438 \u043d\u0435 \u0434\u0432\u0438\u0433\u0430\u044e\u0442\u0441\u044f. \u041d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c FPS \u0443\u0436\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u043a\u0430\u0442\u0430\u0441\u0442\u0440\u043e\u0444\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0441\u0435\u0434\u0430\u0435\u0442 \u0432\u043f\u043b\u043e\u0442\u044c \u00ab\u0434\u043e \u0432\u0438\u0434\u0438\u043c\u043e\u0433\u043e \u0437\u0430\u0432\u0438\u0441\u0430\u043d\u0438\u044f\u00bb \u043f\u0440\u0438 \u00ab\u0433\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u043c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0438\u00bb. \u0418\u043b\u0438 \u043a\u043e\u0433\u0434\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043c\u0438\u043a\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e PositionalAudio \u2014 \u0441\u043b\u044b\u0448\u0435\u043d \u043d\u0435\u043f\u0440\u0438\u044f\u0442\u043d\u044b\u0439 \u0442\u0440\u0435\u0441\u043a \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0430\u0443\u043d\u0434\u0442\u0440\u0435\u043a\u0430. \u041d\u043e, \u0431\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e \u2014 Three.js \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0433\u043b\u043e\u0442\u043a\u043e\u043c \u0441\u0432\u0435\u0436\u0435\u0433\u043e \u0432\u043e\u0437\u0434\u0443\u0445\u0430 \u0432 \u0443\u043d\u044b\u043b\u043e\u0439 \u0440\u0443\u0442\u0438\u043d\u0435 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e-\u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430, \u0434\u0430\u0435\u0442 \u0431\u0435\u0437\u0431\u0440\u0435\u0436\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u0443\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0442\u0432\u043e\u0440\u0447\u0435\u0441\u0442\u0432\u0430. \u0414\u0435\u0440\u0437\u0430\u0439\u0442\u0435!<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/707518\/\"> https:\/\/habr.com\/ru\/post\/707518\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption>\u041e\u043b\u0434\u044b \u0437\u0434\u0435\u0441\u044c? )<\/figcaption><\/figure>\n<p>\u0421\u0430\u043c\u043e\u0439 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u043c\u043e\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435\u0439 \u0434\u043b\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u0430 \u0431\u044b\u043b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 \u043e\u0442\u0447\u0435\u0442 <a href=\"https:\/\/habr.com\/ru\/post\/556238\/\" rel=\"noopener noreferrer nofollow\"><u>\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e FPS<\/u><\/a>. \u0421\u0443\u0434\u044f \u043f\u043e \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u2014 \u043d\u0435\u043e\u0436\u0438\u0434\u0430\u043d\u043d\u043e \u043e\u0433\u0440\u043e\u043c\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043b\u044e\u0434\u0435\u0439 \u0437\u0430\u0448\u043b\u043e \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b\u043e \u0441\u044b\u0433\u0440\u0430\u0442\u044c, \u044f \u043f\u043e\u043b\u0443\u0447\u0430\u043b \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432\u043e\u043f\u0440\u043e\u0441\u044b \u0432 \u043b\u0438\u0447\u043a\u0443 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0412 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u0435\u0449\u0435 \u043e\u0434\u043d\u0443 \u043f\u043e\u043f\u044b\u0442\u043a\u0443 \u043a\u0440\u0430\u0444\u0442\u043e\u0432\u043e\u0433\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0433\u043e \u0433\u0435\u0439\u043c\u0434\u0435\u0432\u0430 \u043d\u0430 javascript \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0432 \u0434\u0443\u0445\u0435 \u043a\u0443\u043b\u044c\u0442\u043e\u0432\u043e\u0439 Dune \u0438\u0437 \u0434\u0435\u0442\u0441\u0442\u0432\u0430. \u0412 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442 \u044f \u0443\u043f\u0435\u0440\u0441\u044f \u0432 \u043d\u0438\u0437\u043a\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0432\u0448\u0435\u0439\u0441\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0437\u0430\u0441\u043a\u0443\u0447\u0430\u043b, \u0443\u0436\u0435 \u043f\u043e\u0447\u0442\u0438 \u0433\u043e\u0434 \u043a\u0430\u043a \u0437\u0430\u0431\u0440\u043e\u0441\u0438\u043b \u044d\u0442\u043e \u0434\u0435\u043b\u043e. \u041d\u043e \u0443 \u043c\u0435\u043d\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b, \u0441\u0435\u0439\u0447\u0430\u0441 \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0438 \u0434\u0435\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u0442\u0440\u043e\u0439\u043a\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u0445\u043e\u0447\u0443, \u043f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e, \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443 \u0434\u043b\u044f \u0441\u0435\u0431\u044f, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0432 \u0438 \u043e \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0442\u0435\u0435 \u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043b\u044f \u043a\u043e\u0433\u043e-\u0442\u043e \u043e\u043a\u0430\u0436\u0443\u0442\u0441\u044f \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c\u0438 \u043c\u043e\u0438 \u0443\u0441\u0438\u043b\u0438\u044f. \u0421\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u043e\u0431\u044a\u0435\u043c\u043d\u043e\u0439, \u0434\u043e\u0442\u043e\u0448\u043d\u043e\u0439 \u0438 \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u043e\u0439 \u043a\u0430\u043a \u043f\u0435\u0440\u0432\u0430\u044f \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u0448\u0443\u0442\u0435\u0440\u0430, \u0437\u0430\u0442\u043e \u0441\u0430\u043c \u043a\u043e\u0434 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u0442\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0431\u043e\u043b\u0435\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u0435\u043a \u0438\u0437 Vue3 \u0438 TypeScript. \u0412\u043e \u043c\u043d\u043e\u0433\u043e, \u044d\u0442\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0435\u0442 \u0438\u0434\u0435\u0438 \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u043f\u0435\u0440\u0432\u043e\u0439, \u0441 \u0442\u0435\u043c \u043e\u0442\u043b\u0438\u0447\u0438\u0435\u043c, \u0447\u0442\u043e \u043c\u044b \u043f\u0438\u043b\u0438\u043c \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u044e, \u0430 \u043d\u0435 \u0448\u0443\u0442\u0435\u0440 \u043e\u0442 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043b\u0438\u0446\u0430. \u042f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c \u0442\u043e \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0443\u0436\u0435 \u043f\u0440\u043e\u0439\u0434\u0435\u043d\u043e \u0438 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u043e \u0432 \u043f\u0435\u0440\u0432\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0431\u0435\u0433\u043b\u043e \u043f\u043e\u043a\u0430\u0436\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u00ab\u043d\u043e\u0432\u044b\u0435 \u0444\u0438\u0447\u0438\u00bb.<\/p>\n<p><a href=\"https:\/\/dune-three.vercel.app\/\" rel=\"noopener noreferrer nofollow\"><u>\u0414\u0435\u043c\u043e-\u0441\u0442\u0435\u043d\u0434<\/u><\/a>.<\/p>\n<p><a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\" rel=\"noopener noreferrer nofollow\"><u>\u0420\u0435\u043f\u043e<\/u><\/a>.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0441\u0442\u0430\u0442\u044c\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0430, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u043a\u0430\u043a \u00ab\u043a\u0440\u0430\u0442\u043a\u0430\u044f \u043e\u0431\u0437\u043e\u0440\u043d\u0430\u044f \u044d\u043a\u0441\u043a\u0443\u0440\u0441\u0438\u044f\u00bb \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u0432\u0430\u0436\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u0430\u043c, \u043c\u043e\u0434\u0443\u043b\u044f\u043c \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<p><strong>\u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f<\/strong><\/p>\n<p>\u041c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u043a\u043e\u0434 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0432 \u0441\u0432\u043e\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0432 \u043e\u0431\u0449\u0435\u043c \u0438 \u0446\u0435\u043b\u043e\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442 \u043b\u044e\u0431\u043e\u0439 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043d\u0430 \u0441\u0445\u043e\u0436\u0438\u0445 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u0445. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u00ab\u0441\u0430\u043c\u044b\u043c \u043f\u0435\u0440\u0432\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c\u00bb \u0432\u0441\u0435 \u0442\u0430\u043a\u0436\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0444\u0430\u0439\u043b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u043c\u0443 \u043a\u043e\u0434\u0443 \u0441\u043f\u0438\u0441\u043a\u0438 \u0432\u0441\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0438\u043c\u0435\u043d \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u0446\u0432\u0435\u0442\u043e\u0432-\u0442\u0435\u043a\u0441\u0442\u0443\u0440, \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0433\u0435\u0439\u043c\u043f\u043b\u0435\u044f, \u043f\u0435\u0440\u0435\u0432\u043e\u0434\u044b \u0442\u0435\u043a\u0441\u0442\u043e\u0432: <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/utils\/constants.ts\" rel=\"noopener noreferrer nofollow\"><u>@\/src\/utils\/constants.ts<\/u><\/a><\/p>\n<p><strong>\u041a\u043e\u043d\u0442\u0440\u043e\u043b<\/strong><\/p>\n<figure class=\"full-width\"><figcaption>\u041f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c<\/figcaption><\/figure>\n<p>\u0422\u043e \u0447\u0442\u043e, \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0432\u043f\u043e\u043b\u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043a\u043e\u043c\u0443-\u0442\u043e \u00ab\u043f\u043e\u0434\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c\u00bb \u2014 \u044d\u0442\u043e \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 <a href=\"https:\/\/threejs.org\/examples\/?q=control#misc_controls_map\" rel=\"noopener noreferrer nofollow\"><u>MapControl<\/u><\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u0435\u0442 \u00ab\u0432\u044b\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c\u00bb \u043f\u043e\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u0436\u0430\u0442\u043e\u0439 \u043a\u043b\u0430\u0432\u0438\u0448\u0435 Tab, \u0430 \u043f\u0440\u0438 \u0437\u0430\u0436\u0430\u0442\u043e\u043c Space \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u0432 \u00ab\u0433\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u0439 \u0432\u044b\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c\u00bb. \u0412\u0441\u0435 \u044d\u0442\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u0421\u0446\u0435\u043d\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u00ab\u0432\u0441\u0435\u0433\u043e \u043e\u0434\u0438\u043d \u0434\u0438\u0432\u00bb \u2014 \u0434\u043b\u044f Three, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0430 \u0438\u0433\u0440\u044b.\u00a0 <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/components\/Scene\/Scene.vue\" rel=\"noopener noreferrer nofollow\"><u>@\/src\/components\/Scene\/Scene.vue<\/u><\/a>.<\/p>\n<figure class=\"full-width\"><figcaption>\u0412\u044b\u0434\u0435\u043b\u0438\u0442\u044c<\/figcaption><\/figure>\n<p><strong>\u041c\u043e\u0434\u0443\u043b\u0438<\/strong><\/p>\n<p>\u0414\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0430 \u0431\u0430\u0437\u044b \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 [\u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 \u0448\u0443\u0442\u0435\u0440\u0430] \u043d\u0430\u043c\u043d\u043e\u0433\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0432\u044b\u0431\u043e\u0440 \u0442\u0438\u043f\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u0437\u0434\u0435\u0441\u044c \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0438\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b. \u0418 \u00ab\u0441\u0430\u043c\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c\u00bb \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <a href=\"https:\/\/github.com\/ushliypakostnik\/dune-three\/blob\/master\/src\/models\/modules.ts\" rel=\"noopener noreferrer nofollow\">\u0444\u0430\u0439\u043b<\/a> \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u0438\u0433\u0440\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0438 \u043c\u043e\u0434\u0443\u043b\u0435\u0439. \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043e\u043d \u0441 \u0441\u0430\u043c\u043e\u0439 \u0441\u0430\u043a\u0440\u0430\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0449\u0438 \u0432\u043e \u0432\u0441\u0435\u0439 \u043a\u0443\u0445\u043d\u0435 \u2014 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u00ab\u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430\u00bb \u2014 \u043e\u0431\u0449\u0435\u0433\u043e \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439-\u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435.<\/p>\n<pre><code class=\"typescript\">\/\/ \u0412 @\/src\/models\/modules.ts: \/\/ Main object export interface ISelf {  \/\/ Utils  helper: Helper; \/\/ \"\u043d\u0430\u0448\u0435 \u0432\u0441\u0435\" - \u043d\u0430\u0431\u043e\u0440 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443, \u043e\u0431\u0441\u0447\u0435\u0442\u044b \u0438 \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c - \"\u044d\u043a\u043e\u043d\u043e\u043c\u044f\u0449\u0438\u0439 \u043f\u0430\u043c\u044f\u0442\u044c\" ))  assets: Assets; \/\/ \u043c\u043e\u0434\u0443\u043b\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u044e\u0449\u0438\u0439 \u0432\u0441\u0435 \u0430\u0441\u0441\u0435\u0442\u044b - \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b, \u043e\u0431\u044a\u0435\u043a\u0442\u044b-\u043c\u043e\u0434\u0435\u043b\u0438 \u0438 \u0437\u0432\u0443\u043a\u0438  events: Events; \/\/ \u0448\u0438\u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439  audio: AudioBus; \/\/ \u0430\u0443\u0434\u0438\u043e\u043c\u0438\u043a\u0448\u0435\u0440   \/\/ Core  store: Store&lt;State>;  scene: Scene;  listener: AudioListener;  render: () => void; } <\/code><\/pre>\n<p>\u0412\u043e\u0442 \u044d\u0442\u043e\u0442 \u0430\u0440\u0445\u0438\u0432\u0430\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0431\u044b\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u043d\u043e\u0433\u043e\u0441\u043b\u043e\u0432\u043d\u043e \u043e\u0431\u043e\u0439\u0434\u0435\u043d \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435. \u0415\u0441\u043b\u0438 \u043a\u0440\u0430\u0442\u043a\u043e, \u0442\u043e \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u043c\u044b \u00ab\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0438 \u0432 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c \u0430\u043d\u0438\u043c\u0438\u0440\u0443\u0435\u043c \u0432\u043e\u043e\u0431\u0449\u0435 \u0432\u0441\u0435\u00bb \u2014 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044f \u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435\u043c\u0443 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u0446\u0435\u043d\u044b. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e \u0447\u0442\u043e \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043b\u044e\u0431\u044b\u043c \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c \u043c\u043e\u0434\u0443\u043b\u044f\u043c \u043a\u043e \u0432\u0441\u0435\u043c \u0432\u0430\u0436\u043d\u044b\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0438, \u0447\u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u0432\u043e \u0432\u0441\u0435\u043c \u044d\u0442\u043e\u043c \u2014 \u043c\u043e\u0436\u0435\u043c \u00ab\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c\u00bb \u0440\u0430\u0434\u0438 \u043b\u0443\u0447\u0448\u0435\u0439 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u044f \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0435\u043c\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443. \u041d\u0430 js \u0432 \u0448\u0443\u0442\u0435\u0440\u0435 \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u0432\u043e\u0442 \u0442\u0430\u043a, \u0432 \u00ab\u0441\u0446\u0435\u043d\u0435\u00bb Scene.vue:<\/p>\n<pre><code class=\"javascript\">\/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u201c\u043c\u0438\u0440\u0430\u201d (\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0439\u0448\u0438\u0439 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438-\u043e\u0431\u044a\u0435\u043a\u0442\u044b) this.world = new World(); this.world.init(this);<\/code><\/pre>\n<p>\u0413\u0434\u0435 <code>World<\/code> \u0438 \u043b\u044e\u0431\u044b\u0435 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u043d \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043f\u043e\u0440\u043e\u0436\u0434\u0430\u0435\u0442 \u0438 \u0430\u043d\u0438\u043c\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435:<\/p>\n<pre><code class=\"javascript\">function Module() {   this.init = (     scope,     texture1,     material1,     \/\/ ...   ) => {};     this.animate = (scope) => {}; }  export default Module;<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041d\u0430 ts, \u0432 \u0421\u0446\u0435\u043d\u0435:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">&lt;template>   &lt;div id=\"scene\" class=\"scene\" :class=\"isSelection &amp;&amp; 'scene--selection'\" \/> &lt;\/template>  &lt;script lang=\"ts\"> \/\/ ...  \/\/ Types import type { ISelf } from '@\/models\/modules'; \/\/ ...  export default defineComponent({   name: 'Scene',    setup() {     const store = useStore(key);      \/\/ Core      let container: HTMLElement;      let camera: PerspectiveCamera = new THREE.PerspectiveCamera();     let listener: AudioListener = new THREE.AudioListener();      let scene: Scene = new THREE.Scene();      let renderer: WebGLRenderer = new THREE.WebGLRenderer({       antialias: true,     });      \/\/ Helpers     let helper: Helper = new Helper();     let assets: Assets = new Assets();     let events: Events = new Events();     let audio: AudioBus = new AudioBus();      \/\/ Modules     let world = new World();     \/\/ Functions     let init: () => void;     let animate: () => void;     let render: () => void;      \/\/ Store getters     const isPause = computed(() => store.getters['layout\/isPause']);     \/\/ ..          \/\/ ...      \/\/ Go!     init = () => {       \/\/ Core       container = document.getElementById('scene') as HTMLElement;        \/\/ ...        \/\/ Modules       \/\/ ...       world.init(self);        \/\/ First render       \/\/ ...       render();     };      \/\/ ...      animate = () => {       if (!isPause.value) {         world.animate(self);          render();       }        \/\/ ...        requestAnimationFrame(animate);     };       render = () => {       renderer.render(scene, camera);       \/\/ console.log('Renderer info: ', renderer.info.memory.geometries, renderer.info.memory.textures, renderer.info.render);        \/\/ ...     };      \/\/ This is self )     let self: ISelf = {       \/\/ Utils       helper,       assets,       events,       audio,        \/\/ Core       store,       scene,       listener,       render,     };      \/\/ ...      onMounted(() => {       init();       animate();        \/\/ audio.toggle(isPause.value);     });      \/\/ ...   }, }); &lt;\/script><\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>TS \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u00ab\u043f\u0440\u044f\u043c\u043e \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0435 \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u044b\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b\u00bb, \u0431\u043e\u043b\u0435\u0435 \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u0435\u043b\u044c\u043d\u043e, \u044f\u0432\u043d\u043e \u0438 \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432\u044b\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441. \u0412\u043e\u0442 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0440\u043e\u0441\u043b\u0435\u0434\u0438\u043c \u00ab\u043f\u0443\u0442\u044c \u043e\u0434\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0439\u043a\u0438\u00bb \u043e\u0442 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438, \u043a \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>\u0412 @\/src\/models\/modules.ts:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"typescript\">\/\/ Interfaces \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/  \/\/ \u0421\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0431\u0435\u0437 \u043a\u043e\u043f\u0438\u0439 - \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0410\u0442\u043c\u043e\u0441\u0444\u0435\u0440\u0430 export interface ISimpleModule {  init(self: ISelf): void; }  \/\/ \u041c\u043e\u0434\u0443\u043b\u0438 interface IModule extends ISimpleModule {  isCanAdd(self: ISelf, vector: Vector3, name?: Names): boolean;  add(self: ISelf, vector: Vector3, name?: Names): void;  remove(self: ISelf, items: string[], name?: Names): void; }  \/\/ A\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 interface IAnimatedModule extends IModule {  animate(self: ISelf): void; }  \/\/ \u041c\u043e\u0434\u0443\u043b\u0438 \u0441 \u043a\u043e\u043f\u0438\u044f\u043c\u0438 interface IModules extends IModule {  initItem(self: ISelf, item: TObject, isStart: boolean): void; }  \/\/ \u0410\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 \u0441 \u043a\u043e\u043f\u0438\u044f\u043c\u0438 interface IAnimatedModules extends IAnimatedModule {  initItem(self: ISelf, item: TObject, isStart: boolean): void; }  \/\/ Abstract \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/  \/\/ \u0421\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0431\u0435\u0437 \u043a\u043e\u043f\u0438\u0439 - \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0410\u0442\u043c\u043e\u0441\u0444\u0435\u0440\u0430 export abstract class SimpleModule implements ISimpleModule {  constructor(public name: Names) {    this.name = name;  }   \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f  public abstract init(self: ISelf): void; }  \/\/ \u041e\u0431\u0435\u0440\u0442\u043a\u0438 \u0438 \u043c\u043e\u0434\u0443\u043b\u0438 abstract class Module extends SimpleModule implements IModule {  constructor(public name: Names) {    super(name);  }   \/\/ \u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442?  public abstract isCanAdd(self: ISelf, vector: Vector3, name?: Names): boolean;   \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0435\u0434\u0438\u043d\u0438\u0446\u0443  public abstract add(self: ISelf, vector: Vector3, name?: Names): void;   \/\/ \u0423\u0431\u0440\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b  public abstract remove(self: ISelf, items: string[], name?: Names): void; }  \/\/ \u0410\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c export abstract class AnimatedModule extends Module implements IAnimatedModule {  constructor(public name: Names) {    super(name);  }   \/\/ \u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f  public abstract animate(self: ISelf): void; }  \/\/  \u041c\u043e\u0434\u0443\u043b\u0438 abstract class Modules extends Module implements IModules {  constructor(public name: Names) {    super(name);  }   \/\/ \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0435\u0434\u0438\u043d\u0438\u0446\u0443  public abstract initItem(self: ISelf, item: TObject, isStart: boolean): void; }  \/\/ \u0410\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u0438 abstract class AnimatedModules extends Modules implements IAnimatedModules {  constructor(public name: Names) {    super(name);  }   \/\/ \u0410\u043d\u0438\u043c\u0430\u0446\u0438\u044f  public abstract animate(self: ISelf): void; }  \/\/ Real \/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/  \/\/ \u041e\u0431\u0435\u0440\u0442\u043a\u0438 export class Wrapper extends AnimatedModule implements IAnimatedModule {  constructor(public name: Names) {    super(name);  }   public init(self: ISelf): void {    console.log('modules.ts', 'Wrapper', 'init ', this.name, self);  }   \/\/ \u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442?  public isCanAdd(self: ISelf, vector: Vector3, name?: Names): boolean {    console.log('modules.ts', 'Wrapper', 'isCanAdd ', vector, name);    return false;  }   \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442  public add(self: ISelf, vector: Vector3, name?: Names): void {    console.log('modules.ts', 'Wrapper', 'add ', vector, name);  }   \/\/ \u0423\u0434\u0430\u043b\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b  public remove(self: ISelf, items: string[], name?: Names): void {    console.log('modules.ts', 'Wrapper', 'remove ', items, name);  }   public animate(self: ISelf): void {    console.log('modules.ts', 'Wrapper', 'animate ', this.name, self);  } <\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-343102","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/343102","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=343102"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/343102\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=343102"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=343102"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=343102"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}