{"id":380065,"date":"2024-06-27T09:03:34","date_gmt":"2024-06-27T09:03:34","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=380065"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=380065","title":{"rendered":"<span>\u0423\u0447\u0438\u043c\u0441\u044f \u043b\u0435\u0442\u0430\u0442\u044c: \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u044f \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u0438 \u043d\u0430 Rust. 4\/5<\/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-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ok\/13\/y9\/ok13y9vlz-qasq8lvjgusd0lpyk.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ok\/13\/y9\/ok13y9vlz-qasq8lvjgusd0lpyk.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>\u043d\u0435\u0439\u0440\u043e\u043d\u043d\u043e\u0439 \u0441\u0435\u0442\u0438<\/strong> \u0438 <strong>\u0433\u0435\u043d\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430<\/strong>.<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/habr.com\/ru\/companies\/timeweb\/articles\/817585\/\">\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/companies\/timeweb\/articles\/818985\/\">\u0412\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/companies\/timeweb\/articles\/820699\/\">\u0422\u0440\u0435\u0442\u044c\u044f \u0447\u0430\u0441\u0442\u044c<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0435\u043c \u0432\u044b\u043f\u0443\u0441\u043a\u0435:<\/p>\n<p>  <\/p>\n<p><strong>\u0421\u0435\u043a\u0441\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438<\/strong><\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/-i\/de\/tp\/-idetpdvew-dvgkpoqpfhc2cu5o.png\" data-src=\"https:\/\/habrastorage.org\/webt\/-i\/de\/tp\/-idetpdvew-dvgkpoqpfhc2cu5o.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p><strong>\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 ISO \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u044b ASCII<\/strong><\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">------------ | \\...%....| |   \\......| |    @>....| |      \\...| |        \\.| ------------<\/code><\/pre>\n<p>  <\/p>\n<p><strong>\u041a\u043b\u0435\u0432\u044b\u0435 \u0447\u0438\u0441\u043b\u0430<\/strong><\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/oa\/e3\/qa\/oae3qagiitbt05snamjya54ks9q.png\" data-src=\"https:\/\/habrastorage.org\/webt\/oa\/e3\/qa\/oae3qagiitbt05snamjya54ks9q.png\"\/>  <\/p>\n<p>  <\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u043d\u0435\u0439\u0440\u043e\u043d\u043d\u0443\u044e \u0441\u0435\u0442\u044c \u0438 \u0433\u0435\u043d\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c, \u043d\u0430\u0441 \u0436\u0434\u0435\u0442 \u0441\u0430\u043c\u0430\u044f \u0432\u043e\u0441\u0445\u0438\u0442\u0438\u0442\u0435\u043b\u044c\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c: \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0430\u043d\u0446\u0443\u044e\u0449\u0438\u0445 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u043d\u0430 \u043d\u0430\u0448\u0438\u0445 \u044d\u043a\u0440\u0430\u043d\u0430\u0445!<\/p>\n<p>  <\/p>\n<p><em>\u041f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0435\u043d\u0438\u0435: \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u043e\u0434 JavaScript.<\/em><\/p>\n<p>  <\/p>\n<blockquote><p>\u041d\u0435 \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0439\u0442\u0435\u0441\u044c, \u0435\u0441\u043b\u0438 JavaScript (\u0434\u0430\u043b\u0435\u0435 \u0442\u0430\u043a\u0436\u0435 \u2014 JS) \u0438\u043b\u0438 HTML \u0432\u0430\u043c \u043d\u0435\u0437\u043d\u0430\u043a\u043e\u043c\u044b, \u044f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043e\u0431\u044a\u044f\u0441\u043d\u0438\u0442\u044c \u0432\u0441\u0435 \u043a\u043e\u043d\u0446\u0435\u043f\u0446\u0438\u0438 \u043f\u043e \u0445\u043e\u0434\u0443 \u0434\u0435\u043b\u0430.<\/p><\/blockquote>\n<p>  <\/p>\n<h2 id=\"proekt\">\u041f\u0440\u043e\u0435\u043a\u0442<\/h2>\n<p>  <\/p>\n<p>\u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c <code>struct NeuralNetwork<\/code> \u0438 <code>struct GeneticAlgorithm<\/code>, \u0430 \u043a\u0430\u043a \u043d\u0430\u0441\u0447\u0435\u0442 <code>struct Eye<\/code> \u0438\u043b\u0438 <code>struct World<\/code>? \u0412\u0435\u0434\u044c \u0443 \u043d\u0430\u0448\u0438\u0445 \u043f\u0442\u0438\u0446 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0433\u043b\u0430\u0437\u0430 \u0438 \u043c\u0435\u0441\u0442\u043e \u0434\u043b\u044f \u0436\u0438\u0437\u043d\u0438!<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/_q\/ln\/t3\/_qlnt3bu1bm07zvid46phbgawo4.png\" data-src=\"https:\/\/habrastorage.org\/webt\/_q\/ln\/t3\/_qlnt3bu1bm07zvid46phbgawo4.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0442 \u0447\u0435\u043c \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0438 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435: \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c, <code>\u0447\u0442\u043e \u0432\u0438\u0434\u0438\u0442 \u043f\u0442\u0438\u0446\u0430<\/code> \u0438\u043b\u0438 <code>\u043a\u0430\u043a \u043e\u043d\u0430 \u0434\u0432\u0438\u0433\u0430\u0435\u0442\u0441\u044f<\/code>. \u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0430\u043c \u0432\u0438\u0434\u0435\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0441\u0443\u0445\u0438\u0435 \u0447\u0438\u0441\u043b\u0430 \u2014 \u043f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f \u043b\u0443\u0447\u0448\u0435 \u0437\u0430\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u0437\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u0440\u0443!<\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0440\u0430\u0432\u044f\u0442\u0441\u044f \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u044b, \u0442\u043e \u043c\u044b \u0441\u0442\u0440\u0435\u043c\u0438\u043c\u0441\u044f \u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c\u0443:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/rz\/wd\/4q\/rzwd4qoad42r98yp22mb655sulk.png\" data-src=\"https:\/\/habrastorage.org\/webt\/rz\/wd\/4q\/rzwd4qoad42r98yp22mb655sulk.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u0432\u0441\u0435\u0433\u0434\u0430, \u043f\u043e\u043c\u0438\u043c\u043e \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043c\u044b \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u0441\u043b\u0435\u0434\u0443\u0435\u043c, \u0447\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0434 \u0432\u0441\u0435\u043c\u0438 \u0441\u043b\u043e\u044f\u043c\u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u0432\u0441\u0442\u0440\u0435\u0442\u044f\u0442\u0441\u044f. \u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u044d\u0442\u043e\u0433\u043e \u0437\u043d\u0430\u0442\u044c, \u043d\u0435 \u0441\u0442\u0435\u0441\u043d\u044f\u0439\u0442\u0435\u0441\u044c \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u044b.<\/p>\n<p>  <\/p>\n<p>\u0413\u043e\u0442\u043e\u0432\u044b? \u0422\u043e\u0433\u0434\u0430 \u0432\u043f\u0435\u0440\u0435\u0434.<\/p>\n<p>  <\/p>\n<h2 id=\"predvaritelnye-usloviya\">\u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f<\/h2>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 WebAssembly (\u0434\u0430\u043b\u0435\u0435 \u0442\u0430\u043a\u0436\u0435 \u2014 WA) \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0434\u0432\u0430 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430:<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/www.npmjs.com\/get-npm\">npm<\/a> (Cargo \u0434\u043b\u044f JS)<\/li>\n<li><a href=\"https:\/\/rustwasm.github.io\/wasm-pack\/installer\/\">wasm-pack<\/a> (\u043d\u0430\u0431\u043e\u0440 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432, \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u044e WA \u0432 Rust)<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u044d\u0442\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<p>  <\/p>\n<h2 id=\"privet-wa-rust\">\u041f\u0440\u0438\u0432\u0435\u0442, WA (Rust)!<\/h2>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0435\u0433\u043e \u0437\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u043e\u043c:<\/p>\n<p>  <\/p>\n<blockquote><p>\u0424\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u043e \u0442\u0430\u043a\u043e\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f &#171;\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439&#187; \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <strong>\u043c\u043e\u0441\u0442\u043e\u043c<\/strong> (bridge) \u0438\u043b\u0438 <strong>\u043c\u043e\u0434\u0443\u043b\u0435\u043c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f<\/strong> (interop).<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"bash\">cd shorelark\/libs cargo new simulation-wasm --lib --name lib-simulation-wasm<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448 \u043a\u0440\u0435\u0439\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u043b WA, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0432 \u0435\u0433\u043e \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442 2 \u0432\u0435\u0449\u0438:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c <a href=\"https:\/\/doc.rust-lang.org\/reference\/linkage.html\">crate-type<\/a> \u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>cdylib<\/code>:<\/li>\n<\/ol>\n<p>  <\/p>\n<pre><code class=\"plaintext\">[package] # ...  [lib] crate-type = [\"cdylib\"]<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u0442 \u043a\u043e\u0434 \u0432 \u043d\u0435\u0447\u0442\u043e, \u0430 <code>crate-type<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442, \u043a\u0430\u043a\u0438\u043c \u0431\u0443\u0434\u0435\u0442 \u044d\u0442\u043e \u043d\u0435\u0447\u0442\u043e, \u0442\u0430\u043a\u0436\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u043c\u043e\u0435 <strong>\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u043e\u043c<\/strong>:  <\/p>\n<ul>\n<li><code>crate-type = [\"bin\"]<\/code> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442: \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0439 <strong>\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443<\/strong> (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0444\u0430\u0439\u043b <code>.exe<\/code> \u043d\u0430 Windows)<\/li>\n<li><code>create-type = [\"lib\"]<\/code> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442: \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0439 <strong>\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443<\/strong><\/li>\n<\/ul>\n<p>  \u0413\u0434\u0435:  <\/p>\n<ul>\n<li><strong>\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430<\/strong> \u2014 \u044d\u0442\u043e \u043d\u0435\u0447\u0442\u043e, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u0442\u0435\u0440\u043c\u0438\u043d\u0430\u043b\u0435)<br \/>  <strong>\u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430<\/strong> \u2014 \u043a\u043e\u0434, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u0440\u0435\u0439\u0442\u043e\u0432<\/li>\n<\/ul>\n<p>  \u0422\u0438\u043f, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c, <a href=\"https:\/\/github.com\/rust-lang\/rfcs\/blob\/master\/text\/1510-cdylib.md\">cdylib<\/a>, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442 <strong>\u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 C<\/strong> \u0438 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:  <\/p>\n<ul>\n<li>\u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u044b \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0438\u0437\u0432\u043d\u0435, \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 Rust.<\/li>\n<\/ul>\n<p>  \u042d\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0440\u0430\u0437\u0434\u0443\u0432\u0430\u043d\u0438\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 &#171;\u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c\u0438&#187; \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0447\u0442\u043e \u0432\u0430\u0436\u043d\u043e \u0434\u043b\u044f WA (\u043c\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043e\u0431\u0430\u043d\u043a\u0440\u043e\u0442\u0438\u043b\u0438\u0441\u044c \u0438\u0437-\u0437\u0430 \u0441\u0447\u0435\u0442\u043e\u0432 \u0437\u0430 \u0418\u043d\u0442\u0435\u0440\u043d\u0435\u0442, \u043d\u0435 \u0442\u0430\u043a \u043b\u0438?).  <\/p>\n<ul>\n<li>\u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c <strong>\u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443<\/strong>, \u0442.\u0435. \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043a\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0435\u043c-\u0442\u043e \u0434\u0440\u0443\u0433\u0438\u043c.<\/li>\n<\/ul>\n<p>  \u042d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043b\u044f WA, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e, \u043a\u0430\u043a \u0432\u044b \u0432\u0441\u043a\u043e\u0440\u0435 \u0443\u0432\u0438\u0434\u0438\u0442\u0435, \u043d\u0430\u0448 \u043a\u043e\u0434 Rust \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e: \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0432 \u043f\u043e\u043b\u043d\u043e\u0435 \u0440\u0430\u0441\u043f\u043e\u0440\u044f\u0436\u0435\u043d\u0438\u0435 JS.<\/p>\n<p>  \u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043d\u0438\u043a\u0430\u043a\u0438\u0445 <code>fn main() { ...\u200b }<\/code>, \u0430 \u0431\u0443\u0434\u0435\u0442 <code>pub fn do_something() { ...\u200b }<\/code>.<\/p><\/blockquote>\n<p>  <\/p>\n<ol>\n<li>\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c <a href=\"https:\/\/github.com\/rustwasm\/wasm-bindgen\">wasm-bindgen<\/a> \u0432 \u043d\u0430\u0448\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438:<\/li>\n<\/ol>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># ...  [dependencies] wasm-bindgen = \"0.2\"<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p><code>wasm-bindgen<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0442\u0438\u043f\u044b \u0438 \u043c\u0430\u043a\u0440\u043e\u0441\u044b, \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0449\u0438\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430, \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e \u0432 WA.<\/p>\n<p>  Rust + WA \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0438 \u0431\u0435\u0437 \u043d\u0435\u0433\u043e, \u043f\u0440\u043e\u0441\u0442\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u043d\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c.<\/p><\/blockquote>\n<p>\u0421 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u043b\u0438, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043a\u043e\u0434!<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u0437\u0430\u0439\u043c\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u0430 \u0431\u044b\u043b\u043e \u0431\u044b \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u043a\u0430\u043a \u0447\u0442\u043e-\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u043e\u0440\u0435\u0435, \u044f \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u0437 JS, \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u044d\u0442\u0430 \u0448\u0442\u0443\u043a\u0430 \u043d\u0430 WA \u043d\u0435 \u043e\u0431\u043c\u0430\u043d:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">pub fn whos_that_dog() -> String {     \"Mister Peanutbutter\".into() }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438 \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u043a\u0440\u0435\u0439\u0442 \u0434\u043b\u044f \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u043d\u0430 crates.io, \u044d\u0442\u043e\u0433\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u043d\u043e \u0434\u043b\u044f WA \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u043d\u0443 \u0432\u0435\u0449\u044c, <code>#[wasm_bindgen]<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">use wasm_bindgen::prelude::*;  #[wasm_bindgen] pub fn whos_that_dog() -> String {     \"Mister Peanutbutter\".into() }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u044f, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e <a href=\"https:\/\/doc.rust-lang.org\/book\/ch19-06-macros.html#procedural-macros-for-generating-code-from-attributes\">\u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u043d\u044b\u0439 \u043c\u0430\u043a\u0440\u043e\u0441<\/a> <code>#[wasm_bindgen]<\/code> \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u0443, \u0447\u0442\u043e \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u043b\u0438 \u0442\u0438\u043f, \u0442.\u0435. \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0435 \u0432\u0438\u0434\u0438\u043c\u043e\u0439 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 JS.<\/p>\n<p>  \u0412\u0441\u0435 \u0441\u0438\u043c\u0432\u043e\u043b\u044b Rust \u0432 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u043c \u0438\u0442\u043e\u0433\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 WA, \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435, \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d <code>#[wasm_bindgen]<\/code>, \u043c\u043e\u0433\u0443\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0438\u0437 JS.<\/p><\/blockquote>\n<p>\u0427\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u0440\u0435\u0439\u0442 WA, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c <code>wasm-pack<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cd simulation-wasm wasm-pack build<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 \u043e\u0431\u044b\u0447\u043d\u044b\u043c <code>cargo<\/code> \u0438 <code>wasm-pack<\/code> \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u0434, \u043d\u043e \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 JS, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u0438\u0441\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u042d\u0442\u0438 \u0444\u0430\u0439\u043b\u044b \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0439\u0442\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0439 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>pkg<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">ls -l pkg total 36 -rw-r--r-- 1 pwy   110 Apr  2 17:20 lib_simulation_wasm.d.ts -rw-r--r-- 1 pwy   184 Apr  2 17:20 lib_simulation_wasm.js -rw-r--r-- 1 pwy  1477 Apr  2 17:20 lib_simulation_wasm_bg.js -rw-r--r-- 1 pwy 13155 Apr  2 17:20 lib_simulation_wasm_bg.wasm -rw-r--r-- 1 pwy   271 Apr  2 17:20 lib_simulation_wasm_bg.wasm.d.ts -rw-r--r-- 1 pwy   356 Apr  2 17:20 package.json<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0440\u0430\u0442\u043a\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c:<\/p>\n<p>  <\/p>\n<ul>\n<li><code>package.json<\/code> \u2014 \u044d\u0442\u043e \u043a\u0430\u043a <code>Cargo.toml<\/code> \u0434\u043b\u044f <code>npm<\/code>, \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0434\u0443\u043b\u044f:<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"json\">{   \"name\": \"lib-simulation-wasm\",   \"version\": \"0.1.0\",   \/* ... *\/ }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>lib_simulation_wasm.d.ts<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 (forward declarations), \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f IDE \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043e\u043a:<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"plaintext\">\/**  * @returns {string}  *\/ export function whos_that_dog(): string;<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>lib_simulation_wasm_bg.wasm<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Bytecode\">\u0431\u0430\u0439\u0442-\u043a\u043e\u0434<\/a> WA \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430; \u044d\u0442\u043e \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 <code>.dll<\/code> \u0438\u043b\u0438 <code>.so<\/code>, \u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/github.com\/WebAssembly\/wabt\">wabt<\/a> \u0434\u043b\u044f \u0435\u0433\u043e \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u044f (\u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0434\u043b\u044f \u0440\u0430\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f, \u043f\u043e\u043b\u0430\u0433\u0430\u044e):<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"plaintext\">(module   (func (type 1) (param i32) (result i32)     (local i32 i32 i32 i32)     global.get 0     i32.const 16     i32.sub     local.tee 11     ;; ...<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li><code>lib_simulation_wasm_bg.js<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0443\u0433\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u0448\u0443 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 WA:<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/**  * @returns {string}  *\/ export function whos_that_dog() {     try {         const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);         wasm.whos_that_dog(retptr);         var r0 = getInt32Memory0()[retptr \/ 4 + 0];         var r1 = getInt32Memory0()[retptr \/ 4 + 1];         return getStringFromWasm0(r0, r1);     } finally {         wasm.__wbindgen_add_to_stack_pointer(16);         wasm.__wbindgen_free(r0, r1);     } }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u0415\u0441\u043b\u0438 \u043d\u0430\u0448 \u043a\u043e\u0434 Rust \u043f\u043e\u0447\u0442\u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u0442:<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"rust\">pub fn whos_that_dog() -> String {     \"Mister Peanutbutter\".into() }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u2026 \u043f\u043e\u0447\u0435\u043c\u0443 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0442\u0430\u043a \u043c\u043d\u043e\u0433\u043e?<\/p>\n<p>  \u0412\u043a\u0440\u0430\u0442\u0446\u0435, \u044d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e WA <strong>\u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0438<\/strong>, \u0438 <code>wasm-pack<\/code> \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e \u043e\u0431\u043e\u0439\u0442\u0438.<\/p>\n<p>  \u041d\u043e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0442\u0435\u0440\u043c\u0438\u043d\u043e\u043b\u043e\u0433\u0438\u044f:  <\/p>\n<ul>\n<li>\u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043e\u0434\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0434\u0440\u0443\u0433\u0443\u044e, \u043a\u043e\u0433\u0434\u0430 \u043e\u0431\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u0430\u0445 \u0438\/\u0438\u043b\u0438 \u043a\u043e\u0433\u0434\u0430 \u043e\u043d\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0445 \u044f\u0437\u044b\u043a\u0430\u0445, \u043c\u044b \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u044c \u0433\u0440\u0430\u043d\u0438\u0446\u0443 <a href=\"https:\/\/doc.rust-lang.org\/nomicon\/ffi.html\">\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0432\u043d\u0435\u0448\u043d\u0435\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (foreign function interface, FFI)<\/a>:<\/li>\n<\/ul>\n<p>  <\/p><\/blockquote>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ic\/ws\/xs\/icwsxs_wwcojcdkkun1qrib3qdm.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ic\/ws\/xs\/icwsxs_wwcojcdkkun1qrib3qdm.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<blockquote><p>\u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0433\u043e\u0432\u043e\u0440\u0438\u043c, \u0447\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f <code>whos_that_dog()<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u0435\u0440\u0435\u0441\u0435\u043a\u0430\u0435\u0442 \u0433\u0440\u0430\u043d\u0438\u0446\u0443 FFI \u0438\u0437 Rust (\u0433\u0434\u0435 \u043e\u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f) \u0432 JS (\u0433\u0434\u0435 \u043e\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f).<\/p>\n<p>  \u041f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435 \u0433\u0440\u0430\u043d\u0438\u0446\u044b FFI \u2014 \u044d\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0434\u0435\u043b\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0430\u0437\u043d\u044b\u0435 \u044f\u0437\u044b\u043a\u0438 \u0447\u0430\u0441\u0442\u043e \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443 <strong>\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0432 \u043f\u0430\u043c\u044f\u0442\u0438<\/strong>. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 <code>struct Foo<\/code> \u0432 Rust \u0438 <code>class Foo<\/code> \u0432 JS \u043d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u044f\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e, <strong>\u0432 \u043f\u0430\u043c\u044f\u0442\u0438<\/strong> \u043e\u043d\u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443.<\/p>\n<p>  \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439, \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c: &#171;\u042d\u0439, \u043f\u043e \u0430\u0434\u0440\u0435\u0441\u0443 0x0000CAFE \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0430\u0439\u0442\u043e\u0432 \u2014 \u044d\u0442\u043e Foo&#187;. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u0442\u043e, \u0447\u0442\u043e \u0441\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u044c \u0434\u0440\u0443\u0433\u0430\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u0430:<\/p><\/blockquote>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/bn\/k1\/bw\/bnk1bwygzwdakqpaxqvm57ov8r0.png\" data-src=\"https:\/\/habrastorage.org\/webt\/bn\/k1\/bw\/bnk1bwygzwdakqpaxqvm57ov8r0.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<blockquote>\n<ul>\n<li>\u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0434\u0440\u0443\u0433\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <strong>\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439<\/strong> (serialization).<\/li>\n<\/ul>\n<p>  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a\u043e\u0439 \u0442\u0438\u043f:<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"rust\">struct Foo {     value: String, }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u2026 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432, \u0441\u043a\u0430\u0436\u0435\u043c, \u0442\u0430\u043a\u043e\u0439 JSON:<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"json\">{   \"value\": \"Hi!\" }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u2026 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0442\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043b\u0435\u0433\u043a\u043e <strong>\u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d<\/strong> (deserialize) \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 JS:<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"javascript\">const foo = JSON.parse('{ \"value\": \"Hi!\" }'); console.log(foo);<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u0421\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0443\u0434\u043e\u0431\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0430\u043c\u0438, \u0442\u0430\u043a\u0438\u043c\u0438 \u043a\u0430\u043a JSON, YAML \u0438\u043b\u0438 XML. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0430\u043a\u0436\u0435 \u0442\u0430\u043a\u0438\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u044b \u043a\u0430\u043a <a href=\"https:\/\/hacks.mozilla.org\/2019\/04\/crossing-the-rust-ffi-frontier-with-protocol-buffers\/\">Protocol Buffers<\/a>.<\/p>\n<p>  \u0425\u043e\u0442\u044f \u0438 Rust, \u0438 JS \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u0441\u0442\u0440\u043e\u043a\u0438, WA \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0447\u0438\u0441\u043b\u0430. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0432\u0441\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0447\u0435\u0440\u0435\u0437 <code>#[wasm_bindgen]<\/code>, \u043c\u043e\u0433\u0443\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0447\u0438\u0441\u0435\u043b (\u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f WA).<\/p>\n<p>  \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u043b\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0441\u0442\u0440\u043e\u043a\u0438 <code>wasm-pack<\/code> \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u044f\u0432\u0438\u0442\u044c \u0442\u0432\u043e\u0440\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u043e\u0434\u0445\u043e\u0434:<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"rust\">pub extern \"C\" fn __wasm_bindgen_generated_whos_that_dog()     -> &lt;String as ReturnWasmAbi>::Abi {     let _ret = { whos_that_dog() };     &lt;String as ReturnWasmAbi>::return_abi(_ret) }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u042d\u0442\u043e \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e \u043a\u0430\u043a <strong>\u0448\u0438\u043c (shim)<\/strong> (\u0438\u043b\u0438 <strong>\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0441\u043a\u043b\u0435\u0438\u0432\u0430\u043d\u0438\u044f (glue-function)<\/strong>, \u0438\u043b\u0438 <strong>\u0441\u043a\u043b\u0435\u0438\u0432\u0430\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 (glue-code)<\/strong>).<\/p>\n<p>  \u042d\u0442\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 Rust \u0432 \u043f\u0430\u0440\u0443 \u0447\u0438\u0441\u0435\u043b:  <\/p>\n<ul>\n<li><code>r0<\/code>, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0435\u0435 \u043b\u043e\u043a\u0430\u0446\u0438\u044e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 (\u0441\u0442\u0430\u0440\u044b\u0439-\u0434\u043e\u0431\u0440\u044b\u0439 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Pointer_(computer_programming)\">\u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c<\/a>)<\/li>\n<li><code>r1<\/code>, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0435\u0435 \u0434\u043b\u0438\u043d\u0443 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438<\/li>\n<\/ul>\n<p>  \u042d\u0442\u0438 \u0434\u0432\u0430 \u0447\u0438\u0441\u043b\u0430 \u0437\u0430\u0442\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>getStringFromWasm0()<\/code> \u0434\u043b\u044f \u0432\u043e\u0441\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f (&#171;\u0434\u0435\u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438&#187;) \u0441\u0442\u0440\u043e\u043a\u0438 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 JS \u2014 \u0438 \u0432\u0441\u0435 \u044d\u0442\u043e \u0431\u0435\u0437 \u043d\u0430\u0448\u0435\u0433\u043e \u0443\u0447\u0430\u0441\u0442\u0438\u044f.<\/p><\/blockquote>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u043a\u0440\u0435\u0439\u0442, \u043d\u043e \u043a\u0430\u043a \u0435\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c?<\/p>\n<p>  <\/p>\n<h2 id=\"privet-wa-js\">\u041f\u0440\u0438\u0432\u0435\u0442, WA (JS)!<\/h2>\n<p>  <\/p>\n<p>\u0412\u0440\u0435\u043c\u044f \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430!<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u0432 \u043a\u043e\u0440\u043d\u0435\u0432\u0443\u044e \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cd ..\/..<\/code><\/pre>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0442\u0430\u043a\u0436\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430. \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u043d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <code>npm init<\/code>, \u0447\u0442\u043e\u0431\u044b \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0434\u043b\u044f \u043d\u0430\u0441 \u0448\u0430\u0431\u043b\u043e\u043d \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 WA:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">npm init wasm-app www<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>www<\/code> \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u0444\u0430\u0439\u043b\u0430\u043c\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">ls -l www total 248 -rw-r--r-- 1 pwy  10850 Apr  2 17:24 LICENSE-APACHE -rw-r--r-- 1 pwy   1052 Apr  2 17:24 LICENSE-MIT -rw-r--r-- 1 pwy   2595 Apr  2 17:24 README.md -rw-r--r-- 1 pwy    279 Apr  2 17:24 bootstrap.js -rw-r--r-- 1 pwy    297 Apr  2 17:24 index.html -rw-r--r-- 1 pwy     56 Apr  2 17:24 index.js -rw-r--r-- 1 pwy 209434 Apr  2 17:24 package-lock.json -rw-r--r-- 1 pwy    937 Apr  2 17:24 package.json -rw-r--r-- 1 pwy    311 Apr  2 17:24 webpack.config.js<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0440\u0430\u0442\u043a\u043e \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0438\u0445.<\/p>\n<p>  <\/p>\n<p><strong>\u0417\u043d\u0430\u0439 \u0441\u0432\u043e\u0435\u0433\u043e \u0432\u0440\u0430\u0433\u0430<\/strong><\/p>\n<p>  <\/p>\n<p>\u0422\u043e\u0447\u043a\u043e\u0439 \u0432\u0445\u043e\u0434\u0430 (<code>main.rs<\/code> \u0432 Rust), \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>index.html<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;!DOCTYPE html> &lt;html>   &lt;head>     &lt;meta charset=\"utf-8\">     &lt;title>Hello wasm-pack!&lt;\/title>   &lt;\/head>    &lt;body>     &lt;script src=\".\/bootstrap.js\">&lt;\/script>   &lt;\/body> &lt;\/html><\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0440\u0430\u0442\u043a\u0438\u0439 \u043e\u0431\u0437\u043e\u0440 HTML:<\/p>\n<p>  <\/p>\n<ul>\n<li><code>&lt;something><\/code> \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <strong>\u0442\u0435\u0433\u043e\u043c (tag)<\/strong><\/li>\n<li>\u0442\u0435\u0433\u0438 \u0431\u044b\u0432\u0430\u044e\u0442 <strong>\u043e\u0442\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0435<\/strong> (<code>&lt;something><\/code>) \u0438 <strong>\u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0449\u0438\u0435<\/strong> (<code>&lt;\/something><\/code>)<\/li>\n<li>\u0442\u0435\u0433 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c <strong>\u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b<\/strong>: <code>key=\"value\"<\/code><\/li>\n<li>\u0442\u0435\u0433 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c <strong>\u0434\u0435\u0442\u0435\u0439 (children)<\/strong> (\u0434\u0440\u0443\u0433\u0438\u0435 \u0442\u0435\u0433\u0438)<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u043e\u0431\u0449\u0435\u043c, \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 HTML \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432 \u0432\u0438\u0434\u0435 \u0434\u0435\u0440\u0435\u0432\u0430 (\u044d\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <a href=\"https:\/\/en.wikipedia.org\/wiki\/Document_Object_Model\">\u043e\u0431\u044a\u0435\u043a\u0442\u043d\u044b\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 (document object model, DOM)<\/a>):<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">html \u251c\u2500\u2500 head \u2502   \u251c\u2500\u2500 meta \u2502   \u2514\u2500\u2500 title \u2514\u2500\u2500 body     \u2514\u2500\u2500 script<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0430\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442, \u043f\u044b\u0442\u0430\u044f\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0437 \u043d\u0435\u0433\u043e \u0447\u0442\u043e-\u0442\u043e \u043f\u0440\u0438\u044f\u0442\u043d\u043e\u0435.<\/p>\n<p>  <\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0442\u0435\u0433 \u0438\u043c\u0435\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<ul>\n<li><code>html<\/code> \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0435\u0441\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442<\/li>\n<li><code>head<\/code> \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430 (\u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u044f\u0437\u044b\u043a \u0438\u043b\u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a)<\/li>\n<li><code>body<\/code> \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430<\/li>\n<li><code>script<\/code> \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0444\u0430\u0439\u043b JS<\/li>\n<li><code>p<\/code> (\u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435) \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442<\/li>\n<li><code>b<\/code> (\u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435) \u0434\u0435\u043b\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u043f\u043e\u043b\u0443\u0436\u0438\u0440\u043d\u044b\u043c \u0438 \u0442.\u0434.<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;body>   &lt;p>yes... ha ha ha... &lt;b>yes!&lt;\/b>&lt;\/p> &lt;\/body><\/code><\/pre>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/vf\/pb\/fw\/vfpbfwlztrp_k7dd9pmaumym8uy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/vf\/pb\/fw\/vfpbfwlztrp_k7dd9pmaumym8uy.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u0448\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0435 \u0442\u0430\u043a \u0443\u0436 \u043c\u043d\u043e\u0433\u043e \u2014 \u0441\u0430\u043c\u043e\u0435 \u0433\u043b\u0430\u0432\u043d\u043e\u0435, \u0447\u0442\u043e \u043e\u043d\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 <code>bootstrap.js<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import(\".\/index.js\")   .catch(e => console.error(\"Error importing `index.js`:\", e));<\/code><\/pre>\n<p>  <\/p>\n<p><code>import<\/code> \u2014 \u044d\u0442\u043e \u043a\u0430\u043a <code>use<\/code> \u0438\u043b\u0438 <code>extern crate<\/code> \u0432 Rust. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 Rust, \u0432 JS <code>import<\/code> \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a <strong>\u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f<\/strong>, \u0442.\u0435. \u043c\u043e\u0436\u0435\u0442 <strong>\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f<\/strong>. \u041d\u0430 \u043f\u0441\u0435\u0432\u0434\u043e\u043a\u043e\u0434\u0435 Rust \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">(mod \".\/index.js\")     .await     .map_err(|e| {         eprintln!(\"Error importing `index.js`:\", e);     });<\/code><\/pre>\n<p>  <\/p>\n<p>\u041c\u044b \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 <code>index.js<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430\u0433\u043b\u044f\u043d\u0435\u043c \u0442\u0443\u0434\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import * as wasm from \"hello-wasm-pack\"; \/\/                     ^-------------^ \/\/                      \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 package.json  wasm.greet();<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e\u0442 <code>import<\/code> \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 <code>extern crate<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">extern crate hello_wasm_pack as wasm;  wasm::greet();<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u043a\u043e\u0434\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u043e \u044d\u0442\u043e \u0432\u0441\u0435.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u0438 <code>www<\/code> \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u2014 <code>webpack.config.js<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">const CopyWebpackPlugin = require(\"copy-webpack-plugin\"); const path = require('path');  module.exports = {   entry: \".\/bootstrap.js\",   output: {     path: path.resolve(__dirname, \"dist\"),     filename: \"bootstrap.js\",   },   mode: \"development\",   plugins: [     new CopyWebpackPlugin(['index.html'])   ], };<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f <a href=\"https:\/\/webpack.js.org\/\">webpack<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 Cargo \u0434\u043b\u044f JS.<\/p>\n<p>  <\/p>\n<blockquote><p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043a\u043e\u0435-\u0447\u0442\u043e \u043f\u0440\u043e\u044f\u0441\u043d\u0438\u043c:  <\/p>\n<ul>\n<li><code>npm<\/code> \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438<\/li>\n<li><code>webpack<\/code> \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/li>\n<\/ul>\n<p>  \u0412 Rust \u0432\u0441\u0435 \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 Cargo (\u043a\u0430\u043a \u0443\u0434\u043e\u0431\u043d\u043e!), \u043d\u043e \u0432 JS \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u044b \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b.<\/p><\/blockquote>\n<p><strong>\u041c\u044b \u0443\u0437\u043d\u0430\u043b\u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u0432\u0440\u0430\u0433\u0430, \u0447\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/strong><\/p>\n<p>  <\/p>\n<p>\u041e\u0431\u043c\u0435\u043d\u044f\u0432\u0448\u0438\u0441\u044c \u043b\u044e\u0431\u0435\u0437\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0441 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439, \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u0434\u0435\u043b\u0443:<\/p>\n<p>  <\/p>\n<ol>\n<li>\u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 <code>npm<\/code> \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043e <code>lib-simulation-wasm<\/code>, \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c \u044d\u0442\u043e:<\/li>\n<\/ol>\n<p>  <\/p>\n<pre><code class=\"json\">\/\/ www\/package.json {   \/* ... *\/   \"devDependencies\": {     \"lib-simulation-wasm\": \"file:..\/libs\/simulation-wasm\/pkg\",     \/* ... *\/   } }<\/code><\/pre>\n<p>  <\/p>\n<ol>\n<li>\u0421\u043e\u043e\u0431\u0449\u0430\u0435\u043c <code>npm<\/code> \u043e\u0431 \u044d\u0442\u043e\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438:<\/li>\n<\/ol>\n<p>  <\/p>\n<pre><code class=\"bash\">cd www npm install<\/code><\/pre>\n<p>  <\/p>\n<ol>\n<li>\u041f\u0440\u0438\u0448\u043b\u043e \u0432\u0440\u0435\u043c\u044f <code>index.js<\/code>:<\/li>\n<\/ol>\n<p>  <\/p>\n<pre><code class=\"javascript\">import * as sim from \"lib-simulation-wasm\";  alert(\"Who's that dog? \" + sim.whos_that_dog() + \"!\");<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u0417\u0434\u0435\u0441\u044c \u043d\u0435\u0442 <code>function main() { }<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 JS \u043e\u043d\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u0430, \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0432\u0435\u0440\u0445\u0443 \u0432\u043d\u0438\u0437 (<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Glossary\/Hoisting\">\u0431\u043e\u043b\u0435\u0435 \u0438\u043b\u0438 \u043c\u0435\u043d\u0435\u0435<\/a>).<\/p><\/blockquote>\n<p>  <\/p>\n<ol>\n<li>\u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 (\u043f\u043e \u0441\u0443\u0442\u0438, \u044d\u0442\u043e <code>cargo run<\/code>):<\/li>\n<\/ol>\n<p>  <\/p>\n<pre><code class=\"bash\">npm run start<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"bash\">... \u2139 \uff62wds\uff63: Project is running at http:\/\/localhost:8080\/ ...<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u0415\u0441\u043b\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u0440\u043e\u0432\u0430\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 <code>error:0308010C<\/code>, \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 <a href=\"https:\/\/stackoverflow.com\/questions\/69692842\/error-message-error0308010cdigital-envelope-routinesunsupported\">\u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e Node.js<\/a>. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0442\u0430\u043a:<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"bash\">NODE_OPTIONS=--openssl-legacy-provider npm run start<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c <code>http:\/\/localhost:8080\/<\/code> \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/bu\/fq\/b7\/bufqb7gcppjozkjdh2tsxkyj7mc.png\" data-src=\"https:\/\/habrastorage.org\/webt\/bu\/fq\/b7\/bufqb7gcppjozkjdh2tsxkyj7mc.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0423\u0440\u0430!<\/p>\n<p>  <\/p>\n<blockquote><p>\u0421\u0435\u0440\u0432\u0435\u0440, \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>npm run start<\/code>, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0440\u0435\u0430\u0433\u0438\u0440\u0443\u0435\u0442 \u043d\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u0432\u0435\u0440\u043d\u0438\u0442\u0435\u0441\u044c \u0432 <code>lib.rs<\/code>, \u0441\u0434\u0435\u043b\u0430\u0439\u0442\u0435, \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u0442\u0435, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 <code>wasm-pack build<\/code>, \u0438 \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0435\u043a\u0443\u043d\u0434 \u0441\u0430\u0439\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c\u0441\u044f.<\/p>\n<p>  \u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u043a HTML \u0438 JS, \u0445\u043e\u0442\u044f \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c <code>wasm-pack<\/code> \u043d\u0435 \u043d\u0443\u0436\u043d\u043e.<\/p><\/blockquote>\n<p>  <\/p>\n<h2 id=\"privet-wa-zaklyuchenie\">\u041f\u0440\u0438\u0432\u0435\u0442, WA (\u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435)!<\/h2>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a\u2026 \u0427\u0442\u043e \u044d\u0442\u043e \u0432\u0441\u0435 \u0437\u043d\u0430\u0447\u0438\u0442?<\/p>\n<p>  <\/p>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0430\u044e\u0449\u0435\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043d\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0430\u0441 \u043b\u0430\u0443\u0440\u0435\u0430\u0442\u0430\u043c\u0438 \u041d\u043e\u0431\u0435\u043b\u0435\u0432\u0441\u043a\u043e\u0439 \u043f\u0440\u0435\u043c\u0438\u0438, \u043d\u043e \u043d\u0430\u0448\u0435\u0439 \u0446\u0435\u043b\u044c\u044e \u0431\u044b\u043b\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c, \u0438 \u043c\u044b \u0435\u0435 \u0434\u043e\u0441\u0442\u0438\u0433\u043b\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043c\u044b \u043d\u0430\u0447\u043d\u0435\u043c \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0435\u0439.<\/p>\n<p>  <\/p>\n<h2 id=\"privet-simulyaciya\">\u041f\u0440\u0438\u0432\u0435\u0442, \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u044f!<\/h2>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043a\u0440\u0435\u0439\u0442\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">cd ..\/libs cargo new simulation --lib --name lib-simulation<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e\u0442 \u043a\u0440\u0435\u0439\u0442 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0434\u0432\u0438\u0436\u043e\u043a \u043d\u0430\u0448\u0435\u0439 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">pub struct Simulation;<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0434\u0438\u0437\u0430\u0439\u043d \u0438\u0437 \u0432\u043e\u0437\u0434\u0443\u0445\u0430, \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u0440\u0438\u0441\u0443\u043d\u043e\u043a:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ed\/md\/ls\/edmdlsb13ldxgl_8ico-flefqog.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ed\/md\/ls\/edmdlsb13ldxgl_8ico-flefqog.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u043c\u044b \u0437\u0434\u0435\u0441\u044c \u0432\u0438\u0434\u0438\u043c? \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u043c\u044b \u0432\u0438\u0434\u0438\u043c \u0437\u0434\u0435\u0441\u044c <strong>\u043c\u0438\u0440<\/strong>:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">pub struct Simulation {     world: World, }  #[derive(Debug)] pub struct World;<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 <strong>\u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0445<\/strong> (\u043f\u0442\u0438\u0446!) \u0438 <strong>\u0435\u0434\u0443<\/strong> (\u0431\u043e\u0433\u0430\u0442\u0443\u044e \u0431\u0435\u043b\u043a\u0430\u043c\u0438 \u0438 \u043a\u043b\u0435\u0442\u0447\u0430\u0442\u043a\u043e\u0439!):<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[derive(Debug)] pub struct World {     animals: Vec&lt;Animal>,     foods: Vec&lt;Food>, }  #[derive(Debug)] pub struct Animal;  #[derive(Debug)] pub struct Food;<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u0445:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[derive(Debug)] pub struct Animal {     position: ?, }  #[derive(Debug)] pub struct Food {     position: ?, }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u0448 \u043c\u0438\u0440 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0432\u0443\u043c\u0435\u0440\u043d\u044b\u043c, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043d\u0430\u0441 \u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[derive(Debug)] pub struct Animal {     position: Point2, }  #[derive(Debug)] pub struct Food {     position: Point2, }  #[derive(Debug)] pub struct Point2 {     x: f32,     y: f32, }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0435 \u0438\u043c\u0435\u044e\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0443\u0433\u043e\u043b \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430&#8230;<\/p>\n<p>  <\/p>\n<p>\u0414\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u043f\u043e\u0447\u0442\u0438 \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u043c\u044b \u043f\u0438\u0441\u0430\u043b\u0438 \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<p>  <\/p>\n<p>\u0421\u0435\u0439\u0447\u0430\u0441, \u043a\u043e\u0433\u0434\u0430 \u0434\u0435\u043b\u043e \u0434\u043e\u0448\u043b\u043e \u0434\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0434\u0430\u043d\u043d\u044b\u0445, \u043c\u043d\u0435 \u0431\u044b \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0442\u044c \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434 \u2014 \u043e\u0442\u0447\u0430\u0441\u0442\u0438 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u0440\u0443\u0447\u043d\u043e\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u043f\u043e\u0447\u0442\u0438 \u043d\u0438\u0447\u0435\u043c\u0443 \u043d\u0430\u0441 \u043d\u0435 \u043d\u0430\u0443\u0447\u0438\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">#[derive(Copy, Clone, Debug)] pub struct Point2 {     x: f32,     y: f32, }  impl Point2 {     pub fn new(...) -> Self {         \/* ... *\/     }      \/* ... *\/ }  impl Add&lt;Point2> for Point2 {     \/* ... *\/ }  impl Sub&lt;Point2> for Point2 {     \/* ... *\/ }  impl Mul&lt;Point2> for f32 {     \/* ... *\/ }  impl Mul&lt;f32> for Point2 {     \/* ... *\/ }  #[cfg(test)] mod tests {     \/* ... *\/ }<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0438 \u043e\u0442\u0447\u0430\u0441\u0442\u0438 \u043f\u043e\u0442\u043e\u043c\u0443, \u0447\u0442\u043e \u044f \u0445\u043e\u0447\u0443 \u043f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c \u0432\u0430\u0441 \u0441 \u043a\u0440\u0435\u0439\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f: <a href=\"https:\/\/nalgebra.org\/\">nalgebra<\/a>!<\/p>\n<p>  <\/p>\n<p>\u0426\u0438\u0442\u0438\u0440\u0443\u044f <a href=\"https:\/\/docs.rs\/nalgebra\/0.26.2\/nalgebra\/\">\u0438\u0445 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e<\/a>:<\/p>\n<p>  <\/p>\n<blockquote><p><code>nalgebra<\/code> \u2014 \u044d\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043b\u0438\u043d\u0435\u0439\u043d\u043e\u0439 \u0430\u043b\u0433\u0435\u0431\u0440\u044b, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u0430\u044f \u0434\u043b\u044f Rust:  <\/p>\n<ul>\n<li>\u043b\u0438\u043d\u0435\u0439\u043d\u0430\u044f \u0430\u043b\u0433\u0435\u0431\u0440\u0430 \u043e\u0431\u0449\u0435\u0433\u043e \u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f (\u0432\u0441\u0435 \u0435\u0449\u0435 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u043c\u043d\u043e\u0433\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439&#8230;)<\/li>\n<li>\u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u0430\u044f \u0433\u0440\u0430\u0444\u0438\u043a\u0430 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/li>\n<li>\u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u043d\u0430\u044f \u0444\u0438\u0437\u0438\u043a\u0430 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438<\/li>\n<\/ul>\n<p>  <\/p><\/blockquote>\n<p>\u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, <code>nalgebra<\/code> \u2014 \u044d\u0442\u043e \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u0434\u043b\u044f \u043b\u044e\u0434\u0435\u0439, \u0441\u0434\u0435\u043b\u0430\u043d\u043d\u0430\u044f \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e, \u0445\u043e\u0440\u043e\u0448\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0430\u044f \u0441 WA.<\/p>\n<p>  <\/p>\n<p><code>nalgebra<\/code> \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432: \u043e\u0442 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a <code>clamp<\/code>, \u0434\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a <a href=\"https:\/\/docs.rs\/nalgebra\/0.26.2\/nalgebra\/geometry\/type.UnitDualQuaternion.html\">\u043a\u0432\u0430\u0442\u0435\u0440\u043d\u0438\u043e\u043d\u044b<\/a>, \u0438 \u0434\u043e \u043d\u0430\u0448\u0435\u0439 \u043b\u044e\u0431\u0438\u043c\u043e\u0439 <a href=\"https:\/\/docs.rs\/nalgebra\/0.26.2\/nalgebra\/geometry\/type.Point2.html\">\u0442\u043e\u0447\u043a\u0438<\/a>.<\/p>\n<p>  <\/p>\n<p>\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># libs\/simulation\/Cargo.toml # ...  [dependencies] nalgebra = \"0.26\"<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0438 \u0437\u0430\u0442\u0435\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">use nalgebra as na; \/\/ --------- ^^ \/\/ | \u0422\u0430\u043a\u043e\u0439 \u0432\u0438\u0434 \u0438\u043c\u043f\u043e\u0440\u0442\u0430 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u043e\u043c (alias). \/\/ | \u041f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c\u043e\u043c `nalgebra` \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f `na`. \/\/ ---  \/* ... *\/  #[derive(Debug)] pub struct Animal {     position: na::Point2&lt;f32>, }  #[derive(Debug)] pub struct Food {     position: na::Point2&lt;f32>, }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u0447\u0435\u043c \u043c\u044b \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c? \u0410\u0445 \u0434\u0430, \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0435 \u0438\u043c\u0435\u044e\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0443\u0433\u043e\u043b \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[derive(Debug)] pub struct Animal {     position: na::Point2&lt;f32>,     rotation: na::Rotation2&lt;f32>,     speed: f32, }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u0412 \u0446\u0435\u043b\u043e\u043c \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432\u043c\u0435\u0441\u0442\u0435 \u0432 \u0432\u0438\u0434\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u0430:<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"rust\">#[derive(Debug)] pub struct Animal {     position: na::Point2&lt;f32>,     velocity: na::Vector2&lt;f32>, }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u041c\u044b \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0432\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043e\u043b\u044f, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u044d\u0442\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439&#8230;\u200b<\/p><\/blockquote>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0431\u044b\u043b\u043e \u0431\u044b \u043d\u0435\u043f\u043b\u043e\u0445\u043e \u0438\u0445 \u043a\u0430\u043a-\u043d\u0438\u0431\u0443\u0434\u044c \u0441\u043a\u043e\u043d\u0441\u0442\u0440\u0443\u0438\u0440\u043e\u0432\u0430\u0442\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># ...  [dependencies] nalgebra = \"0.26\" rand = \"0.8\"<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0438 \u043f\u043e\u043a\u0430 \u043c\u044b \u0437\u0434\u0435\u0441\u044c, \u0432\u043a\u043b\u044e\u0447\u0438\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 <code>rand<\/code> \u0432 <code>nalgebra<\/code> \u2014 \u043e\u043d\u0430 \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u0438\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># ...  [dependencies] nalgebra = { version = \"0.26\", features = [\"rand-no-std\"] } rand = \"0.8\"<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0440\u043d\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0441\u0435 \u0440\u0430\u043d\u0434\u043e\u043c\u0438\u0437\u0438\u0440\u0443\u044e\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">use nalgebra as na; use rand::{Rng, RngCore};  \/* ... *\/  impl Simulation {     pub fn random(rng: &amp;mut dyn RngCore) -> Self {         Self {             world: World::random(rng),         }     } }  impl World {     pub fn random(rng: &amp;mut dyn RngCore) -> Self {         let animals = (0..40)             .map(|_| Animal::random(rng))             .collect();          let foods = (0..60)             .map(|_| Food::random(rng))             .collect();          \/\/ ^ \u041d\u0430\u0448 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u043c \u0438 \u0435\u0434\u0435 \u043d\u0430\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0440\u0443\u0433 \u043d\u0430 \u0434\u0440\u0443\u0433\u0430,         \/\/ | \u044d\u0442\u043e \u043d\u0435 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u043e, \u043d\u043e \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u0441\u043e\u0439\u0434\u0435\u0442.         \/\/ |         \/\/ | \u0411\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430         \/\/ | \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e\u0439 \u0432\u044b\u0431\u043e\u0440\u043a\u0435 \u0441\u0433\u043b\u0430\u0436\u0438\u0432\u0430\u043d\u0438\u044f:         \/\/ |         \/\/ | https:\/\/en.wikipedia.org\/wiki\/Supersampling         \/\/ ---          Self { animals, foods }     } }  impl Animal {     pub fn random(rng: &amp;mut dyn RngCore) -> Self {         Self {             position: rng.gen(),             \/\/ ------ ^-------^             \/\/ | \u0415\u0441\u043b\u0438 \u0431\u044b \u043d\u0435 `rand-no-std`, \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b \u0434\u0435\u043b\u0430\u0442\u044c             \/\/ | `na::Point2::new(rng.gen(), rng.gen())`             \/\/ ---              rotation: rng.gen(),             speed: 0.002,         }     } }  impl Food {     pub fn random(rng: &amp;mut dyn RngCore) -> Self {         Self {             position: rng.gen(),         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p><strong>\u0413\u0435\u0442\u0442\u0435\u0440<\/strong> \u2014 \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u0430, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043f\u0430\u0440\u043e\u0447\u043a\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  impl Simulation {     \/* ... *\/      pub fn world(&amp;self) -> &amp;World {         &amp;self.world     } }  impl World {     \/* ... *\/      pub fn animals(&amp;self) -> &amp;[Animal] {         &amp;self.animals     }      pub fn foods(&amp;self) -> &amp;[Food] {         &amp;self.foods     } }  impl Animal {     \/* ... *\/      pub fn position(&amp;self) -> na::Point2&lt;f32> {         \/\/ ------------------ ^         \/\/ | \u041d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 `na::Point2` \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c\u044b\u043c (\u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0442\u0438\u043f\u0430\u0436 `Copy`).         \/\/ |         \/\/ | (\u043e\u043d \u043d\u0430\u0441\u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0439, \u0447\u0442\u043e \u043a\u043b\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0435\u0448\u0435\u0432\u043b\u0435, \u0447\u0435\u043c \u0432\u043e\u0437\u043d\u044f \u0441 \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438)         \/\/ ---          self.position     }      pub fn rotation(&amp;self) -> na::Rotation2&lt;f32> {         self.rotation     } }  impl Food {     \/* ... *\/      pub fn position(&amp;self) -> na::Point2&lt;f32> {         self.position     } }<\/code><\/pre>\n<p>  <\/p>\n<ul>\n<li>\u041c\u0438\u0440? \u0415\u0441\u0442\u044c.<\/li>\n<li>\u0416\u0438\u0432\u043e\u0442\u043d\u044b\u0435? \u0415\u0441\u0442\u044c.<\/li>\n<li>\u0415\u0434\u0430? \u0415\u0441\u0442\u044c.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e.<\/p>\n<p>  <\/p>\n<p>\u0415\u0449\u0435 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043a\u043e\u0434\u0430, \u043d\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0435\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e JS.<\/p>\n<p>  <\/p>\n<p><strong>JS<\/strong><\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u044c: &#171;\u0415\u0441\u043b\u0438 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u044d\u0442\u043e \u0438\u0437 JS, \u0440\u0430\u0437\u0432\u0435 \u043c\u044b \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u0435\u0437\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>#[wasm_bindgen]<\/code>?&#187;<\/p>\n<p>  <\/p>\n<p>\u2026 \u043d\u0430 \u0447\u0442\u043e \u044f \u043e\u0442\u0432\u0435\u0447\u0443: &#171;\u041e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441!&#187;<\/p>\n<p>  <\/p>\n<p>\u042f \u0434\u0443\u043c\u0430\u044e, \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u044c \u043e <a href=\"https:\/\/en.wikipedia.org\/wiki\/Separation_of_concerns\">\u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u0437\u0430\u0434\u0430\u0447<\/a>: \u0432 <code>lib-simulation<\/code> \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0443\u0434\u0435\u043b\u044f\u0442\u044c\u0441\u044f \u0442\u043e\u043c\u0443, &#171;\u043a\u0430\u043a \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u044e&#187;, \u0430 \u043d\u0435 &#171;\u043a\u0430\u043a \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u044e \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441 WA&#187;.<\/p>\n<p>  <\/p>\n<p>\u0427\u0435\u0440\u0435\u0437 \u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c <code>lib-simulation-wasm<\/code>, \u0438 \u0435\u0441\u043b\u0438 \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u0438\u043c <code>lib-simulation<\/code> \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u043c \u043e\u0442 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430, \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c, \u0441\u043a\u0430\u0436\u0435\u043c, <code>lib-simulation-bevy<\/code> \u0438\u043b\u0438 <code>lib-simulation-cli<\/code> \u2014 \u0432\u0441\u0435 \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u0434 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c.<\/p>\n<p>  <\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e, \u0432\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a <code>lib-simulation-wasm<\/code>. \u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0438\u0442\u044c \u0435\u043c\u0443 \u043e <code>rand<\/code> \u0438 <code>lib-simulation<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># libs\/simulation-wasm\/Cargo.toml  [dependencies] rand = \"0.8\" wasm-bindgen = \"0.2\"  lib-simulation = { path = \"..\/simulation\" }                         # ^ \u043f\u0443\u0442\u044c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043a *\u044d\u0442\u043e\u043c\u0443* Cargo.toml<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u043d\u0443\u0442\u0440\u0438 <code>lib-simulation-wasm<\/code> \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c\u0441\u044f \u043a <code>lib_simulation<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">use lib_simulation as sim;<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0435\u0440\u0442\u043a\u0443 \u0434\u043b\u044f WA (\u044d\u0442\u043e \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <a href=\"https:\/\/en.wikipedia.org\/wiki\/Proxy_pattern\">\u043f\u0440\u043e\u043a\u0441\u0438<\/a>):<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">use lib_simulation as sim; use rand::prelude::*; use wasm_bindgen::prelude::*;  #[wasm_bindgen] pub struct Simulation {     rng: ThreadRng,     sim: sim::Simulation, }  #[wasm_bindgen] impl Simulation {     #[wasm_bindgen(constructor)]     pub fn new() -> Self {         let mut rng = thread_rng();         let sim = sim::Simulation::random(&amp;mut rng);          Self { rng, sim }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u043f\u043b\u043e\u0445\u043e, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043a\u043e\u0434.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">wasm-pack build<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"bash\">INFO]: Checking for the Wasm target... [INFO]: Compiling to Wasm...     Compiling getrandom v0.2.2     error: target is not supported, for more information see:           https:\/\/docs.rs\/getrandom\/#unsupported-targets --> \/home\/pwy\/.cargo\/registry\/src\/... 3:9     | 213 | \/         compile_error!(\"target is not supported, for more information see: \\\\ 214 | |                         https:\/\/docs.rs\/getrandom\/#unsupported-targets\");     | |_________________________________________________________________________^  error[E0433]: failed to resolve: use of undeclared crate or module `imp`    --> \/home\/pwy\/.cargo\/registry\/src\/... 5:5     | 235 |     imp::getrandom_inner(dest)     |     ^^^ use of undeclared crate or module `imp`<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0435\u0441\u0442\u043d\u043e \u0433\u043e\u0432\u043e\u0440\u044f, \u044d\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u0437\u0430\u0441\u0442\u0430\u043b\u0430 \u043c\u0435\u043d\u044f \u0432\u0440\u0430\u0441\u043f\u043b\u043e\u0445. \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, <a href=\"https:\/\/docs.rs\/getrandom\/0.2.2\/getrandom\/#unsupported-targets\">\u0441\u0432\u044f\u0437\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430<\/a> \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443: <code>rand<\/code> \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 <code>getrandom<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 WA \u0434\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u0433\u0434\u0430 \u0435\u0433\u043e \u044f\u0432\u043d\u043e \u043e\u0431 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0441\u044f\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\"># libs\/simulation-wasm\/Cargo.toml  [dependencies] # ... getrandom = { version = \"0.2\", features = [\"js\"] }<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c\u0441\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">[INFO]: Checking for the Wasm target... [INFO]: Compiling to Wasm...  warning: field is never read: `rng`     ...  warning: field is never read: `sim`     ...  warning: 2 warnings emitted      Finished release [optimized] target(s) in 0.01s  [WARN]: origin crate has no README [INFO]: Installing wasm-bindgen... [INFO]: Optimizing wasm binaries with `wasm-opt`... [INFO]: Optional fields missing from Cargo.toml: 'description',         'repository', and 'license'. These are not necessary, but          recommended [INFO]: :-) Done in 0.63s [INFO]: :-) Your wasm pkg is ready to publish at \/home\/pwy\/Projects\/...<\/code><\/pre>\n<p>  <\/p>\n<p>\u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 JS \u043c\u044b \u0442\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ www\/index.js import * as sim from \"lib-simulation-wasm\";  const simulation = new sim.Simulation();<\/code><\/pre>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438!<\/p>\n<p>  <\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0442\u0438\u0445\u0438\u0439 \u0434\u0432\u0438\u0436\u043e\u043a, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u043e\u043d \u043f\u0440\u043e\u0441\u0442\u043e \u0440\u0430\u043d\u0434\u043e\u043c\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0445 \u0438 \u0435\u0434\u0443 \u0438 \u0437\u0430\u043c\u043e\u043b\u043a\u0430\u0435\u0442. \u0427\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0435\u0435, \u043f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 JS.<\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0435\u0449\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043a\u0430\u043a \u0431\u044b \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0438\u0437 <code>lib-simulation<\/code>, \u043d\u043e \u0441 \u0443\u0447\u0435\u0442\u043e\u043c WA:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/\/ libs\/simulation-wasm\/src\/lib.rs \/* ... *\/  #[wasm_bindgen] pub struct Simulation {     \/* ... *\/ }  #[wasm_bindgen] #[derive(Clone, Debug)] pub struct World {     pub animals: Vec&lt;Animal>, }  #[wasm_bindgen] #[derive(Clone, Debug)] pub struct Animal {     pub x: f32,     pub y: f32, } \/\/ ^ \u042d\u0442\u0430 \u043c\u043e\u0434\u0435\u043b\u044c \u043c\u0435\u043d\u044c\u0448\u0435 `lib_simulation::Animal`, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \/\/ | \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u043f\u0442\u0438\u0446\u044b - \u044d\u0442\u043e \u0432\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \/\/ | \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 JS, \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u043b\u044f \u043d\u0430\u043c \u043f\u043e\u043a\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u044b.  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0438 2 \u043c\u0435\u0442\u043e\u0434\u0430 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[wasm_bindgen] impl Simulation {     \/* ... *\/ }  \/* ... *\/  impl From&lt;&amp;sim::World> for World {     fn from(world: &amp;sim::World) -> Self {         let animals = world.animals().iter().map(Animal::from).collect();          Self { animals }     } }  impl From&lt;&amp;sim::Animal> for Animal {     fn from(animal: &amp;sim::Animal) -> Self {         Self {             x: animal.position().x,             y: animal.position().y,         }     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[wasm_bindgen] impl Simulation {     \/* ... *\/      pub fn world(&amp;self) -> World {         World::from(self.sim.world())     } }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c <code>wasm-pack build<\/code> \u0438&#8230;<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">error[E0277]: the trait bound `Vec&lt;Animal>: std::marker::Copy` is not satisfied   --> libs\/simulation-wasm\/src\/lib.rs    |    |     pub animals: Vec&lt;Animal>,    |                            ^ the trait `std::marker::Copy` is not ...    |<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e <code>#[wasm_bindgen]<\/code> \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0433\u0435\u0442\u0442\u0435\u0440\u044b \u0438 \u0441\u0435\u0442\u0442\u0435\u0440\u044b \u0434\u043b\u044f JS, \u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u0438 \u043f\u043e\u043b\u044f \u0431\u044b\u043b\u0438 <code>Copy<\/code>. \u041c\u0430\u043a\u0440\u043e\u0441 \u0434\u0435\u043b\u0430\u0435\u0442 \u043d\u0435\u0447\u0442\u043e \u043f\u043e\u0445\u043e\u0436\u0435\u0435 \u043d\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">impl World {     pub fn animals(&amp;self) -> Vec&lt;Animal> {         self.animals     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0447\u0442\u043e \u0442\u043e\u0436\u0435 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0435\u0437 \u044f\u0432\u043d\u043e\u0433\u043e <code>.clone()<\/code> \u2014 \u044d\u0442\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u043e\u0431\u0449\u0438\u0442\u044c <code>#[wasm_bindgen]<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[wasm_bindgen] #[derive(Clone, Debug)] pub struct World {     #[wasm_bindgen(getter_with_clone)]     pub animals: Vec&lt;Animal>, }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/\/ www\/index.js import * as sim from \"lib-simulation-wasm\";  const simulation = new sim.Simulation(); const world = simulation.world();<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u0441\u0435 \u044d\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c&#8230;\u200b \u0432 \u0442\u0435\u043e\u0440\u0438\u0438, \u043d\u043e \u043a\u0430\u043a \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u043d\u0430\u0448 \u043c\u0438\u0440 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u0437\u043d\u0430\u0447\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435? \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043d\u0430\u0448\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u0433\u043b\u0430\u0437\u0430!<\/p>\n<p>  <\/p>\n<p>\u0411\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430, \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c, \u043d\u0430\u0436\u0430\u0432 <code>F12<\/code>.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c? \u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u0442\u044c \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u0438:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  for (const animal of world.animals) {   console.log(animal.x, animal.y); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0437\u043d\u0430\u0435\u043c \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0445, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0445 \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c!<\/p>\n<p>  <\/p>\n<h2 id=\"privet-grafika\">\u041f\u0440\u0438\u0432\u0435\u0442, \u0433\u0440\u0430\u0444\u0438\u043a\u0430!<\/h2>\n<p>  <\/p>\n<p>\u0420\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0432 HTML + JS \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043b\u0435\u0433\u043a\u043e \u2014 \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0449\u044c \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Canvas_API\/Tutorial\">canvas (\u0445\u043e\u043b\u0441\u0442)<\/a>:<\/p>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;!DOCTYPE html> &lt;html>   &lt;head>     &lt;meta charset=\"utf-8\">     &lt;title>Hello wasm-pack!&lt;\/title>   &lt;\/head>    &lt;body>     &lt;canvas id=\"viewport\">&lt;\/canvas>     &lt;script src=\".\/bootstrap.js\">&lt;\/script>   &lt;\/body> &lt;\/html><\/code><\/pre>\n<p>  <\/p>\n<p>\u0423 \u043d\u0430\u0448\u0435\u0433\u043e \u0445\u043e\u043b\u0441\u0442\u0430 \u0435\u0441\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442 <code>id<\/code> \u2014 \u044d\u0442\u043e\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0442\u0435\u0433\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0439\u0442\u0438 \u0432 JS:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  const viewport = document.getElementById('viewport'); \/\/ ------------- ^------^ \/\/ | `document` - \u044d\u0442\u043e \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \/\/ | \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438 \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043d\u0430 \u043d\u0435\u0439). \/\/ ---<\/code><\/pre>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u043f\u0435\u0440\u0435\u0432\u0430\u0440\u0438\u0442\u044c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0435, \u0441\u043c\u0435\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 <code>console.log(viewport)<\/code> \u0438 \u0438\u0437\u0443\u0447\u0438\u0442\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u0445\u043e\u043b\u0441\u0442\u0430 \u2014 \u0438\u0445 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e!<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u0447\u0442\u043e-\u043b\u0438\u0431\u043e \u043d\u0430 <code>canvas<\/code>, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f (2D \u0438\u043b\u0438 3D):<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  const ctxt = viewport.getContext('2d');<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u0414\u043b\u044f \u0441\u043f\u0440\u0430\u0432\u043a\u0438, \u043d\u0430\u0448 <code>ctxt<\/code> \u0438\u043c\u0435\u0435\u0442 \u0442\u0438\u043f <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/CanvasRenderingContext2D\">CanvasRenderingContext2D<\/a>.<\/p><\/blockquote>\n<p>\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0432\u044b\u0437\u0432\u0430\u0442\u044c \u043d\u0430 <code>ctxt<\/code>. \u041d\u0430\u0447\u043d\u0435\u043c \u0441 <code>fillStyle<\/code> \u0438 <code>fillRect()<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  \/\/ --- \/\/ | \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0446\u0432\u0435\u0442 \u0444\u0438\u0433\u0443\u0440\u044b. \/\/ - v-------v ctxt.fillStyle = 'rgb(255, 0, 0)'; \/\/ ------------------ ^-^ -^ -^ \/\/ | \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u0442\u0440\u0435\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 - \u0447\u0438\u0441\u043b\u043e \u043e\u0442 0 \u0434\u043e 255, \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e: \/\/ | \/\/ | rgb(0, 0, 0) = black \/\/ | \/\/ | rgb(255, 0, 0) = red \/\/ | rgb(0, 255, 0) = green \/\/ | rgb(0, 0, 255) = blue \/\/ | \/\/ | rgb(255, 255, 0) = yellow \/\/ | rgb(0, 255, 255) = cyan \/\/ | rgb(255, 0, 255) = magenta \/\/ | \/\/ | rgb(128, 128, 128) = gray \/\/ | rgb(255, 255, 255) = white \/\/ ---  ctxt.fillRect(10, 10, 100, 50); \/\/ ---------- X   Y   W    H \/\/ | \u0420\u0438\u0441\u0443\u0435\u0442 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a, \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0432\u0435\u0442\u043e\u043c, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e `fillStyle`. \/\/ | \/\/ | X = \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430 \u043f\u043e \u043e\u0441\u0438 X (\u0441\u043b\u0435\u0432\u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043e) \/\/ | Y = \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430 \u043f\u043e \u043e\u0441\u0438 Y (\u0441\u0432\u0435\u0440\u0445\u0443 \u0432\u043d\u0438\u0437) \/\/ | W = \u0448\u0438\u0440\u0438\u043d\u0430 \/\/ | X = \u0432\u044b\u0441\u043e\u0442\u0430 \/\/ | \/\/ | (\u0435\u0434\u0438\u043d\u0438\u0446\u0430 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f - \u043f\u0438\u043a\u0441\u0435\u043b\u044c) \/\/ ---<\/code><\/pre>\n<p>  <\/p>\n<p>\u0417\u0430\u043f\u0443\u0441\u043a \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0448 <code>canvas<\/code> \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043a\u0440\u0430\u0441\u043d\u044b\u0439 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/vh\/ps\/7y\/vhps7yrw8aasjekmg-v5z3_n-qy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/vh\/ps\/7y\/vhps7yrw8aasjekmg-v5z3_n-qy.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0410\u0445, \u041c\u043e\u043d\u0434\u0440\u0438\u0430\u043d \u0431\u044b\u043b \u0431\u044b \u0442\u0430\u043a \u0433\u043e\u0440\u0434 \u2014 \u0433\u043e\u0432\u043e\u0440\u044e \u0432\u0430\u043c: \u043c\u044b \u0434\u0432\u0438\u0433\u0430\u0435\u043c\u0441\u044f \u0432 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438!<\/p>\n<p>  <\/p>\n<blockquote><p>\u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 <code>canvas<\/code>:<\/p><\/blockquote>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/u_\/ak\/zb\/u_akzbulraxvb88oaxb1-2629cy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/u_\/ak\/zb\/u_akzbulraxvb88oaxb1-2629cy.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p><strong>\u042d\u0442\u043e \u043c\u043e\u0438 \u0434\u0430\u043d\u043d\u044b\u0435<\/strong><\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0437\u043d\u0430\u0435\u043c, \u043a\u0430\u043a \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">import * as sim from \"lib-simulation-wasm\";  const simulation = new sim.Simulation(); const viewport = document.getElementById('viewport'); const ctxt = viewport.getContext('2d');  ctxt.fillStyle = 'rgb(0, 0, 0)';  for (const animal of simulation.world().animals) {     ctxt.fillRect(animal.x, animal.y, 15, 15); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0438:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/lo\/zk\/du\/lozkdutqig7pzeudrsrzhv6vrpo.png\" data-src=\"https:\/\/habrastorage.org\/webt\/lo\/zk\/du\/lozkdutqig7pzeudrsrzhv6vrpo.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u0441\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c? \u0418\u0437\u0443\u0447\u0438\u043c \u043d\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0435\u0449\u0435 \u0440\u0430\u0437:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  for (const animal of simulation.world().animals) {   console.log(animal.x, animal.y); }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"bash\">0.6751065850257874 0.9448947906494141 0.2537931203842163 0.4474523663520813 0.7111597061157227 0.731094241142273 0.20178401470184326 0.5820554494857788 0.7062546610832214 0.3024316430091858 0.030273854732513428 0.4638679623603821 0.48392945528030396 0.9207395315170288 0.49439138174057007 0.24340438842773438 0.5087683200836182 0.10066533088684082 \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u0437\u0438\u0446\u0438\u0438 \u043d\u0430\u0448\u0438\u0445 \u0436\u0438\u0432\u043e\u0442\u043d\u044b\u0445 \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0430\u0442 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0443 <code>&lt;0.0, 1.0><\/code>, \u0430 <code>canvas<\/code> \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445 \u2014 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u044f \u0447\u0438\u0441\u043b\u0430 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  const viewport = document.getElementById('viewport'); const viewportWidth = viewport.width; const viewportHeight = viewport.height;  \/* ... *\/  for (const animal of simulation.world().animals) {     ctxt.fillRect(         animal.x * viewportWidth,         animal.y * viewportHeight,         15,         15,     ); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0447\u0442\u043e \u0434\u0430\u0435\u0442 \u043d\u0430\u043c:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/mg\/ef\/fz\/mgeffz1rzr6r987vtcs4jq6ofzy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/mg\/ef\/fz\/mgeffz1rzr6r987vtcs4jq6ofzy.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<blockquote><p>\u0415\u0441\u043b\u0438 \u0432\u044b \u044f\u0432\u043b\u044f\u0435\u0442\u0435\u0441\u044c \u0441\u0447\u0430\u0441\u0442\u043b\u0438\u0432\u044b\u043c \u043e\u0431\u043b\u0430\u0434\u0430\u0442\u0435\u043b\u0435\u043c \u0434\u0438\u0441\u043f\u043b\u0435\u044f HiDPI, \u0442\u043e \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0445\u043e\u043b\u0441\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u044b\u0442\u044b\u043c \u2014 \u043d\u0435 \u0442\u0440\u043e\u0433\u0430\u0439\u0442\u0435 \u043c\u043e\u043d\u0438\u0442\u043e\u0440, \u0432\u0441\u0435 &#171;\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e&#187;.<\/p>\n<p>  \u042d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0432\u0441\u0435, \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442 \u0445\u043e\u043b\u0441\u0442\u044b \u0431\u0435\u0437 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u043f\u043b\u043e\u0442\u043d\u043e\u0441\u0442\u0438 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u044d\u043a\u0440\u0430\u043d\u0430, \u0430 \u0437\u0430\u0442\u0435\u043c \u0438\u0441\u043a\u0443\u0441\u0441\u0442\u0432\u0435\u043d\u043d\u043e <strong>\u043f\u043e\u0432\u044b\u0448\u0430\u044e\u0442<\/strong> \u043c\u0430\u0441\u0448\u0442\u0430\u0431 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u043e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u043e \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c\u0443 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044e \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<p>  \u041f\u0440\u0435\u043e\u0434\u043e\u043b\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e &#171;\u043d\u0435\u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430&#187; \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0445\u0438\u0442\u0440\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u0440\u0443\u0447\u043d\u043e\u043c\u0443 \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u0438\u044e \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432 \u0445\u043e\u043b\u0441\u0442\u0430 \u043f\u0435\u0440\u0435\u0434 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435\u043c, \u0447\u0442\u043e\u0431\u044b &#171;\u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c&#187; \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e:<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  const viewportWidth = viewport.width; const viewportHeight = viewport.height;  const viewportScale = window.devicePixelRatio || 1; \/\/ ------------------------------------------ ^^^^ \/\/ | \u042d\u0442\u043e \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 `.unwrap_or(1)` \/\/ | \/\/ | \u042d\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \/\/ | \u0432 \u043e\u0434\u043d\u043e\u043c \u043f\u0438\u043a\u0441\u0435\u043b\u0435 \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435. \/\/ | \/\/ | \u041d\u0435 HiDPI \u0434\u0438\u0441\u043f\u043b\u0435\u0438 \u043e\u0431\u044b\u0447\u043d\u043e \u0438\u043c\u0435\u044e\u0442 \u043f\u043b\u043e\u0442\u043d\u043e\u0441\u0442\u044c \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439, \u0440\u0430\u0432\u043d\u0443\u044e 1.0. \/\/ | \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435 \u0440\u0430\u0441\u043a\u0440\u0430\u0441\u0438\u0442 \/\/ | \u0440\u043e\u0432\u043d\u043e \u043e\u0434\u0438\u043d \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0438\u043a\u0441\u0435\u043b\u044c \u043d\u0430 \u044d\u043a\u0440\u0430\u043d\u0435. \/\/ | \/\/ | \u041c\u043e\u0439 \u0434\u0438\u0441\u043f\u043b\u0435\u0439 \u0438\u043c\u0435\u0435\u0442 \u043f\u043b\u043e\u0442\u043d\u043e\u0441\u0442\u044c \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439, \u0440\u0430\u0432\u043d\u0443\u044e 2.0. \/\/ | \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u043f\u0438\u043a\u0441\u0435\u043b\u044e, \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u043c\u0443 \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435, \/\/ | \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0434\u0432\u0430 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0438\u043a\u0441\u0435\u043b\u044f, \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c. \/\/ ---  \/\/ \u0422\u0440\u044e\u043a, \u0447\u0430\u0441\u0442\u044c 1: \u043c\u044b \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u043c *\u0431\u0443\u0444\u0435\u0440* \u0445\u043e\u043b\u0441\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043e\u043d \/\/ \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u043b \u0441 \u043f\u043b\u043e\u0442\u043d\u043e\u0441\u0442\u044c\u044e \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u044d\u043a\u0440\u0430\u043d\u0430 viewport.width = viewportWidth * viewportScale; viewport.height = viewportHeight * viewportScale;  \/\/ \u0422\u0440\u044e\u043a, \u0447\u0430\u0441\u0442\u044c 2: \u043c\u044b \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u0435\u043c *\u044d\u043b\u0435\u043c\u0435\u043d\u0442* \u0445\u043e\u043b\u0441\u0442\u0430, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \/\/ \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0443\u043c\u043d\u043e\u0436\u0438\u0442 \u0435\u0433\u043e \u043d\u0430 \u043f\u043b\u043e\u0442\u043d\u043e\u0441\u0442\u044c \u043f\u0438\u043a\u0441\u0435\u043b\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 \u043c\u0433\u043d\u043e\u0432\u0435\u043d\u0438\u0435. \/\/ \/\/ \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0431\u0435\u0441\u043f\u043e\u043b\u0435\u0437\u043d\u044b\u043c, \u043d\u043e \u0441\u0443\u0442\u044c \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \/\/ \u0447\u0442\u043e \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0445\u043e\u043b\u0441\u0442\u0430 \u043d\u0435 \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \/\/ \u0440\u0430\u0437\u043c\u0435\u0440 \u0435\u0433\u043e \u0431\u0443\u0444\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 *\u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f* \u0443\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u044b\u043c: \/\/ \/\/ ----------- &lt; \u043d\u0430\u0448\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \/\/ |         | \/\/ |   ---   | \/\/ |   | | &lt; | &lt; \u043d\u0430\u0448 \u0445\u043e\u043b\u0441\u0442 \/\/ |   ---   |   (\u0440\u0430\u0437\u043c\u0435\u0440: viewport.style.width &amp; viewport.style.height) \/\/ |         | \/\/ ----------- \/\/ \/\/ \u0417\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430: \/\/ \/\/ ----- &lt; \u0431\u0443\u0444\u0435\u0440 \u043d\u0430\u0448\u0435\u0433\u043e \u0445\u043e\u043b\u0441\u0442\u0430 \/\/ |   | (\u0440\u0430\u0437\u043c\u0435\u0440: viewport.width &amp; viewport.height) \/\/ |   | \/\/ ----- viewport.style.width = viewportWidth + 'px'; viewport.style.height = viewportHeight + 'px';  const ctxt = viewport.getContext('2d');  \/\/ \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442 \u0432\u0441\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u0430 `viewportScale`, \u0438\u043d\u0430\u0447\u0435 \/\/ \u043d\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0431\u044b `* viewportScale` \u0432\u0441\u0435 \u0432\u0440\u0443\u0447\u043d\u0443\u044e ctxt.scale(viewportScale, viewportScale);  \/\/ \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0434 \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 ctxt.fillStyle = 'rgb(0, 0, 0)';  for (const animal of simulation.world().animals) {     ctxt.fillRect(         animal.x * viewportWidth,         animal.y * viewportHeight,         15,         15,     ); }<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u042d\u0442\u043e \u0434\u0430\u0435\u0442 \u043d\u0430\u043c \u0447\u0435\u0442\u043a\u043e\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435:<\/p><\/blockquote>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/w3\/ck\/4l\/w3ck4lzano-ktld2bjftqyy4ddu.png\" data-src=\"https:\/\/habrastorage.org\/webt\/w3\/ck\/4l\/w3ck4lzano-ktld2bjftqyy4ddu.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0412\u0435\u0440\u0438\u0442\u0435 \u0438\u043b\u0438 \u043d\u0435\u0442, \u043d\u043e \u043a\u0442\u043e-\u0442\u043e \u0441\u043a\u0430\u0437\u0430\u043b \u043c\u043d\u0435, \u0447\u0442\u043e \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u043d\u043e\u0435 \u0443\u0436\u0435 <strong>\u043d\u0435 \u0432 \u043c\u043e\u0434\u0435<\/strong>!<\/p>\n<p>  <\/p>\n<p>\u0421\u0443\u0434\u044f \u043f\u043e \u0432\u0441\u0435\u043c\u0443, \u0441\u0435\u0439\u0447\u0430\u0441 \u0432 \u043c\u043e\u0434\u0435 \u25bc \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u25b2, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043e\u0434\u0438\u043d.<\/p>\n<p>  <\/p>\n<p>\u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, JS \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u0430 \u0434\u043b\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432\u0440\u0443\u0447\u043d\u0443\u044e, \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u0437\u0430 \u0432\u0435\u0440\u0448\u0438\u043d\u043e\u0439.<\/p>\n<p>  <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u0436\u0435\u0441\u0442\u043a\u043e \u0437\u0430\u043a\u043e\u0434\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  \/\/ \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a ctxt.beginPath();  \/\/ \u041f\u0435\u0440\u0435\u0434\u0432\u0438\u0433\u0430\u0435\u043c \u043a\u0443\u0440\u0441\u043e\u0440 \u043d\u0430 x=50, y=0 ctxt.moveTo(50, 0);  \/\/ \u0420\u0438\u0441\u0443\u0435\u043c \u043b\u0438\u043d\u0438\u044e \u043e\u0442 (50,0) \u0434\u043e (100,50) \u0438 \u043f\u0435\u0440\u0435\u0434\u0432\u0438\u0433\u0430\u0435\u043c \u043a\u0443\u0440\u0441\u043e\u0440 \u0442\u0443\u0434\u0430 \/\/ (\u044d\u0442\u043e \u0440\u0438\u0441\u0443\u0435\u0442 \u043f\u0440\u0430\u0432\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443 \u043d\u0430\u0448\u0435\u0433\u043e \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430) ctxt.lineTo(100, 50);  \/\/ \u0420\u0438\u0441\u0443\u0435\u043c \u043b\u0438\u043d\u0438\u044e \u043e\u0442 (100,50) \u0434\u043e (0,50) \u0438 \u043f\u0435\u0440\u0435\u0434\u0432\u0438\u0433\u0430\u0435\u043c \u043a\u0443\u0440\u0441\u043e\u0440 \u0442\u0443\u0434\u0430 \/\/ (\u044d\u0442\u043e \u0440\u0438\u0441\u0443\u0435\u0442 \u043d\u0438\u0436\u043d\u044e\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443) ctxt.lineTo(0, 50);  \/\/ \u0420\u0438\u0441\u0443\u0435\u043c \u043b\u0438\u043d\u0438\u044e \u043e\u0442 (0,50) \u0434\u043e (50,0) \u0438 \u043f\u0435\u0440\u0435\u0434\u0432\u0438\u0433\u0430\u0435\u043c \u043a\u0443\u0440\u0441\u043e\u0440 \u0442\u0443\u0434\u0430 \/\/ (\u044d\u0442\u043e \u0440\u0438\u0441\u0443\u0435\u0442 \u043b\u0435\u0432\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443) ctxt.lineTo(50, 0);  \/\/ \u0417\u0430\u043b\u0438\u0432\u0430\u0435\u043c \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0447\u0435\u0440\u043d\u044b\u043c \u0446\u0432\u0435\u0442\u043e\u043c \/\/ (\u0442\u0430\u043a\u0436\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 `ctxt.stroke();`, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0440\u0438\u0441\u0443\u0435\u0442 \/\/ \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u0431\u0435\u0437 \u0437\u0430\u043b\u0438\u0432\u043a\u0438). ctxt.fillStyle = 'rgb(0, 0, 0)'; ctxt.fill();<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u0430\u043a\u0430\u044f \u043a\u0440\u0430\u0441\u043e\u0442\u0430!<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0448\u0430\u0433\u043e\u0432, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  function drawTriangle(ctxt, x, y, size) {     ctxt.beginPath();     ctxt.moveTo(x, y);     ctxt.lineTo(x + size, y + size);     ctxt.lineTo(x - size, y + size);     ctxt.lineTo(x, y);      ctxt.fillStyle = 'rgb(0, 0, 0)';     ctxt.fill(); }  drawTriangle(ctxt, 50, 0, 50);<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0438\u043b\u0438 \u0435\u0441\u043b\u0438 \u0431\u044b\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0438\u0434\u0438\u043e\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  \/\/ --- \/\/ | \u0422\u0438\u043f (\u0442\u043e\u0447\u043d\u0435\u0435, \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f) \u043d\u0430\u0448\u0435\u0433\u043e `ctxt`. \/\/ v------------------ v CanvasRenderingContext2D.prototype.drawTriangle =     function (x, y, size) {         this.beginPath();         this.moveTo(x, y);         this.lineTo(x + size, y + size);         this.lineTo(x - size, y + size);         this.lineTo(x, y);          this.fillStyle = 'rgb(0, 0, 0)';         this.fill();     };  ctxt.drawTriangle(50, 0, 50);<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u0438\u043c. \u043f\u0435\u0440.: \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <a href=\"https:\/\/flaviocopes.com\/javascript-why-not-modify-object-prototype\/\">\u0430\u043d\u0442\u0438\u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u043c \u0432 JS<\/a>.<\/p>\n<p>  <\/p>\n<blockquote><p>JS \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043a\u043e\u0434 \u043d\u0430 Rust \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b \u0431\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0438\u043f\u0430\u0436\u0430:<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"rust\">trait DrawTriangle {     fn draw_triangle(&amp;mut self, x: f32, y: f32, size: f32); }  impl DrawTriangle for CanvasRenderingContext2D {     fn draw_triangle(&amp;mut self, x: f32, y: f32, size: f32) {         self.begin_path();         \/* ... *\/     } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a:<\/p>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;!-- ... --> &lt;canvas id=\"viewport\" width=\"800\" height=\"800\">&lt;\/canvas> &lt;!-- ... --><\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  for (const animal of simulation.world().animals) {     ctxt.drawTriangle(         animal.x * viewportWidth,         animal.y * viewportHeight,         0.01 * viewportWidth,     ); }<\/code><\/pre>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/-i\/de\/tp\/-idetpdvew-dvgkpoqpfhc2cu5o.png\" data-src=\"https:\/\/habrastorage.org\/webt\/-i\/de\/tp\/-idetpdvew-dvgkpoqpfhc2cu5o.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0415\u0441\u043b\u0438 \u044d\u0442\u0438 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u043a\u0430\u0436\u0443\u0442\u0441\u044f \u0432\u0430\u043c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u043c\u0438, \u0441\u043c\u0435\u043b\u043e \u0440\u0435\u0433\u0443\u043b\u0438\u0440\u0443\u0439\u0442\u0435 \u0440\u0430\u0437\u043c\u0435\u0440 \u0445\u043e\u043b\u0441\u0442\u0430 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>0.01<\/code>.<\/p>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e ?<\/p>\n<p>  <\/p>\n<p>\u2026 \u0438 \u0437\u043d\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0435\u0449\u0435 \u043b\u0443\u0447\u0448\u0435? \u0415\u0441\u043b\u0438 \u0431\u044b \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u0431\u044b\u043b\u0438 \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044b\u043c\u0438!<\/p>\n<p>  <\/p>\n<p><strong>\u0412\u0435\u0440\u0448\u0438\u043d\u044b<\/strong><\/p>\n<p>  <\/p>\n<p>\u0423 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u0435 <code>rotation<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 <code>lib-simulation<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[derive(Debug)] pub struct Animal {     \/* ... *\/     rotation: na::Rotation2&lt;f32>,     \/* ... *\/ }<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u044d\u0442\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u0433\u043e \u0432 JS:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[wasm_bindgen] #[derive(Clone, Debug)] pub struct Animal {     pub x: f32,     pub y: f32,     pub rotation: f32, }  impl From&lt;&amp;sim::Animal> for Animal {     fn from(animal: &amp;sim::Animal) -> Self {         Self {             x: animal.position().x,             y: animal.position().y,             rotation: animal.rotation().angle(),         }     } }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c <code>wasm-pack build<\/code> \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u043a JS.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u043d\u044b\u043c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430, \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  CanvasRenderingContext2D.prototype.drawTriangle =     function (x, y, size, rotation) {         \/* ... *\/     };  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u043c\u044b \u0438\u0449\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/kw\/rt\/ug\/kwrtug4dbrbnklbcl64wwysahdg.png\" data-src=\"https:\/\/habrastorage.org\/webt\/kw\/rt\/ug\/kwrtug4dbrbnklbcl64wwysahdg.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u2026 \u043d\u043e \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u043e\u0435 \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u0443\u0433\u043b\u0430.<\/p>\n<p>  <\/p>\n<p><strong>\u0412\u0435\u0440\u0448\u0438\u043d\u044b (\u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430)<\/strong><\/p>\n<p>  <\/p>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0443 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043e\u043a\u0440\u0443\u0436\u043d\u043e\u0441\u0442\u044c\u044e:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/gl\/hy\/eq\/glhyeq8kpnridzqw214hla0m-hi.png\" data-src=\"https:\/\/habrastorage.org\/webt\/gl\/hy\/eq\/glhyeq8kpnridzqw214hla0m-hi.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u044f \u0431\u044b \u043e\u043f\u0438\u0441\u0430\u043b \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u0432\u0434\u043e\u043b\u044c \u043a\u0440\u0443\u0433\u0430 &#171;\u043f\u043e\u0434&#187; \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0443\u0433\u043b\u043e\u043c:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/iz\/pn\/aj\/izpnajmfowimoipxbwoz74yzd_e.png\" data-src=\"https:\/\/habrastorage.org\/webt\/iz\/pn\/aj\/izpnajmfowimoipxbwoz74yzd_e.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041a\u0430\u043a \u0443\u0437\u043d\u0430\u0442\u044c, \u043a\u0443\u0434\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0442\u044c \u044d\u0442\u0438 \u0442\u043e\u0447\u043a\u0438? \u0427\u0442\u043e \u0436, \u043a\u043e\u0433\u0434\u0430 \u0440\u0435\u0447\u044c \u0438\u0434\u0435\u0442 \u043e \u043a\u0440\u0443\u0433\u0435, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043f\u0440\u0438\u0431\u0435\u0433\u0430\u044e\u0442 \u043a \u0442\u0440\u0438\u0433\u043e\u043d\u043e\u043c\u0435\u0442\u0440\u0438\u0438.<\/p>\n<p>  <\/p>\n<p>\u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0432\u044b \u0441\u043b\u044b\u0448\u0430\u043b\u0438 \u043e <code>cos()<\/code> \u0438 <code>sin()<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/5h\/au\/ei\/5haueietgachmdspxhziznnvdva.png\" data-src=\"https:\/\/habrastorage.org\/webt\/5h\/au\/ei\/5haueietgachmdspxhziznnvdva.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u041f\u0440\u0438 \u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043a \u043a\u0440\u0443\u0433\u0443, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e <code>cos(angle)<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0443 <code>y<\/code> \u0442\u043e\u0447\u043a\u0438, &#171;\u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u043e\u0439&#187; \u043d\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0443\u0433\u043e\u043b, \u0430 <code>sin(angle)<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0443 <code>x<\/code>:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/3f\/s2\/su\/3fs2suxnezf9tc5zimarlqhidyw.png\" data-src=\"https:\/\/habrastorage.org\/webt\/3f\/s2\/su\/3fs2suxnezf9tc5zimarlqhidyw.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<blockquote><p>\u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u043a\u0430\u0432\u044b\u0447\u043a\u0438 \u0432\u043e\u043a\u0440\u0443\u0433 <em>\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u044f<\/em> \u0442\u043e\u0447\u043a\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u0442\u043e\u0447\u043a\u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0441\u043c\u044b\u0441\u043b\u0430. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0438 \u0441\u0440\u0435\u0434\u0438 \u0432\u0430\u0441 \u043f\u0440\u043e\u0441\u0442\u044f\u0442 \u043c\u0435\u043d\u044f \u0437\u0430 \u044d\u0442\u043e\u0442 \u0434\u043e\u0431\u0440\u043e\u0441\u043e\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u0441\u0435\u043c\u0430\u043d\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0433\u0440\u0435\u0445.<\/p>\n<p>  \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>x = -sin(angle)<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e <code>nalgebra<\/code> \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u0442 \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043f\u0440\u043e\u0442\u0438\u0432 \u0447\u0430\u0441\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0435\u043b\u043a\u0438.<\/p><\/blockquote>\n<p>\u0415\u0441\u043b\u0438 \u0442\u043e, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">this.moveTo(x, y);<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0437\u043d\u0430\u0447\u0438\u0442, \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b <code>x<\/code> \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f <code>- sin()<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">this.moveTo(     x - Math.sin(rotation) * size,     y, );<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0430 \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b <code>y<\/code> \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u044f <code>+ cos()<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">this.moveTo(     x - Math.sin(rotation) * size,     y + Math.cos(rotation) * size, );<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0433\u0434\u0435 <code>rotation<\/code> \u0438\u0437\u043c\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0432 <strong>\u0440\u0430\u0434\u0438\u0430\u043d\u0430\u0445<\/strong>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 <code>&lt;0\u00b0, 360\u00b0><\/code> \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f <code>&lt;0, 2 * PI><\/code>:<\/p>\n<p>  <\/p>\n<ul>\n<li>0\u00b0 \u21d2 <code>rotation = 0<\/code><\/li>\n<li>180\u00b0 \u21d2 <code>rotation = PI<\/code><\/li>\n<li>360\u00b0 \u21d2 <code>rotation = 2 * PI<\/code><\/li>\n<li>90\u00b0 \u21d2 180\u00b0 \/ 2 \u21d2 <code>rotation = PI \/ 2<\/code><\/li>\n<li>45\u00b0 \u21d2 180\u00b0 \/ 4 \u21d2 <code>rotation = PI \/ 4<\/code><\/li>\n<li>\u0438 \u0442.\u0434.<\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u0441 \u043e\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u043e\u0439 \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/uh\/jh\/j8\/uhjhj8s8ealtniwfpfafdfhlw5w.png\" data-src=\"https:\/\/habrastorage.org\/webt\/uh\/jh\/j8\/uhjhj8s8ealtniwfpfafdfhlw5w.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u2026 \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0435\u0449\u0435 \u0434\u0432\u0435.<\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432\u0435\u0441\u044c \u043a\u0440\u0443\u0433 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 360\u00b0, \u0430 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0442\u0440\u0438 \u0432\u0435\u0440\u0448\u0438\u043d\u044b, \u0442\u043e \u043a\u0430\u0436\u0434\u0430\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043d\u0438\u043c\u0430\u0442\u044c 360\u00b0\/3 = 120\u00b0; \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u044f, \u0447\u0442\u043e \u043f\u0435\u0440\u0432\u0430\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u043b\u0435\u0436\u0438\u0442 \u043d\u0430 0\u00b0, \u0432\u0442\u043e\u0440\u0430\u044f \u0432\u0435\u0440\u0448\u0438\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0430 \u043d\u0430 120\u00b0.<\/p>\n<p>  <\/p>\n<p>\u0411\u044b\u0441\u0442\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0432\u043e\u0434 \u0432 \u0440\u0430\u0434\u0438\u0430\u043d\u044b \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u043f\u043e\u0440\u0446\u0438\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">{ 2 * PI = 360\u00b0 {      x = 120\u00b0           ^          |          v  360\u00b0 * x = 2 * PI * 120\u00b0    | \u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 2 180\u00b0 * x = PI * 120\u00b0        | \u0434\u0435\u043b\u0438\u0442\u044c \u043d\u0430 180\u00b0        x = PI * 120\u00b0 \/ 180\u00b0 | \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442\u044c        x = PI * 2 \/ 3       | \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u0443        x = 2 \/ 3 * PI       | \u043d\u0430\u0441\u043b\u0430\u0436\u0434\u0430\u0442\u044c\u0441\u044f<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0447\u0442\u043e \u0434\u0430\u0435\u0442 \u043d\u0430\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">this.moveTo(     x - Math.sin(rotation) * size,     y + Math.cos(rotation) * size, );  this.lineTo(     x - Math.sin(rotation + 2.0 \/ 3.0 * Math.PI) * size,     y + Math.cos(rotation + 2.0 \/ 3.0 * Math.PI) * size, );<\/code><\/pre>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/hw\/d2\/ee\/hwd2eeazeiaxmtznlyzu1iqj_ye.png\" data-src=\"https:\/\/habrastorage.org\/webt\/hw\/d2\/ee\/hwd2eeazeiaxmtznlyzu1iqj_ye.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0414\u043b\u044f \u0442\u0440\u0435\u0442\u044c\u0435\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">2 * PI = 360\u00b0      x = 120\u00b0 + 120\u00b0  \/* ... *\/  x = 4 \/ 3 * PI<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0447\u0442\u043e \u0434\u0430\u0435\u0442 \u043d\u0430\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">this.moveTo(     x - Math.sin(rotation) * size,     y + Math.cos(rotation) * size, );  this.lineTo(     x - Math.sin(rotation + 2.0 \/ 3.0 * Math.PI) * size,     y + Math.cos(rotation + 2.0 \/ 3.0 * Math.PI) * size, );  this.lineTo(     x - Math.sin(rotation + 4.0 \/ 3.0 * Math.PI) * size,     y + Math.cos(rotation + 4.0 \/ 3.0 * Math.PI) * size, );<\/code><\/pre>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/-i\/tk\/vu\/-itkvu95qd--0wwf85-qfvuuqcc.png\" data-src=\"https:\/\/habrastorage.org\/webt\/-i\/tk\/vu\/-itkvu95qd--0wwf85-qfvuuqcc.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<blockquote><p>\u0412\u043c\u0435\u0441\u0442\u043e <code>+ 4.0 \/ 3.0<\/code>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>- 2.0 \/ 3.0<\/code> (60\u00b0 \u043f\u0440\u043e\u0442\u0438\u0432 \u0447\u0430\u0441\u043e\u0432\u043e\u0439 \u0441\u0442\u0440\u0435\u043b\u043a\u0438 \u043e\u0442 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b):<\/p><\/blockquote>\n<p>  <\/p>\n<pre><code class=\"javascript\">this.lineTo(     x - Math.sin(rotation - 2.0 \/ 3.0 * Math.PI) * size,     y + Math.cos(rotation - 2.0 \/ 3.0 * Math.PI) * size, );<\/code><\/pre>\n<p>  <\/p>\n<blockquote><p>\u2026 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0431\u0443\u0434\u0435\u0442 <a href=\"https:\/\/www.wolframalpha.com\/input\/?i=sin%28x+-+2%2F3+*+pi%29+%3D+sin%28x+%2B+4%2F3+*+pi%29\">\u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c<\/a>.<\/p><\/blockquote>\n<p>\u041d\u0430\u043c \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0440\u0435\u0431\u0440\u0430, \u0438\u0434\u0443\u0449\u0435\u0433\u043e \u0438\u0437 \u0442\u0440\u0435\u0442\u044c\u0435\u0439 \u0432\u0435\u0440\u0448\u0438\u043d\u044b \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 \u043f\u0435\u0440\u0432\u0443\u044e:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/xt\/-g\/px\/xt-gpx1vq3psjlgvrioplttgzni.png\" data-src=\"https:\/\/habrastorage.org\/webt\/xt\/-g\/px\/xt-gpx1vq3psjlgvrioplttgzni.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u2026 \u043f\u043e\u044d\u0442\u043e\u043c\u0443:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  this.lineTo(     x - Math.sin(rotation + 4.0 \/ 3.0 * Math.PI) * size,     y + Math.cos(rotation + 4.0 \/ 3.0 * Math.PI) * size, );  this.lineTo(     x - Math.sin(rotation) * size,     y + Math.cos(rotation) * size, );<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u0434:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  CanvasRenderingContext2D.prototype.drawTriangle =     function (x, y, size, rotation) {         this.beginPath();          this.moveTo(             x - Math.sin(rotation) * size,             y + Math.cos(rotation) * size,         );          this.lineTo(             x - Math.sin(rotation + 2.0 \/ 3.0 * Math.PI) * size,             y + Math.cos(rotation + 2.0 \/ 3.0 * Math.PI) * size,         );          this.lineTo(             x - Math.sin(rotation + 4.0 \/ 3.0 * Math.PI) * size,             y + Math.cos(rotation + 4.0 \/ 3.0 * Math.PI) * size,         );          this.lineTo(             x - Math.sin(rotation) * size,             y + Math.cos(rotation) * size,         );          this.stroke();     };  ctxt.drawTriangle(50, 50, 25, Math.PI \/ 4);<\/code><\/pre>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442?<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/rl\/eq\/de\/rleqde1qwdqwbbaqc9knfjzylpy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/rl\/eq\/de\/rleqde1qwdqwbbaqc9knfjzylpy.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u2026 \u043d\u043e \u0441\u043b\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442. \u0427\u0442\u043e, \u0435\u0441\u043b\u0438 \u043c\u044b \u0432\u044b\u0442\u044f\u043d\u0435\u043c \u043e\u0434\u043d\u0443 \u0438\u0437 \u0432\u0435\u0440\u0448\u0438\u043d?<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  CanvasRenderingContext2D.prototype.drawTriangle =     function (x, y, size, rotation) {         this.beginPath();          this.moveTo(             x - Math.sin(rotation) * size * 1.5,             y + Math.cos(rotation) * size * 1.5,         );          \/* ... *\/          this.lineTo(             x - Math.sin(rotation) * size * 1.5,             y + Math.cos(rotation) * size * 1.5,         );          this.stroke();     };  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u043b\u0443\u0447\u0448\u0435:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/yf\/fi\/mf\/yffimfvoqxef9lrbveymvadzcjk.png\" data-src=\"https:\/\/habrastorage.org\/webt\/yf\/fi\/mf\/yffimfvoqxef9lrbveymvadzcjk.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p><strong>\u0416\u0438\u0432\u043e\u0442\u043d\u044b\u0435<\/strong><\/p>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430\u0448 \u043a\u043e\u0434:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  for (const animal of simulation.world().animals) {     ctxt.drawTriangle(         animal.x * viewportWidth,         animal.y * viewportHeight,         0.01 * viewportWidth,         animal.rotation,     ); }<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0447\u0442\u043e \u0434\u0430\u0435\u0442 \u043d\u0430\u043c:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ip\/vy\/nt\/ipvyntxf-1enwql1kdtncp6mxqy.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ip\/vy\/nt\/ipvyntxf-1enwql1kdtncp6mxqy.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u0417\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e!<\/p>\n<p>  <\/p>\n<h2 id=\"razrabotka-step\">\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430: step()<\/h2>\n<p>  <\/p>\n<p>\u0421\u0442\u0430\u0446\u0438\u043e\u043d\u0430\u0440\u043d\u044b\u0435 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u2014 \u044d\u0442\u043e \u043a\u0440\u0443\u0442\u043e, \u043d\u043e <strong>\u0434\u0432\u0438\u0436\u0443\u0449\u0438\u0435\u0441\u044f<\/strong> \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u043a\u0440\u0443\u0447\u0435.<\/p>\n<p>  <\/p>\n<p>\u0423 \u043d\u0430\u0448\u0438\u0445 \u043f\u0442\u0438\u0446 \u043d\u0435\u0442 \u043c\u043e\u0437\u0433\u0430, \u043d\u043e \u0443 \u043d\u0438\u0445 \u0435\u0441\u0442\u044c \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0438 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c. \u042d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c \u043a \u043d\u0438\u043c \u0444\u0438\u0437\u0438\u043a\u0443, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u043f\u043e\u043a\u0430 \u043d\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0441\u0440\u0435\u0434\u043e\u0439:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  impl Simulation {     \/* ... *\/      \/\/\/ \u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0434\u0438\u043d \u0448\u0430\u0433 - \u043e\u0434\u043d\u0443 \u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u043d\u0430\u0448\u0435\u0439 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438, \u0442\u0430\u043a \u0441\u043a\u0430\u0437\u0430\u0442\u044c.     pub fn step(&amp;mut self) {         for animal in &amp;mut self.world.animals {             animal.position += animal.rotation * animal.speed;         }     } }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c <code>cargo check<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">error[E0277]: cannot multiply `Rotation&lt;f32, 2_usize>` by `f32`    |    |             animal.position += animal.rotation * animal.speed;    |                                                ^    |             -----------------------------------|    |             no implementation for `Rotation&lt;f32, 2_usize> * f32`    |    = help: the trait `Mul&lt;f32>` is not implemented for      `Rotation&lt;f32, 2_usize>`<\/code><\/pre>\n<p>  <\/p>\n<p>\u0425\u043c, <code>nalgebra<\/code> \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 <code>Rotation2 * f32<\/code>. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u043a\u0442\u043e\u0440?<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">animal.position += animal.rotation * na::Vector2::new(0.0, animal.speed);<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"bash\">cargo check  Finished dev [unoptimized + debuginfo] target(s) in 18.04s<\/code><\/pre>\n<p>  <\/p>\n<p>\u0411\u0438\u043d\u0433\u043e!<\/p>\n<p>  <\/p>\n<blockquote><p>\u041f\u043e\u0447\u0435\u043c\u0443 <code>::new(0.0, animal.speed)<\/code>?<\/p>\n<p>  <code>nalgebra<\/code> \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0442\u043e\u0447\u043a\u0438 \u043e\u0442\u0441\u0447\u0435\u0442\u0430, \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f <code>\u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0441\u044c \u043d\u0430 45\u00b0<\/code> \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u044f \u0442\u043e\u0433\u043e, \u043a\u0443\u0434\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c\u0441\u044f \u043f\u0442\u0438\u0447\u043a\u0430: 45\u00b0 \u043f\u043e \u043a\u0430\u043a\u043e\u0439 \u043e\u0441\u0438?<\/p><\/blockquote>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/-5\/md\/yr\/-5mdyrynrrtyrxqvcw6tythoo9i.png\" data-src=\"https:\/\/habrastorage.org\/webt\/-5\/md\/yr\/-5mdyrynrrtyrxqvcw6tythoo9i.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<blockquote><p>\u042d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0440\u0435\u0448\u0430\u0435\u0442 \u043d\u0430\u0448 <code>::new(0.0, animal.speed)<\/code> \u2014 \u043d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0441\u0438 Y, \u0442.\u0435. \u043f\u0442\u0438\u0446\u0430 \u0441 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u043e\u043c 0\u00b0 \u0431\u0443\u0434\u0435\u0442 \u043b\u0435\u0442\u0435\u0442\u044c <strong>\u0432\u0432\u0435\u0440\u0445<\/strong>.<\/p>\n<p>  \u0412 \u043e\u0431\u0449\u0435\u043c, \u044d\u0442\u043e \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0442\u043e\u043c\u0443, \u043a\u0430\u043a \u043c\u044b \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438 \u043d\u0430 \u0445\u043e\u043b\u0441\u0442\u0435; \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>::new(-animal.speed, 0.0)<\/code> \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>drawTriangle()<\/code> \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c.<\/p><\/blockquote>\n<p>\u0418\u043c\u0435\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>step()<\/code> \u0432\u043d\u0443\u0442\u0440\u0438 <code>lib-simulation<\/code>, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0435 \u0447\u0435\u0440\u0435\u0437 <code>lib-simulation-wasm<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[wasm_bindgen] impl Simulation {     \/* ... *\/      pub fn step(&amp;mut self) {         self.sim.step();     } }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u041a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u0435\u043c \u043a\u043e\u0434:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">wasm-pack build  .... [INFO]: :-) Done in 3.58s [INFO]: :-) Your wasm pkg is ready to publish at \/home\/pwy\/Projects\/...<\/code><\/pre>\n<p>  <\/p>\n<p>\u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432\u0430 <code>.step()<\/code> \u0438\u0437 JS, \u0445\u043e\u0442\u044f \u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044f\u0437\u044b\u043a\u0430\u0445 \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0446\u0438\u043a\u043b:<\/p>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  while (true) {      ctxt.clearRect(0, 0, viewportWidth, viewportHeight);       simulation.step();       for (const animal of simulation.world().animals) {          ctxt.drawTriangle(              animal.x * viewportWidth,              animal.y * viewportHeight,              0.01 * viewportWidth,              animal.rotation,          );      } }<\/code><\/pre>\n<p>  <\/p>\n<p>\u2026 \u0441\u0440\u0435\u0434\u0430 \u0432\u0435\u0431-\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430\u0448 \u043a\u043e\u0434 <strong>\u043d\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u043c<\/strong>. \u042d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u043a\u043e\u0433\u0434\u0430 JS \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f, \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0436\u0434\u0435\u0442 \u0435\u0433\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f, \u0437\u0430\u043c\u043e\u0440\u0430\u0436\u0438\u0432\u0430\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0438 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u043e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435\u0439.<\/p>\n<p>  <\/p>\n<p>\u0427\u0435\u043c \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0434\u0430, \u0442\u0435\u043c \u0434\u043e\u043b\u044c\u0448\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u043a\u043b\u0430\u0434\u043a\u0430 \u2014 \u043f\u043e \u0441\u0443\u0442\u0438, \u043e\u043d\u0430 \u043e\u0434\u043d\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u0430\u044f. \u0418\u0442\u0430\u043a, \u0435\u0441\u043b\u0438 \u043c\u044b \u043d\u0430\u043f\u0438\u0448\u0435\u043c <code>while (true) { ...\u200b }<\/code>, \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u043d\u0430\u0432\u0441\u0435\u0433\u0434\u0430, \u0442\u0435\u0440\u043f\u0435\u043b\u0438\u0432\u043e \u043e\u0436\u0438\u0434\u0430\u044f, \u043f\u043e\u043a\u0430 \u043a\u043e\u0434 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442 \u0440\u0430\u0431\u043e\u0442\u0443.<\/p>\n<p>  <\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c <a href=\"https:\/\/developer.mozilla.org\/pl\/docs\/Web\/API\/Window\/requestAnimationFrame\">requestAnimationFrame()<\/a> \u2014 \u043e\u043d\u0430 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u043e\u0439 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u043a\u0430\u0434\u0440\u0430, \u0430 \u0441\u0430\u043c\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  function redraw() {     ctxt.clearRect(0, 0, viewportWidth, viewportHeight);      simulation.step();      for (const animal of simulation.world().animals) {         ctxt.drawTriangle(             animal.x * viewportWidth,             animal.y * viewportHeight,             0.01 * viewportWidth,             animal.rotation,         );     }      \/\/ requestAnimationFrame() \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u043f\u0435\u0440\u0435\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u043e\u0439 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u043a\u0430\u0434\u0440\u0430.     \/\/     \/\/ \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448\u0430 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0430\u0441\u044c \u0432\u0435\u0447\u043d\u043e,     \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u0446\u0438\u043a\u043b\u0438\u0442\u044c     requestAnimationFrame(redraw); }  redraw();<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u0443\u0430\u043b\u044f:<\/p>\n<p>  <\/p>\n<div class=\"oembed\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/6676ca69d1b5b66d8de7567a\" data-style=\"\" id=\"6676ca69d1b5b66d8de7567a\" width=\"\"><\/div>\n<\/div>\n<p>  <\/p>\n<p>\u2026 \u044d\u043c, \u043f\u043e\u0447\u0435\u043c\u0443 \u043f\u0442\u0438\u0446\u044b \u0447\u0435\u0440\u0435\u0437 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u0447\u0435\u0437\u0430\u044e\u0442?<\/p>\n<p>  <\/p>\n<p>\u0412\u0435\u0440\u043d\u0435\u043c\u0441\u044f \u043a <code>lib-simulation<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  impl Simulation {     \/* ... *\/      pub fn step(&amp;mut self) {         for animal in &amp;mut self.world.animals {             animal.position += animal.rotation * na::Vector2::new(0.0, animal.speed);         }     } }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044e \u0438\u2026 \u0430\u0445, \u0434\u0430! \u041d\u0430\u0448\u0430 \u043a\u0430\u0440\u0442\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0430 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u043c\u0438 <code>&lt;0.0, 1.0><\/code> \u2014 \u0432\u0441\u0435, \u0447\u0442\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 \u044d\u0442\u0438\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442, \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 \u0445\u043e\u043b\u0441\u0442\u0430.<\/p>\n<p>  <\/p>\n<p>\u0418\u0441\u043f\u0440\u0430\u0432\u0438\u043c \u044d\u0442\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  impl Simulation {     \/* ... *\/      pub fn step(&amp;mut self) {         for animal in &amp;mut self.world.animals {             animal.position += animal.rotation * na::Vector2::new(0.0, animal.speed);              animal.position.x = na::wrap(animal.position.x, 0.0, 1.0);             animal.position.y = na::wrap(animal.position.y, 0.0, 1.0);         }     } }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p><a href=\"https:\/\/docs.rs\/nalgebra\/0.26.2\/nalgebra\/fn.wrap.html\">wrap()<\/a> \u0434\u0435\u043b\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435: \u043f\u0435\u0440\u0432\u044b\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u0438 \u0442\u0440\u0435\u0442\u0438\u0439 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0438 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f:<\/p>\n<p>  <\/p>\n<ul>\n<li><code>na::wrap(0.5, 0.0, 1.0) == 0.5<\/code> (\u0447\u0438\u0441\u043b\u0430 \u043c\u0435\u0436\u0434\u0443 <code>[min,max]<\/code> \u043e\u0441\u0442\u0430\u044e\u0442\u0441\u044f \u043d\u0435\u0442\u0440\u043e\u043d\u0443\u0442\u044b\u043c\u0438)<\/li>\n<li><code>na::wrap(-0.5, 0.0, 1.0) == 1.0<\/code> (<code>if \u0447\u0438\u0441\u043b\u043e &lt; min { return max; }<\/code>)<\/li>\n<li><code>na::wrap(1.5, 0.0, 1.0) == 0.0<\/code> (<code>if \u0447\u0438\u0441\u043b\u043e > max { return min; }<\/code>)<\/li>\n<\/ul>\n<p>  <\/p>\n<pre><code class=\"bash\">wasm-pack build<\/code><\/pre>\n<p>  <\/p>\n<div class=\"oembed\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/6676ca6928dfc09d9e4c6d11\" data-style=\"\" id=\"6676ca6928dfc09d9e4c6d11\" width=\"\"><\/div>\n<\/div>\n<p>  <\/p>\n<p>\u041e\u0442\u043b\u0438\u0447\u043d\u043e!<\/p>\n<p>  <\/p>\n<h2 id=\"ty-ne-ty-kogda-goloden\">\u0422\u044b \u043d\u0435 \u0442\u044b (\u043a\u043e\u0433\u0434\u0430 \u0433\u043e\u043b\u043e\u0434\u0435\u043d)<\/h2>\n<p>  <\/p>\n<p>\u041f\u0442\u0438\u0446\u044b \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u043b\u0438\u0448\u044c \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0443 \u043d\u0430\u0448\u0435\u0439 \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0443 \u043d\u0430\u0441 \u0435\u0449\u0435 \u0435\u0441\u0442\u044c \u0435\u0434\u0430.<\/p>\n<p>  <\/p>\n<p><strong>\u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0435\u0434\u044b<\/strong><\/p>\n<p>  <\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043c\u044b \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043b\u0438 \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0435\u0434\u044b \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  #[wasm_bindgen] #[derive(Clone, Debug)] pub struct World {     #[wasm_bindgen(getter_with_clone)]     pub animals: Vec&lt;Animal>,      #[wasm_bindgen(getter_with_clone)]     pub foods: Vec&lt;Food>, }  impl From&lt;&amp;sim::World> for World {     fn from(world: &amp;sim::World) -> Self {         let animals = world.animals().iter().map(Animal::from).collect();         let foods = world.foods().iter().map(Food::from).collect();          Self { animals, foods }     } }  \/* ... *\/  #[wasm_bindgen] #[derive(Clone, Debug)] pub struct Food {     pub x: f32,     pub y: f32, }  impl From&lt;&amp;sim::Food> for Food {     fn from(food: &amp;sim::Food) -> Self {         Self {             x: food.position().x,             y: food.position().y,         }     } }<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  CanvasRenderingContext2D.prototype.drawTriangle =     function (x, y, size, rotation) {         \/* ... *\/     };  CanvasRenderingContext2D.prototype.drawCircle =     function(x, y, radius) {         this.beginPath();          \/\/ ---         \/\/ | \u0426\u0435\u043d\u0442\u0440 \u043a\u0440\u0443\u0433\u0430.         \/\/ ----- v -v         this.arc(x, y, radius, 0, 2.0 * Math.PI);         \/\/ ------------------- ^ -^-----------^         \/\/ | \u041d\u0430\u0447\u0430\u043b\u043e \u0438 \u043a\u043e\u043d\u0435\u0446 \u043e\u043a\u0440\u0443\u0436\u043d\u043e\u0441\u0442\u0438, \u0432 \u0440\u0430\u0434\u0438\u0430\u043d\u0430\u0445.         \/\/ |         \/\/ | \u041c\u0435\u043d\u044f\u044f \u044d\u0442\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u043e\u0436\u043d\u043e, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c         \/\/ | \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0443 \u043a\u0440\u0443\u0433\u0430.         \/\/ ---          this.fillStyle = 'rgb(0, 0, 0)';         this.fill();     };  function redraw() {     ctxt.clearRect(0, 0, viewportWidth, viewportHeight);      simulation.step();      const world = simulation.world();      for (const food of world.foods) {         ctxt.drawCircle(             food.x * viewportWidth,             food.y * viewportHeight,             (0.01 \/ 2.0) * viewportWidth,         );     }      for (const animal of world.animals) {         \/* ... *\/     }      \/* ... *\/ }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0412\u0435\u0440\u0438\u0442\u0435 \u0438\u043b\u0438 \u043d\u0435\u0442, \u043d\u043e \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e!<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">wasm-pack build  .... [INFO]: :-) Done in 1.25s [INFO]: :-) Your wasm pkg is ready to publish at \/home\/pwy\/Projects\/...<\/code><\/pre>\n<p>  <\/p>\n<div class=\"oembed\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/6676ca6a87bb36d4b3ad63af\" data-style=\"\" id=\"6676ca6a87bb36d4b3ad63af\" width=\"\"><\/div>\n<\/div>\n<p>  <\/p>\n<p><strong>\u041d\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043a\u0440\u0430\u0441\u043e\u0442\u044b<\/strong><\/p>\n<p>  <\/p>\n<p>\u041d\u0430\u0448\u0430 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0432\u0438\u0434 \u043d\u0430\u0448\u0435\u0439 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438\u2026 \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0436\u0435\u043b\u0430\u0442\u044c \u043b\u0443\u0447\u0448\u0435\u0433\u043e. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c:<\/p>\n<p>  <\/p>\n<pre><code class=\"html\">&lt;!DOCTYPE html> &lt;html>   &lt;head>     &lt;meta charset=\"utf-8\">     &lt;title>Shorelark&lt;\/title>   &lt;\/head>   &lt;style>     body {       background: #1f2639;     }   &lt;\/style>   &lt;body>     &lt;canvas id=\"viewport\" width=\"800\" height=\"800\">&lt;\/canvas>     &lt;script src=\".\/bootstrap.js\">&lt;\/script>   &lt;\/body> &lt;\/html><\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"javascript\">\/* ... *\/  CanvasRenderingContext2D.prototype.drawTriangle =     function (x, y, size, rotation) {         \/* ... *\/          this.fillStyle = 'rgb(255, 255, 255)';         this.fill();     };  CanvasRenderingContext2D.prototype.drawCircle =     function(x, y, radius) {         \/* ... *\/          this.fillStyle = 'rgb(0, 255, 128)';         this.fill();     };  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0430\u043a \u043b\u0443\u0447\u0448\u0435:<\/p>\n<p>  <\/p>\n<div class=\"oembed\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/6676ca6aee68229db649c52d\" data-style=\"\" id=\"6676ca6aee68229db649c52d\" width=\"\"><\/div>\n<\/div>\n<p>  <\/p>\n<p><strong>\u0421\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u044f \u0435\u0434\u044b<\/strong><\/p>\n<p>  <\/p>\n<p>\u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u043a\u043e\u0433\u0434\u0430 \u043f\u0442\u0438\u0447\u043a\u0438 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u0435\u0434\u043e\u0439, \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u2014 \u043f\u043e\u0440\u0430 \u044d\u0442\u043e \u043f\u043e\u0444\u0438\u043a\u0441\u0438\u0442\u044c!<\/p>\n<p>  <\/p>\n<p>\u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043e\u0442\u0440\u0435\u0444\u0430\u043a\u0442\u043e\u0440\u0438\u043c <code>step()<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  impl Simulation {     \/* ... *\/      pub fn step(&amp;mut self) {         self.process_movements();     }      fn process_movements(&amp;mut self) {         for animal in &amp;mut self.world.animals {             animal.position += animal.rotation * na::Vector2::new(0.0, animal.speed);              animal.position.x = na::wrap(animal.position.x, 0.0, 1.0);             animal.position.y = na::wrap(animal.position.y, 0.0, 1.0);         }     } }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  impl Simulation {     \/* ... *\/      pub fn step(&amp;mut self) {         self.process_collisions();         self.process_movements();     }      fn process_collisions(&amp;mut self) {         todo!();     }      \/* ... *\/ }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0413\u043e\u0432\u043e\u0440\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c, \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0434\u043e\u0441\u0442\u0438\u0447\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/* ... *\/  fn process_collisions(&amp;mut self) {     for \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0436\u0438\u0432\u043e\u0442\u043d\u043e\u0433\u043e {         for \u043a\u0430\u0436\u0434\u043e\u0439 \u0435\u0434\u044b {             if \u0436\u0438\u0432\u043e\u0442\u043d\u043e\u0435 \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u043e\u0441\u044c \u0441 \u0435\u0434\u043e\u0439 {                 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u0442\u043e\u043b\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u044f             }         }     } }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0441\u0442\u043e\u043b\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u044f \u0434\u0432\u0443\u0445 \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u043d\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <a href=\"https:\/\/en.wikipedia.org\/wiki\/Hit-testing\">\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043d\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0435 (hit testing)<\/a>. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043d\u0430\u0448\u0438 \u043f\u0442\u0438\u0446\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u0431\u043e\u0439 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438, \u0430 \u043d\u0430\u0448\u0430 \u0435\u0434\u0430 \u2014 \u043a\u0440\u0443\u0433\u0438, \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u043a\u0430\u043a\u043e\u0439-\u0442\u043e &#171;\u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430 \u0432 \u043a\u0440\u0443\u0433&#187;.<\/p>\n<p>  <\/p>\n<p>\u041d\u043e \u0442\u0430\u043a\u043e\u0439 \u0432\u0438\u0434 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u0435 <a href=\"http:\/\/www.phatcode.net\/articles.php?id=459\">\u043d\u0435\u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e \u0441\u043b\u043e\u0436\u0435\u043d<\/a>, \u0442\u0430\u043a \u0447\u0442\u043e \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u043e\u043f\u0440\u043e\u0449\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u043d\u0430\u0448\u0438 \u043f\u0442\u0438\u0446\u044b \u2014 <strong>\u043a\u0440\u0443\u0433\u0438<\/strong>.<\/p>\n<p>  <\/p>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0438\u0445 \u0432 \u0432\u0438\u0434\u0435 \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u2014 \u0434\u0435\u043b\u043e \u0432 \u0444\u0438\u0437\u0438\u043a\u0435.<\/p>\n<p>  <\/p>\n<p>\u0418\u0442\u0430\u043a, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u043d\u0438\u044f &#171;\u043a\u0440\u0443\u0433-\u043a\u0440\u0443\u0433&#187; \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043e \u043d\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 \u0442\u043e\u0433\u043e, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u043a\u0440\u0443\u0433\u0430\u043c\u0438 \u043c\u0435\u043d\u044c\u0448\u0435 \u0438\u043b\u0438 \u0440\u0430\u0432\u043d\u044b\u043c \u0441\u0443\u043c\u043c\u0435 \u0438\u0445 \u0440\u0430\u0434\u0438\u0443\u0441\u043e\u0432:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/wi\/os\/a1\/wiosa1yd_wp6tjqzuvxofdyhik8.png\" data-src=\"https:\/\/habrastorage.org\/webt\/wi\/os\/a1\/wiosa1yd_wp6tjqzuvxofdyhik8.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p><em>\u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435(A, B) > \u0440\u0430\u0434\u0438\u0443\u0441(A) + \u0440\u0430\u0434\u0438\u0443\u0441(B) \u21d2 \u043d\u0435\u0442 \u0441\u0442\u043e\u043b\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u044f<\/em><\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/9_\/ex\/my\/9_exmye6q4rr1ha5aknoscixm6o.png\" data-src=\"https:\/\/habrastorage.org\/webt\/9_\/ex\/my\/9_exmye6q4rr1ha5aknoscixm6o.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p><em>\u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435(A, B) &lt;= \u0440\u0430\u0434\u0438\u0443\u0441(A) + \u0440\u0430\u0434\u0438\u0443\u0441(B) \u21d2 \u0441\u0442\u043e\u043b\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0435<\/em><\/p>\n<p>  <\/p>\n<p>\u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u044d\u0442\u043e \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 <code>if<\/code>:<\/p>\n<p>  <\/p>\n<pre><code class=\"rust\">\/\/ libs\/simulation\/src\/lib.rs \/* ... *\/  pub fn step(&amp;mut self, rng: &amp;mut dyn RngCore) {     self.process_collisions(rng);     self.process_movements(); }  fn process_collisions(&amp;mut self, rng: &amp;mut dyn RngCore) {     for animal in &amp;mut self.world.animals {         for food in &amp;mut self.world.foods {             let distance = na::distance(&amp;animal.position, &amp;food.position);              if distance &lt;= 0.01 {                 food.position = rng.gen();             }         }     } }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<pre><code class=\"rust\">\/\/ libs\/simulation-wasm\/src\/lib.rs \/* ... *\/  #[wasm_bindgen] impl Simulation {     \/* ... *\/      pub fn step(&amp;mut self) {         self.sim.step(&amp;mut self.rng);     } }  \/* ... *\/<\/code><\/pre>\n<p>  <\/p>\n<p>\u0420\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 <code>nalgebra<\/code>, \u0432\u044b\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u0435\u0445 \u0436\u0435 \u0435\u0434\u0438\u043d\u0438\u0446\u0430\u0445, \u0447\u0442\u043e \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 <code>0.5<\/code> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0436\u0438\u0432\u043e\u0442\u043d\u043e\u0435 \u0438 \u0435\u0434\u0430 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u044b \u043a\u0430\u0440\u0442\u044b \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430, \u0430 <code>0.0<\/code> \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043e\u043d\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u0438\u0445 \u0438 \u0442\u0435\u0445 \u0436\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u0430\u0445.<\/p>\n<p>  <\/p>\n<p><code>0.01<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0440\u0430\u0434\u0438\u0443\u0441 \u0435\u0434\u044b. \u042f \u0432\u044b\u0431\u0440\u0430\u043b <code>0.01<\/code>, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043e\u043d\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u0441\u043e\u0447\u0435\u0442\u0430\u0435\u0442\u0441\u044f \u0441 \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0434\u043b\u044f \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442? \u041e \u0431\u043e\u0436\u0435!<\/p>\n<p>  <\/p>\n<div class=\"oembed\">\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/6676ca6ad1b5b66d8de7567e\" data-style=\"\" id=\"6676ca6ad1b5b66d8de7567e\" width=\"\"><\/div>\n<\/div>\n<p>  <\/p>\n<p>\u041d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044d\u0442\u043e \u0432\u0441\u0435, \u0434\u0440\u0443\u0437\u044c\u044f. \u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043c \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435.<\/p>\n<p>  <\/p>\n<hr\/>\n<p>  <\/p>\n<blockquote><p><a href=\"https:\/\/t.me\/timewebru\"><b>\u041d\u043e\u0432\u043e\u0441\u0442\u0438, \u043e\u0431\u0437\u043e\u0440\u044b \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432 \u0438 \u043a\u043e\u043d\u043a\u0443\u0440\u0441\u044b \u043e\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b Timeweb.Cloud \u2014 \u0432 \u043d\u0430\u0448\u0435\u043c Telegram-\u043a\u0430\u043d\u0430\u043b\u0435<\/b><\/a> <b>\u21a9<\/b><\/p><\/blockquote>\n<p><a href=\"https:\/\/timeweb.cloud\/?i=106909\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/webt\/r8\/ms\/jc\/r8msjcfet9mgza3ybpor_sdgrt0.jpeg\" data-src=\"https:\/\/habrastorage.org\/webt\/r8\/ms\/jc\/r8msjcfet9mgza3ybpor_sdgrt0.jpeg\" data-blurred=\"true\"\/><\/a><\/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\/articles\/823676\/\"> https:\/\/habr.com\/ru\/articles\/823676\/<\/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-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/ok\/13\/y9\/ok13y9vlz-qasq8lvjgusd0lpyk.png\" data-src=\"https:\/\/habrastorage.org\/webt\/ok\/13\/y9\/ok13y9vlz-qasq8lvjgusd0lpyk.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p>\u042d\u0442\u043e \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u0435\u0440\u0438\u0438 \u0441\u0442\u0430\u0442\u0435\u0439 \u043f\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u044d\u0432\u043e\u043b\u044e\u0446\u0438\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <strong>\u043d\u0435\u0439\u0440\u043e\u043d\u043d\u043e\u0439 \u0441\u0435\u0442\u0438<\/strong> \u0438 <strong>\u0433\u0435\u043d\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0430<\/strong>.<\/p>\n<p>  <\/p>\n<ul>\n<li><a href=\"https:\/\/habr.com\/ru\/companies\/timeweb\/articles\/817585\/\">\u041f\u0435\u0440\u0432\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/companies\/timeweb\/articles\/818985\/\">\u0412\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/a><\/li>\n<li><a href=\"https:\/\/habr.com\/ru\/companies\/timeweb\/articles\/820699\/\">\u0422\u0440\u0435\u0442\u044c\u044f \u0447\u0430\u0441\u0442\u044c<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n<p>\u0412 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0435\u043c \u0432\u044b\u043f\u0443\u0441\u043a\u0435:<\/p>\n<p>  <\/p>\n<p><strong>\u0421\u0435\u043a\u0441\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u043c\u043d\u043e\u0433\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0438<\/strong><\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/-i\/de\/tp\/-idetpdvew-dvgkpoqpfhc2cu5o.png\" data-src=\"https:\/\/habrastorage.org\/webt\/-i\/de\/tp\/-idetpdvew-dvgkpoqpfhc2cu5o.png\"\/>  <\/p>\n<p>  <\/p>\n<p>  <\/p>\n<p><strong>\u0421\u0435\u0440\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 ISO \u0434\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u044b ASCII<\/strong><\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">------------ | \\...%....| |   \\......| |    @>....| |      \\...| |        \\.| ------------<\/code><\/pre>\n<p>  <\/p>\n<p><strong>\u041a\u043b\u0435\u0432\u044b\u0435 \u0447\u0438\u0441\u043b\u0430<\/strong><\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/webt\/oa\/e3\/qa\/oae3qagiitbt05snamjya54ks9q.png\" data-src=\"https:\/\/habrastorage.org\/webt\/oa\/e3\/qa\/oae3qagiitbt05snamjya54ks9q.png\"\/>  <\/p>\n<p>  <\/p>\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-380065","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/380065","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=380065"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/380065\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=380065"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=380065"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=380065"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}