{"id":455221,"date":"2025-04-09T03:00:12","date_gmt":"2025-04-09T03:00:12","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=455221"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=455221","title":{"rendered":"<span>\u0421\u0432\u043e\u0439 3d \u0434\u0432\u0438\u0436\u043e\u043a \u043d\u0430 Python [\u0427\u0430\u0441\u0442\u044c 1]<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u042d\u044d\u044d\u043c \u0430 \u043f\u043e\u0447\u0435\u043c\u0443 Python?<\/h2>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d35\/fa0\/042\/d35fa0042d9215194e7a2b71152b02da.webp\" alt=\"Pygame library\" title=\"Pygame library\" width=\"1280\" height=\"720\"\/><\/p>\n<div><figcaption>Pygame library<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0432\u044b \u0441\u0440\u0430\u0437\u0443 \u0441\u043a\u0430\u0436\u0435\u0442\u0435 \u0442\u043e \u0447\u0442\u043e\u00a0Python\u00a0\u2014 \u044d\u0442\u043e \u044f\u0437\u044b\u043a \u043d\u0435\u00a0\u0434\u043b\u044f\u00a0\u0438\u0433\u0440! \u0418 \u043e\u043a\u0430\u0436\u0435\u0442\u0435\u0441\u044c \u043f\u0440\u0430\u0432\u044b! Python\u00a0\u2014 \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u00a0\u0431\u044b\u043b \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u043e\u0434\u00a0\u0438\u0433\u0440\u044b, \u043d\u043e\u00a0\u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u0432\u043e\u0435\u043c\u0443 \u043f\u0440\u043e\u0441\u0442\u043e\u043c\u0443 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0443 \u0432\u00a0\u043d\u0435\u043c \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f pygame \u0438 PyOpenGL \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u00a0\u0436\u0435 Ursina.<\/p>\n<blockquote>\n<p><strong>Pygame<\/strong>\u00a0\u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 Python \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043d\u0430\u00a0<a href=\"https:\/\/sdl.com\" rel=\"noopener noreferrer nofollow\">SDL 2<\/a>\u00a0\u0434\u043b\u044f\u00a0\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u0433\u0440.<\/p>\n<\/blockquote>\n<p>\u0418\u043c\u0435\u043d\u043d\u043e \u0441\u00a0\u043f\u043e\u043c\u043e\u0449\u044c\u044e Pygame \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u044b \u043d\u0430\u00a0\u044d\u043a\u0440\u0430\u043d\u0435, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u00a0\u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u0438\u0433\u0440\u044b!<\/p>\n<h2>\u041d\u0443 \u0438 \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u043c \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c?<\/h2>\n<p>Pygame \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e 2D \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u044b \u0438 \u0434\u043b\u044f\u00a0\u043e\u043f\u044b\u0442\u0430 \u044f \u0440\u0435\u0448\u0438\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c 3D \u0434\u0432\u0438\u0436\u043e\u043a.<\/p>\n<p>\u0412\u00a0\u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0443\u00a0\u043c\u0435\u043d\u044f\u00a0\u0431\u044b\u043b\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0432\u0438\u0436\u043e\u043a \u043d\u0430\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0447\u0442\u043e\u2011\u0442\u043e \u0442\u0438\u043f\u043e Doom. \u041d\u043e\u00a0\u043a\u0430\u043a? \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0432\u0441\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c 3D: <\/p>\n<ul>\n<li>\n<p>RayCasting\u00a0\u2014 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 2.5D \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 \u043b\u0443\u0447\u0438.<\/p>\n<\/li>\n<li>\n<p>RayMarching\u00a0\u2014 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 3D \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0438\u0433\u043e\u043d\u044b\u00a0\u2014 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 3D<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u2011\u043a\u0430\u043a \u0443\u00a0\u043d\u0430\u0441 Python \u044f \u0440\u0435\u0448\u0438\u043b \u0432\u044b\u0431\u0440\u0430\u0442\u044c RayCasting. <\/p>\n<p>RayCasting \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e\u00a0\u2014 \u043c\u044b \u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043b\u0443\u0447\u0438 \u0438 \u0447\u0435\u043c \u043e\u043d \u0434\u043b\u0438\u043d\u043d\u0435\u0435 \u0442\u0435\u043c \u043c\u0435\u043d\u044c\u0448\u0435 \u0440\u0438\u0441\u0443\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442. \u041d\u043e\u00a0\u043a\u0430\u043a\u00a0\u043d\u0430\u043c \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u00a0Python? <\/p>\n<h2>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c!<\/h2>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7a1\/4c6\/227\/7a14c6227507b3d45d7f554f2a68e2cd.png\" alt=\"\u041f\u0440\u0438\u043c\u0435\u0440 Raycasting.\" title=\"\u041f\u0440\u0438\u043c\u0435\u0440 Raycasting.\" width=\"1680\" height=\"605\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7a1\/4c6\/227\/7a14c6227507b3d45d7f554f2a68e2cd.png\"\/><\/p>\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 Raycasting.<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c Python(3.7 \u0438 \u0432\u044b\u0448\u0435), pygame,\u0438 \u0435\u0449\u0435 \u0434\u0432\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u0445 \u0441\u043a\u0430\u0447\u0430\u0435\u043c:<\/p>\n<pre><code class=\"bash\">pip install pygame numpy numba<\/code><\/pre>\n<p>\u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0441\u043d\u043e\u0432\u0443 \u0434\u043b\u044f pygame :<\/p>\n<pre><code class=\"python\"># main.py import pygame from settings import *  # \u0418\u043c\u043f\u043e\u0440\u0442 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a  # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f pygame pygame.init() # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u043a\u043d\u0430 \u0441 \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u043c\u0438 \u0438\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a sc = pygame.display.set_mode((WIDTH, HEIGHT)) # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f FPS clock = pygame.time.Clock()  # \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0446\u0438\u043a\u043b while True:     # \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439     for event in pygame.event.get():         # \u0412\u044b\u0445\u043e\u0434 \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u043e\u043a\u043d\u0430         if event.type == pygame.QUIT:             exit()          # \u0417\u0430\u043b\u0438\u0432\u043a\u0430 \u044d\u043a\u0440\u0430\u043d\u0430 \u0447\u0435\u0440\u043d\u044b\u043c \u0446\u0432\u0435\u0442\u043e\u043c     sc.fill(BLACK)          # \u0417\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0438\u0433\u0440\u044b          # \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u043a\u0440\u0430\u043d\u0430     pygame.display.flip()     # \u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 FPS \u0434\u043e 60 \u043a\u0430\u0434\u0440\u043e\u0432 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443     clock.tick(60)<\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u0433\u0440\u043e\u043a\u0430 \u0438 \u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441:<\/p>\n<pre><code class=\"python\"># player.py from settings import * import pygame  class Player:     def __init__(self):         # \u041d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0438 \u0443\u0433\u043e\u043b \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430         self.x, self.y = player_pos         self.angle = player_angle      @property     def pos(self):         # \u0422\u0435\u043a\u0443\u0449\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0438\u0433\u0440\u043e\u043a\u0430         return (self.x, self.y)      def movement(self):         keys = pygame.key.get_pressed()          # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0435\u0440\u0435\u0434\/\u043d\u0430\u0437\u0430\u0434 (W\/S)         if keys[pygame.K_w]:             self.y -= player_speed         if keys[pygame.K_s]:             self.y += player_speed          # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043b\u0435\u0432\u043e\/\u0432\u043f\u0440\u0430\u0432\u043e (A\/D)         if keys[pygame.K_a]:             self.x -= player_speed         if keys[pygame.K_d]:             self.x += player_speed          # \u041f\u043e\u0432\u043e\u0440\u043e\u0442 (\u0441\u0442\u0440\u0435\u043b\u043a\u0438 \u0432\u043b\u0435\u0432\u043e\/\u0432\u043f\u0440\u0430\u0432\u043e)         if keys[pygame.K_LEFT]:             self.angle -= 0.02         if keys[pygame.K_RIGHT]:             self.angle += 0.02<\/code><\/pre>\n<pre><code class=\"python\">pygame.draw.circle(sc, GREEN, player_pos, 12)<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u0433\u043b\u0430\u0432\u043d\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 main \u0438\u043c\u043f\u043e\u0440\u0442 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u043f\u0435\u0440\u0435\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0438\u0433\u0440\u043e\u043a\u0430 (<code>player.movement()<\/code>) <\/p>\n<pre><code class=\"python\">#main.py import pygame from settings import * from player import Player   pygame.init() sc = pygame.display.set_mode( (WIDTH,HEIGHT) ) clock = pygame.time.Clock() player = Player()  while True:     for event in pygame.event.get():         if event.type == pygame.QUIT:             exit()     player.movement()     sc.fill(BLACK)      pygame.draw.circle(sc, GREEN, player.pos, 12)          pygame.display.flip()     clock.tick(60)<\/code><\/pre>\n<h2>\u041a\u0430\u043a \u043a\u0438\u0434\u0430\u0442\u044c \u043b\u0443\u0447\u0438 ?<\/h2>\n<p>\u041a\u0430\u043a \u043d\u0430\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043b\u0443\u0447\u0430? \u041d\u0430\u0448 \u0438\u0433\u0440\u043e\u043a &#8212; \u044d\u0442\u043e \u0437\u0435\u043b\u0435\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430, \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0442\u043e\u0447\u043a\u0430 O.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/8b8\/1b0\/475\/8b81b047581d3d7b1213fdba133b43d7.png\" alt=\"\u041f\u0435\u0440\u0432\u044b\u0439 \u044d\u0442\u0430\u043f\" title=\"\u041f\u0435\u0440\u0432\u044b\u0439 \u044d\u0442\u0430\u043f\" width=\"900\" height=\"700\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/8b8\/1b0\/475\/8b81b047581d3d7b1213fdba133b43d7.png\"\/><\/p>\n<div><figcaption>\u041f\u0435\u0440\u0432\u044b\u0439 \u044d\u0442\u0430\u043f<\/figcaption><\/div>\n<\/figure>\n<p>\u0410\u00a0\u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u0440\u0435\u0437\u043e\u043a \u0434\u043e\u00a0\u043a\u0440\u0430\u0441\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 P. \u041d\u0430\u043c \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0438\u0433\u0440\u043e\u043a\u0430 \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u0448 angle,\u0430 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u043c\u044b \u0441\u0430\u043c\u0438 \u0437\u0430\u0434\u0430\u0435\u043c!<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/689\/d92\/4cc\/689d924cc45c3364a24c8cfb59b33b11.png\" alt=\"\u041d\u0430\u0445\u043e\u0434\u0438\u043c OP\" title=\"\u041d\u0430\u0445\u043e\u0434\u0438\u043c OP\" width=\"900\" height=\"700\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/689\/d92\/4cc\/689d924cc45c3364a24c8cfb59b33b11.png\"\/><\/p>\n<div><figcaption>\u041d\u0430\u0445\u043e\u0434\u0438\u043c OP<\/figcaption><\/div>\n<\/figure>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0443\u044e \u0442\u0440\u0438\u0433\u043e\u043d\u043e\u043c\u0435\u0442\u0440\u0438\u044e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u043a\u0443\u044e \u0444\u043e\u0440\u043c\u0443\u043b\u0443 \u0434\u043b\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 P:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"formula\" source=\"Xo +d * cos(a)\" alt=\"Xo +d * cos(a)\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/af7\/31f\/a58\/af731fa58cbda7dc322a7b894cbe7351.svg\" width=\"130\" height=\"22\"\/><img decoding=\"async\" class=\"formula\" source=\"Yp = Yo + d* sin(a)\" alt=\"Yp = Yo + d* sin(a)\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/formulas\/5\/55\/554\/5544fb404ade7ceea063de7ad11f425d.svg\" width=\"auto\" height=\"auto\"\/><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/644\/02f\/a2b\/64402fa2bccd7acc506adf94b12cb065.png\" alt=\"\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0444\u043e\u0440\u043c\u0443\u043b\u0443!\" title=\"\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0444\u043e\u0440\u043c\u0443\u043b\u0443!\" width=\"900\" height=\"700\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/644\/02f\/a2b\/64402fa2bccd7acc506adf94b12cb065.png\"\/><\/p>\n<div><figcaption>\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0444\u043e\u0440\u043c\u0443\u043b\u0443!<\/figcaption><\/div>\n<\/figure>\n<h2>\u041f\u0443\u0441\u043a\u0430\u0435\u043c \u043b\u0443\u0447!<\/h2>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e math \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u0438\u043d\u0443\u0441 \u0438 \u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u0443\u0433\u043b\u0430 \u0438\u0433\u0440\u043e\u043a\u0430, \u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u043e\u0439 \u043b\u0438\u043d\u0438\u0438, \u0434\u043b\u0438\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0432\u043d\u0430 \u0448\u0438\u0440\u0438\u043d\u0435 \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<pre><code class=\"python\">    pygame.draw.line(sc, GREEN, player.pos, (player.x +WIDTH * math.cos(player.angle),                                              player.y +WIDTH * math.sin(player.angle)) )<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u043a \u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">#main.py import pygame from settings import * from player import Player import math   pygame.init() sc = pygame.display.set_mode( (WIDTH,HEIGHT) ) clock = pygame.time.Clock() player = Player()  while True:     for event in pygame.event.get():         if event.type == pygame.QUIT:             exit()     player.movement()     sc.fill(BLACK)      pygame.draw.circle(sc, GREEN, player.pos, 12)     pygame.draw.line(sc, GREEN, player.pos, (player.x +WIDTH * math.cos(player.angle), player.y +WIDTH * math.sin(player.angle)) )          pygame.display.flip()     clock.tick(FPS) <\/code><\/pre>\n<hr\/>\n<pre><code class=\"python\"># player.py from settings import * import pygame  class Player:     def __init__(self):         # \u041d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0438 \u0443\u0433\u043e\u043b \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430         self.x, self.y = player_pos         self.angle = player_angle      @property     def pos(self):         # \u0422\u0435\u043a\u0443\u0449\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0438\u0433\u0440\u043e\u043a\u0430         return (self.x, self.y)      def movement(self):         keys = pygame.key.get_pressed()          # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0435\u0440\u0435\u0434\/\u043d\u0430\u0437\u0430\u0434 (W\/S)         if keys[pygame.K_w]:             self.y -= player_speed         if keys[pygame.K_s]:             self.y += player_speed          # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043b\u0435\u0432\u043e\/\u0432\u043f\u0440\u0430\u0432\u043e (A\/D)         if keys[pygame.K_a]:             self.x -= player_speed         if keys[pygame.K_d]:             self.x += player_speed          # \u041f\u043e\u0432\u043e\u0440\u043e\u0442 (\u0441\u0442\u0440\u0435\u043b\u043a\u0438 \u0432\u043b\u0435\u0432\u043e\/\u0432\u043f\u0440\u0430\u0432\u043e)         if keys[pygame.K_LEFT]:             self.angle -= 0.02         if keys[pygame.K_RIGHT]:             self.angle += 0.02          <\/code><\/pre>\n<hr\/>\n<pre><code class=\"python\">#settings.py  WIDTH = 600 HEIGHT = 400 HALF_WIDTH = WIDTH \/\/ 2 HALF_HEIGHT = HEIGHT \/\/ 2 FPS = 60  BLACK = (0,0,0) GREEN = (0,244,0)  player_speed = 2 player_pos = (HALF_WIDTH,HALF_HEIGHT) player_angle = 0<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0443 \u0432\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0430\u043b\u043e \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e \u0432\u0438\u0434\u043d\u043e \u0432 \u043a\u0430\u043a\u0443\u044e \u0441\u0442\u0440\u043e\u043d\u0443 \u0441\u043c\u043e\u0442\u0440\u0438\u0442 \u0438\u0433\u0440\u043e\u043a. <\/p>\n<h2>\u041a\u0430\u0440\u0442\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043c\u0438\u0440\u0430.<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0433\u0440\u043e\u043a \u043c\u043e\u0433 \u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e \u043c\u0438\u0440\u0443 \u0438 \u043f\u0440\u0435\u043e\u0434\u043e\u043b\u0435\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0438\u044f \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043a\u0430\u0440\u0442\u0443.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043f\u043e\u0439\u043b\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c <strong>\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 <\/strong>\u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043a\u0430\u043a \u0440\u0430\u0437 \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u0438\u0433\u0440\u0443 \u0438 \u043a\u0430\u0440\u0442\u0443!<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u0434\u0435\u043b\u0430\u0442\u044c <em>\u043a\u0430\u0440\u0442\u0443 <\/em>&#8212; \u044d\u0442\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u0443 \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u043c \u0432\u0438\u0434\u0435! \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 \u0432\u0441\u0435\u0445 \u044f \u0440\u0435\u0448\u0438\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b &#8212; \u0447\u0442\u0435\u043d\u0438\u0435 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0437\u0430\u0434\u0430\u0447\u0438 \u043a\u0430\u0440\u0442\u044b!<\/p>\n<pre><code class=\"python\">#map.py from settings import *  # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430 \u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b text_map = []  def init_map():     f = open(\"map.txt\", \"r\")          # \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 - \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0442\u0440\u043e\u043a \u043a\u0430\u0440\u0442\u044b     num = int(f.readline())          # \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 text_map     for i in range(num):         text_map.append(f.readline())           f.close()   # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u0430\u0440\u0442\u044b \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 init_map()  # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0441\u0442\u0435\u043d world_map = set()  # \u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b for j, row in enumerate(text_map):      # \u041f\u0440\u043e\u0445\u043e\u0434 \u043f\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c \u043a\u0430\u0440\u0442\u044b     for i, char in enumerate(row):       # \u041f\u0440\u043e\u0445\u043e\u0434 \u043f\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c \u0432 \u0441\u0442\u0440\u043e\u043a\u0435         if char == 'W':                  # \u0415\u0441\u043b\u0438 \u0441\u0438\u043c\u0432\u043e\u043b - \u0441\u0442\u0435\u043d\u0430 ('W')             # \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0441\u0442\u0435\u043d\u044b \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0445 \u0435\u0434\u0438\u043d\u0438\u0446\u0430\u0445 (\u0443\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u043d\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0430\u0439\u043b\u0430)             world_map.add((i * TILE, j * TILE))         if char == '1':                  # \u0415\u0441\u043b\u0438 \u0441\u0438\u043c\u0432\u043e\u043b - \u0441\u0442\u0435\u043d\u0430 ('1')             # \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0441\u0442\u0435\u043d\u044b \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0445 \u0435\u0434\u0438\u043d\u0438\u0446\u0430\u0445 (\u0443\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u043d\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0430\u0439\u043b\u0430)             world_map.add((i * TILE, j * TILE))<\/code><\/pre>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448\u0443 \u043a\u0430\u0440\u0442\u0443 \u0432 main.py &#8212;<code> from map import world_map <\/code><\/p>\n<p>\u041d\u0430\u0441\u0447\u0435\u0442 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u043e\u0442 \u0442\u0430\u043a :<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0441\u0438\u043c\u0432\u043e\u043b\u0443 \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0438\u00a0&#8216;W&#8217;\u00a0\u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0441\u0442\u0435\u043d\u044b \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445 (\u0443\u043c\u043d\u043e\u0436\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0441\u0438\u043c\u0432\u043e\u043b\u0430 \u043d\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0430\u0439\u043b\u0430\u00a0TILE)<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u00a0world_map\u00a0\u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u043e\u043b\u043b\u0438\u0437\u0438\u0439<\/p>\n<\/li>\n<\/ul>\n<h2>\u0418\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043a\u0438!<\/h2>\n<p>\u041a\u0430\u043a \u0432\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u0434\u043b\u044f 2D \u0438\u0433\u0440\u044b \u0438 \u043e\u043d\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f 3D! \u0418 \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0435 <strong>:<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e13\/dfb\/468\/e13dfb468176211e5688e2a51288ae64.png\" alt=\"\u0414\u043e\u0441\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0441 \u043a\u0430\u043d\u0430\u043b\u0430 Stndalone Coder\" title=\"\u0414\u043e\u0441\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0441 \u043a\u0430\u043d\u0430\u043b\u0430 Stndalone Coder\" width=\"751\" height=\"490\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e13\/dfb\/468\/e13dfb468176211e5688e2a51288ae64.png\"\/><\/p>\n<div><figcaption>\u0414\u043e\u0441\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0441 \u043a\u0430\u043d\u0430\u043b\u0430 <a href=\"https:\/\/rutube.ru\/video\/person\/23872600\/\" rel=\"noopener noreferrer nofollow\">Stndalone Coder<\/a><\/figcaption><\/div>\n<\/figure>\n<p>\u042d\u0442\u043e\u0442 \u043a\u0440\u0443\u0433 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u0438\u0433\u0440\u043e\u043a\u0430. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043b\u0443\u0447, \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0434 \u0443\u0433\u043b\u043e\u043c \u03b1. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u043c \u0435\u0433\u043e \u043a\u0430\u043a\u00a0d.<\/p>\n<p>\u041c\u044b \u0443\u043c\u0435\u0435\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443 \u0432 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043b\u0443\u0447\u0430. \u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430 \u043d\u0430 90 \u0433\u0440\u0430\u0434\u0443\u0441\u043e\u0432. \u0421\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0443\u043b\u044b \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0440\u0438\u0433\u043e\u043d\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043b\u0430\u0432\u0438\u0448\u0438.<\/p>\n<p>\u0418 \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u043c \u0443\u0436\u0435 \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f 3D!<\/p>\n<pre><code class=\"python\">from settings import * import pygame import math  class Player:     def __init__(self):         # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0438 \u0443\u0433\u043b\u0430 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \u0438\u0433\u0440\u043e\u043a\u0430         self.x, self.y = player_pos         self.angle = player_angle      @property     def pos(self):         # \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0432 \u0432\u0438\u0434\u0435 \u043a\u043e\u0440\u0442\u0435\u0436\u0430         return (self.x, self.y)      def movement(self):         # \u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0441\u0447\u0435\u0442 \u0441\u0438\u043d\u0443\u0441\u0430 \u0438 \u043a\u043e\u0441\u0438\u043d\u0443\u0441\u0430 \u0443\u0433\u043b\u0430 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430         sin_a = math.sin(self.angle)         cos_a = math.cos(self.angle)                  keys = pygame.key.get_pressed()                  # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0435\u0440\u0435\u0434 (W) - \u043f\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0432\u0437\u0433\u043b\u044f\u0434\u0430         if keys[pygame.K_w]:             self.x += player_speed * cos_a             self.y += player_speed * sin_a                      # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0437\u0430\u0434 (S) - \u043f\u0440\u043e\u0442\u0438\u0432 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0437\u0433\u043b\u044f\u0434\u0430         if keys[pygame.K_s]:             self.x -= player_speed * cos_a             self.y -= player_speed * sin_a                      # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043b\u0435\u0432\u043e (A) - \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e (\u0432\u0435\u043a\u0442\u043e\u0440 \u0432\u043b\u0435\u0432\u043e)         if keys[pygame.K_a]:             self.x += player_speed * sin_a  # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c sin \u0434\u043b\u044f \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e\u0433\u043e \u0432\u0435\u043a\u0442\u043e\u0440\u0430             self.y -= player_speed * cos_a  # \u041e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 cos \u0434\u043b\u044f \u043b\u0435\u0432\u043e\u0433\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f                      # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0440\u0430\u0432\u043e (D) - \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e (\u0432\u0435\u043a\u0442\u043e\u0440 \u0432\u043f\u0440\u0430\u0432\u043e)         if keys[pygame.K_d]:             self.x -= player_speed * sin_a  # \u041e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 sin \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u043e\u0433\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f             self.y += player_speed * cos_a  # \u041f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 cos                      # \u041f\u043e\u0432\u043e\u0440\u043e\u0442 \u0432\u043b\u0435\u0432\u043e (\u0441\u0442\u0440\u0435\u043b\u043a\u0430 \u0432\u043b\u0435\u0432\u043e)         if keys[pygame.K_LEFT]:             self.angle -= 0.02                      # \u041f\u043e\u0432\u043e\u0440\u043e\u0442 \u0432\u043f\u0440\u0430\u0432\u043e (\u0441\u0442\u0440\u0435\u043b\u043a\u0430 \u0432\u043f\u0440\u0430\u0432\u043e)         if keys[pygame.K_RIGHT]:             self.angle += 0.02<\/code><\/pre>\n<p>\u0418 \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u0448\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u043b\u043e \u0431\u043b\u0438\u0437\u043a\u043e \u043a \u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043c\u044b \u043f\u0440\u0438\u0432\u044b\u043a\u043b\u0438 \u0432\u0438\u0434\u0435\u0442\u044c \u0432 \u0448\u0443\u0442\u0435\u0440\u0430\u0445 \u043e\u0442 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043b\u0438\u0446\u0430!<\/p>\n<h2>\u041f\u0435\u0440\u0435\u0445\u043e\u0434 \u0432 3D !!!<\/h2>\n<p><strong>\u0414\u0430 \u0438 \u043e\u043f\u044f\u0442\u044c \u0442\u0435\u043e\u0440\u0438\u044f!<\/strong><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/29a\/b07\/2c7\/29ab072c7b421a693289c8b99a40d848.png\" alt=\"2d -&gt; 3d\" title=\"2d -&gt; 3d\" width=\"957\" height=\"389\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/29a\/b07\/2c7\/29ab072c7b421a693289c8b99a40d848.png\"\/><\/p>\n<div><figcaption>2d -&gt; 3d<\/figcaption><\/div>\n<\/figure>\n<p>\u0412\u0432\u0435\u0434\u0451\u043c \u043f\u043e\u043d\u044f\u0442\u0438\u0435\u00a0<strong>\u043f\u043e\u043b\u044f \u0437\u0440\u0435\u043d\u0438\u044f (FOV \u2014 Field of View)<\/strong>\u00a0\u2014 \u044d\u0442\u043e \u0443\u0433\u043b\u043e\u0432\u043e\u0439 \u0441\u0435\u043a\u0442\u043e\u0440, \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u0438\u0441\u043f\u0443\u0441\u043a\u0430\u0442\u044c\u0441\u044f \u043b\u0443\u0447\u0438.<\/p>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043b\u0443\u0447\u0430\u043c\u0438 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<ul>\n<li>\n<p><code><strong>num_rays<\/strong><\/code>\u00a0\u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043b\u0443\u0447\u0435\u0439 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 FOV.<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u0443\u0433\u043e\u043b<\/strong>\u00a0\u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043b\u0443\u0447\u0430:\u00a0<img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"a - FOV \/ 2\" alt=\"a - FOV \/ 2\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/289\/6f2\/e12\/2896f2e127035cd80172a44a4747c793.svg\" width=\"97\" height=\"22\"\/>.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u043e\u043d\u0435\u0447\u043d\u044b\u0439 \u0443\u0433\u043e\u043b<\/strong>\u00a0\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043b\u0443\u0447\u0430:\u00a0<img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"a + FOV \/ 2\" alt=\"a + FOV \/ 2\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/86d\/dfa\/a94\/86ddfaa94c951839e5ecc79fa1ac3ab5.svg\" width=\"97\" height=\"22\"\/>.<\/p>\n<\/li>\n<li>\n<p><code><strong>DELTA_ANGLE<\/strong><\/code>\u00a0\u2014 \u0443\u0433\u043b\u043e\u0432\u043e\u0439 \u0448\u0430\u0433 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0441\u0435\u0434\u043d\u0438\u043c\u0438 \u043b\u0443\u0447\u0430\u043c\u0438 (\u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a\u00a0<img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"FOV \/ (num_rays - 1)\" alt=\"FOV \/ (num_rays - 1)\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5da\/c04\/a52\/5dac04a52091c91ff2bd15223839be82.svg\" width=\"178\" height=\"22\"\/>, \u0435\u0441\u043b\u0438 \u043b\u0443\u0447\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u043e).<\/p>\n<\/li>\n<li>\n<p><code><strong>MAX_DEPTH<\/strong><\/code>\u00a0\u2014 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0438\u0441\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u043b\u0443\u0447\u0438 (\u0433\u043b\u0443\u0431\u0438\u043d\u0430 \u043f\u0440\u043e\u0440\u0438\u0441\u043e\u0432\u043a\u0438).<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043b\u0443\u0447\u0438 \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0432\u043d\u043e\u043c\u0435\u0440\u043d\u043e \u043f\u043e\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u043a\u0442\u043e\u0440 FOV, \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 \u0443\u0433\u043b\u0430\u00a0<img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"a - FOV \/ 2\" alt=\"a - FOV \/ 2\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/60f\/ba2\/b0a\/60fba2b0a6188f41454b6b4406cde997.svg\" width=\"97\" height=\"22\"\/>\u00a0\u0438 \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044f<code><img loading=\"lazy\" decoding=\"async\" class=\"formula inline\" source=\"\u00a0a + FOV \/ 2\" alt=\"\u00a0a + FOV \/ 2\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c31\/ad0\/371\/c31ad0371904927d0ec2c4090066ee73.svg\" width=\"97\" height=\"22\"\/><\/code>, \u0441 \u0448\u0430\u0433\u043e\u043c\u00a0<code><strong>DELTA_ANGLE<\/strong><\/code>.<\/p>\n<p>\u0412\u0432\u0435\u0434\u0435\u043c \u0432\u0441\u0435 \u044d\u0442\u043e \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438:<\/p>\n<pre><code class=\"python\"># ray casting settings FOV = math.pi \/ 3 HALF_FOV = FOV \/ 2 NUM_RAYS = 120 MAX_DEPTH = 800 DELTA_ANGLE = FOV \/ NUM_RAYS<\/code><\/pre>\n<p>\u0418 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0444\u0430\u0439\u043b ray_casting.py:<\/p>\n<pre><code class=\"python\"> #\u041d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b import pygame from settings import * from map import world_map  <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u0430\u0448 \u044d\u043a\u0440\u0430\u043d, \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0438 \u0443\u0433\u043e\u043b \u0438\u0433\u0440\u043e\u043a\u0430:<\/p>\n<pre><code class=\"python\">def ray_casting(sc, player_pos, player_angle):     pass<\/code><\/pre>\n<p>\u0418 \u0437\u0430\u043f\u043e\u043b\u043d\u0438\u043c \u0435\u0451:<\/p>\n<pre><code class=\"python\">import pygame import math from numba import njit from settings import * from map import world_map  def ray_casting(sc, player_pos, player_angle):     cur_angle = player_angle - HALF_FOV     #\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0442\u043e\u0447\u043a\u0438 O     xo, yo = player_pos      #\u041f\u0440\u043e\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u043f\u043e \u0432\u0441\u0435\u043c \u043b\u0443\u0447\u0430\u043c     for ray in range(NUM_RAYS):         #\u0421\u0438\u043d\u0443\u0441 \u0438 \u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f          sin_a = math.sin(cur_angle)         cos_a = math.cos(cur_angle)         #\u0418\u0434\u0435\u043c \u0432 \u0433\u043b\u0443\u0431\u044c \u043a\u0430\u0440\u0442\u044b         for depth in range(MAX_DEPTH):             x = xo + depth * cos_a             y = yo + depth * sin_a             pygame.draw.line(sc, DARKGRAY, player_pos, (x, y), 2) #            if (x \/\/ TILE * TILE, y \/\/ TILE * TILE) in world_map: #                depth *= math.cos(player_angle - cur_angle) #                proj_height = min(PROJ_COEFF \/ (depth + 0.0001), HEIGHT) #                c = 255 \/ (1 + depth * depth * 0.0001) #                color = (c \/\/ 2, c, c \/\/ 3) #                pygame.draw.rect(sc, color, (ray * SCALE, HALF_HEIGHT - proj_height \/\/ 2, SCALE, proj_height)) #                break         cur_angle += DELTA_ANGLE<\/code><\/pre>\n<p>\u041d\u0443 \u0447\u0442\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u0432\u0441\u0435 \u0447\u0442\u043e \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0431\u043e\u043a\u0443!<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f32\/2e2\/d53\/f322e2d539410d85547187b9a1b9fbcd.png\" alt=\"\u0421\u0445\u0435\u043c\u0430 \u0441 \u0431\u043e\u043a\u0443\" title=\"\u0421\u0445\u0435\u043c\u0430 \u0441 \u0431\u043e\u043a\u0443\" width=\"1014\" height=\"676\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f32\/2e2\/d53\/f322e2d539410d85547187b9a1b9fbcd.png\"\/><\/p>\n<div><figcaption>\u0421\u0445\u0435\u043c\u0430 \u0441 \u0431\u043e\u043a\u0443<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430\u0440\u0438\u0441\u0443\u0435\u043c \u0441\u0442\u0435\u043d\u0443 \u0438 \u0435\u0451 \u043f\u0440\u043e\u0435\u043a\u0446\u0438\u044e \u043d\u0430 \u043d\u0430\u0448 \u044d\u043a\u0440\u0430\u043d. \u0418\u0441\u043a\u043e\u043c\u0443\u044e \u0432\u044b\u0441\u043e\u0442\u0443 \u0431\u0443\u0434\u0435\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0438\u0437 \u043f\u043e\u0434\u043e\u0431\u0438\u044f \u0442\u0440\u0435\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b \u0432\u0438\u0434\u0438\u0442\u0435 \u043d\u0430 \u0440\u0438\u0441\u0443\u043d\u043a\u0435 :<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f39\/b1d\/a3e\/f39b1da3eea5f9afe9d69b8d4d0ff11d.png\" alt=\"\u0414\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0431\u043e\u043a\u0443 \" title=\"\u0414\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0431\u043e\u043a\u0443 \" width=\"1017\" height=\"676\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f39\/b1d\/a3e\/f39b1da3eea5f9afe9d69b8d4d0ff11d.png\"\/><\/p>\n<div><figcaption>\u0414\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0441\u0431\u043e\u043a\u0443 <\/figcaption><\/div>\n<\/figure>\n<pre><code class=\"python\">DIST = NUM_RAYS \/ (2 * math.tan(HALF_FOV)) PROJ_COEFF = 3 * DIST * TILE SCALE = WIDTH \/\/ NUM_RAYS<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0432\u0441\u0435 \u0441\u0434\u0435\u043b\u0430\u043d\u043d\u043e\u0435 \u0440\u0430\u043d\u0435\u0435 \u0432 \u043d\u0430\u0448\u0435\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u0449\u0438\u043a\u0435 :<\/p>\n<pre><code class=\"python\">            if (x \/\/ TILE * TILE, y \/\/ TILE * TILE) in world_map:                 depth *= math.cos(player_angle - cur_angle)                 proj_height = min(PROJ_COEFF \/ (depth + 0.0001), HEIGHT)                 c = 255 \/ (1 + depth * depth * 0.0001)                 color = (c \/\/ 2, c, c \/\/ 3)                 pygame.draw.rect(sc, color, (ray * SCALE, HALF_HEIGHT - proj_height \/\/ 2, SCALE, proj_height))                 break<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0412\u0435\u0441\u044c \u0431\u043e\u0436\u0435\u0447\u043a\u0438 \u043a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">#main.py import pygame from settings import * from player import Player import math from map import text_map,world_map from ray_casting import ray_casting  pygame.init() sc = pygame.display.set_mode( (WIDTH,HEIGHT) ) clock = pygame.time.Clock() player = Player()  while True:     for event in pygame.event.get():         if event.type == pygame.QUIT:             exit()     player.movement()     sc.fill(BLACK)      ray_casting(sc,player.pos,player.angle)      pygame.draw.circle(sc, GREEN, (int(player.x),int(player.y)), 12)     pygame.draw.line(sc, GREEN, player.pos, (player.x +WIDTH * math.cos(player.angle), player.y +WIDTH * math.sin(player.angle)) )      for x,y in world_map:         pygame.draw.rect(sc, DARKGRAY, (x, y, TILE, TILE), 2)          pygame.display.flip()     clock.tick(FPS) <\/code><\/pre>\n<pre><code class=\"python\">from settings import * import pygame import math  class Player:     def __init__(self):         # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0438 \u0443\u0433\u043b\u0430 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \u0438\u0433\u0440\u043e\u043a\u0430         self.x, self.y = player_pos         self.angle = player_angle      @property     def pos(self):         # \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0432 \u0432\u0438\u0434\u0435 \u043a\u043e\u0440\u0442\u0435\u0436\u0430         return (self.x, self.y)      def movement(self):         # \u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0441\u0447\u0435\u0442 \u0441\u0438\u043d\u0443\u0441\u0430 \u0438 \u043a\u043e\u0441\u0438\u043d\u0443\u0441\u0430 \u0443\u0433\u043b\u0430 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430         sin_a = math.sin(self.angle)         cos_a = math.cos(self.angle)                  keys = pygame.key.get_pressed()                  # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0435\u0440\u0435\u0434 (W) - \u043f\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0432\u0437\u0433\u043b\u044f\u0434\u0430         if keys[pygame.K_w]:             self.x += player_speed * cos_a             self.y += player_speed * sin_a                      # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0437\u0430\u0434 (S) - \u043f\u0440\u043e\u0442\u0438\u0432 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0437\u0433\u043b\u044f\u0434\u0430         if keys[pygame.K_s]:             self.x -= player_speed * cos_a             self.y -= player_speed * sin_a                      # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043b\u0435\u0432\u043e (A) - \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e (\u0432\u0435\u043a\u0442\u043e\u0440 \u0432\u043b\u0435\u0432\u043e)         if keys[pygame.K_a]:             self.x += player_speed * sin_a  # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c sin \u0434\u043b\u044f \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e\u0433\u043e \u0432\u0435\u043a\u0442\u043e\u0440\u0430             self.y -= player_speed * cos_a  # \u041e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 cos \u0434\u043b\u044f \u043b\u0435\u0432\u043e\u0433\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f                      # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0440\u0430\u0432\u043e (D) - \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e (\u0432\u0435\u043a\u0442\u043e\u0440 \u0432\u043f\u0440\u0430\u0432\u043e)         if keys[pygame.K_d]:             self.x -= player_speed * sin_a  # \u041e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 sin \u0434\u043b\u044f \u043f\u0440\u0430\u0432\u043e\u0433\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f             self.y += player_speed * cos_a  # \u041f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 cos                      # \u041f\u043e\u0432\u043e\u0440\u043e\u0442 \u0432\u043b\u0435\u0432\u043e (\u0441\u0442\u0440\u0435\u043b\u043a\u0430 \u0432\u043b\u0435\u0432\u043e)         if keys[pygame.K_LEFT]:             self.angle -= 0.02                      # \u041f\u043e\u0432\u043e\u0440\u043e\u0442 \u0432\u043f\u0440\u0430\u0432\u043e (\u0441\u0442\u0440\u0435\u043b\u043a\u0430 \u0432\u043f\u0440\u0430\u0432\u043e)         if keys[pygame.K_RIGHT]:             self.angle += 0.02<\/code><\/pre>\n<pre><code class=\"python\">import pygame import math from numba import njit from settings import * from map import world_map  def ray_casting(sc, player_pos, player_angle):     cur_angle = player_angle - HALF_FOV     #\u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0442\u043e\u0447\u043a\u0438 O     xo, yo = player_pos      #\u041f\u0440\u043e\u0445\u043e\u0434\u0438\u043c\u0441\u044f \u043f\u043e \u0432\u0441\u0435\u043c \u043b\u0443\u0447\u0430\u043c     for ray in range(NUM_RAYS):         #\u0421\u0438\u043d\u0443\u0441 \u0438 \u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f          sin_a = math.sin(cur_angle)         cos_a = math.cos(cur_angle)         #\u0418\u0434\u0435\u043c \u0432 \u0433\u043b\u0443\u0431\u044c \u043a\u0430\u0440\u0442\u044b         for depth in range(MAX_DEPTH):             x = xo + depth * cos_a             y = yo + depth * sin_a             pygame.draw.line(sc, DARKGRAY, player_pos, (x, y), 2)             if (x \/\/ TILE * TILE, y \/\/ TILE * TILE) in world_map:                 depth *= math.cos(player_angle - cur_angle)                 proj_height = min(PROJ_COEFF \/ (depth + 0.0001), HEIGHT)                 c = 255 \/ (1 + depth * depth * 0.0001)                 color = (c \/\/ 2, c, c \/\/ 3)                 pygame.draw.rect(sc, color, (ray * SCALE, HALF_HEIGHT - proj_height \/\/ 2, SCALE, proj_height))                 break         cur_angle += DELTA_ANGLE<\/code><\/pre>\n<pre><code class=\"python\"># \u0418\u043c\u043f\u043e\u0440\u0442 \u0432\u0441\u0435\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 settings.py from settings import *  # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430 \u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b text_map = []  def init_map():     f = open(\"map.txt\", \"r\")          # \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 - \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0442\u0440\u043e\u043a \u043a\u0430\u0440\u0442\u044b     num = int(f.readline())          # \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 text_map     for i in range(num):         text_map.append(f.readline())           f.close()   # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u0430\u0440\u0442\u044b \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 init_map()  print(text_map)  # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0441\u0442\u0435\u043d world_map = set()  # \u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b for j, row in enumerate(text_map):      # \u041f\u0440\u043e\u0445\u043e\u0434 \u043f\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c \u043a\u0430\u0440\u0442\u044b     for i, char in enumerate(row):       # \u041f\u0440\u043e\u0445\u043e\u0434 \u043f\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c \u0432 \u0441\u0442\u0440\u043e\u043a\u0435         if char == 'W':                  # \u0415\u0441\u043b\u0438 \u0441\u0438\u043c\u0432\u043e\u043b - \u0441\u0442\u0435\u043d\u0430 ('W')             # \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0441\u0442\u0435\u043d\u044b \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0445 \u0435\u0434\u0438\u043d\u0438\u0446\u0430\u0445 (\u0443\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u043d\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0430\u0439\u043b\u0430)             world_map.add((i * TILE, j * TILE))         if char == '1':                  # \u0415\u0441\u043b\u0438 \u0441\u0438\u043c\u0432\u043e\u043b - \u0441\u0442\u0435\u043d\u0430 ('1')             # \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0441\u0442\u0435\u043d\u044b \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0445 \u0435\u0434\u0438\u043d\u0438\u0446\u0430\u0445 (\u0443\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u043d\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0430\u0439\u043b\u0430)             world_map.add((i * TILE, j * TILE))<\/code><\/pre>\n<pre><code class=\"python\">import math  # game settings WIDTH = 1200 HEIGHT = 800 HALF_WIDTH = WIDTH \/\/ 2 HALF_HEIGHT = HEIGHT \/\/ 2 FPS = 60 TILE = 100  # ray casting settings FOV = math.pi \/ 3 HALF_FOV = FOV \/ 2 NUM_RAYS = 120 MAX_DEPTH = 800 DELTA_ANGLE = FOV \/ NUM_RAYS DIST = NUM_RAYS \/ (2 * math.tan(HALF_FOV)) PROJ_COEFF = 3 * DIST * TILE SCALE = WIDTH \/\/ NUM_RAYS  # player settings player_pos = (HALF_WIDTH, HALF_HEIGHT) player_angle = 0 player_speed = 2  # colors WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (220, 0, 0) GREEN = (0, 220, 0) BLUE = (0, 0, 255) DARKGRAY = (40, 40, 40) PURPLE = (120, 0, 120)<\/code><\/pre>\n<pre><code class=\"markdown\">7 WWWWWWWWWWWW W..........W W...WW.....W W..........W W..WW......W W..........W W....WWW...W WWWWWWWWWWWW<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h2>\u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043c\u0435\u043b\u043a\u0438\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u043f\u0435\u0440\u0435\u0434 \u043a\u043e\u043d\u0446\u043e\u043c!<\/h2>\n<p>\u041d\u0435\u0431\u043e! \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0435\u0431\u043e!<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0440\u0438\u0441\u0443\u0435\u043c \u0434\u0432\u0430 \u043f\u0440\u044f\u043c\u043e\u0443\u0433\u043e\u043b\u044c\u043d\u0438\u043a\u0430. \u041e\u0434\u0438\u043d &#8212; \u044d\u0442\u043e \u0437\u0435\u043c\u043b\u044f, \u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u044d\u0442\u043e \u043d\u0435\u0431\u043e<\/p>\n<pre><code class=\"python\">    pygame.draw.rect(sc, BLUE, (0, 0, WIDTH, HALF_HEIGHT))     pygame.draw.rect(sc, DARKGRAY, (0, HALF_HEIGHT, WIDTH, HALF_HEIGHT))<\/code><\/pre>\n<p> \u0418 \u0434\u0430 \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0443\u0431\u0435\u0440\u0435\u043c \u044d\u0442\u043e\u0442 2D! \u0423\u0431\u0435\u0440\u0438\u0442\u0435 \u0438\u043b\u0438 \u0437\u0430\u043a\u043e\u043c\u0435\u043d\u0442\u0438\u0442\u0435 \u044d\u0442\u0438 \u0441\u0442\u0440\u043e\u043a\u0438 :<\/p>\n<pre><code class=\"python\">     pygame.draw.circle(sc, GREEN, (int(player.x),int(player.y)), 12)     pygame.draw.line(sc, GREEN, player.pos, (player.x +WIDTH * math.cos(player.angle), player.y +WIDTH * math.sin(player.angle)) )<\/code><\/pre>\n<pre><code class=\"python\">    # pygame.draw.circle(sc, GREEN, (int(player.x), int(player.y)), 12)     # pygame.draw.line(sc, GREEN, player.pos, (player.x + WIDTH * math.cos(player.angle),     #                                          player.y + WIDTH * math. sin(player.angle)), 2)     # for x,y in world_map:     #     pygame.draw.rect(sc, DARKGRAY, (x, y, TILE, TILE), 2)<\/code><\/pre>\n<h2>\u041a\u043e\u043d\u0435\u0446.<\/h2>\n<p>\u042d\u0442\u043e \u043a\u043e\u043d\u0435\u0446 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0438 \u0432\u043e\u0442 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u044b \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c :<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0e2\/3f8\/2e7\/0e23f82e75f36077329b641643b13b9d.png\" alt=\"1\" title=\"1\" width=\"1200\" height=\"800\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0e2\/3f8\/2e7\/0e23f82e75f36077329b641643b13b9d.png\"\/><\/p>\n<div><figcaption>1<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a84\/4b1\/677\/a844b1677d0396a4412e85eb4cdab260.gif\" alt=\"2\" title=\"2\" width=\"1200\" height=\"800\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a84\/4b1\/677\/a844b1677d0396a4412e85eb4cdab260.gif\"\/><\/p>\n<div><figcaption>2<\/figcaption><\/div>\n<\/figure>\n<h2>\u0421\u043f\u0438\u0441\u043e\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432:<\/h2>\n<ol>\n<li>\n<p><strong>\u041a\u0430\u043a \u0441\u0434\u0435\u043b\u0430\u0442\u044c 3D \u0418\u0433\u0440\u0443 \u043d\u0430 Python \u0441 \u041d\u0443\u043b\u044f [ Pygame ] <\/strong>\u2014  <a href=\"https:\/\/rutube.ru\/video\/10d8a78011fde530ac10eb7bc51cb7a9\/?playlist=56799\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u0442\u0443\u0434\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><strong>\u0412\u0438\u0434\u0435\u043e \u0438\u0437 2d \u0432 3d<\/strong>  \u2014 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0438\u0434\u043e\u0441\u0438\u043a<\/p>\n<\/li>\n<\/ol>\n<p>\u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u043f\u0440\u043e\u0447\u0442\u0435\u043d\u0438\u0435 !  \u041f\u043e\u043c\u043d\u0438\u0442\u0435 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c \u0432\u0441\u0435 \u0431\u0430\u0433\u0438 \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u043c FPS \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043a\u0430\u0440\u0442.<\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/404\" rel=\"noopener noreferrer nofollow\">\u0421\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0434\u0430\u043b\u0435\u0435<\/a> -&gt;<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/898960\/\"> https:\/\/habr.com\/ru\/articles\/898960\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u042d\u044d\u044d\u043c \u0430 \u043f\u043e\u0447\u0435\u043c\u0443 Python?<\/h2>\n<figure class=\"full-width\">\n<div><figcaption>Pygame library<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0440\u043e\u0447\u0438\u0442\u0430\u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a \u0432\u044b \u0441\u0440\u0430\u0437\u0443 \u0441\u043a\u0430\u0436\u0435\u0442\u0435 \u0442\u043e \u0447\u0442\u043e\u00a0Python\u00a0\u2014 \u044d\u0442\u043e \u044f\u0437\u044b\u043a \u043d\u0435\u00a0\u0434\u043b\u044f\u00a0\u0438\u0433\u0440! \u0418 \u043e\u043a\u0430\u0436\u0435\u0442\u0435\u0441\u044c \u043f\u0440\u0430\u0432\u044b! Python\u00a0\u2014 \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u00a0\u0431\u044b\u043b \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u043e\u0434\u00a0\u0438\u0433\u0440\u044b, \u043d\u043e\u00a0\u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0441\u0432\u043e\u0435\u043c\u0443 \u043f\u0440\u043e\u0441\u0442\u043e\u043c\u0443 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0443 \u0432\u00a0\u043d\u0435\u043c \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f pygame \u0438 PyOpenGL \u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u00a0\u0436\u0435 Ursina.<\/p>\n<blockquote>\n<p><strong>Pygame<\/strong>\u00a0\u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 Python \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043d\u0430\u00a0<a href=\"https:\/\/sdl.com\" rel=\"noopener noreferrer nofollow\">SDL 2<\/a>\u00a0\u0434\u043b\u044f\u00a0\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u0433\u0440.<\/p>\n<\/blockquote>\n<p>\u0418\u043c\u0435\u043d\u043d\u043e \u0441\u00a0\u043f\u043e\u043c\u043e\u0449\u044c\u044e Pygame \u043c\u044b \u0441\u043c\u043e\u0436\u0435\u043c \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u044b \u043d\u0430\u00a0\u044d\u043a\u0440\u0430\u043d\u0435, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441\u00a0\u043b\u043e\u0433\u0438\u043a\u043e\u0439 \u0438\u0433\u0440\u044b!<\/p>\n<h2>\u041d\u0443 \u0438 \u043a\u0430\u043a \u0431\u0443\u0434\u0435\u043c \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c?<\/h2>\n<p>Pygame \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e 2D \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u044b \u0438 \u0434\u043b\u044f\u00a0\u043e\u043f\u044b\u0442\u0430 \u044f \u0440\u0435\u0448\u0438\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c 3D \u0434\u0432\u0438\u0436\u043e\u043a.<\/p>\n<p>\u0412\u00a0\u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u0443\u00a0\u043c\u0435\u043d\u044f\u00a0\u0431\u044b\u043b\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0432\u0438\u0436\u043e\u043a \u043d\u0430\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0447\u0442\u043e\u2011\u0442\u043e \u0442\u0438\u043f\u043e Doom. \u041d\u043e\u00a0\u043a\u0430\u043a? \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0451\u043c \u0432\u0441\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c 3D: <\/p>\n<ul>\n<li>\n<p>RayCasting\u00a0\u2014 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 2.5D \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 \u043b\u0443\u0447\u0438.<\/p>\n<\/li>\n<li>\n<p>RayMarching\u00a0\u2014 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 3D \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 \u0448\u0430\u0433\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u0438\u0433\u043e\u043d\u044b\u00a0\u2014 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 3D<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u2011\u043a\u0430\u043a \u0443\u00a0\u043d\u0430\u0441 Python \u044f \u0440\u0435\u0448\u0438\u043b \u0432\u044b\u0431\u0440\u0430\u0442\u044c RayCasting. <\/p>\n<p>RayCasting \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e\u00a0\u2014 \u043c\u044b \u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043b\u0443\u0447\u0438 \u0438 \u0447\u0435\u043c \u043e\u043d \u0434\u043b\u0438\u043d\u043d\u0435\u0435 \u0442\u0435\u043c \u043c\u0435\u043d\u044c\u0448\u0435 \u0440\u0438\u0441\u0443\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442. \u041d\u043e\u00a0\u043a\u0430\u043a\u00a0\u043d\u0430\u043c \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u00a0Python? <\/p>\n<h2>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c!<\/h2>\n<figure class=\"full-width\">\n<div><figcaption>\u041f\u0440\u0438\u043c\u0435\u0440 Raycasting.<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0430\u043c Python(3.7 \u0438 \u0432\u044b\u0448\u0435), pygame,\u0438 \u0435\u0449\u0435 \u0434\u0432\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0434\u043b\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u0445 \u0441\u043a\u0430\u0447\u0430\u0435\u043c:<\/p>\n<pre><code class=\"bash\">pip install pygame numpy numba<\/code><\/pre>\n<p>\u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u0441\u043d\u043e\u0432\u0443 \u0434\u043b\u044f pygame :<\/p>\n<pre><code class=\"python\"># main.py import pygame from settings import *  # \u0418\u043c\u043f\u043e\u0440\u0442 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a  # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f pygame pygame.init() # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u043a\u043d\u0430 \u0441 \u0440\u0430\u0437\u043c\u0435\u0440\u0430\u043c\u0438 \u0438\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a sc = pygame.display.set_mode((WIDTH, HEIGHT)) # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f FPS clock = pygame.time.Clock()  # \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0446\u0438\u043a\u043b while True:     # \u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439     for event in pygame.event.get():         # \u0412\u044b\u0445\u043e\u0434 \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0438 \u043e\u043a\u043d\u0430         if event.type == pygame.QUIT:             exit()          # \u0417\u0430\u043b\u0438\u0432\u043a\u0430 \u044d\u043a\u0440\u0430\u043d\u0430 \u0447\u0435\u0440\u043d\u044b\u043c \u0446\u0432\u0435\u0442\u043e\u043c     sc.fill(BLACK)          # \u0417\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0438\u0433\u0440\u044b          # \u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u043a\u0440\u0430\u043d\u0430     pygame.display.flip()     # \u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 FPS \u0434\u043e 60 \u043a\u0430\u0434\u0440\u043e\u0432 \u0432 \u0441\u0435\u043a\u0443\u043d\u0434\u0443     clock.tick(60)<\/code><\/pre>\n<p>\u0414\u0430\u043b\u044c\u0448\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0438\u0433\u0440\u043e\u043a\u0430 \u0438 \u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441:<\/p>\n<pre><code class=\"python\"># player.py from settings import * import pygame  class Player:     def __init__(self):         # \u041d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0438 \u0443\u0433\u043e\u043b \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430         self.x, self.y = player_pos         self.angle = player_angle      @property     def pos(self):         # \u0422\u0435\u043a\u0443\u0449\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0438\u0433\u0440\u043e\u043a\u0430         return (self.x, self.y)      def movement(self):         keys = pygame.key.get_pressed()          # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0435\u0440\u0435\u0434\/\u043d\u0430\u0437\u0430\u0434 (W\/S)         if keys[pygame.K_w]:             self.y -= player_speed         if keys[pygame.K_s]:             self.y += player_speed          # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043b\u0435\u0432\u043e\/\u0432\u043f\u0440\u0430\u0432\u043e (A\/D)         if keys[pygame.K_a]:             self.x -= player_speed         if keys[pygame.K_d]:             self.x += player_speed          # \u041f\u043e\u0432\u043e\u0440\u043e\u0442 (\u0441\u0442\u0440\u0435\u043b\u043a\u0438 \u0432\u043b\u0435\u0432\u043e\/\u0432\u043f\u0440\u0430\u0432\u043e)         if keys[pygame.K_LEFT]:             self.angle -= 0.02         if keys[pygame.K_RIGHT]:             self.angle += 0.02<\/code><\/pre>\n<pre><code class=\"python\">pygame.draw.circle(sc, GREEN, player_pos, 12)<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a \u043d\u0430\u0448\u0435\u043c\u0443 \u0433\u043b\u0430\u0432\u043d\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 main \u0438\u043c\u043f\u043e\u0440\u0442 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0438 \u043f\u0435\u0440\u0435\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0438\u0433\u0440\u043e\u043a\u0430 (<code>player.movement()<\/code>) <\/p>\n<pre><code class=\"python\">#main.py import pygame from settings import * from player import Player   pygame.init() sc = pygame.display.set_mode( (WIDTH,HEIGHT) ) clock = pygame.time.Clock() player = Player()  while True:     for event in pygame.event.get():         if event.type == pygame.QUIT:             exit()     player.movement()     sc.fill(BLACK)      pygame.draw.circle(sc, GREEN, player.pos, 12)          pygame.display.flip()     clock.tick(60)<\/code><\/pre>\n<h2>\u041a\u0430\u043a \u043a\u0438\u0434\u0430\u0442\u044c \u043b\u0443\u0447\u0438 ?<\/h2>\n<p>\u041a\u0430\u043a \u043d\u0430\u043c \u043e\u0442\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043b\u0443\u0447\u0430? \u041d\u0430\u0448 \u0438\u0433\u0440\u043e\u043a &#8212; \u044d\u0442\u043e \u0437\u0435\u043b\u0435\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430, \u043d\u0430\u0437\u043e\u0432\u0435\u043c \u0442\u043e\u0447\u043a\u0430 O.<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041f\u0435\u0440\u0432\u044b\u0439 \u044d\u0442\u0430\u043f<\/figcaption><\/div>\n<\/figure>\n<p>\u0410\u00a0\u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u0440\u0435\u0437\u043e\u043a \u0434\u043e\u00a0\u043a\u0440\u0430\u0441\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 P. \u041d\u0430\u043c \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u0433\u043e \u0438\u0433\u0440\u043e\u043a\u0430 \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u0448 angle,\u0430 \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435, \u043c\u044b \u0441\u0430\u043c\u0438 \u0437\u0430\u0434\u0430\u0435\u043c!<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041d\u0430\u0445\u043e\u0434\u0438\u043c OP<\/figcaption><\/div>\n<\/figure>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u0440\u043e\u0441\u0442\u0435\u0439\u0448\u0443\u044e \u0442\u0440\u0438\u0433\u043e\u043d\u043e\u043c\u0435\u0442\u0440\u0438\u044e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0442\u0430\u043a\u0443\u044e \u0444\u043e\u0440\u043c\u0443\u043b\u0443 \u0434\u043b\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 P:<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0444\u043e\u0440\u043c\u0443\u043b\u0443!<\/figcaption><\/div>\n<\/figure>\n<h2>\u041f\u0443\u0441\u043a\u0430\u0435\u043c \u043b\u0443\u0447!<\/h2>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e math \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0441\u0438\u043d\u0443\u0441 \u0438 \u043a\u043e\u0441\u0438\u043d\u0443\u0441 \u0443\u0433\u043b\u0430 \u0438\u0433\u0440\u043e\u043a\u0430, \u0430 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u043e\u0439 \u043b\u0438\u043d\u0438\u0438, \u0434\u043b\u0438\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0432\u043d\u0430 \u0448\u0438\u0440\u0438\u043d\u0435 \u044d\u043a\u0440\u0430\u043d\u0430.<\/p>\n<pre><code class=\"python\">    pygame.draw.line(sc, GREEN, player.pos, (player.x +WIDTH * math.cos(player.angle),                                              player.y +WIDTH * math.sin(player.angle)) )<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u0412\u0435\u0441\u044c \u043a\u043e\u0434 \u043a \u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"python\">#main.py import pygame from settings import * from player import Player import math   pygame.init() sc = pygame.display.set_mode( (WIDTH,HEIGHT) ) clock = pygame.time.Clock() player = Player()  while True:     for event in pygame.event.get():         if event.type == pygame.QUIT:             exit()     player.movement()     sc.fill(BLACK)      pygame.draw.circle(sc, GREEN, player.pos, 12)     pygame.draw.line(sc, GREEN, player.pos, (player.x +WIDTH * math.cos(player.angle), player.y +WIDTH * math.sin(player.angle)) )          pygame.display.flip()     clock.tick(FPS) <\/code><\/pre>\n<hr\/>\n<pre><code class=\"python\"># player.py from settings import * import pygame  class Player:     def __init__(self):         # \u041d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0438 \u0443\u0433\u043e\u043b \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430         self.x, self.y = player_pos         self.angle = player_angle      @property     def pos(self):         # \u0422\u0435\u043a\u0443\u0449\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u0438\u0433\u0440\u043e\u043a\u0430         return (self.x, self.y)      def movement(self):         keys = pygame.key.get_pressed()          # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0435\u0440\u0435\u0434\/\u043d\u0430\u0437\u0430\u0434 (W\/S)         if keys[pygame.K_w]:             self.y -= player_speed         if keys[pygame.K_s]:             self.y += player_speed          # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043b\u0435\u0432\u043e\/\u0432\u043f\u0440\u0430\u0432\u043e (A\/D)         if keys[pygame.K_a]:             self.x -= player_speed         if keys[pygame.K_d]:             self.x += player_speed          # \u041f\u043e\u0432\u043e\u0440\u043e\u0442 (\u0441\u0442\u0440\u0435\u043b\u043a\u0438 \u0432\u043b\u0435\u0432\u043e\/\u0432\u043f\u0440\u0430\u0432\u043e)         if keys[pygame.K_LEFT]:             self.angle -= 0.02         if keys[pygame.K_RIGHT]:             self.angle += 0.02          <\/code><\/pre>\n<hr\/>\n<pre><code class=\"python\">#settings.py  WIDTH = 600 HEIGHT = 400 HALF_WIDTH = WIDTH \/\/ 2 HALF_HEIGHT = HEIGHT \/\/ 2 FPS = 60  BLACK = (0,0,0) GREEN = (0,244,0)  player_speed = 2 player_pos = (HALF_WIDTH,HALF_HEIGHT) player_angle = 0<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u041d\u0443 \u0432\u043e\u0442 \u0442\u0435\u043f\u0435\u0440\u044c \u0441\u0442\u0430\u043b\u043e \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e \u0432\u0438\u0434\u043d\u043e \u0432 \u043a\u0430\u043a\u0443\u044e \u0441\u0442\u0440\u043e\u043d\u0443 \u0441\u043c\u043e\u0442\u0440\u0438\u0442 \u0438\u0433\u0440\u043e\u043a. <\/p>\n<h2>\u041a\u0430\u0440\u0442\u0430 \u043d\u0430\u0448\u0435\u0433\u043e \u043c\u0438\u0440\u0430.<\/h2>\n<p>\u0427\u0442\u043e\u0431\u044b \u0438\u0433\u0440\u043e\u043a \u043c\u043e\u0433 \u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e \u043c\u0438\u0440\u0443 \u0438 \u043f\u0440\u0435\u043e\u0434\u043e\u043b\u0435\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0438\u044f \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043a\u0430\u0440\u0442\u0443.<\/p>\n<details class=\"spoiler\">\n<summary>\u0421\u043f\u043e\u0439\u043b\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<p>\u0412 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u043c\u044b \u0441 \u0432\u0430\u043c\u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u043c <strong>\u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 <\/strong>\u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u043a\u0430\u043a \u0440\u0430\u0437 \u0431\u0443\u0434\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u0438\u0433\u0440\u0443 \u0438 \u043a\u0430\u0440\u0442\u0443!<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0441\u0434\u0435\u043b\u0430\u0442\u044c <em>\u043a\u0430\u0440\u0442\u0443 <\/em>&#8212; \u044d\u0442\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u043a\u0430\u0440\u0442\u0443 \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u043c \u0432\u0438\u0434\u0435! \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 \u0432\u0441\u0435\u0445 \u044f \u0440\u0435\u0448\u0438\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b &#8212; \u0447\u0442\u0435\u043d\u0438\u0435 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0437\u0430\u0434\u0430\u0447\u0438 \u043a\u0430\u0440\u0442\u044b!<\/p>\n<pre><code class=\"python\">#map.py from settings import *  # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u0441\u043f\u0438\u0441\u043a\u0430 \u0434\u043b\u044f \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b text_map = []  def init_map():     f = open(\"map.txt\", \"r\")          # \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0447\u0438\u0441\u043b\u0430 - \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0441\u0442\u0440\u043e\u043a \u043a\u0430\u0440\u0442\u044b     num = int(f.readline())          # \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u0442\u0440\u043e\u0447\u043d\u043e \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 text_map     for i in range(num):         text_map.append(f.readline())           f.close()   # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043a\u0430\u0440\u0442\u044b \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 init_map()  # \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0441\u0442\u0435\u043d world_map = set()  # \u041f\u0430\u0440\u0441\u0438\u043d\u0433 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0439 \u043a\u0430\u0440\u0442\u044b \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b for j, row in enumerate(text_map):      # \u041f\u0440\u043e\u0445\u043e\u0434 \u043f\u043e \u0441\u0442\u0440\u043e\u043a\u0430\u043c \u043a\u0430\u0440\u0442\u044b     for i, char in enumerate(row):       # \u041f\u0440\u043e\u0445\u043e\u0434 \u043f\u043e \u0441\u0438\u043c\u0432\u043e\u043b\u0430\u043c \u0432 \u0441\u0442\u0440\u043e\u043a\u0435         if char == 'W':                  # \u0415\u0441\u043b\u0438 \u0441\u0438\u043c\u0432\u043e\u043b - \u0441\u0442\u0435\u043d\u0430 ('W')             # \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0441\u0442\u0435\u043d\u044b \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0445 \u0435\u0434\u0438\u043d\u0438\u0446\u0430\u0445 (\u0443\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u043d\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0430\u0439\u043b\u0430)             world_map.add((i * TILE, j * TILE))         if char == '1':                  # \u0415\u0441\u043b\u0438 \u0441\u0438\u043c\u0432\u043e\u043b - \u0441\u0442\u0435\u043d\u0430 ('1')             # \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0441\u0442\u0435\u043d\u044b \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0445 \u0435\u0434\u0438\u043d\u0438\u0446\u0430\u0445 (\u0443\u043c\u043d\u043e\u0436\u0430\u0435\u043c \u043d\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0430\u0439\u043b\u0430)             world_map.add((i * TILE, j * TILE))<\/code><\/pre>\n<p>\u0418\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u043d\u0430\u0448\u0443 \u043a\u0430\u0440\u0442\u0443 \u0432 main.py &#8212;<code> from map import world_map <\/code><\/p>\n<p>\u041d\u0430\u0441\u0447\u0435\u0442 \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 \u0432 \u043c\u0438\u0440\u043e\u0432\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u043e\u043d \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432\u043e\u0442 \u0442\u0430\u043a :<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u043c\u0443 \u0441\u0438\u043c\u0432\u043e\u043b\u0443 \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u0438\u0438\u00a0&#8216;W&#8217;\u00a0\u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0441\u0442\u0435\u043d\u044b \u0432 \u043f\u0438\u043a\u0441\u0435\u043b\u044f\u0445 (\u0443\u043c\u043d\u043e\u0436\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0441\u0438\u043c\u0432\u043e\u043b\u0430 \u043d\u0430 \u0440\u0430\u0437\u043c\u0435\u0440 \u0442\u0430\u0439\u043b\u0430\u00a0TILE)<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u0432 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0435\u00a0world_map\u00a0\u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u043e\u043b\u043b\u0438\u0437\u0438\u0439<\/p>\n<\/li>\n<\/ul>\n<h2>\u0418\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043a\u0438!<\/h2>\n<p>\u041a\u0430\u043a \u0432\u044b \u043d\u0430\u0432\u0435\u0440\u043d\u044f\u043a\u0430 \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438 \u043c\u044b \u0441\u0434\u0435\u043b\u0430\u043b\u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u0430\u043a \u0434\u043b\u044f 2D \u0438\u0433\u0440\u044b \u0438 \u043e\u043d\u043e \u043d\u0438\u043a\u0430\u043a \u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f 3D! \u0418 \u0447\u0442\u043e\u0431\u044b \u044d\u0442\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0435 <strong>:<\/strong><\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0414\u043e\u0441\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0441 \u043a\u0430\u043d\u0430\u043b\u0430 <a href=\"https:\/\/rutube.ru\/video\/person\/23872600\/\" rel=\"noopener noreferrer nofollow\">Stndalone Coder<\/a><\/figcaption><\/div>\n<\/figure>\n<p>\u042d\u0442\u043e\u0442 \u043a\u0440\u0443\u0433 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0448\u0435\u0433\u043e \u0438\u0433\u0440\u043e\u043a\u0430. \u0423 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043b\u0443\u0447, \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0434 \u0443\u0433\u043b\u043e\u043c \u03b1. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043b\u0430\u0432\u0438\u0448\u0438 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0438\u043c \u0435\u0433\u043e \u043a\u0430\u043a\u00a0d.<\/p>\n<p>\u041c\u044b \u0443\u043c\u0435\u0435\u043c \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u0442\u043e\u0447\u043a\u0443 \u0432 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u043b\u0443\u0447\u0430. \u0417\u0430\u043c\u0435\u0442\u0438\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0442\u043b\u0438\u0447\u0430\u044e\u0442\u0441\u044f \u0434\u0440\u0443\u0433 \u043e\u0442 \u0434\u0440\u0443\u0433\u0430 \u043d\u0430 90 \u0433\u0440\u0430\u0434\u0443\u0441\u043e\u0432. \u0421\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u043e\u0440\u043c\u0443\u043b\u044b \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0440\u0438\u0433\u043e\u043d\u043e\u043c\u0435\u0442\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043b\u0430\u0432\u0438\u0448\u0438.<\/p>\n<p>\u0418 \u0441\u0435\u0439\u0447\u0430\u0441 \u043d\u0430\u043c \u0443\u0436\u0435 \u043b\u0435\u0433\u043a\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f 3D!<\/p>\n<pre><code class=\"python\">from settings import * import pygame import math  class Player:     def __init__(self):         # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0438 \u0443\u0433\u043b\u0430 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430 \u0438\u0433\u0440\u043e\u043a\u0430         self.x, self.y = player_pos         self.angle = player_angle      @property     def pos(self):         # \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0432 \u0432\u0438\u0434\u0435 \u043a\u043e\u0440\u0442\u0435\u0436\u0430         return (self.x, self.y)      def movement(self):         # \u041f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0440\u0430\u0441\u0447\u0435\u0442 \u0441\u0438\u043d\u0443\u0441\u0430 \u0438 \u043a\u043e\u0441\u0438\u043d\u0443\u0441\u0430 \u0443\u0433\u043b\u0430 \u043f\u043e\u0432\u043e\u0440\u043e\u0442\u0430         sin_a = math.sin(self.angle)         cos_a = math.cos(self.angle)                  keys = pygame.key.get_pressed()                  # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0435\u0440\u0435\u0434 (W) - \u043f\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0432\u0437\u0433\u043b\u044f\u0434\u0430         if keys[pygame.K_w]:             self.x += player_speed * cos_a             self.y += player_speed * sin_a                      # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0437\u0430\u0434 (S) - \u043f\u0440\u043e\u0442\u0438\u0432 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0432\u0437\u0433\u043b\u044f\u0434\u0430         if keys[pygame.K_s]:             self.x -= player_speed * cos_a             self.y -= player_speed * sin_a                      # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043b\u0435\u0432\u043e (A) - \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e (\u0432\u0435\u043a\u0442\u043e\u0440 \u0432\u043b\u0435\u0432\u043e)         if keys[pygame.K_a]:             self.x += player_speed * sin_a  # \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c sin \u0434\u043b\u044f \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e\u0433\u043e \u0432\u0435\u043a\u0442\u043e\u0440\u0430             self.y -= player_speed * cos_a  # \u041e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 cos \u0434\u043b\u044f \u043b\u0435\u0432\u043e\u0433\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f                      # \u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0440\u0430\u0432\u043e (D) - \u043f\u0435\u0440\u043f\u0435\u043d\u0434\u0438\u043a\u0443\u043b\u044f\u0440\u043d\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e (\u0432\u0435\u043a\u0442\u043e\u0440 \u0432\u043f\u0440\u0430\u0432\u043e)         if keys[pygame.K_d]:<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-455221","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/455221","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=455221"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/455221\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=455221"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=455221"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=455221"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}