{"id":293759,"date":"2019-08-23T15:00:11","date_gmt":"2019-08-23T15:00:11","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=293759"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=293759","title":{"rendered":"\u041d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0437\u043c\u0435\u0439\u043a\u0438 \u043d\u0430 ipad (pythonista)"},"content":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\"><i>\u2026 \u0438\u043b\u0438 \u043a\u0430\u043a \u0443\u0431\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0438\u043c\u0435\u044f ipad \u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e&#8230;<\/i><\/p>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0442!<\/p>\n<h3>\u041e \u0447\u0435\u043c \u0440\u0435\u0447\u044c?<\/h3>\n<p>  \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043f\u043b\u0430\u043d\u0448\u0435\u0442\u044b \u043f\u043e\u043a\u0430 \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u044e\u0442 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u044b. \u041d\u043e \u043f\u043e\u043a\u043e\u0434\u0438\u0442\u044c \u0432 \u043f\u043e\u0435\u0437\u0434\u043a\u0435\/\u043f\u043e\u043b\u0435\u0442\u0435 \u044d\u0442\u043e \u0436\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043f\u043e\u0438\u0441\u043a\u0430\u043b \u043a\u0430\u043a\u0438\u0435 ide \u0435\u0441\u0442\u044c \u043f\u043e\u0434 ipad, \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0431\u0443\u0434\u0443 \u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0433\u0440\u0443\u043b\u044c\u043a\u0443 \u043d\u0430 Pythonista.<\/p>\n<h3>\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c?<\/h3>\n<p>  \u041f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u0440\u0438\u0441\u0442\u0430\u043b\u043b\u0438\u043a\u0438 (\u0434\u0430 \u0434\u0430, \u0442\u0435 \u0441\u0430\u043c\u044b\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u0438\u0433\u0440\u0430\u0435\u0442\u0435 \u0432 \u043c\u0435\u0442\u0440\u043e). \u0422\u0435\u0442\u0440\u0438\u0441, \u0437\u043c\u0435\u0439\u043a\u0430, fill \u2014 \u043b\u044e\u0431\u043e\u0439 \u043d\u043e\u0432\u0438\u0447\u043e\u043a, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0432\u0448\u0438\u0441\u044c, \u043d\u0430\u043f\u0438\u0448\u0435\u0442 \u0438\u0445 \u0437\u0430 30 \u043c\u0438\u043d\u0443\u0442. \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u2014 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b, \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b, \u043a\u043e\u0434.<\/p>\n<p>  <a name=\"habracut\"><\/a><\/p>\n<p>  \u0412\u043e\u0442 \u043f\u0430\u0440\u0430 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u043e\u0432 \u0441 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u044f \u043d\u0430\u043b\u044f\u043f\u0430\u043b:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/n5\/t-\/0l\/n5t-0lksjmfrqpvj-hphcjrqgv4.png\"><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/lv\/a0\/ay\/lva0ay1p6xghjzuh60hbewak8-i.png\"><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/az\/ow\/zh\/azowzhphjmi5xju-ynvluvhot48.png\"><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/pf\/vq\/yj\/pfvqyj1em0bsun4ozseqvjl6458.png\"><br \/>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/4k\/lo\/w9\/4klow9qq74gspnkh888hsksgk7c.png\"><\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0414\u0438\u0441\u043a\u043b\u0435\u0439\u043c\u0435\u0440<\/b><\/p>\n<div class=\"spoiler_text\">\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u043d\u043e\u0432\u0438\u0447\u043a\u043e\u0432 (\u043d\u043e \u0437\u043d\u0430\u044e\u0449\u0438\u0445 python) \u0438 \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c world of tanks \u0437\u0430 \u0434\u0435\u0441\u044f\u0442\u044c \u043c\u0438\u043d\u0443\u0442 \u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043a\u0430\u043a\u043e\u0435-\u043b\u0438\u0431\u043e \u0433\u043e\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043d\u043e \u0438 \u0430\u0432\u0442\u043e\u0440 \u043d\u0435 \u0440\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0437\u0430 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0440\u0435\u043b\u0438\u0433\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f (\u0445\u043e\u0442\u044f \u0441\u0442\u0430\u0440\u0430\u0435\u0442\u0441\u044f). \u0410 \u0435\u0449\u0435 \u0447\u0442\u043e-\u0442\u043e \u0441\u0442\u044b\u0440\u0435\u043d\u043e \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 \u043a pythonista \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438.  <\/div>\n<\/div>\n<p>  <i>\u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d \u0432 \u043a\u043e\u043d\u0446\u0435<\/i><\/p>\n<h3>\u041f\u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u043c\u0441\u044f \u0441 \u0433\u0440\u0430\u0444\u0438\u043a\u043e\u0439 \u0432 pythonista<\/h3>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0418\u043c\u043f\u043e\u0440\u0442<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"python\">from scene import * import random <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0421\u0440\u0430\u0437\u0443 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0441\u0446\u0435\u043d\u0443:  <\/p>\n<pre><code class=\"python\">class Game(Scene):     def setup(self):         self.background_color = \"green\"  run(Game(), LANDSCAPE) <\/code><\/pre>\n<p>  \u041d\u0443 \u0438 \u0441\u0440\u0430\u0437\u0443 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c. \u0423 \u0432\u0430\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u043b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c\u0441\u044f \u0437\u0435\u043b\u0435\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043a\u0430\u043a\u0443\u044e-\u043d\u0438\u0431\u0443\u0434\u044c \u043a\u043b\u0430\u0441\u0441\u043d\u0443\u044e \u0448\u0442\u0443\u043a\u0443, \u0434\u043e\u0431\u0430\u0432\u0438\u0432 \u0432 \u043a\u043b\u0430\u0441\u0441 Game \u043c\u0435\u0442\u043e\u0434 update (\u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0430\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439), \u0430 \u0432 \u043d\u0435\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0446\u0432\u0435\u0442\u0430 \u0444\u043e\u043d\u0430.<\/p>\n<pre><code class=\"python\">class Game(Scene):     # \u0420\u0430\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b     def update(self):         self.background_color = (1.0, 1.0, (math.sin(self.t) + 1) \/ 2) <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u044d\u043a\u0440\u0430\u043d \u043f\u043b\u0430\u0432\u043d\u043e \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0441 \u0436\u0435\u043b\u0442\u043e\u0433\u043e \u043d\u0430 \u0431\u0435\u043b\u044b\u0439 \u0438 \u043e\u0431\u0440\u0430\u0442\u043d\u043e. <\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/-h\/h_\/vu\/-hh_vuqntwuqqpno4h_jtu0944m.png\"><\/p>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u0430\u043a\u043e\u0439-\u043d\u0438\u0431\u0443\u0434\u044c \u043e\u0431\u044a\u0435\u043a\u0442. \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0435\u0433\u043e \u0442\u0430\u043a\u0436\u0435 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 setup:<\/p>\n<pre><code class=\"python\"> class Game(Scene):     def setup(self):         self.background_color = \"white\"         mypath = ui.Path.rect(0, 0, 50, 50)         self.obj = ShapeNode(mypath)         self.obj.color = \"purple\" #\u0410 \u0435\u0449\u0435 \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0432 html, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 #FF00FF. \u0418\u043b\u0438 \u0432 tuple, \u0442\u043e \u0435\u0441\u0442\u044c (1.0, 0.0, 1.0). \u0410 \u0435\u0449\u0435 \u0432 \u043a\u043e\u043d\u0435\u0446 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043f\u0438\u0441\u0430\u0442\u044c alpha, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0441\u0442\u044c         self.add_child(self.obj)          def update(self):         self.obj.position = (500 + 200 * math.sin(self.t), 500 + 200 * math.cos(self.t)) <\/code><\/pre>\n<p>  \u041c\u044b \u0437\u0430\u0434\u0430\u043b\u0438 \u043b\u0438\u043d\u0438\u044e (mypath), \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043f\u043e \u043d\u0435\u0439 ShapeNode, \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0435\u0439 \u0446\u0432\u0435\u0442, \u0430 \u0437\u0430\u0442\u0435\u043c \u0443\u043a\u0430\u0437\u0430\u043b\u0438 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f (\u043f\u043e \u0441\u0443\u0442\u0438 \u043e\u0434\u043d\u043e \u0438 \u0442\u043e \u0436\u0435 \u2014 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438, \u0442\u043e \u0435\u0441\u0442\u044c ShapeNode(*&#8230;, parent=self) \u043b\u0438\u0431\u043e self.add_child(obj)).<\/p>\n<p>  \u041d\u0443 \u0430 \u0432 Game.update() \u043c\u044b \u043c\u0435\u043d\u044f\u0435\u043c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 (tuple), \u043f\u0440\u0438\u0447\u0435\u043c \u043e\u043d\u043e \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445 \u0438 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043b\u0435\u0432\u043e\u0433\u043e \u043d\u0438\u0436\u043d\u0435\u0433\u043e \u0443\u0433\u043b\u0430.<\/p>\n<blockquote><p>\u0417\u0430\u043c\u0435\u0442\u044c\u0442\u0435, \u043d\u0430\u043c \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0441\u0446\u0435\u043d\u0443 (\u0445\u043e\u0442\u044f \u043c\u043e\u0436\u043d\u043e). \u041e\u0431\u044a\u0435\u043a\u0442\u044b \u0438 \u043d\u043e\u0434\u044b, \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u2014 \u0441\u0446\u0435\u043d\u0430 (\u0438\u043b\u0438 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0435\u0435 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442) \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0441\u0430\u043c\u0438  <\/p><\/blockquote>\n<p>  \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435, \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u043e\u0439\u0434\u0435\u043c \u0432 \u044d\u0442\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u2014 touch_began (\u0430 \u0442\u0430\u043a\u0436\u0435 touch_moved \u0438 touch_ended). \u041d\u0435\u0441\u043b\u043e\u0436\u043d\u043e \u0434\u043e\u0433\u0430\u0434\u0430\u0442\u044c\u0441\u044f, \u043c\u0435\u0442\u043e\u0434 \u043b\u043e\u0432\u0438\u0442 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043d\u0430 \u044d\u043a\u0440\u0430\u043d. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c:<\/p>\n<pre><code class=\"python\">class Game(Scene):     def touch_began(self, touch):         mypath = ui.Path.oval(0, 0, 50, 50)         obj = ShapeNode(mypath)         obj.color = (0.5, 0.5, 1.0)         self.add_child(obj)         obj.position = touch.location <\/code><\/pre>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/gp\/1m\/mu\/gp1mmunnpgr5y6_c0ge8hpzqn8q.png\"><\/p>\n<p>  \u041f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043a\u0440\u0443\u0436\u043e\u0447\u0435\u043a, \u043c\u0435\u0441\u0442\u043e \u043a\u043b\u0438\u043a\u0430 \u2014 touch.location.<\/p>\n<h3>\u0413\u043e\u0442\u043e\u0432\u044b \u043f\u0438\u0441\u0430\u0442\u044c \u0437\u043c\u0435\u0439\u043a\u0443<\/h3>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0438\u0433\u0440\u044b<\/b><\/p>\n<div class=\"spoiler_text\">\u0417\u043c\u0435\u0439\u043a\u0430 \u2014 \u043c\u0430\u0441\u0441\u0438\u0432 \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u043a\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 \u0434\u0432\u0438\u0433\u0430\u0435\u0442\u0441\u044f \u0433\u043e\u043b\u043e\u0432\u0430 \u2014 \u0432\u0442\u043e\u0440\u043e\u0439 \u043a\u0443\u0441\u043e\u0447\u0435\u043a \u043f\u043e\u0434\u043e\u0434\u0432\u0438\u0433\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043c\u0435\u0441\u0442\u043e \u043f\u0435\u0440\u0432\u043e\u0433\u043e, \u0442\u0440\u0435\u0442\u0438\u0439 \u2014 \u043d\u0430 \u043c\u0435\u0441\u0442\u043e \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0438 \u0442. \u0434. \u0427\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435 \u0433\u043e\u043b\u043e\u0432\u044b \u0441 \u0445\u0432\u043e\u0441\u0442\u043e\u043c, \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0435\u0435 \u0441 \u043a\u0430\u0436\u0434\u044b\u043c \u043a\u0443\u0441\u043e\u0447\u043a\u043e\u043c \u0445\u0432\u043e\u0441\u0442\u0430  <\/div>\n<\/div>\n<p>  \u0423\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0435\u0441\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0445\u043e\u0442\u0438\u043c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043c\u0435\u043d\u0435\u0435 \u043a\u0440\u0430\u0441\u0438\u0432\u043e (\u043d\u043e, \u0440\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u0434\u0435\u043b\u0430\u0442\u044c \u0431\u0443\u0434\u0435\u043c \u0432\u0435\u043b\u043e\u0441\u0438\u043f\u0435\u0434\u044b).<\/p>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0430\u0441\u0441 PhyObj:<\/p>\n<pre><code class=\"python\">class PhyObj:     def __init__(self, path, color, parent):         self.graph_obj = ShapeNode(path, parent=parent)         self.parent = parent         self.graph_obj.color = color          def setpos(self, x, y):         self.graph_obj.position = (x, y)          def getpos(self):         return self.graph_obj.position          def move(self, x, y):         self.graph_obj.position += (x, y) <\/code><\/pre>\n<p>  \u0414\u0443\u043c\u0430\u044e, \u0442\u0443\u0442 \u0432\u0441\u0435 \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u043e. \u0412\u043d\u0443\u0442\u0440\u0438 \u0441\u0430\u043c\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u043b\u0438 \u043d\u043e\u0434\u0443, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u043f\u0438\u0441\u0430\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u0434\u0435\u043b\u0430\u0442\u044c \u043d\u0430\u0448 \u043a\u043e\u0434 \u0431\u043e\u043b\u0435\u0435 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0425\u043e\u043b\u0438\u0432\u0430\u0440\u044b<\/b><\/p>\n<div class=\"spoiler_text\">\u041b\u0438\u0447\u043d\u043e \u044f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u0443\u0441\u0442\u044c \u0431\u0443\u0434\u0435\u0442 \u043c\u043d\u043e\u0433\u043e \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0445\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432, \u0437\u0430\u0442\u043e \u043f\u043e\u0442\u043e\u043c \u0443\u0436\u0435 \u043a\u043e\u0434 \u0432 \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0445 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u043c \u0438 \u0447\u0438\u0442\u0430\u0435\u043c\u044b\u043c.  <\/div>\n<\/div>\n<p>  PhyObj \u2014 \u044d\u0442\u043e \u0441\u0430\u043c\u044b\u0439 \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 \u043d\u0430\u0448\u0435\u0439 \u0438\u0433\u0440\u0435, \u043f\u043e \u0441\u0443\u0442\u0438 \u2014 \u044d\u0442\u043e \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442.<\/p>\n<h4>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0437\u043c\u0435\u0439\u043a\u0438<\/h4>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0434\u043e \u0431\u044b \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0437\u043c\u0435\u0439\u043a\u0443, \u0430 \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0430 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u043a\u0443\u0441\u043e\u0447\u043a\u043e\u0432, \u043e\u043f\u0438\u0448\u0435\u043c \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043e\u0434\u0438\u043d:<\/p>\n<pre><code class=\"python\"> class Tile(PhyObj):     def __init__(self, parent, size, margin=4):         super().__init__(ui.Path.rect(0, 0, size[0] - margin, size[1] - margin), \"#66FF66\", parent)          def die(self):         self.graph_obj.color = \"red\"  <\/code><\/pre>\n<p>  \u0412 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044f \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u043f\u0440\u0438\u0434\u0430\u0435\u043c \u0441\u0435\u0431\u0435 \u0444\u043e\u0440\u043c\u0443 \u0438 \u0446\u0432\u0435\u0442. margin \u043d\u0443\u0436\u0435\u043d \u0447\u0442\u043e\u0431\u044b \u043a\u0432\u0430\u0434\u0440\u0430\u0442\u0438\u043a\u0438 \u043d\u0435 \u0441\u043b\u0438\u043f\u0430\u043b\u0438\u0441\u044c \u0438 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0441\u0435\u0442\u043e\u0447\u043a\u0443.<\/p>\n<pre><code class=\"python\">class Game(Scene):     def setup(self):         self.tile = Tile(self, (40, 40))         self.tile.setpos(100, 100)  <\/code><\/pre>\n<p>  \u0414\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/dg\/yl\/tf\/dgyltfilompjygqnrriiio1mhv8.png\"><\/p>\n<p>  \u0410 \u0432\u043e\u0442 \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443 \u0437\u0430\u0447\u0435\u043c \u043d\u0443\u0436\u0435\u043d margin:<\/p>\n<pre><code class=\"python\">class Game(Scene):     def setup(self):         tile1 = Tile(self, (40, 40))         tile1.setpos(100, 100)         tile2 = Tile(self, (40, 40))         tile2.setpos(140, 100)  <\/code><\/pre>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/0n\/p8\/i0\/0np8i041mbo7udct2rsi3twsj18.png\"><\/p>\n<p>  \u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u0442\u0435\u043f\u0435\u0440\u044c \u0438\u0437 \u044d\u0442\u0438\u0445 \u043a\u0443\u0441\u043e\u0447\u043a\u043e\u0432 \u043d\u0430\u0434\u043e \u0441\u043a\u043b\u0435\u0438\u0442\u044c \u0437\u043c\u0435\u044e. \u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043c\u0435\u0442\u043e\u0434 move.<\/p>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e:  <\/p>\n<pre><code class=\"python\"> class Snake:     def __init__(self, length, width, initpos, parent):         self.width = width # \u042d\u0442\u043e \u0448\u0438\u0440\u0438\u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043b\u0435\u0442\u043a\u0438         self.tiles = [Tile(parent, (width, width)) for i in range(length)] # \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0438\u0437 \u043d\u0430\u0448\u0438\u0445 \u043a\u043b\u0435\u0442\u043e\u043a         for i, tile in enumerate(self.tiles):             tile.setpos(initpos[0] + i * self.width, initpos[1]) #\u041d\u0443 \u0430 \u0437\u0434\u0435\u0441\u044c \u043c\u044b \u0441\u0442\u0430\u0432\u0438\u043c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043b\u0435\u0442\u043a\u0435  <\/code><\/pre>\n<p>  \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0435\u0435 \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"python\">class Game(Scene):     def setup(self):         self.snake = Snake(10, 40, (200, 200), self)  <\/code><\/pre>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/gv\/kl\/gg\/gvklgg1stltccf2hxsyyuae_rsu.png\"><\/p>\n<p>  \u041d\u0443 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 move.<\/p>\n<pre><code class=\"python\">class Snake:     def move(self, x, y):         for i in range(len(self.tiles) - 1, 0, -1):             self.tiles[i].setpos(*self.tiles[i - 1].getpos())         self.tiles[0].move(x * self.width, y * self.width) <\/code><\/pre>\n<p>  \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u0432\u0438\u0433\u0430\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u043a \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439, \u043f\u043e\u0442\u043e\u043c \u043f\u0440\u0435\u0434\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u043a \u043f\u0440\u0435\u0434\u043f\u0440\u0435\u0434\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0439\u2026 \u043f\u043e\u0442\u043e\u043c \u0432\u0442\u043e\u0440\u0443\u044e \u043a \u043f\u0435\u0440\u0432\u043e\u0439. \u0410 \u043f\u0435\u0440\u0432\u0443\u044e \u043d\u0430 (x, y).<\/p>\n<p>  \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0437\u043c\u0435\u0439\u043a\u0430 \u0443 \u043d\u0430\u0441 \u0434\u0432\u0438\u0433\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u044f\u043c \u0445\u043e\u0440\u043e\u0448\u043e. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c:<\/p>\n<pre><code class=\"python\">class Game(self): # &lt;...&gt;     def update(self):         self.snake.move(0, 1)  <\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u044b \u0443\u0441\u043f\u0435\u043b\u0438 \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0442\u043e \u0443\u043f\u043e\u043b\u0437\u043b\u0430 \u043e\u043d\u0430 \u043a\u0430\u043a \u043d\u0430\u0434\u043e. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e update \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u0447\u0430\u0441\u0442\u043e (\u0438 \u043a\u0441\u0442\u0430\u0442\u0438 \u043d\u0435\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u043c), \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u0442\u044c, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043f\u0440\u043e\u0448\u043b\u043e \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 \u0438 \u0436\u0434\u0430\u0442\u044c, \u043f\u043e\u043a\u0430 \u0435\u0433\u043e \u00ab\u043d\u0430\u043a\u043e\u043f\u0438\u0442\u0441\u044f\u00bb \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/p>\n<p>  \u041a\u043e\u0440\u043e\u0447\u0435, \u0434\u0435\u043b\u0430\u0435\u043c:<\/p>\n<pre><code class=\"python\">class Game(Scene):     def time_reset(self):         self.last_time = self.t          def time_gone(self, t):         if self.t - self.last_time &gt; t:             res = True             self.time_reset()         else:             res = False         return res      def setup(self):         self.snake = Snake(10, 40, (200, 200), self)         self.time_reset()       def update(self):         if self.time_gone(0.3):             self.snake.move(0, 1) <\/code><\/pre>\n<p>  time_gone \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 True, \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u0448\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0447\u0435\u043c t. \u0422\u0435\u043f\u0435\u0440\u044c \u0437\u043c\u0435\u0439\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0432\u0438\u0433\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u0435 0.3 \u0441\u0435\u043a\u0443\u043d\u0434\u044b. \u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c?<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/it\/ew\/cn\/itewcnxtf37hx-bkj2-_tnrjnug.png\"><\/p>\n<h4>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/h4>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u043e\u0432\u043e\u0440\u043e\u0442 \u0432\u043e \u0432\u0441\u0435 \u0447\u0435\u0442\u044b\u0440\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/5l\/hw\/mo\/5lhwmoxex5c_lfafmihwivyw1ym.png\"><\/p>\n<pre><code class=\"python\">class Game(Scene): # &lt;...&gt;     def setup(self):         # &lt;...&gt;         self.dir = (0, 1) # \u044d\u0442\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e      def update(self):         if self.time_gone(0.3):             self.snake.move(*self.dir) <\/code><\/pre>\n<p>  \u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0434\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 touch_began, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c \u0432 \u043a\u0430\u043a\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0442\u043a\u043d\u0443\u043b \u044e\u0437\u0435\u0440. \u041d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u044d\u0442\u043e \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u043d\u0435 \u0442\u0430\u043a \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043a\u0430\u043a \u044f \u0434\u0443\u043c\u0430\u043b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0442\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c:<\/p>\n<pre><code class=\"python\">class Game(Scene): # &lt;...&gt;     def touch_began(self, touch):         ws = touch.location[0] \/ self.size.w         hs = touch.location[1] \/ self.size.h         aws = 1 - ws         if ws &gt; hs and aws &gt; hs:             self.dir = (0, -1)         elif ws &gt; hs and aws &lt;= hs:             self.dir = (1, 0)         elif ws &lt;= hs and aws &gt; hs:             self.dir = (-1, 0)         else:             self.dir = (0, 1)  <\/code><\/pre>\n<p>  \u041d\u0443 \u0432\u043e\u0442, \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/-a\/s5\/8p\/-as58pqevh1gfcxx4a556pttljo.png\"><\/p>\n<p>  \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043d, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u043d\u0430 \u0441\u0442\u043e\u043b\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u044f \u0438 \u044f\u0431\u043b\u043e\u0447\u043a\u0438. <\/p>\n<h4>\u0421\u0442\u043e\u043b\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u0435 \u0441 \u0445\u0432\u043e\u0441\u0442\u043e\u043c<\/h4>\n<p>  \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u0437\u043c\u0435\u0439\u043a\u0443 \u043c\u0435\u0442\u043e\u0434 find_collisions<\/p>\n<pre><code class=\"python\">class Snake: # &lt;...&gt;     def find_collisions(self):         for i in range(1, len(self.tiles)):             if self.tiles[i].getpos() == self.tiles[0].getpos():                 return self.tiles[i], self.tiles[0]         return False  <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0430\u0440\u0443 \u043a\u043b\u0435\u0442\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0435\u0440\u0435\u0441\u0435\u043a\u043b\u0438\u0441\u044c. \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b \u043f\u043e\u043a\u0440\u0430\u0441\u0438\u0442\u044c \u0438\u0445 \u0432 \u043a\u0440\u0430\u0441\u043d\u044b\u0439, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043c\u0435\u0442\u043e\u0434 die \u0432 Tile:<\/p>\n<pre><code class=\"python\">class Tile(PhyObj): # &lt;...&gt;     def die(self):         self.graph_obj.color = \"red\" <\/code><\/pre>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0443 \u0432 update \u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u043c setup:<\/p>\n<pre><code class=\"python\">class Game(Scene): # &lt;...&gt;     def setup(self):         self.snake = Snake(30, 40, (200, 200), self) # \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u0437\u043c\u0435\u0439\u043a\u0443         self.time_reset()          self.dir = (0, 1)          self.game_on = True #\u0410 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430 \u043b\u0438 \u0438\u0433\u0440\u0430?          def update(self):         if not self.game_on: #\u0415\u0441\u043b\u0438 \u043d\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430, \u0432\u044b\u0445\u043e\u0434\u0438\u043c             return         col = self.snake.find_collisions() #\u0415\u0441\u0442\u044c \u043b\u0438 \u043a\u043e\u043b\u043b\u0438\u0437\u0438\u0438?         if col:             for tile in col:                 tile.die() # \u041a\u0440\u0430\u0441\u0438\u043c \u0432\u0441\u0435 \u0432 \u043a\u0440\u0430\u0441\u043d\u044b\u0439             self.game_on = False # \u041e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0438\u0433\u0440\u0443         if self.time_gone(0.3):             self.snake.move(*self.dir)  <\/code><\/pre>\n<p>  \u0427\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0443 \u043c\u0435\u043d\u044f:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/zu\/gx\/n2\/zugxn2bxvlbhj6cagawcjy-qsdi.png\"><\/p>\n<p>  \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044f\u0431\u043b\u043e\u0447\u043a\u0438. <\/p>\n<h4>\u0423\u0434\u043b\u0438\u043d\u0435\u043d\u0438\u0435 \u0438 \u044f\u0431\u043b\u043e\u0447\u043a\u0438<\/h4>\n<p>  \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u0443\u0434\u043b\u0438\u043d\u0435\u043d\u0438\u0435 \u0437\u043c\u0435\u0439\u043a\u0438, \u043f\u0440\u0438\u0447\u0435\u043c \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u043b\u043e \u043a\u0440\u0430\u0441\u0438\u0432\u043e, \u043d\u043e\u0432\u043e\u0435 \u0437\u0432\u0435\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c\u0438 \u0434\u0432\u0443\u043c\u044f, \u0442\u043e \u0435\u0441\u0442\u044c:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/kl\/sg\/uv\/klsguvpmusyky4y78dvdmk_nvdu.png\"><\/p>\n<p>  \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u0437\u043c\u0435\u044e \u043c\u0435\u0442\u043e\u0434\u044b:  <\/p>\n<pre><code class=\"python\">class Snake: # &lt;...&gt;     def find_dir(self, x1, y1, x2, y2):         if x1 == x2 and y1 &gt; y2:             return (0, 1)         elif x1 == x2 and y1 &lt; y2:             return (0, -1)         elif y1 == y2 and x1 &gt; x2:             return (1, 0)         elif y1 == y2 and x1 &lt; x2:             return (-1, 0)         else:             assert False, \"Error!\"              def append(self):         if len(self.tiles) &gt; 1:             lastdir = self.find_dir(*self.tiles[-1].getpos(), *self.tiles[-2].getpos())         else:             lastdir = (-self.parent.dir[0], -self.parent.dir[1])         self.tiles.append(Tile(self.parent, (self.width, self.width)))         x_prev, y_prev = self.tiles[-2].getpos()         self.tiles[-1].setpos(x_prev + lastdir[0] * self.width, y_prev + lastdir[1] * self.width)  <\/code><\/pre>\n<p>  find_dir \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d \u043a\u043e\u043d\u0447\u0438\u043a \u0445\u0432\u043e\u0441\u0442\u0430 \u043d\u0430\u0448\u0435\u0439 \u0433\u0435\u0440\u043e\u0438\u043d\u0438. append, \u043d\u0435\u0441\u043b\u043e\u0436\u043d\u043e \u0434\u043e\u0433\u0430\u0434\u0430\u0442\u044c\u0441\u044f, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u044f\u0447\u0435\u0439\u043a\u0443. \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0435\u0449\u0435 \u043c\u0435\u0442\u043e\u0434 snake_lengthen \u0432 Game:<\/p>\n<pre><code class=\"python\"> class Game(Scene): # &lt;...&gt;     def snake_lengthen(self):         self.snake.append()         self.time_reset()  <\/code><\/pre>\n<p>  \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u043d\u0443\u0436\u043d\u0430 \u0447\u0442\u043e\u0431\u044b \u0437\u043c\u0435\u0439\u043a\u0430 \u043d\u0435\u043c\u043d\u043e\u0436\u043a\u043e \u043f\u043e\u0434\u043e\u0436\u0434\u0430\u043b\u0430, \u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0443\u0441\u043f\u0435\u043b \u0443\u0432\u0438\u0434\u0435\u0442\u044c, \u0447\u0442\u043e \u043a\u0443\u0441\u043e\u0447\u0435\u043a \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0441\u044f.<\/p>\n<p>  \u0427\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0441\u0435\u043a\u0430\u0435\u0442\u0441\u044f \u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u0441\u043e \u0437\u043c\u0435\u0435\u0439, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043d\u0435\u0435 \u043c\u0435\u0442\u043e\u0434 intersect<\/p>\n<pre><code class=\"python\">class Snake: # &lt;...&gt;     def getpos(self):         return self.tiles[0].getpos()          def intersect(self, x, y):         return self.getpos() == (x, y)  <\/code><\/pre>\n<p>  \u0423\u0440\u0430, \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044f\u0431\u043b\u043e\u043a\u043e. \u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043e\u043f\u0438\u0448\u0435\u043c \u044f\u0431\u043b\u043e\u043a\u043e \u0437\u0430 \u043e\u0434\u0438\u043d \u0437\u0430\u0445\u043e\u0434:<\/p>\n<pre><code class=\"python\"> class Apple(PhyObj):     def __init__(self, width, size, parent):         super().__init__(ui.Path.oval(0, 0, size[0], size[1]), \"#55AAFF\", parent)         self.parent = parent         self.width = width         self.dislocate()          def dislocate(self):         a = random.randint(2, int(self.parent.size.w \/ self.width) - 2)         b = random.randint(2, int(self.parent.size.h \/ self.width) - 2)         self.setpos(a * self.width, b * self.width)  <\/code><\/pre>\n<p>  \u0422\u0430\u043a\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0434\u043e\u043c \u043d\u0443\u0436\u0435\u043d \u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u043d\u0430\u0448\u0435 \u044f\u0431\u043b\u043e\u0447\u043a\u043e \u043f\u043e \u0441\u0435\u0442\u043a\u0435. \u0422\u043e\u0433\u0434\u0430 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043a\u0430\u0442\u044c \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u043c\u043e\u0440\u0434\u043e\u0439 \u0438 \u044f\u0431\u043b\u043e\u043a\u043e\u043c \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0442\u044b\u0440\u044b-\u043f\u044b\u0440\u044b. \u041f\u0440\u043e\u0441\u0442\u043e \u043d\u0430 \u0438\u0444\u0430\u0445. \u041f\u043e\u0439\u0434\u0435\u043c \u0432 update \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0432 \u043a\u043e\u043d\u0435\u0446 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<pre><code class=\"python\">class Game(Scene): # &lt;...&gt;     def setup(self):         self.apple = Apple(40, (50, 50), self) #\u0427\u0438\u0441\u043b\u043e 40 - \u0448\u0438\u0440\u0438\u043d\u0430 \u0441\u0435\u0442\u043a\u0438, \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c \u0441 \u0432\u0442\u043e\u0440\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0432 Snake()         # &lt;...&gt;      def update(self):         # &lt;...&gt;         if self.snake.intersect(*self.apple.getpos()):             self.snake_lengthen()             self.apple.dislocate()  <\/code><\/pre>\n<p>  \u041d\u0443 \u0432\u0440\u043e\u0434\u0435 \u0432\u0441\u0435, \u0442\u0435\u043f\u0435\u0440\u044c \u0437\u043c\u0435\u044f \u0443\u0434\u043b\u0438\u043d\u044f\u0435\u0442\u0441\u044f \u0435\u0441\u043b\u0438 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u044f\u0431\u043b\u043e\u043a\u043e \u0438 \u0443\u043c\u0438\u0440\u0430\u0435\u0442, \u0435\u0441\u043b\u0438 \u0441\u0442\u0443\u043a\u0430\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u0430 \u043e \u0441\u0435\u0431\u044f.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/0r\/de\/gw\/0rdegw0knuwccnbh6jz5oy5hova.png\"><\/p>\n<h4>\u0411\u043e\u043d\u0443\u0441<\/h4>\n<p>  \u041c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0437\u0432\u0443\u043a\u043e\u0432\u044b\u0435 \u044d\u0444\u0444\u0435\u043a\u0442\u044b:  <\/p>\n<pre><code class=\"python\">import sound  class Game(Scene): # &lt;...&gt;     def snake_lengthen(self):         self.snake.append()         self.time_reset()         sound.play_effect('arcade:Powerup_1', 0.25, 0.8)  <\/code><\/pre>\n<p>  \u0421\u0434\u0435\u043b\u0430\u0442\u044c \u043f\u043b\u0430\u0432\u043d\u043e\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"python\">class Game(Scene): # &lt;...&gt;     def setup(self):         self.game_on = False         self.GLOBAL_TIMING = 0.2         self.GLOBAL_WIDTH = 40         self.apple = Apple(self.GLOBAL_WIDTH, (50, 50), self)         self.snake = Snake(10, self.GLOBAL_WIDTH, (200, 200), self)         self.time_reset()         self.dir = (0, 1)          self.game_on = True  class Snake: # &lt;...&gt;     def move(self, x, y):         for i in range(len(self.tiles) - 1, 0, -1):             self.tiles[i].setpos(*self.tiles[i - 1].getpos(), self.parent.GLOBAL_TIMING)         self.tiles[0].move(x * self.width, y * self.width, self.parent.GLOBAL_TIMING)  class PhyObj:     def __init__(self, path, color, parent):         self.graph_obj = ShapeNode(path, parent=parent)         self.parent = parent         self.graph_obj.color = color         self.pos = self.graph_obj.position          def setpos(self, x, y, t=0.0):         self.pos = (x, y)         self.graph_obj.run_action(Action.move_to(x, y, t)) # \u041f\u043b\u0430\u0432\u043d\u043e\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043a x, y \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0438 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 t          def getpos(self):         return self.pos          def move(self, x, y, t=0.0):         self.pos = (self.pos[0] + x, self.pos[1] + y)         self.graph_obj.run_action(Action.move_by(x, y, t))   <\/code><\/pre>\n<p>  \u0418\u043d\u0430\u0447\u0435 \u0433\u043e\u0432\u043e\u0440\u044f, \u043c\u044b \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0438 \u043b\u043e\u0433\u0438\u043a\u0443 position PhyObj. \u0420\u0430\u043d\u044c\u0448\u0435 \u043c\u044b \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u043d\u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430, \u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438 (\u0442\u043e \u0435\u0441\u0442\u044c \u0442\u043e\u0439, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u043a\u0438 \u0438\u0433\u0440\u044b), \u0438 \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u0430 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a-\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0430 \u043f\u043e-\u0441\u0432\u043e\u0435\u043c\u0443. \u0410 \u0438\u043c\u0435\u043d\u043d\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f Action, \u043c\u044b \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0435\u0439 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a, \u0433\u0434\u0435 \u043e\u043d\u0430 \u0438 \u0434\u0432\u0438\u0433\u0430\u0435\u0442\u0441\u044f.<\/p>\n<p>  \u0422\u0430\u043a\u0430\u044f \u043f\u043b\u0430\u0432\u043d\u0430\u044f \u0437\u043c\u0435\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c:<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/8g\/ma\/4x\/8gma4xndidknidevmnr49pleuyc.png\"><\/p>\n<p>  \u041d\u0443 \u0438 \u043d\u0430\u043a\u043e\u043d\u0435\u0446 label \u0441 \u0434\u043b\u0438\u043d\u043e\u0439 \u0437\u043c\u0435\u0438:<\/p>\n<pre><code class=\"python\">class Game(Scene): # &lt;...&gt;     def setup(self):         self.game_on = False         self.GLOBAL_TIMING = 0.2         self.GLOBAL_WIDTH = 40         self.apple = Apple(self.GLOBAL_WIDTH, (50, 50), self)         self.snake = Snake(30, self.GLOBAL_WIDTH, (200, 200), self)         self.time_reset()         self.dir = (0, 1)         self.label = LabelNode(\"\", font=(\"Chalkduster\", 20), parent=self, position=(self.size.w \/ 2, self.size.h - 100)) #\u0420\u0430\u0437\u043c\u0435\u0449\u0430\u0435\u043c \u0435\u0435 \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443         self.update_labels()         self.game_on = True          def update_labels(self):         self.label.text = \"Length: \" + str(len(self.snake.tiles))          def update(self):         if not self.game_on:             return         col = self.snake.find_collisions()         if col:             for tile in col:                 tile.die()             self.game_on = False         if self.time_gone(self.GLOBAL_TIMING):             self.snake.move(*self.dir)         if self.snake.intersect(*self.apple.getpos()):             self.snake_lengthen()             self.apple.dislocate()             self.update_labels() #\u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0442\u0443\u0442  <\/code><\/pre>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/pu\/vk\/s5\/puvks5yyrimbzdvzfbt4kwysml4.png\"><\/p>\n<p>  \u0414\u0440\u0443\u0437\u044c\u044f, \u0441\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435! \u0415\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0441\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0439\u0442\u0435. \u0410 \u0435\u0441\u043b\u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u2014 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0443, \u0435\u0449\u0435 \u0435\u0441\u0442\u044c \u0447\u0442\u043e \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c (\u043d\u043e \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u0435\u0439\u043a\u0430 \u0438 \u0442\u0430\u043a \u0434\u043b\u0438\u043d\u043d\u043e\u0432\u0430\u0442\u0430).<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u0437\u043c\u0435\u0439\u043a\u0438<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"python\"> from scene import * import random import math import sound  class PhyObj:     def __init__(self, path, color, parent):         self.graph_obj = ShapeNode(path, parent=parent)         self.parent = parent         self.graph_obj.color = color         self.pos = self.graph_obj.position          def setpos(self, x, y, t=0.0):         self.pos = (x, y)         self.graph_obj.run_action(Action.move_to(x, y, t))          def getpos(self):         return self.pos          def move(self, x, y, t=0.0):         self.pos = (self.pos[0] + x, self.pos[1] + y)         self.graph_obj.run_action(Action.move_by(x, y, t))  class Tile(PhyObj):     def __init__(self, parent, size, margin=4):         super().__init__(ui.Path.rect(0, 0, size[0] - margin, size[1] - margin), \"#66FF66\", parent)          def die(self):         self.graph_obj.color = \"red\"  class Snake:     def __init__(self, length, width, initpos, parent):         self.width = width         self.tiles = [Tile(parent, (width, width)) for i in range(length)]         for i, tile in enumerate(self.tiles):             tile.setpos(initpos[0] + i * self.width, initpos[1])         self.parent = parent          def move(self, x, y):         for i in range(len(self.tiles) - 1, 0, -1):             self.tiles[i].setpos(*self.tiles[i - 1].getpos(), self.parent.GLOBAL_TIMING)         self.tiles[0].move(x * self.width, y * self.width, self.parent.GLOBAL_TIMING)          def find_collisions(self):         for i in range(1, len(self.tiles)):             if self.tiles[i].getpos() == self.tiles[0].getpos():                 return self.tiles[i], self.tiles[0]         return False              def find_dir(self, x1, y1, x2, y2):         if x1 == x2 and y1 &gt; y2:             return (0, 1)         elif x1 == x2 and y1 &lt; y2:             return (0, -1)         elif y1 == y2 and x1 &gt; x2:             return (1, 0)         elif y1 == y2 and x1 &lt; x2:             return (-1, 0)         else:             assert False, \"Error!\"              def append(self):         if len(self.tiles) &gt; 1:             lastdir = self.find_dir(*self.tiles[-1].getpos(), *self.tiles[-2].getpos())         else:             lastdir = (-self.parent.dir[0], -self.parent.dir[1])         self.tiles.append(Tile(self.parent, (self.width, self.width)))         x_prev, y_prev = self.tiles[-2].getpos()         self.tiles[-1].setpos(x_prev + lastdir[0] * self.width, y_prev + lastdir[1] * self.width)          def getpos(self):         return self.tiles[0].getpos()          def intersect(self, x, y):         return self.getpos() == (x, y)  class Apple(PhyObj):     def __init__(self, width, size, parent):         super().__init__(ui.Path.oval(0, 0, size[0], size[1]), \"#55AAFF\", parent)         self.parent = parent         self.width = width         self.dislocate()          def dislocate(self):         a = random.randint(2, int(self.parent.size.w \/ self.width) - 2)         b = random.randint(2, int(self.parent.size.h \/ self.width) - 2)         self.setpos(a * self.width, b * self.width)  class Game(Scene):     def snake_lengthen(self):         self.snake.append()         self.time_reset()         sound.play_effect('arcade:Powerup_1', 0.25, 0.8)          def time_reset(self):         self.last_time = self.t          def time_gone(self, t):         if self.t - self.last_time &gt; t:             res = True             self.time_reset()         else:             res = False         return res          def setup(self):         self.game_on = False         self.GLOBAL_TIMING = 0.2         self.GLOBAL_WIDTH = 40         self.apple = Apple(self.GLOBAL_WIDTH, (50, 50), self)         self.snake = Snake(30, self.GLOBAL_WIDTH, (200, 200), self)         self.time_reset()         self.dir = (0, 1)         self.label = LabelNode(\"\", font=(\"Chalkduster\", 20), parent=self, position=(self.size.w \/ 2, self.size.h - 100))         self.update_labels()         self.game_on = True          def update_labels(self):         self.label.text = \"Length: \" + str(len(self.snake.tiles))          def update(self):         if not self.game_on:             return         col = self.snake.find_collisions()         if col:             for tile in col:                 tile.die()             self.game_on = False         if self.time_gone(self.GLOBAL_TIMING):             self.snake.move(*self.dir)         if self.snake.intersect(*self.apple.getpos()):             self.snake_lengthen()             self.apple.dislocate()             self.update_labels()          def touch_began(self, touch):         ws = touch.location[0] \/ self.size.w         hs = touch.location[1] \/ self.size.h         aws = 1 - ws         if ws &gt; hs and aws &gt; hs:             self.dir = (0, -1)         elif ws &gt; hs and aws &lt;= hs:             self.dir = (1, 0)         elif ws &lt;= hs and aws &gt; hs:             self.dir = (-1, 0)         else:             self.dir = (0, 1)        run(Game(), LANDSCAPE) <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u043e\u0434 \u043a\u0440\u0438\u0441\u0442\u0430\u043b\u043b\u0438\u043a\u043e\u0432 WhiteBlackGoose edition<\/b><\/p>\n<div class=\"spoiler_text\">\u0417\u0430\u0431\u0430\u0432\u043d\u043e, \u0447\u0442\u043e \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u044f \u0435\u0435 \u0441\u0434\u0435\u043b\u0430\u043b, \u044f \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u043b \u0447\u0442\u043e-\u0442\u043e \u041e\u0427\u0415\u041d\u042c \u043f\u043e\u0445\u043e\u0436\u0435\u0435 \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445 \u0438\u0437 \u0441\u0430\u043c\u043e\u0439 pythonista. \u041d\u043e \u0443 \u043c\u0435\u043d\u044f \u0447\u0443\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0435 \u0444\u0438\u0447 \ud83d\ude42  <\/p>\n<pre><code class=\"python\"> from scene import * from math import pi from random import uniform as rnd, choice, randint import sys import random A = Action sys.setrecursionlimit(1000000)  colors = ['pzl:Green5', \"pzl:Red5\", \"pzl:Blue5\"] + [\"pzl:Purple5\", \"pzl:Button2\"] + [\"plf:Item_CoinGold\"] global inited inited = False class Explosion (Node):     def __init__(self, brick, *args, **kwargs):         Node.__init__(self, *args, **kwargs)         self.position = brick.position         for dx, dy in ((-1, -1), (1, -1), (-1, 1), (1, 1)):             p = SpriteNode(brick.texture, scale=0.5, parent=self)             p.position = brick.size.w\/4 * dx, brick.size.h\/4 * dy             p.size = brick.size             d = 0.6             r = 30             p.run_action(A.move_to(rnd(-r, r), rnd(-r, r), d))             p.run_action(A.scale_to(0, d))             p.run_action(A.rotate_to(rnd(-pi\/2, pi\/2), d))         self.run_action(A.sequence(A.wait(d), A.remove()))  class Brick (SpriteNode):     def __init__(self, brick_type, *args, **kwargs):         img = colors[brick_type]         SpriteNode.__init__(self, img, *args, **kwargs)         self.brick_type = brick_type         self.is_on = True         self.lf = True         self.enabled = True          def destroy(self):         self.remove_from_parent()         self.is_on = False          def mark(self):         self.lf = False          def demark(self):         self.lf = True  class Game(Scene):     def brickgetpos(self, i, j):         return (self.Woff + j * self.W, self.Hoff + i * self.H)          def brick(self, ty, i, j):         b = Brick(ty, size=(self.W, self.H), position=self.brickgetpos(i, j), parent=self.game_node)         b.rotation = random.random()         return b      def random_brick_type(self):         if random.random() &lt; 0.992:             return random.randint(0, 3)         else:             if random.random() &lt; 0.8:                 return 5             else:                 return 4     def setup(self):         FONT = ('Chalkduster', 20)         self.score_label = LabelNode('Score: 0', font=FONT, position=(self.size.w\/2-100, self.size.h-40), parent=self)         self.score = 0         self.last_score_label = LabelNode('Delta: +0', font=FONT, position=(self.size.w\/2-300, self.size.h-40), parent=self)         self.last_score = 0         #self.avg_label = LabelNode('Speed: +0\/s', font=FONT, position=(self.size.w\/2+100, self.size.h-40), parent=self)         #self.max_label = LabelNode('Peak: +0\/s', font=FONT, position=(self.size.w\/2+300, self.size.h-40), parent=self)         #self.max_speed = 0         self.game_time = 120         self.timel = LabelNode('Time: ' + str(self.game_time) + \"s\", font=FONT, position=(self.size.w\/2+300, self.size.h-40), parent=self)         self.gems = [0 for i in colors]         self.effect_node = EffectNode(parent=self)         self.game_node = Node(parent=self.effect_node)         self.l = [0 for i in colors]         self.lt = [0 for i in colors]         for i in range(len(colors)):             R = 50 if i == 6 else 35             self.l[i] = Brick(i, size=(R, R), position=(40, self.size.h-100-i*40), parent=self.game_node)             self.lt[i] = LabelNode(\": 0\", font=FONT, position=(self.l[i].position[0] + 40, self.l[i].position[1]), parent=self)         self.WB = 30         self.HB = 30         self.W = 900 \/\/ self.WB         self.H = 900 \/\/ self.HB         self.colcount = 4         self.Woff = (int(self.size.w) - self.W * self.WB + self.W) \/\/ 2         self.Hoff = self.H + 10          self.net = [[self.brick(self.random_brick_type(), i, j) for i in range(self.HB)] for j in range(self.WB)]                  #self.touch_moved = self.touch_began         self.start_time = self.t         self.game_on = True                  global inited         inited = True          def demark(self):         for bricks in self.net:             for brick in bricks:                 brick.demark()          def howfar(self, x, y):         alt = 0         for i in range(y):             if not self.net[x][i].is_on:                 alt += 1         return alt          def update(self):         global inited         if not inited:             return         self.game_on = self.t - self.start_time &lt; self.game_time         if self.game_on:             self.timel.text = \"Time: \" + str(round(self.game_time - (self.t - self.start_time))) + \"s\"         else:             self.timel.text = \"Game over\"         #if speed &gt; self.max_speed:         #    self.max_speed = speed         #    self.max_label.text = \"Peak: +\" + str(round(self.max_speed)) + \"\/s\"          def gravity(self, x, y):         alt = self.howfar(x, y)         if alt == 0:             return                  self.net[x][y].destroy()         self.net[x][y - alt] = self.brick(self.net[x][y].brick_type, y, x)         self.net[x][y - alt].position = self.net[x][y].position         self.net[x][y - alt].rotation = self.net[x][y].rotation         self.net[x][y - alt].enabled = False         self.net[x][y - alt].run_action(A.sequence(A.move_to(*self.brickgetpos(y - alt, x), 0.2 * alt ** 0.5, TIMING_EASE_IN_2), A.call(lambda: self.enable_cell(x, y - alt))))          def enable_cell(self, x, y):         self.net[x][y].enabled = True          def fall(self):         for x in range(self.WB):             for y in range(self.HB):                 if self.net[x][y].is_on:                     self.gravity(x, y)          def update_scores(self):         self.score += self.last_score         self.score_label.text = \"Score: \" + str(self.score)         self.last_score_label.text = \"Delta: +\" + str(self.last_score)         self.last_score = 0          def update_cells(self):         for i in range(self.WB):             for j in range(self.HB):                 if not self.net[i][j].is_on:                     self.net[i][j] = self.brick(self.random_brick_type(), j + self.HB, i)                     self.net[i][j].enabled = True                     self.net[i][j].run_action(A.sequence(A.move_to(*self.brickgetpos(j, i), 0.2 * self.HB ** 0.5, TIMING_EASE_IN_2), A.call(lambda: self.enable_cell(i, j))))          def inbounds(self, x, y):         return (x &gt;= 0) and (y &gt;= 0) and (x &lt; self.WB) and (y &lt; self.HB)          def bomb(self, x, y, radius):         score = 0         bc = 0         for i in range(round(4 * radius ** 2)):             rad = random.random() * radius             ang = random.random() * 2 * pi             xp, yp = x + sin(ang) * rad, y + cos(ang) * rad             xp, yp = int(xp), int(yp)             if self.inbounds(xp, yp):                 score += self.explode(xp, yp)         self.fall()         self.give_score(round(score \/ 1.7), self.brickgetpos(y, x))          def laser(self, x, y):         score = 0         coords = []         for i in range(self.HB):             for j in range(-1, 1 + 1, 1):                 coords.append((x + j, i))         for i in range(self.WB):             coords.append((i, y))         for i in range(-self.HB, self.HB):             coords.append((x + i, y + i))         for i in range(-self.WB, self.WB):             coords.append((x - i, y + i))         bc = 0         for x, y in coords:             if not self.inbounds(x, y):                 continue             score += self.explode(x, y)         self.fall()         self.give_score(score, self.brickgetpos(y, x))          def getty(self, x, y):         if not self.inbounds(x, y) or not self.net[x][y].is_on:             return -1         else:             return self.net[x][y].brick_type          def popupt(self, text, position_, font_=(\"Arial\", 30), color_=\"white\"):         label = LabelNode(text, font=font_, color=color_, parent=self, position=position_)         label.run_action(A.sequence(A.wait(1), A.call(label.remove_from_parent)))          def give_score(self, count, xy):         self.last_score = int(count ** 2.5)         size = 10         if self.last_score &gt; 50000:             size = 60         elif self.last_score &gt; 20000:             size = 40         elif self.last_score &gt; 10000:             size = 30         elif self.last_score &gt; 5000:             size = 25         elif self.last_score &gt; 2000:             size = 20         elif self.last_score &gt; 1000:             size = 15         if self.last_score &gt; 0:             self.popupt(\"+\" + str(self.last_score), xy, font_=(\"Chalkduster\", int(size * 1.5)))         self.update_scores()          def touch_began(self, touch):         if not self.game_on:             return         x, y = touch.location         x, y = x + self.W \/ 2, y + self.H \/ 2         W, H = get_screen_size()         x, y = x, y         x, y = int(x), int(y)         x, y = x - self.Woff, y - self.Hoff         x, y = x \/\/ self.W, y \/\/ self.H         if not self.inbounds(x, y):             return                  count = self.react(self.net[x][y].brick_type, x, y, True)         self.demark()         if self.getty(x, y) in [0, 1, 2, 3]:             if count &gt;= 2:                 self.react(self.net[x][y].brick_type, x, y)                 self.fall()                 self.give_score(count, touch.location)         elif self.getty(x, y) == 4:             self.bomb(x, y, 5 * count)         elif self.getty(x, y) == 5:             self.explode(x, y)             self.fall()         self.update_cells()          def explode(self, x, y):         if self.net[x][y].is_on:             self.net[x][y].destroy()             self.gems[self.net[x][y].brick_type] += 1             s = str(self.gems[self.net[x][y].brick_type])             self.lt[self.net[x][y].brick_type].text = \" \" * len(s) +  \": \" + s             self.game_node.add_child(Explosion(self.net[x][y]))             return True         else:             return False          def react(self, col, x, y, ignore=False):         if self.inbounds(x, y) and self.net[x][y].brick_type == col and self.net[x][y].is_on and self.net[x][y].lf and self.net[x][y].enabled:             if not ignore:                    self.explode(x, y)             else:                 self.net[x][y].mark()             r = 1             r += self.react(col, x + 1, y + 0, ignore)             r += self.react(col, x - 1, y - 0, ignore)             r += self.react(col, x + 0, y + 1, ignore)             r += self.react(col, x - 0, y - 1, ignore)             return r         else:             return 0          def destroy_brick(self, x, y):         self.net[x][y].destroy()          run(Game(), LANDSCAPE, show_fps=True)  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<\/div>\n<p>               <script class=\"js-mediator-script\">!function(e){function t(t,n){if(!(n in e)){for(var r,a=e.document,i=a.scripts,o=i.length;o--;)if(-1!==i[o].src.indexOf(t)){r=i[o];break}if(!r){r=a.createElement(\"script\"),r.type=\"text\/javascript\",r.async=!0,r.defer=!0,r.src=t,r.charset=\"UTF-8\";var d=function(){var e=a.getElementsByTagName(\"script\")[0];e.parentNode.insertBefore(r,e)};\"[object Opera]\"==e.opera?a.addEventListener?a.addEventListener(\"DOMContentLoaded\",d,!1):e.attachEvent(\"onload\",d):d()}}}t(\"\/\/mediator.mail.ru\/script\/2820404\/\",\"_mediator\")}(window);<\/script>     <br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/464805\/\"> https:\/\/habr.com\/ru\/post\/464805\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html js-mediator-article\"><i>\u2026 \u0438\u043b\u0438 \u043a\u0430\u043a \u0443\u0431\u0438\u0442\u044c \u0432\u0440\u0435\u043c\u044f \u0438\u043c\u0435\u044f ipad \u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0438\u0447\u0435\u0433\u043e&#8230;<\/i><\/p>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0442!<\/p>\n<h3>\u041e \u0447\u0435\u043c \u0440\u0435\u0447\u044c?<\/h3>\n<p>  \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043f\u043b\u0430\u043d\u0448\u0435\u0442\u044b \u043f\u043e\u043a\u0430 \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u044e\u0442 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u044b. \u041d\u043e \u043f\u043e\u043a\u043e\u0434\u0438\u0442\u044c \u0432 \u043f\u043e\u0435\u0437\u0434\u043a\u0435\/\u043f\u043e\u043b\u0435\u0442\u0435 \u044d\u0442\u043e \u0436\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043f\u043e\u0438\u0441\u043a\u0430\u043b \u043a\u0430\u043a\u0438\u0435 ide \u0435\u0441\u0442\u044c \u043f\u043e\u0434 ipad, \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0431\u0443\u0434\u0443 \u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0433\u0440\u0443\u043b\u044c\u043a\u0443 \u043d\u0430 Pythonista.<\/p>\n<h3>\u0427\u0442\u043e \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c?<\/h3>\n<p>  \u041f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0438\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u043a\u0440\u0438\u0441\u0442\u0430\u043b\u043b\u0438\u043a\u0438 (\u0434\u0430 \u0434\u0430, \u0442\u0435 \u0441\u0430\u043c\u044b\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u0438\u0433\u0440\u0430\u0435\u0442\u0435 \u0432 \u043c\u0435\u0442\u0440\u043e). \u0422\u0435\u0442\u0440\u0438\u0441, \u0437\u043c\u0435\u0439\u043a\u0430, fill \u2014 \u043b\u044e\u0431\u043e\u0439 \u043d\u043e\u0432\u0438\u0447\u043e\u043a, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u0432\u0448\u0438\u0441\u044c, \u043d\u0430\u043f\u0438\u0448\u0435\u0442 \u0438\u0445 \u0437\u0430 30 \u043c\u0438\u043d\u0443\u0442. \u041f\u043e\u0434 \u043a\u0430\u0442\u043e\u043c \u2014 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b, \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b, \u043a\u043e\u0434.<\/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-293759","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/293759","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=293759"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/293759\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=293759"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=293759"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=293759"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}