<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Кудрявый микрофон</title><subtitle>Меня зовут Валерий Линьков.
Я эксперт в сфере IT-образования. Больше 8 лет учу студентов по всему миру.</subtitle><author><name>Кудрявый микрофон</name></author><id>https://teletype.in/atom/valerylinkov</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/valerylinkov?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/valerylinkov?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-04T10:27:17.209Z</updated><entry><id>valerylinkov:GULm4mVGJTF</id><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov/GULm4mVGJTF?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><title>Как получить продукты JetBrains бесплатно</title><published>2024-10-30T17:46:39.341Z</published><updated>2024-10-30T17:46:39.341Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/2d/50/2d5048c4-032d-4996-bc11-b14cc3a79ba2.png"></media:thumbnail><category term="gajdy" label="Гайды 📖"></category><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/01/40/0140f050-0953-4aa0-a613-a4e56b5162af.png&quot;&gt;Вам нужно перейти на сайт студенческих аккаунтов GitHub https://education.github.com/.</summary><content type="html">
  &lt;nav&gt;
    &lt;ul&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#o2tf&quot;&gt;Шаг 1. Перейти на сайт.&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#9Qrb&quot;&gt;Шаг 2. Прислать фото студенческого билета.&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#kMUk&quot;&gt;Шаг 3. На сайт JetBrains&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/nav&gt;
  &lt;h2 id=&quot;o2tf&quot;&gt;Шаг 1. Перейти на сайт.&lt;/h2&gt;
  &lt;p id=&quot;tJ7s&quot;&gt;Вам нужно перейти на сайт студенческих аккаунтов GitHub &lt;a href=&quot;https://education.github.com/&quot; target=&quot;_blank&quot;&gt;https://education.github.com/&lt;/a&gt;.&lt;/p&gt;
  &lt;figure id=&quot;o3cy&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/01/40/0140f050-0953-4aa0-a613-a4e56b5162af.png&quot; width=&quot;929&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;EpaD&quot;&gt;Регистрируемся там (если у вас нет аккаунта GitHub, то сразу и на гите). &lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;Be2G&quot;&gt;Главное, чтобы в профиле на гитхабе было написано такое же имя&lt;/p&gt;
  &lt;/section&gt;
  &lt;h1 id=&quot;9Qrb&quot;&gt;Шаг 2. Прислать фото студенческого билета.&lt;/h1&gt;
  &lt;p id=&quot;sbDn&quot;&gt;Фото должно быть аналогично тому, что ниже&lt;/p&gt;
  &lt;figure id=&quot;R7O9&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/df/b8/dfb8fd52-b061-4c30-b762-33a64e94c900.png&quot; width=&quot;916&quot; /&gt;
  &lt;/figure&gt;
  &lt;h1 id=&quot;kMUk&quot;&gt;Шаг 3. На сайт JetBrains&lt;/h1&gt;
  &lt;p id=&quot;umbU&quot;&gt;Перейдите на сайт &lt;a href=&quot;https://www.jetbrains.com/&quot; target=&quot;_blank&quot;&gt;https://www.jetbrains.com/&lt;/a&gt;&lt;/p&gt;
  &lt;figure id=&quot;ZK5n&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/0c/0f/0c0f9649-cff8-4589-81ba-25d9eff15699.png&quot; width=&quot;928&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;yVWJ&quot;&gt;Далее&lt;/p&gt;
  &lt;figure id=&quot;3Q8g&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/89/62/896251a3-2184-48be-90e0-220a44e1ff13.png&quot; width=&quot;928&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;nrse&quot;&gt;Заполняем анкету через гитхаб:&lt;/p&gt;
  &lt;figure id=&quot;LqH5&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/1f/3f/1f3f464a-7cb2-4b69-86e4-ccee787af469.png&quot; width=&quot;931&quot; /&gt;
  &lt;/figure&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;DPXw&quot;&gt;В поле где почта указываем любую без приписки .ru&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;hip7&quot;&gt;&lt;strong&gt;&lt;u&gt;Шаг 4. Радуемся &lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;

</content></entry><entry><id>valerylinkov:LH9pm4VG4hg</id><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov/LH9pm4VG4hg?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><title>Создаём крутую тему для терминала в винде</title><published>2024-10-30T17:43:54.339Z</published><updated>2024-10-30T17:43:54.339Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/f1/ac/f1acb0dd-5749-42f1-bb2f-9c046bd9251f.png"></media:thumbnail><category term="gajdy" label="Гайды 📖"></category><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/cf/26/cf26a6b6-3085-470b-8a55-cd50bb9349b0.jpeg&quot;&gt;Сегодня при слове &quot;терминал&quot; есть сочетание слов типа Ubuntu, Linux ну и или MacOS. Операционная система Windows неправомерно подвержена гонению. Я намерен это исправить и создать офигенный шаблон для написания ПО в ОС Windows. Все темы бесплатны и в свободном доступе.</summary><content type="html">
  &lt;nav&gt;
    &lt;ul&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#3RUq&quot;&gt;Цели&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#i2J2&quot;&gt;Программы&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#9QQH&quot;&gt;Настройка терминала&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#Idxf&quot;&gt;Установка Nerd Fonts&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#S3GA&quot;&gt;Настройка цветов&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#d0Q4&quot;&gt;Starship&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/nav&gt;
  &lt;h2 id=&quot;3RUq&quot;&gt;Цели&lt;/h2&gt;
  &lt;p id=&quot;MKN8&quot;&gt;Сегодня при слове &amp;quot;терминал&amp;quot; есть сочетание слов типа Ubuntu, Linux ну и или MacOS. Операционная система Windows неправомерно подвержена гонению. Я намерен это исправить и создать офигенный шаблон для написания ПО в ОС Windows. Все темы бесплатны и в свободном доступе.&lt;/p&gt;
  &lt;p id=&quot;JLJL&quot;&gt;Иными словами, мы делаем из этого:&lt;/p&gt;
  &lt;figure id=&quot;cDmT&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/e9/68/e9688437-0878-44f9-8982-2f4abf508514.png&quot; width=&quot;930&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;MOv8&quot;&gt;Это:&lt;/p&gt;
  &lt;h2 id=&quot;i2J2&quot;&gt;Программы&lt;/h2&gt;
  &lt;p id=&quot;hDyt&quot;&gt;Для работы нам понадобится несколько программ. Для базовой работы я возьму такие приложения как:&lt;/p&gt;
  &lt;ul id=&quot;39Ro&quot;&gt;
    &lt;li id=&quot;7Y0m&quot;&gt;&lt;a href=&quot;https://www.sublimetext.com/3&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Sublime Text 3&lt;/strong&gt;&lt;/a&gt;. Задача Sublime Text&amp;#x27;а создать удобную среду для работы с кодом. Сейчас я больше всего пишу на Python и покажу как выглядит код в Sublime из коробки. Я использую автоматическую тему, которая подстроится под системную.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;LpCr&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/88/bb/88bbb476-7721-48b6-b8a9-6f795cba1736.png&quot; width=&quot;880&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;ZrYM&quot;&gt;
    &lt;li id=&quot;SyO0&quot;&gt;&lt;a href=&quot;https://typora.io/&quot; target=&quot;_blank&quot;&gt;Typora&lt;/a&gt;. Так как я пишу много текста про код — его нужно оформить. Я оформляю текст в маркдауне (это такой шаблон написания текста с кодом). Все PDFки, которые вы тут видите (в том числе и эту) — работа данного ПО. Тема — Night. Дополнительные темы можно посмотреть &lt;a href=&quot;https://theme.typora.io/&quot; target=&quot;_blank&quot;&gt;тут&lt;/a&gt;.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;PpHN&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/60/9b/609bf408-d9d9-4f67-b990-b8a537bb6ace.png&quot; width=&quot;869&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;lR72&quot;&gt;
    &lt;li id=&quot;JBN4&quot;&gt;&lt;a href=&quot;https://notepad-plus-plus.org/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;NotePad++&lt;/strong&gt;&lt;/a&gt;. Это ещё один текстовый редактор. С ним я чиню конфигурационные файлы, так как очень легко менять кодировки и размеры символов. Тема как у системы + фиолетовая.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;yoFl&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/2b/b5/2bb5c8ce-405f-479e-9f8c-163703d791aa.png&quot; width=&quot;883&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;pluQ&quot;&gt;
    &lt;li id=&quot;sD7q&quot;&gt;&lt;a href=&quot;https://apps.microsoft.com/store/detail/windows-terminal/9N0DX20HK701?hl=ru-ru&amp;gl=ru&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Windows Terminal&lt;/strong&gt;&lt;/a&gt;. Это улучшенная версия системного ПО Windows (командной строки). Добавлены много фич. О них мы ещё поговорим.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;5ESz&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/aa/b9/aab93bbe-7a47-4a52-b507-f97a16155931.png&quot; width=&quot;895&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;iJX2&quot;&gt;На данный момент есть несколько сложностей со скачиванием всех утилит. Чтобы упростить задачу, всё что нужно дня скачивания из программ я поместил в &lt;a href=&quot;https://disk.yandex.ru/d/tYUBUHKnqKDcAg&quot; target=&quot;_blank&quot;&gt;этот архив&lt;/a&gt;.&lt;/p&gt;
  &lt;h2 id=&quot;9QQH&quot;&gt;Настройка терминала&lt;/h2&gt;
  &lt;p id=&quot;VVQY&quot;&gt;Какие настройки я выставил в самом терминале. Для их настройки я перешёл во вкладку &amp;quot;Параметры&amp;quot;:&lt;/p&gt;
  &lt;figure id=&quot;U86h&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/f6/a0/f6a0031e-50a6-44f3-b932-89e667617de8.png&quot; width=&quot;921&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;I492&quot;&gt;По умолчанию, настройки выставятся в очень стандартный и весьма красивый вид.&lt;/p&gt;
  &lt;figure id=&quot;0DAm&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/18/30/18307ea8-1a9a-4528-9003-d75a3accdaeb.png&quot; width=&quot;921&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;YAaw&quot;&gt;Многие спрашивали меня как установить Ubuntu в терминал Windows. На самом деле, это проще чем кажется.&lt;/p&gt;
  &lt;ul id=&quot;T1Eu&quot;&gt;
    &lt;li id=&quot;lO2F&quot;&gt;Переходим в панель управления.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;ZX9y&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/14/6f/146fdd31-bca4-4114-a5f9-5dda46518dc5.png&quot; width=&quot;882&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;BtZO&quot;&gt;
    &lt;li id=&quot;DvIC&quot;&gt;Затем, выбираем пункт &amp;quot;Удаление программ&amp;quot; (не волнуйтесь, мы не будем ничего удалять).&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;zpZN&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/cc/6d/cc6db12c-42f1-4932-b3c3-d96c1eafaeb7.png&quot; width=&quot;886&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;wJAc&quot;&gt;
    &lt;li id=&quot;qUEz&quot;&gt;Выбираем в открывшемся окошке пункт &amp;quot;Включение или отключение компонентов Windows&amp;quot;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;zvy9&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/ea/41/ea41c438-d4e1-471a-9af7-bda53db72602.png&quot; width=&quot;871&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;TMeB&quot;&gt;
    &lt;li id=&quot;L3g7&quot;&gt;Далее, нас интересует пункт &amp;quot;Подсистема Windows для Linux&amp;quot;. Этот пункт нужно включить.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;evs9&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/79/92/79928a7c-c503-46c6-a90b-31a3dd0a7575.png&quot; width=&quot;881&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;Ocvr&quot;&gt;
    &lt;li id=&quot;E326&quot;&gt;Дальше, всё просто — &lt;a href=&quot;https://apps.microsoft.com/store/search/linux&quot; target=&quot;_blank&quot;&gt;заходим в MS Store&lt;/a&gt; и скачиваем нужную систему.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;Idxf&quot;&gt;Установка Nerd Fonts&lt;/h2&gt;
  &lt;p id=&quot;5DXG&quot;&gt;Установим крутые темы в виде текста и символов. Переходим на &lt;a href=&quot;https://www.nerdfonts.com/&quot; target=&quot;_blank&quot;&gt;сайт Nerd Fonts&lt;/a&gt;. И нажимаем кнопочку Download. Там выбирайте любую тему, которая вам понравилась. Лично мне очень нравится тема JetBrainsMono. Её я и скачал. Ещё я использовал Hack Nerd Font.&lt;/p&gt;
  &lt;figure id=&quot;mdU7&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/76/b3/76b31911-1d67-4d5e-a108-30294f50b784.png&quot; width=&quot;925&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;iUVh&quot;&gt;Далее, наша задача разархивировать папку куда угодно и установить все шрифты. Самый простой способ это сделать: открыть папку, выделить все файлы (Ctrl+A), правая кнопка мыши, установить для всех пользователей.&lt;/p&gt;
  &lt;figure id=&quot;AQNp&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/c0/d2/c0d2c97a-af27-47fd-bd9f-3a11bb1fbc37.png&quot; width=&quot;933&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Swvz&quot;&gt;Далее, после установки, перейдите в настройки терминала и выберите понравившейся шрифт по умолчанию.&lt;/p&gt;
  &lt;figure id=&quot;M8ri&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/65/8a/658ac61e-0e5f-479f-bf1c-5ea421e6945c.png&quot; width=&quot;921&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;S3GA&quot;&gt;Настройка цветов&lt;/h2&gt;
  &lt;p id=&quot;M9tt&quot;&gt;Настройка цветов может быть любой, но я подготовил отдельный файл, в котором указаны все настройка цветовой схемы. Для её настройки, перейдите в раздел настройки терминала &amp;quot;Цветовые схемы&amp;quot; и используете готовую.&lt;/p&gt;
  &lt;p id=&quot;Apmz&quot;&gt;Чтобы сделать тему уникальной, можно открыть JSON файл (внизу слева) в терминале и настроить цветовую палитру детально. Тут нам тоже помогает Sublime Text&lt;/p&gt;
  &lt;figure id=&quot;QYdT&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/4d/f8/4df8bf53-e073-4d11-9f68-6d152842f405.png&quot; width=&quot;921&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ZL1N&quot;&gt;Чтобы всё работало хорошо, скопируйте и вставьте всё, что в фигурных скобках в пункте &lt;code&gt;defaults&lt;/code&gt;, не трогайте пункт &lt;code&gt;list&lt;/code&gt; и вставьте пункт &lt;code&gt;schemes&lt;/code&gt;.&lt;/p&gt;
  &lt;pre id=&quot;GZ5z&quot; data-lang=&quot;jsx&quot;&gt;{
    &amp;quot;$help&amp;quot;: &amp;quot;https://aka.ms/terminal-documentation&amp;quot;,
    &amp;quot;$schema&amp;quot;: &amp;quot;https://aka.ms/terminal-profiles-schema&amp;quot;,
    &amp;quot;actions&amp;quot;: [],
    &amp;quot;defaultProfile&amp;quot;: &amp;quot;{574e775e-4f2a-5b96-ac1e-a2962a402336}&amp;quot;,
    &amp;quot;firstWindowPreference&amp;quot;: &amp;quot;defaultProfile&amp;quot;,
    &amp;quot;profiles&amp;quot;: 
    {
        &amp;quot;defaults&amp;quot;: 
        {
            &amp;quot;colorScheme&amp;quot;: &amp;quot;xcad&amp;quot;,
            &amp;quot;cursorShape&amp;quot;: &amp;quot;filledBox&amp;quot;,
            &amp;quot;font&amp;quot;: 
            {
                &amp;quot;face&amp;quot;: &amp;quot;Hack Nerd Font&amp;quot;,
                &amp;quot;size&amp;quot;: 10
            },
            &amp;quot;historySize&amp;quot;: 12000,
            &amp;quot;intenseTextStyle&amp;quot;: &amp;quot;bright&amp;quot;,
            &amp;quot;opacity&amp;quot;: 95,
            &amp;quot;padding&amp;quot;: &amp;quot;8&amp;quot;,
            &amp;quot;scrollbarState&amp;quot;: &amp;quot;visible&amp;quot;,
            &amp;quot;useAcrylic&amp;quot;: false
        },
        &amp;quot;list&amp;quot;: 
        [
            {
                &amp;quot;commandline&amp;quot;: &amp;quot;C:\\Program Files\\PowerShell\\7\\pwsh.exe --NoLogo&amp;quot;,
                &amp;quot;elevate&amp;quot;: false,
                &amp;quot;guid&amp;quot;: &amp;quot;{574e775e-4f2a-5b96-ac1e-a2962a402336}&amp;quot;,
                &amp;quot;hidden&amp;quot;: false,
                &amp;quot;icon&amp;quot;: &amp;quot;%userprofile%\\WindowsTerminalIcons\\ps.png&amp;quot;,
                &amp;quot;name&amp;quot;: &amp;quot;PowerShell&amp;quot;,
                &amp;quot;source&amp;quot;: &amp;quot;Windows.Terminal.PowershellCore&amp;quot;
            },
            {
                &amp;quot;guid&amp;quot;: &amp;quot;{07b52e3e-de2c-5db4-bd2d-ba144ed6c273}&amp;quot;,
                &amp;quot;hidden&amp;quot;: false,
                &amp;quot;icon&amp;quot;: &amp;quot;%userprofile%\\WindowsTerminalIcons\\ubuntu.png&amp;quot;,
                &amp;quot;name&amp;quot;: &amp;quot;Ubuntu Linux&amp;quot;,
                &amp;quot;source&amp;quot;: &amp;quot;Windows.Terminal.Wsl&amp;quot;,
                &amp;quot;startingDirectory&amp;quot;: &amp;quot;\\\\wsl$\\Ubuntu-20.04\\home\\xcad&amp;quot;
            },
            {
                &amp;quot;guid&amp;quot;: &amp;quot;{46ca431a-3a87-5fb3-83cd-11ececc031d2}&amp;quot;,
                &amp;quot;hidden&amp;quot;: false,
                &amp;quot;icon&amp;quot;: &amp;quot;%userprofile%\\WindowsTerminalIcons\\kali.png&amp;quot;,
                &amp;quot;name&amp;quot;: &amp;quot;Kali Linux&amp;quot;,
                &amp;quot;source&amp;quot;: &amp;quot;Windows.Terminal.Wsl&amp;quot;,
                &amp;quot;startingDirectory&amp;quot;: &amp;quot;\\\\wsl.localhost\\kali-linux\\home\\xcad&amp;quot;
            },
            {
                &amp;quot;guid&amp;quot;: &amp;quot;{0caa0dad-35be-5f56-a8ff-afceeeaa6101}&amp;quot;,
                &amp;quot;icon&amp;quot;: &amp;quot;%userprofile%\\WindowsTerminalIcons\\cmd.png&amp;quot;,
                &amp;quot;name&amp;quot;: &amp;quot;Commandline&amp;quot;
            },
            {
                &amp;quot;guid&amp;quot;: &amp;quot;{b453ae62-4e3d-5e58-b989-0a998ec441b8}&amp;quot;,
                &amp;quot;hidden&amp;quot;: true,
                &amp;quot;icon&amp;quot;: &amp;quot;%userprofile%\\WindowsTerminalIcons\\azure.png&amp;quot;,
                &amp;quot;name&amp;quot;: &amp;quot;Azure Cloud Shell&amp;quot;,
                &amp;quot;source&amp;quot;: &amp;quot;Windows.Terminal.Azure&amp;quot;
            }
        ]
    },
    &amp;quot;schemes&amp;quot;: 
    [
        {
            &amp;quot;background&amp;quot;: &amp;quot;#1A1A1A&amp;quot;,
            &amp;quot;black&amp;quot;: &amp;quot;#121212&amp;quot;,
            &amp;quot;blue&amp;quot;: &amp;quot;#2B4FFF&amp;quot;,
            &amp;quot;brightBlack&amp;quot;: &amp;quot;#666666&amp;quot;,
            &amp;quot;brightBlue&amp;quot;: &amp;quot;#5C78FF&amp;quot;,
            &amp;quot;brightCyan&amp;quot;: &amp;quot;#5AC8FF&amp;quot;,
            &amp;quot;brightGreen&amp;quot;: &amp;quot;#905AFF&amp;quot;,
            &amp;quot;brightPurple&amp;quot;: &amp;quot;#5EA2FF&amp;quot;,
            &amp;quot;brightRed&amp;quot;: &amp;quot;#BA5AFF&amp;quot;,
            &amp;quot;brightWhite&amp;quot;: &amp;quot;#FFFFFF&amp;quot;,
            &amp;quot;brightYellow&amp;quot;: &amp;quot;#685AFF&amp;quot;,
            &amp;quot;cursorColor&amp;quot;: &amp;quot;#FFFFFF&amp;quot;,
            &amp;quot;cyan&amp;quot;: &amp;quot;#28B9FF&amp;quot;,
            &amp;quot;foreground&amp;quot;: &amp;quot;#F1F1F1&amp;quot;,
            &amp;quot;green&amp;quot;: &amp;quot;#7129FF&amp;quot;,
            &amp;quot;name&amp;quot;: &amp;quot;xcad&amp;quot;,
            &amp;quot;purple&amp;quot;: &amp;quot;#2883FF&amp;quot;,
            &amp;quot;red&amp;quot;: &amp;quot;#A52AFF&amp;quot;,
            &amp;quot;selectionBackground&amp;quot;: &amp;quot;#FFFFFF&amp;quot;,
            &amp;quot;white&amp;quot;: &amp;quot;#F1F1F1&amp;quot;,
            &amp;quot;yellow&amp;quot;: &amp;quot;#3D2AFF&amp;quot;
       lebar&amp;quot;: true,
    &amp;quot;tabSwitcherMode&amp;quot;: &amp;quot;inOrder&amp;quot;,
    &amp;quot;useAcrylicInTabRow&amp;quot;: true
}&lt;/pre&gt;
  &lt;p id=&quot;6agR&quot;&gt;Результат:&lt;/p&gt;
  &lt;figure id=&quot;evmJ&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/3a/90/3a90c1a6-e5c1-45ef-b087-00bb1ed8ac65.png&quot; width=&quot;910&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;d0Q4&quot;&gt;Starship&lt;/h2&gt;
  &lt;p id=&quot;4rpQ&quot;&gt;Starship&lt;/p&gt;
  &lt;p id=&quot;8i30&quot;&gt;Установим крутую адаптацию. Как сами про себя пишут &amp;quot;Звёздные кораблики&amp;quot;, их продукт, это минимальная, молниеносная и бесконечно настраиваемая подсказка для любой оболочки!&lt;/p&gt;
  &lt;p id=&quot;QNEY&quot;&gt;Установка весьма проста:&lt;/p&gt;
  &lt;ul id=&quot;TFjG&quot;&gt;
    &lt;li id=&quot;SOWj&quot;&gt;Перейти на &lt;a href=&quot;https://starship.rs/&quot; target=&quot;_blank&quot;&gt;сайт компании&lt;/a&gt;.&lt;/li&gt;
    &lt;li id=&quot;fltO&quot;&gt;Установить через уже улучшенный терминал приложение (списки возможных установок написаны на сайте). Я использовал команду &lt;code&gt;winget install starship&lt;/code&gt;.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;veua&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/b0/dc/b0dc4c43-7462-4546-80e5-c63b7b244f1c.png&quot; width=&quot;886&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;qxDp&quot;&gt;
    &lt;li id=&quot;bioh&quot;&gt;Следующая задача — установить нужные настройки в файлы профилей ваших сред (в которых вы пишите). Для начала, я взял самую сложную часть — работу с командной строкой. Для этого, вам нужно установить &lt;a href=&quot;https://chrisant996.github.io/clink/clink.html&quot; target=&quot;_blank&quot;&gt;Clink&lt;/a&gt;.&lt;/li&gt;
    &lt;li id=&quot;P9sj&quot;&gt;Перейдя на сайт книлка, вы попадёте на сложную страницу. На неё нужно перейти сразу на вкладку репозитория на гитхабе.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;v718&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/27/1e/271e1a11-f7c5-4599-a520-f2122048cc0f.png&quot; width=&quot;617&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;KIRr&quot;&gt;
    &lt;li id=&quot;Mtvv&quot;&gt;Перейдя на данную страницу, нужно скачать файлы. Найти из можно на &lt;a href=&quot;https://github.com/chrisant996/clink/releases&quot; target=&quot;_blank&quot;&gt;странице релиза&lt;/a&gt;.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;GNFc&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/e5/26/e526b4c9-a9bc-4b93-b105-dceae6cb67e9.png&quot; width=&quot;881&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;a1t9&quot;&gt;
    &lt;li id=&quot;b4F8&quot;&gt;Далее, я выбрал просто доступный ассет.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;cCf7&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/69/73/69735af9-463a-4eea-b6c1-b67d820ad082.png&quot; width=&quot;893&quot; /&gt;
  &lt;/figure&gt;
  &lt;ul id=&quot;4Kax&quot;&gt;
    &lt;li id=&quot;a9IL&quot;&gt;Далее, установите программу. По умолчанию, папка установки &lt;code&gt;C:/Program Files (x86)/clink&lt;/code&gt;. Перейдите в данную папку.&lt;/li&gt;
    &lt;li id=&quot;Kp9B&quot;&gt;В это время, в саблайме создайте файл &lt;code&gt;starship.lua&lt;/code&gt; и заполните его строкой&lt;br /&gt;&lt;code&gt;load(io.popen(&amp;#x27;starship init cmd&amp;#x27;):read(&amp;quot;*a&amp;quot;))()&lt;/code&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;T4Ub&quot;&gt;Результат:&lt;/p&gt;
  &lt;figure id=&quot;5OYo&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/4d/97/4d97b6ce-c2a8-43a2-9e7e-fcaea705af38.png&quot; width=&quot;910&quot; /&gt;
  &lt;/figure&gt;

</content></entry><entry><id>valerylinkov:Vbo2TkvnwxJ</id><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov/Vbo2TkvnwxJ?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><title>Супер простая инструкция, как оставаться с заблокированными ресурсами</title><published>2024-10-30T17:25:17.705Z</published><updated>2024-10-30T17:29:52.736Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/43/32/43329698-c05c-4178-a7c9-11143d58a5e3.png"></media:thumbnail><category term="gajdy" label="Гайды 📖"></category><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/84/85/8485c183-37fe-4435-b5ab-93d6773b6a7d.jpeg&quot;&gt;Тут всё просто. Нужно скачать Tor браузер по ссылке. Сеть тор просто так не заблокировать. В ней всегда будет анонимность и доступ к ресурсам. Но есть существенный минус — работать можно только через тулзу. Уберплюс — всё бесплатно.</summary><content type="html">
  &lt;nav&gt;
    &lt;ul&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#bbQI&quot;&gt;Вариант 0. Tor браузер.&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#imMz&quot;&gt;Вариант 1. АнтиЗапрет.&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#RzNu&quot;&gt;Вариант 2. VPN.&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_2&quot;&gt;&lt;a href=&quot;#ITge&quot;&gt;Вариант 2.1. Готовые сервер под L2TP.&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_2&quot;&gt;&lt;a href=&quot;#nLQB&quot;&gt;Вариант 2.2. Всё сам.&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_3&quot;&gt;&lt;a href=&quot;#XoyV&quot;&gt;Шаг 1. Арендуем VDS сервер.&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_3&quot;&gt;&lt;a href=&quot;#5kzb&quot;&gt;Шаг 2. Подключаемся по SSH&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_3&quot;&gt;&lt;a href=&quot;#224a&quot;&gt;Шаг 3. Устанавливаем OpenVPN&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_3&quot;&gt;&lt;a href=&quot;#CyYw&quot;&gt;Шаг 4. Качаем конфиг по FTP&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_3&quot;&gt;&lt;a href=&quot;#qxhb&quot;&gt;Шаг 5. Празднуем&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#bIiz&quot;&gt;Итоги&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/nav&gt;
  &lt;h2 id=&quot;bbQI&quot;&gt;Вариант 0. Tor браузер.&lt;/h2&gt;
  &lt;figure id=&quot;6Hav&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/8f/d3/8fd3df08-e557-4260-98e7-7cf6d974e6fb.png&quot; width=&quot;595&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;NDPw&quot;&gt;Тут всё просто. Нужно скачать Tor браузер &lt;u&gt;по ссылке&lt;/u&gt;. Сеть тор просто так не заблокировать. В ней всегда будет анонимность и доступ к ресурсам. Но есть существенный минус — работать можно только через тулзу. Уберплюс — всё бесплатно.&lt;/p&gt;
  &lt;h1 id=&quot;imMz&quot;&gt;Вариант 1. АнтиЗапрет.&lt;/h1&gt;
  &lt;figure id=&quot;gL2M&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/26/e9/26e9bac0-b648-46d3-9dfc-08af1a96b528.png&quot; width=&quot;601&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Hs4H&quot;&gt;Готовое решение из коробки и бесплатных VPN. Ещё раз скажу, чтобы точно было понятно. &lt;strong&gt;Оно не безопасно&lt;/strong&gt;. Вся инструкция описана на их &lt;a href=&quot;https://antizapret.prostovpn.org/&quot; target=&quot;_blank&quot;&gt;официальном сайте&lt;/a&gt;.&lt;/p&gt;
  &lt;h1 id=&quot;RzNu&quot;&gt;Вариант 2. VPN.&lt;/h1&gt;
  &lt;figure id=&quot;8euz&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/ad/1e/ad1e5f8e-3811-4a2c-82a3-c39d04c7eb75.png&quot; width=&quot;593&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;4CLT&quot;&gt;В посту ранее, я писал, что сам по себе VPN — бесполезен. Вариант нужно разбит на несколько задач:&lt;/p&gt;
  &lt;ul id=&quot;3o7i&quot;&gt;
    &lt;li id=&quot;m3a1&quot;&gt;Найти внешний сервер VDS или VPS.&lt;/li&gt;
    &lt;li id=&quot;47yt&quot;&gt;Настроить форвардинг трафика через данный сервер (создали прокси). &lt;/li&gt;
    &lt;li id=&quot;Irp8&quot;&gt;Фигачим на данное соединение шифрование.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;bZW8&quot;&gt;Приступим.&lt;/p&gt;
  &lt;p id=&quot;FlDu&quot;&gt;Сразу оговорюсь, данный способ, я бы разбил на два разных. Первый попроще, второй посложнее. Обо весьма безопасны. Вопрос в целях. Если цель — скрыть своё пребывание от кучи сторонних глаз (вы творите что-то не оч хорошее), то лучше одумайтесь или используйте вариант&lt;/p&gt;
  &lt;p id=&quot;pWbb&quot;&gt;2.2.  Если же задача вылезти в инсту и не делать себе мозг проблемами — вариант 2.1 точно для вас.&lt;/p&gt;
  &lt;h2 id=&quot;ITge&quot;&gt;Вариант 2.1. Готовые сервер под L2TP.&lt;/h2&gt;
  &lt;p id=&quot;PC7c&quot;&gt;Лично я использую сервера компании Inferno Solutions. &lt;a href=&quot;https://cp.inferno.name/cart.php?gid=56&quot; target=&quot;_blank&quot;&gt;Решение такое&lt;/a&gt;:&lt;/p&gt;
  &lt;ul id=&quot;BGY3&quot;&gt;
    &lt;li id=&quot;XZJB&quot;&gt;5 видов VPN соединений: PPTP, L2TP/IPsec, WireGuard и, конечно же, OpenVPN!&lt;/li&gt;
    &lt;li id=&quot;JbVL&quot;&gt;10+ учетных записей для OpenVPN (5 TCP + 5 UDP), шифрование AES-256 2048 bit&lt;/li&gt;
    &lt;li id=&quot;OFrD&quot;&gt;2+ учетных записи для PPTP и L2TP/IPsec&lt;/li&gt;
    &lt;li id=&quot;p3za&quot;&gt;2+ учетных записи для Socks 5 прокси (идеально для Telegram)&lt;/li&gt;
    &lt;li id=&quot;cPX5&quot;&gt;Поддержка Windows, Linux, Mac OS, iOS, Android, роутеров и других систем!&lt;/li&gt;
    &lt;li id=&quot;uyIm&quot;&gt;Скорость подключения 1 Gbit/s&lt;/li&gt;
    &lt;li id=&quot;b9Of&quot;&gt;22 стран на выбор (я сижу в Эстонии)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;f10d&quot;&gt;Сами Инферно делают оговорку: &lt;strong&gt;Только для индивидуального и легального использования!&lt;/strong&gt;&lt;/p&gt;
  &lt;figure id=&quot;IOEy&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/22/e9/22e9a954-055e-47c5-ab75-b622edf15f16.png&quot; width=&quot;517&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Tj2n&quot;&gt;Что это значит и как всё происходит? Вам настраивают типовой сервер на VPS. VPS — это ситуация, когда вам выдают виртуальный доступ к выделенной удалённой среде. В случае с Инферно, средой выступает CentOS 7 с характеристиками в 512 MB оперативы, 1 ядро проца, 5 Гб SSD-диска.&lt;/p&gt;
  &lt;p id=&quot;oVvM&quot;&gt;Вам предустанавливают систему и настраивают её. Если вы сделаете что-то нехорошее и власти запросят официальным письмом доступ к вашим данным — доступ им будет предоставлен. Но есть нюанс. Компания находится в Лондоне и запрос нужно будет делать в их юрисдикцию, а значит и нарушение, которое вы будете совершать (я надеюсь не будете), должно быть международное.&lt;/p&gt;
  &lt;p id=&quot;s72y&quot;&gt;Лично меня решение от Inferno более чем устроило, так как есть &lt;a href=&quot;https://cp.inferno.name/knowledgebase/19/Instruktsii-po-nastroyke&quot; target=&quot;_blank&quot;&gt;подробные инструкции &lt;/a&gt;для моей семьи и друзей как что ткнуть чтобы работало. Второй крутой момент лично для меня — разные профили в настройках (от OpenVPN, до L2TP).&lt;/p&gt;
  &lt;h2 id=&quot;nLQB&quot;&gt;Вариант 2.2. Всё сам.&lt;/h2&gt;
  &lt;p id=&quot;S2IK&quot;&gt;Вариант для АмаМамаКриминал. Делаем сами всё. Тут несколько шагов.&lt;/p&gt;
  &lt;ol id=&quot;RE30&quot;&gt;
    &lt;li id=&quot;LF0D&quot;&gt;Аренда виртуального сервера.&lt;/li&gt;
    &lt;li id=&quot;OWeU&quot;&gt;Подключение к серверу по SSH.&lt;/li&gt;
    &lt;li id=&quot;vF23&quot;&gt;Установка и настройка OpenVPN.&lt;/li&gt;
    &lt;li id=&quot;dcRT&quot;&gt;Скачивание конфига через FTP-клиент.&lt;/li&gt;
    &lt;li id=&quot;fAoE&quot;&gt;Подключение к VPN.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;XoyV&quot;&gt;Шаг 1. Арендуем VDS сервер.&lt;/h3&gt;
  &lt;p id=&quot;LIYB&quot;&gt;Лично я рекомендую арендовать ваш собственный сервер. Таким образом вы избавитесь от внешних проблем с безопасностью. От физических атак на весь сервер (там ваш и не ваш виртуальные сервера) — упадут все.&lt;/p&gt;
  &lt;p id=&quot;QmQR&quot;&gt;Компаний-поставщиков услуг VDS просто дикое количество. Выбирайте по странам близлежащие страны вне запретов, чтобы уменьшить пинг (Латвия, Эстония, Литва, Нидерланды, Филиппины).&lt;/p&gt;
  &lt;p id=&quot;sD5p&quot;&gt;Установите на ваш сервер Ubuntu 20.04. Чаще всего, она предустановлена. После оплаты и активации вам придут доступы к серверу, которые понадобятся для дальнейшей работы: &lt;strong&gt;логин&lt;/strong&gt;, &lt;strong&gt;пароль &lt;/strong&gt;и &lt;strong&gt;IP-адрес&lt;/strong&gt;.&lt;/p&gt;
  &lt;h3 id=&quot;5kzb&quot;&gt;Шаг 2. Подключаемся по SSH&lt;/h3&gt;
  &lt;p id=&quot;qiNa&quot;&gt;SSH — это протокол, позволяющий производить удаленное управление операционной системой. С помощью SSH-клиента (специальной программы) можно подключаться к VDS/VPS и производить необходимые настройки.&lt;/p&gt;
  &lt;p id=&quot;asUu&quot;&gt;Чтобы не мучать ни вас, ни себя критериями выбора программ, скажу просто — Putty классная тулза. Она бесплатная и скачать её можно с &lt;a href=&quot;https://www.putty.org/&quot; target=&quot;_blank&quot;&gt;официального сайта&lt;/a&gt;.&lt;/p&gt;
  &lt;p id=&quot;Ab88&quot;&gt;Открываем Putty, в поле «Host Name» вводим IP-адрес сервера, в поле «Port» оставляем «22» (SSH). Нажимаем кнопку «Open». Откроется консоль, в которой мы будем работать с сервером.&lt;/p&gt;
  &lt;figure id=&quot;zll6&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/77/e8/77e864db-a677-4d19-8795-f386a8c0b2a4.png&quot; width=&quot;591&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;lHU1&quot;&gt;Вводим логин (можно сразу под «root») и нажимаем Enter. Вводим пароль от сервера и нажимаем Enter. Подключение прошло успешно. Обратите внимание, пароль не отображается в интерфейсе Putty — не пугайтесь, это нормально.&lt;/p&gt;
  &lt;figure id=&quot;VX6X&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/4b/0f/4b0f2a34-b1c2-48f1-b622-9ee4382df3aa.png&quot; width=&quot;601&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;224a&quot;&gt;Шаг 3. Устанавливаем OpenVPN&lt;/h3&gt;
  &lt;p id=&quot;pSkw&quot;&gt;Чтобы установить OpenVPN на сервер, вводим следующую команду и нажимаем Enter:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;o8qx&quot;&gt;wget &lt;a href=&quot;https://git.io/vpn&quot; target=&quot;_blank&quot;&gt;https://git.io/vpn&lt;/a&gt; -O openvpn-install.sh &amp;amp;&amp;amp; bash openvpn-install.sh&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;TCGQ&quot;&gt;Запустится процесс установки. Далее выполним настройку и создадим конфигурационный файл:&lt;/p&gt;
  &lt;ol id=&quot;6qOj&quot;&gt;
    &lt;li id=&quot;Yylu&quot;&gt;&lt;strong&gt;Which protocol should OpenVPN use? &lt;/strong&gt;Выбираем протокол: вводим цифру «1» (UDP) и нажимаем Enter. Можно и TCP, но подключаться будем дольше через трёхфакторное рукопожатие.&lt;/li&gt;
    &lt;li id=&quot;ilEj&quot;&gt;&lt;strong&gt;What port should OpenVPN listen to? &lt;/strong&gt;Ничего не вводим и просто нажимаем Enter.&lt;/li&gt;
    &lt;li id=&quot;eob7&quot;&gt;&lt;strong&gt;Select a DNS server for the clients. &lt;/strong&gt;Выбираем DNS-сервер: например, вводим цифру «2» (Google) и нажимаем Enter.&lt;/li&gt;
    &lt;li id=&quot;BwEG&quot;&gt;&lt;strong&gt;Enter a name for the first client. &lt;/strong&gt;Придумываем имя клиента на английском языке (оно может быть любым) и нажимаем Enter.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;oemP&quot;&gt;Далее нажимаем любую кнопку для начала установки и ждем завершения.&lt;/p&gt;
  &lt;figure id=&quot;8vol&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/14/1d/141d7316-59ef-47f1-bc9f-86f63eec7f3b.png&quot; width=&quot;601&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;CyYw&quot;&gt;Шаг 4. Качаем конфиг по FTP&lt;/h3&gt;
  &lt;p id=&quot;Y16Q&quot;&gt;FTP — протокол передачи файлов по сети, а FTP-клиент — специальная программа для упрощения доступа к FTP-серверу. С помощью этой программы мы подключимся к VDS и скачаем созданный конфигурационный файл.&lt;/p&gt;
  &lt;p id=&quot;27WW&quot;&gt;Опять таки, не разглагольствуя о великом, мой выбор — FileZilla (&lt;a href=&quot;https://filezilla.ru/&quot; target=&quot;_blank&quot;&gt;качать тут&lt;/a&gt;).&lt;/p&gt;
  &lt;p id=&quot;e2Uf&quot;&gt;Открываем FileZilla. В поле «Хост» вводим:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;pQRw&quot;&gt;sftp://ip_нашего_сервера&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;K4iW&quot;&gt;Имя пользователя и пароль — берем из доступов (их вам должны были прислать при закупке VDS). Нажимаем кнопку «Быстрое соединение». После подключения в интерфейсе справа отобразятся папки на сервере, а слева — на вашем компьютере. Находим конфигурационный файл на сервере и сохраняем его у себя на компьютере (с помощью мыши перетаскиваем в левую часть экрана в интерфейсе FileZilla).&lt;/p&gt;
  &lt;figure id=&quot;IjZM&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/56/98/5698cdb3-197a-4846-9b6c-86385200017f.png&quot; width=&quot;601&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;F6bW&quot;&gt;Чтобы открыть конфигурационный файл, нужно скачать программу OpenVPN &lt;a href=&quot;https://openvpn.net/community-downloads/&quot; target=&quot;_blank&quot;&gt;с официального  сайта.&lt;/a&gt;&lt;/p&gt;
  &lt;h3 id=&quot;qxhb&quot;&gt;Шаг 5. Празднуем&lt;/h3&gt;
  &lt;p id=&quot;Nec7&quot;&gt;После установки OpenVPN нажимаем на конфигурационный файл два раза и нажимаем «Да». Обратите внимание, файл сохранился в папке на нашем компьютере, которая была выбрана в программе FileZilla при скачивании.&lt;/p&gt;
  &lt;h1 id=&quot;bIiz&quot;&gt;Итоги&lt;/h1&gt;
  &lt;p id=&quot;wyHA&quot;&gt;Надеюсь, установка прошла успешно! Пишите что думаете и как вы обходите блокировки. Всех люблю!&lt;/p&gt;

</content></entry><entry><id>valerylinkov:PaDWolpUPHY</id><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov/PaDWolpUPHY?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><title>Хабрахабр. Легенда о комьюнити </title><published>2024-10-30T16:56:44.784Z</published><updated>2024-10-30T16:56:44.784Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/71/2b/712b7e70-ab07-4ad7-8a9e-be9d41535030.png"></media:thumbnail><category term="bombyozh" label="Бомбёж 🔥"></category><summary type="html">&lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/45a/fa9/311/45afa93112250808b88a50b97219cd54.png&quot;&gt;Разрабы. Сетевики. Диайвайщики. Прочие айтишники. Когда-то давно четыре народа жили в мире. Но всё изменилось, когда Народ прочих айтишников развязал войну. Только Хабрахабр, властелин всех четырёх платформ, мог остановить захватчиков. Но, когда мир нуждался в Хабрахабре больше всего, он исчез. Прошло сто лет, и я нашёл новый Хабр, в стоке прочих комьюнити именуемых «Флудилки». И хотя его искусство покорения статей было велико, ему предстояло ещё многому научиться. Но я верил, что Хабр спасёт мир!</summary><content type="html">
  &lt;figure id=&quot;GuUq&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/45a/fa9/311/45afa93112250808b88a50b97219cd54.png&quot; width=&quot;604&quot; /&gt;
  &lt;/figure&gt;
  &lt;blockquote id=&quot;Wmrx&quot;&gt;Разрабы. Сетевики. Диайвайщики. Прочие айтишники. Когда-то давно четыре народа жили в мире. Но всё изменилось, когда Народ прочих айтишников развязал войну. Только Хабрахабр, властелин всех четырёх платформ, мог остановить захватчиков. Но, когда мир нуждался в Хабрахабре больше всего, он исчез. Прошло сто лет, и я нашёл новый Хабр, в стоке прочих комьюнити именуемых «Флудилки». И хотя его искусство покорения статей было велико, ему предстояло ещё многому научиться. Но я верил, что Хабр спасёт мир!&lt;/blockquote&gt;
  &lt;h2 id=&quot;B7ot&quot;&gt;Книга 1. Статьи.&lt;/h2&gt;
  &lt;p id=&quot;UUhM&quot;&gt;Чтобы точно не потерять кто понаписал это послание, сразу представлюсь:&lt;/p&gt;
  &lt;figure id=&quot;4C5O&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/ff6/d08/985/ff6d08985c5da83ce00b568b169fbce6.jpg&quot; width=&quot;640&quot; /&gt;
  &lt;/figure&gt;
  &lt;h5 id=&quot;flOj&quot;&gt;Валерий Линьков&lt;/h5&gt;
  &lt;p id=&quot;YCHC&quot;&gt;Писал сам, без угроз и кредитов&lt;/p&gt;
  &lt;p id=&quot;kNWL&quot;&gt;Мой путь в Хабр начался с далёкого 2016 года. Я был супер-активным читателем, так как был школолошником, который фанател об IT и боготворил всех людей внутри. Конечно! Они же пьют сидр, вумничают и получают много деняк! Сердце школьника покорено на ровне со стримлерами.&lt;/p&gt;
  &lt;p id=&quot;0eeV&quot;&gt;Как же долго я пытался попасть на Хабр. Писал новости, статьи, пытался извергнуть из себя мысль как мог и каждый раз НЛО меня динамило. Я понимал, что недотягиваю до звания пре-джуна и нифига не понимаю в IT. Боже, как я переживал по этому поводу. Как самый дёрганный чувак по поводу своих знаний, читал всё что было написано на русском, ломаном английском и мечтал быть среди тех крутых ребят из аськи. Я ждал каждый раз общения со старшими товарищами из индустрии и рвал все жилы, чтобы добиться &lt;strong&gt;признания&lt;/strong&gt; от Хабр.&lt;/p&gt;
  &lt;p id=&quot;cF7N&quot;&gt;И вот, международный женский день 2018 года. &lt;strong&gt;Меня приняло НЛО! &lt;/strong&gt;Моему счастью не было придела. Теперь, я уже не школьник, а работник офиса, цискарь, студент технического ВУЗа и препод инфы в школе. Конечно, я ещё не &lt;strong&gt;айти&lt;/strong&gt;, но уже &lt;em&gt;айтёныш&lt;/em&gt;.&lt;/p&gt;
  &lt;figure id=&quot;GS2k&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/8ca/ed9/466/8caed946674bc49ae716330f1203a567.png&quot; width=&quot;1191&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Dfjx&quot;&gt;Меня читали! Знаете какая оценка у статьи? Не догадываетесь? +4. Ну я же не &lt;strong&gt;айти&lt;/strong&gt;, я &lt;em&gt;айтёныш &lt;/em&gt;(ну недоучка в айти). А знаете сколько комментов? Немножко... 54... Что же мне писали:&lt;/p&gt;
  &lt;figure id=&quot;E6uK&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/a50/8b0/e30/a508b0e300654881cc164670da305a09.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;RWcF&quot;&gt;Есть к чему стремиться! Мотивация поднята! Работаем! Пишем следующую статью, где учёл недостатки.&lt;/p&gt;
  &lt;figure id=&quot;5thX&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b28/650/77a/b2865077a16d0315313620d55ddc41d1.png&quot; width=&quot;1183&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;LpUj&quot;&gt;+1... Комменты (а их всего 15):&lt;/p&gt;
  &lt;figure id=&quot;j1hu&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/add/36c/219/add36c2197c7d282d74dfd18af63fc37.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;OIEm&quot;&gt;Ну да, ну да. Пошёл я нафиг. Буду работать ещё! Потом 6 статей и все до +9. Мало! Надо лучше! Карма болтается на 10. Я айтёныш, а хочу быть айти!&lt;/p&gt;
  &lt;p id=&quot;lAZj&quot;&gt;Дебют! Моя статья написанная с помощью Алексея Лукацкого (кто не знает, это бизнес-консультант циски в те годы, а сейчас на похожей должности в Positive Technologies). Вот он АЙТИ! Скоро будет круто:&lt;/p&gt;
  &lt;figure id=&quot;kKOp&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/69f/663/f65/69f663f654fd94025b5ca042eac3bc94.png&quot; width=&quot;1171&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;qI11&quot;&gt;И тут уже +16! Ура! Я счастлив! Теперь не так мало. Комментов 24 и из них ничего особо интересного, так пара замечаний, что теперь «маркетинговы булшит».&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;qHxK&quot;&gt;То есть, когда я пишу про технологию и разбираю её, я получаю ответ &amp;quot;При чём тут Cisco&amp;quot;, а когда пишу про Cisco &amp;quot;Ну это маркетинговый булшит&amp;quot;. Чё? А как тогда писать?! Ну ладно. Тролли наверное...&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;Jmt6&quot;&gt;В любом случае, это успех! Я рад и хочу выпустить новую статью. Ручки трясутся, ведь не хочется уровень опускать. А я ж &lt;em&gt;айтёныш&lt;/em&gt;. Та статья была популярна только благодаря Лукацкому. Вот он &lt;strong&gt;айти&lt;/strong&gt;, а я... ну вы поняли...&lt;/p&gt;
  &lt;p id=&quot;WoiP&quot;&gt;Год паузы (чуть меньше) и снова 8 марта я пишу статью о сериале, который покорил моё сморщенное айтёнышное сердечко: &amp;quot;Мистер Робот&amp;quot;. Ииииииии. Я в шоке:&lt;/p&gt;
  &lt;figure id=&quot;n88j&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/dc9/8e8/736/dc98e8736ab1f99838076c8820a7ff17.png&quot; width=&quot;1188&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;6SxC&quot;&gt;Оценки +29, комментов 162! Офигеть! И нет негатива. Все благодарят за разбор крутого сериала. Вау!&lt;/p&gt;
  &lt;p id=&quot;Kbt7&quot;&gt;Тут меня начинают покорять смутные сомнения &amp;quot;А может я уже айти?! Или людям просто понравился сериал?&amp;quot;. Надо проверить! Следующая статья через месяц:&lt;/p&gt;
  &lt;figure id=&quot;Ikei&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/3a8/a70/736/3a8a70736e6dea9f808ed31c499a9fe1.png&quot; width=&quot;1205&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;3dak&quot;&gt;-3. Я чмоня. Похороните меня за плинтусом. Далее, я думаю &amp;quot;Может я журналист про сериалы?&amp;quot;. Далее выпускаю несколько статей и карма уже +20 где-то. Ура! А может что-то интересное сделать? Попробую. Пишу про историю с попыткой Хуавей сделать что-то на примере Кремневой долины в IT. Беру интервью с Егором Бугаенко. Нуууу и просто 0. Хмм... Ну хоть не минус.&lt;/p&gt;
  &lt;p id=&quot;G4lL&quot;&gt;Далее, рассказывать про мои статьи не очень интересно. Мой рекорд по статья +43. И это статья про игры.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;ZQmC&quot;&gt;Мы же техно-сообщество. Мы же пишем про айти. Про что-то интересное в нём, а не &amp;quot;Как сделать бутерброд&amp;quot; или &amp;quot;Что посмотреть вечером&amp;quot;. Почему же так с моей кармой и статьями. Может это не моё? Может я чего-то не понимаю? Может я как ЛжеДмитрий ЛжеАйти?&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;qFkS&quot;&gt;Что я понял из своего опыта:&lt;/p&gt;
  &lt;ul id=&quot;dTjI&quot;&gt;
    &lt;li id=&quot;GQST&quot;&gt;Хабру интересно читать про личный опыт работы с конкретной штукой (желательно нишевой);&lt;/li&gt;
    &lt;li id=&quot;zGI4&quot;&gt;Хабру интересно посмотреть что-то прикольное для себя;&lt;/li&gt;
    &lt;li id=&quot;ejum&quot;&gt;На Хабре любят холеварить.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;SHJu&quot;&gt;Книга 2. Технотекст&lt;/h2&gt;
  &lt;p id=&quot;h8Ss&quot;&gt;У Хабра есть такой прикольный конкурс как «Технотекст». Писал статьи в Технотекст я с 2021 года. Что‑то нравилось, что‑то нет. Но я понимал почему я не побеждаю. И вот долгожданная обнова платформы и у нас есть 3 уровня сложности:&lt;/p&gt;
  &lt;figure id=&quot;kBHr&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/893/816/c0e/893816c0e1f02cbcc74fffdc40b167bf.png&quot; width=&quot;1089&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;igtP&quot;&gt;Итак, я на середнячка точно уж тяну. Я ж теперь работаю сеньором в сетях и лидом в проектах. Я справлюсь! Беру супер-неудобную тему и пишу про то как сделать Зельду на питоне. Момент истины и оценки +42 (мы не обогнали игры), но хоть людям интересно. Да же? Или нет?&lt;/p&gt;
  &lt;figure id=&quot;tQCQ&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/281/8db/c3a/2818dbc3aafc314d6d755d47b93d9923.png&quot; width=&quot;1200&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;jc1o&quot;&gt;А посмотрите, сколько прочтений на статье про сети или IP-адреса и сколько тут. Время? Да ну ладно! Оно же не так сильно влияет. Можно всё посчитать. Мы же умеем! Даже если до конца года меня прочитает х2 человек и спрос падать не будет (что уже невозможно), то за 5 лет я наберу только 100к прочтений. Как побить 400к с +1?&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;qXQh&quot;&gt;Как вообще оценки связаны с прочтениями? Типа оценки от &amp;quot;экспертов&amp;quot;, а прочтения от &amp;quot;недо-экспертов&amp;quot;? Как это?!&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;aePU&quot;&gt;Комитет Хабра (тут мне прям хочется назвать их этим словом). Несколько раз переносит выкладывание списка победителей и ночью приходит сообщение. Конечно, меня там нет. Я не расстроился, но хотел узнать, кто победил в номинации «Геймдев на уровне мидл»:&lt;/p&gt;
  &lt;figure id=&quot;DZrT&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/13b/c5c/331/13bc5c33110da026c1e84133dd4308b3.png&quot; width=&quot;1182&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;s4QG&quot;&gt;Сам автор пишет, что его уровень статьи &amp;quot;простой&amp;quot;, а не &amp;quot;средний&amp;quot;. А знаете какие у него оценки? +258. Чего?!...&lt;/p&gt;
  &lt;p id=&quot;mzw5&quot;&gt;Сейчас важное уточнение. Мне самому понравилась статья. Автор классно рассказал про то, как и что реально работает в геймдеве. Я ни коем образом не хочу обидеть автора. Он заслужил своего признания. Лично меня интересует как идёт подсчёт голосов. Кто эксперты? Как и что они оценивали? Ведь, в пунктах указано, что важна техничность статьи. Ну ладно, может я чего не понимаю? Иду спрашивать:&lt;/p&gt;
  &lt;figure id=&quot;bCdo&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/043/691/aa6/043691aa6cdf990d78428c21bc375d5e.png&quot; width=&quot;1123&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;8L6N&quot;&gt;Ответ был странным:&lt;/p&gt;
  &lt;figure id=&quot;bxDp&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/207/5b3/0cb/2075b30cbf2e9b41d6395a68074031f7.png&quot; width=&quot;1125&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;pfMT&quot;&gt;Следующий день:&lt;/p&gt;
  &lt;figure id=&quot;1m01&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/abb/cb5/bb6/abbcb5bb61c360936ca2bfd9ddbad329.png&quot; width=&quot;1020&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;BYh5&quot;&gt;Выложенная статья про &amp;quot;Золотую клаву&amp;quot;:&lt;/p&gt;
  &lt;figure id=&quot;AxeC&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/fa0/7ff/299/fa07ff299fba89073c01cb342ab4a295.png&quot; width=&quot;1110&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;wBLh&quot;&gt;Комментов от организаторов не последовало. Почему‑то. Но я стал победителем Технотекста 2023. Рад ли я? Ну честно, вообще ХЗ. С одной стороны, теперь я точно уж айти, а с другой — а почему так? Что я сделал лучше или хуже? Или я просто «наныл на победу»? Я так не хочу.&lt;/p&gt;
  &lt;p id=&quot;Kf2L&quot;&gt;Мне прислали мерч. Футболку, свитшот, значок и грамоту. Мне приятно. Я хожу в мерче, но как вы думаете сколько людей спросили про него и обратили не него внимание? Пара человек отметили, что мерч сделан красиво (понравилось как нарисована картинка, но люди от айти сильно далеки).&lt;/p&gt;
  &lt;p id=&quot;tM5B&quot;&gt;Прошло уже достаточно времени с события, чтобы я мог с холодной головой задать простой вопрос:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;982r&quot;&gt;А как так получилось, что техническая сложность работы вообще не учитывалась? Что же тогда важно?&lt;/p&gt;
  &lt;/section&gt;
  &lt;h2 id=&quot;4XZ7&quot;&gt;Книга 3. Карма&lt;/h2&gt;
  &lt;p id=&quot;sq6S&quot;&gt;Ну ладно, все эти конкурсы, победы, проигрыши, баллы и лайки с прочтениями — всё это приходит и уходит, но карма остаётся. У меня максимум был +45. Для Хабра это не много и не мало.&lt;/p&gt;
  &lt;p id=&quot;KSzk&quot;&gt;И вот, наступает момент, когда я подготовил для сообщества компании, где работаю (это самый крупная Ed-Tech платформа) целую историю как я хотел переехать на Go, но забил и стал дальше писать на шарпе и питоне. Я очень переживал, что меня закидают тухлыми помидорами фразами &amp;quot;Ты ничё не понимаешь! Вот то ли дело...&amp;quot;.&lt;/p&gt;
  &lt;p id=&quot;wZmu&quot;&gt;И каково было моё удивление, когда люди со мной просто обсудили простой вопрос &amp;quot;что на чём писать удобнее и лучше&amp;quot;. И там были и мидлы, и сеньоры, и лиды (и я в числе тех же). И все уважительно друг с другом говорили и рассуждали. Преза была на 20 минут, а мы сидели час с лишним.&lt;/p&gt;
  &lt;p id=&quot;ZRdK&quot;&gt;Тут я начинаю задумываться, а почему же так нельзя тут. И вот, наш деврел выкладывает текстовую версию моего рассказа. Ииииииииии:&lt;/p&gt;
  &lt;figure id=&quot;vaeB&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/aa6/7f8/fe4/aa67f8fe4565dd196a603dfebb66ea64.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;htw1&quot;&gt;Конечно, после карма немного упала, но я задумался и что? Ведь есть &lt;strong&gt;это&lt;/strong&gt;:&lt;/p&gt;
  &lt;figure id=&quot;fj6i&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/a43/7f3/80f/a437f380f23e18737bce05f5651444da.png&quot; width=&quot;1155&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;HCVu&quot;&gt;Как-то я встречал чувака с -300 кармой. Я не знаю что он сделал, но походу убил кого-то текстом. А какой ограничение? Никакого! Он просто не может публиковать новые статьи. Ну а если надо — да без проблем смени почту и снова получи инвайд от НЛО или попроси у кого-то с высокой кармой. И всё...&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;fJRR&quot;&gt;А зачем тогда вообще карма? Ты можешь получить мерч? Тебя не захейтят? Тебе скажут спасибо за бесплатный вклад? Эммм... Нет. А зачем тогда?&lt;/p&gt;
  &lt;/section&gt;
  &lt;h2 id=&quot;zkKi&quot;&gt;Финал&lt;/h2&gt;
  &lt;p id=&quot;RZXk&quot;&gt;Жаль, что не получилась история, где Хабр победил лорда Тролля и сообщество становится только токсичнее. Я искренне не понимаю зачем мне оно надо. Зачем мне писать статьи сюда? Я хотел вести личный блог, чтобы следить за своим прогрессом. Он у меня есть: Кудрявый микрофон в ТГ-шке (кому надо, тот найдёт). А тут прогресс кому нравится какой сериал...&lt;/p&gt;
  &lt;p id=&quot;Fdyf&quot;&gt;Я хотел принять участие в новом технотексте, но опять таки... &lt;strong&gt;Зачем?!&lt;/strong&gt; Оно ничего не даёт. Ни признания, ни экспертности, ни интересного времени-препровождения. Как написал какой-то комментатор под статьёй с победителями:&lt;/p&gt;
  &lt;figure id=&quot;EHJ1&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/db6/ff3/117/db6ff3117017705dc24d08617ac2ba2c.png&quot; width=&quot;1090&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;JqJn&quot;&gt;Меня узнавали как автора Хакера, как международного спикера, а не как чувачка-дурачка с докладом, о том что я не дурачок. Мне искренне стало от это грустно. Не яростно, не холиварно. Теперь, я буду писать книги или статьи, но за вознаграждения, как это в том же Хакере, а что-то для себя, я буду писать у себя в ТГ-шке (там, где &lt;strong&gt;мне&lt;/strong&gt; это комфортно). Это я делаю выбирая себя.&lt;/p&gt;
  &lt;p id=&quot;Z86J&quot;&gt;Если вы задаётесь вопросом &amp;quot;А нафига я это читаю?&amp;quot;, отвечу просто: &amp;quot;Подумайте надо ли вам писать на Хабре и трястись над кармой от таких приколов, как на картинке ниже, ещё и за бесплатно...&amp;quot;.&lt;/p&gt;
  &lt;figure id=&quot;BA9X&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/49d/918/096/49d918096f92d52569775cf46435ef3c.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;CwI5&quot;&gt;Увидимся в мире! Всем его и желаю!&lt;/p&gt;

</content></entry><entry><id>valerylinkov:tVu_wVBcNd1</id><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov/tVu_wVBcNd1?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><title>PyZelda своими руками или как геймдевить без Unreal, Unity и кредитов</title><published>2024-10-30T15:35:13.758Z</published><updated>2024-10-30T16:52:50.039Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/25/ef/25ef09fe-0c77-4494-84e8-07329a8c1890.png"></media:thumbnail><category term="igry" label="Игры 🎮"></category><summary type="html">&lt;img src=&quot;https://habrastorage.org/r/w1560/webt/hk/pc/jt/hkpcjtucu8_q8r5waklrrytfd78.jpeg&quot;&gt;Хабры и Хаброчки, я хотел бы перед самой статьёй обсудить вопрос целесообразности писать свой движок, вместо готовых решений. Есть куча статей, которые опишут разные движки от более популярных до менее. Я бы хотел затронуть немного другой вопрос: &quot;Как человеку, который изучал программирование много лет заняться геймдевом?&quot;. Обычно, есть два пути в геймдев:</summary><content type="html">
  &lt;figure id=&quot;p6l7&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/hk/pc/jt/hkpcjtucu8_q8r5waklrrytfd78.jpeg&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;PTuv&quot;&gt;Введение&lt;/h3&gt;
  &lt;p id=&quot;R80M&quot;&gt;Хабры и Хаброчки, я хотел бы перед самой статьёй обсудить вопрос целесообразности писать свой движок, вместо готовых решений. Есть куча статей, которые опишут разные движки от более популярных до менее. Я бы хотел затронуть немного другой вопрос: &amp;quot;Как человеку, который изучал программирование много лет заняться геймдевом?&amp;quot;. Обычно, есть два пути в геймдев:&lt;/p&gt;
  &lt;ol id=&quot;KeBw&quot;&gt;
    &lt;li id=&quot;2Bds&quot;&gt;Умышленный путь. Это когда человек, который играет в игры рано или поздно решит их создать. Тогда, он выбирает где ему учиться этому и выучивает игровые движки и C-образные языки к ним (чаще всего, C#).&lt;/li&gt;
    &lt;li id=&quot;4naG&quot;&gt;Путь прогеров. Программист увлекается математикой и пишет код. Так или иначе, везде где есть код — есть компьютер. Цифровые развлечения (в том числе и игры) не проходят мимо тех людей, который постоянно пишут код. Так, &lt;a href=&quot;https://www.stxnext.com/blog/python-for-game-development/&quot; target=&quot;_blank&quot;&gt;часть прогеров решает написать свою игру&lt;/a&gt; и начать свой путь в геймдев. Об этом пути мы и поговорим.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;p57B&quot;&gt;Конечно можно сказать, что если ты хочешь работать — иди учись и получай нужные навыки. Осваивай Unity или Unreal и работай в крутой &lt;a href=&quot;https://dtf.ru/gameindustry/1033019-igrovye-studii-i-mesta-ih-obitaniya-v-rossii&quot; target=&quot;_blank&quot;&gt;геймдев-компании&lt;/a&gt;. В этом есть доля правды. Однако, превращать любое своё хобби в работу — дело не благоразумное. Выгорание скажет об этом достаточно понятно. Тогда вам могут предложить сделать либо мод на игру (например, &lt;a href=&quot;https://skillbox.ru/media/gamedev/7-igr-na-source-sozdannykh-za-predelami-valve/&quot; target=&quot;_blank&quot;&gt;на движке Source&lt;/a&gt;) или поиграть в &lt;a href=&quot;https://dtf.ru/games/51311-interaktivnye-grezy-kak-ustroen-redaktor-dreams-i-chto-tam-mozhno-sozdat&quot; target=&quot;_blank&quot;&gt;Грёзы&lt;/a&gt;, которая тоже очень популярна. Такой вариант вполне подойдёт, но появляется новая проблема: &amp;quot;Выбор варианта работы&amp;quot;.&lt;/p&gt;
  &lt;h3 id=&quot;E472&quot;&gt;Выбор варианта работы&lt;/h3&gt;
  &lt;p id=&quot;Y8SG&quot;&gt;Всего есть три варианта работы над игрой:&lt;/p&gt;
  &lt;ol id=&quot;zTzs&quot;&gt;
    &lt;li id=&quot;iISe&quot;&gt;Создать игру на известном движке-конструкторе&lt;/li&gt;
    &lt;li id=&quot;bt1w&quot;&gt;Сделать мод на существующий движок&lt;/li&gt;
    &lt;li id=&quot;0dqO&quot;&gt;Создать свой движок и написать игру&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;hnRQ&quot;&gt;Каждый из этих вариантов хорош по-своему, но и имеет ряд недоработок. Например, выбрав путь создания игры на популярном движке вы столкнётесь с проблемами самого движка, а главное — с проблемами монетизации проекта. Если выбрать модопуть — вы сразу столкнётесь с тем, что не каждый движок открыт для написания игр, а также, не каждый движок позволяет продавать мод хоть за какую-то цену. Путь написания своего движка вызывает в геймдеве дикий припадок, мол &amp;quot;Да зачем опять идти очень сложно, когда сроки горят, а сам ты ещё не доработал концепцию?&amp;quot;. Данный путь весьма не популярен для общества из-за сложности реализации и проблем с набором хоть какой-то команды, ведь если вы пишете движок, кому-то с ним работать.&lt;/p&gt;
  &lt;p id=&quot;m2vM&quot;&gt;Так зачем выбирать &amp;quot;сложный&amp;quot; путь? Во-первых, не для всех он сложнее. Лично мне сложнее перейти на C# с использованием Unity, чем написать новый проект на Python. Во-вторых, люди не всегда понимают сам движок. Сейчас я преподаю в &lt;a href=&quot;https://obe.ru/&quot; target=&quot;_blank&quot;&gt;институте &amp;quot;Бизнеса и Дизайна&amp;quot;&lt;/a&gt;. Это один из первых профильных учреждений, занимающихся геймдевом. И вот у студентов я спросил зачем им движок. Каково было моё удивление, что далеко не все понимаю, вообще зачем он нужен. Спойлер, не из-за пресетов.&lt;/p&gt;
  &lt;h3 id=&quot;IMQx&quot;&gt;Зачем вам движок?!&lt;/h3&gt;
  &lt;p id=&quot;Z8F8&quot;&gt;По сути, движок решает всего лишь три, но очень важных вопроса:&lt;/p&gt;
  &lt;ol id=&quot;Xq6C&quot;&gt;
    &lt;li id=&quot;tCP9&quot;&gt;&lt;strong&gt;Физика&lt;/strong&gt;. Если вы окончили физмат, вы понимаете насколько сложно определить и прописать траекторию падения стеклянного шара весом в 2 килограмма на доску из дуба, которая лежит под углом 32 градуса. Также, нужно не забыть прописать с какой высоты должен упасть шар, чтобы разбиться. Движок прописывает эту физику за вас, а вы лишь обращаетесь к тем или иным объектам.&lt;/li&gt;
    &lt;li id=&quot;urzu&quot;&gt;&lt;strong&gt;Тайлсеты&lt;/strong&gt;. Тайл — это маленькие картинки для прорисовки графики (чаще всего, карт). Процесс создания тайлов &lt;a href=&quot;https://habr.com/ru/articles/470099/&quot; target=&quot;_blank&quot;&gt;весьма энергозатратный&lt;/a&gt;, а наложение этих тайлов достаточно простое дело. Просто выбрать где лежит камень, а где земля или вода. В движках типа Unreal или Unity вы можете просто выбрать слой карты и нарисовать клеточками из тайтлов карту.&lt;/li&gt;
    &lt;li id=&quot;VkTW&quot;&gt;&lt;strong&gt;Анимация&lt;/strong&gt;. Самый спорный пункт. В движках все элементы на карте — это объекты. Каждый объект имеет форму по координатам x, y, z и их можно менять прямо в самом движке путём перемещения, сжатия или растягивания объекта. Но важное уточнение, прорисовывать анимацию по x, y, z — не самая лучшая идея. Куда надёжнее, красивее и вообще правильнее прописывать каждый шаг объекта путём перемещения по пресету персонажа по графике.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;OwE5&quot;&gt;Иными словами, сам игровой движок — это автоматизирующая система, которая позволяет упростить разработку. Однако, при использовании движка теряется часть гибкости в настройках. Моя задача — описать как можно более подробный процесс написания игры по самому сложному пути, хотя Python и упрощает часть вещей. Что ж, хватит слов и давайте к делу!&lt;/p&gt;
  &lt;h3 id=&quot;XLvB&quot;&gt;Подготовка&lt;/h3&gt;
  &lt;p id=&quot;kQUZ&quot;&gt;Для начала, давайте создадим папку проекта. Я назвал проект PyZelda и в папке проекта есть ещё 4 директории: audio, code, graphic и map.&lt;/p&gt;
  &lt;figure id=&quot;PTeN&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/ex/80/nz/ex80nzsijzxwn-d2kwwbn1_icyc.png&quot; width=&quot;1093&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Xh5B&quot;&gt;Далее, в папке code создадим три файла:&lt;/p&gt;
  &lt;ul id=&quot;uRmN&quot;&gt;
    &lt;li id=&quot;rtcq&quot;&gt;&lt;a href=&quot;http://main.py/&quot; target=&quot;_blank&quot;&gt;main.py&lt;/a&gt; — основной файл игры&lt;/li&gt;
    &lt;li id=&quot;WXio&quot;&gt;&lt;a href=&quot;http://settings.py/&quot; target=&quot;_blank&quot;&gt;settings.py&lt;/a&gt; — настройки игры (тут мы укажем настройки полей и основных данных по окну и прорисовке)&lt;/li&gt;
    &lt;li id=&quot;7cUJ&quot;&gt;&lt;a href=&quot;http://debug.py/&quot; target=&quot;_blank&quot;&gt;debug.py&lt;/a&gt; — файл дебагинга&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;Slsd&quot;&gt;Перед работой, не забудьте скачать библиотеку PyGame (&lt;code&gt;pip install pygame&lt;/code&gt;)&lt;/p&gt;
  &lt;figure id=&quot;GYcS&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/hm/dt/zi/hmdtzidghxionst8damlsi_flzw.png&quot; width=&quot;1350&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;HuJi&quot;&gt;Файл main:&lt;/p&gt;
  &lt;pre id=&quot;R7Hj&quot; data-lang=&quot;python&quot;&gt;import pygame, sys #импортируем библиотеки PyGame и Sys
from settings import * #импорт из файла settings

class Game: #основной класс игры
	def __init__(self): #создаём конструктор класса
		pygame.init() #конструктор использует конструкции из библиотеки PyGame
		self.screen = pygame.display.set_mode((WIDTH,HEIGTH)) #забирает из нашего проекта экран в виде размеров в ширину и высоту
		pygame.display.set_caption(&amp;quot;PyZelda&amp;quot;) #Устанавливаем название нашего окна
		self.clock = pygame.time.Clock() #а также, забирает из проекта время

	def run(self): #функция запуска игры
		while True: #до выхода из игры она активна
			for event in pygame.event.get(): #просмотр событий в игре
				if event.type == pygame.QUIT: #сейчас мы можем только выйти и при выходе:
					pygame.quit() #вызываем метод закрытия игры
					sys.exit() #и закрываем окно системы
			self.screen.fill(&amp;#x27;green&amp;#x27;) #помимо событий, указываем цвет экрана
			pygame.display.update() #обновляем экран
			self.clock.tick(FPS) #запрашиваем FPS

if __name__ == &amp;#x27;__main__&amp;#x27;: #запуск игры только из main-файла
	game = Game() #Если файл main, то сама игра вызывает класс...
	game.run() #...и запускает функцию run из класса&lt;/pre&gt;
  &lt;p id=&quot;BMgz&quot;&gt;В файле main мы запускаем саму игру. Создаём конструктор на базе PyGame и работаем с входными файлами и данными.&lt;/p&gt;
  &lt;p id=&quot;bY8G&quot;&gt;Файл &lt;a href=&quot;http://setting.py/&quot; target=&quot;_blank&quot;&gt;setting.py&lt;/a&gt;:&lt;/p&gt;
  &lt;pre id=&quot;FbRr&quot; data-lang=&quot;python&quot;&gt;WIDTH = 1280 #Ширина экрана
HEIGTH = 720 #Высота экрана
FPS = 60 #Число FPS
TILESIZE = 64 #Размер тайла (квадрата текстуры)

WORLD_MAP = [ #Карта мира игры. Она состоит из 20х20 квадратов
[&amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;,&amp;#x27;, &amp;#x27;x&amp;#x27;],
[&amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;x&amp;#x27;],
]&lt;/pre&gt;
  &lt;p id=&quot;ZeKD&quot;&gt;Далее, файл &lt;a href=&quot;http://debug.py/&quot; target=&quot;_blank&quot;&gt;debug.py&lt;/a&gt;:&lt;/p&gt;
  &lt;pre id=&quot;WYC8&quot; data-lang=&quot;python&quot;&gt;import pygame #Снова обращаемся к PyGame
pygame.init() #Используем базовый конструктор
font = pygame.font.Font(None, 30) #Указываем шрифт

def debug(info, y = 10, x = 10):  #Сама функция дебага
	display_surface = pygame.display.get_surface() #Получаем ссылку на текущую установленную поверхность отображения в игре
	debug_surf = font.render(str(info), True, &amp;quot;Red&amp;quot;) #Рендерим текст (я сделал его красным)
	debug_rect = debug_surf.get_rect(topleft = (x, y)) #Указывамем место отображения инфы на экране (левый верхний угол)
	pygame.draw.rect(display_surface, &amp;quot;White&amp;quot;, debug_rect) #Делаем микро-консоль в виде прямоугольника (и да он белый, будет белая консоль с красным текстом)
	display_surface.blit(debug_surf, debug_rect) #Собираем нашу микро-консоль с параметрами текста&lt;/pre&gt;
  &lt;p id=&quot;IJ68&quot;&gt;В данном файле мы создадим дебаг игры. Это поле, которое мы выводим вверху слева экрана и в нём показываем нужный нам текст. Для запуска дебага, нужно импортировать debug в main-файл и вывести что-то после отрисовки окна. Примерно так (файл &lt;a href=&quot;http://main.py/&quot; target=&quot;_blank&quot;&gt;main.py&lt;/a&gt;):&lt;/p&gt;
  &lt;pre id=&quot;E3aM&quot; data-lang=&quot;python&quot;&gt;import pygame, sys #импортируем библиотеки PyGame и Sys
from settings import * #импорт из файла settings
from debug import debug #импортируем дебаг &amp;lt;------------------

class Game: #основной класс игры
	def __init__(self): #создаём конструктор класса
		pygame.init() #конструктор использует конструкции из библиотеки PyGame
		self.screen = pygame.display.set_mode((WIDTH,HEIGTH)) #забирает из нашего проекта экран в виде размеров в ширину и высоту
		pygame.display.set_caption(&amp;quot;PyZelda&amp;quot;) #Устанавливаем название нашего окна
		self.clock = pygame.time.Clock() #а также, забирает из проекта время

	def run(self): #функция запуска игры
		while True: #до выхода из игры она активна
			for event in pygame.event.get(): #просмотр событий в игре
				if event.type == pygame.QUIT: #сейчас мы можем только выйти и при выходе:
					pygame.quit() #вызываем метод закрытия игры
					sys.exit() #и закрываем окно системы
			self.screen.fill(&amp;#x27;green&amp;#x27;) #помимо событий, указываем цвет экрана
			debug(&amp;#x27;Чё как? Я дебаг!&amp;#x27;) #Дебажим &amp;lt;------------------
			pygame.display.update() #обновляем экран
			self.clock.tick(FPS) #запрашиваем FPS

if __name__ == &amp;#x27;__main__&amp;#x27;: #запуск игры только из main-файла
	game = Game() #Если файл main, то сама игра вызывает класс...
	game.run() #...и запускает функцию run из класса&lt;/pre&gt;
  &lt;p id=&quot;oPbO&quot;&gt;Получим феерическую игру цветов:&lt;/p&gt;
  &lt;figure id=&quot;siGZ&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/_b/t0/i5/_bt0i5v_zg2q9mwccux-ch_xfd4.png&quot; width=&quot;1084&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;swK2&quot;&gt;&lt;a href=&quot;https://disk.yandex.ru/d/8jdGZBe3w3plAg&quot; target=&quot;_blank&quot;&gt;Стартовый набор файлов для скачивания&lt;/a&gt;.&lt;/p&gt;
  &lt;h3 id=&quot;WU3P&quot;&gt;Пишем уровень&lt;/h3&gt;
  &lt;p id=&quot;B4RA&quot;&gt;Итак, для начала давайте разберёмся в понятии &amp;quot;класс&amp;quot; в концепции ООП (объектно-ориентированного программирования). Сейчас мы создадим класс &lt;code&gt;Level&lt;/code&gt;. В этом классе есть всё необходимое для работы с объектами внутри. По сути, класс &lt;code&gt;Level&lt;/code&gt; и есть наша игра, так как именно этот класс собирает все &lt;strong&gt;спрайты&lt;/strong&gt; (игрок, враги, карта мира и т.д.). Помимо самих спрайтов, нас интересует набор элементов связанных с подсчётом тех или иных пунктов. Как я говорил ранее, движок нужен для прописывания физики, а физика — это математический способ описать поведение объекта. Таким образом, мы взаимодействуем с &lt;strong&gt;числами&lt;/strong&gt; и &lt;strong&gt;параметрами&lt;/strong&gt;. Это тоже находится в классе &lt;code&gt;Level&lt;/code&gt;. Например, если игрока ударит враг, то игрок потеряет 5% здоровья — это и есть наши параметры.&lt;/p&gt;
  &lt;p id=&quot;dayO&quot;&gt;Но есть одна проблема. Объектов очень много. Чтобы не рыскать в коде в поисках конкретного камня №67, код будем разбивать группами объектов. Сейчас мы создадим две группы: &lt;code&gt;visible_sprites&lt;/code&gt; и &lt;code&gt;obstacle_sprites&lt;/code&gt;. Как вы уже поняли, группа &lt;code&gt;visible_sprites&lt;/code&gt; отвечает за все объекты, которые пользователь видит (например, карту мира и персонажа), а &lt;code&gt;obstacle_sprites&lt;/code&gt; — это объекты, которые нужны для технического использования. Все объекты можно сослать на конкретные группы или на набор групп. Так, объект &amp;quot;кот&amp;quot; может быть в группе объектов движущихся, но не взаимодействующих с игроком. Если же добавить кота в обе группы, он будет отображён и активен.&lt;/p&gt;
  &lt;p id=&quot;eklM&quot;&gt;Приступим к коду. Создадим новый файл &lt;code&gt;level.py&lt;/code&gt;. Пропишем в нём следующий код:&lt;/p&gt;
  &lt;pre id=&quot;DoFm&quot; data-lang=&quot;python&quot;&gt;import pygame

class Level: #Создали класс
	def __init__(self): #Базовые параметры
		self.visible_sprites = pygame.sprite.Group() #Создали группу видимых элементов
		self.obstacle_sprites = pygame.sprite.Group() #Создали группу технических элементов

	def run(self): #Создали метод в классе
		pass&lt;/pre&gt;
  &lt;p id=&quot;dRys&quot;&gt;Мы просто создали класс и в нём 2 группы, а затем в классе создали метод вызова данного класса. Далее, нужно вернуться в main-файл и импортировать класс &lt;code&gt;Level&lt;/code&gt; (&lt;code&gt;from level import Level&lt;/code&gt;), объявить класс &lt;code&gt;Level&lt;/code&gt; (&lt;code&gt;self.level = Level()&lt;/code&gt;), а таже запустить его в самом run-методе в main (&lt;code&gt;self.level.run()&lt;/code&gt;). Я решил пока убрать дебаг из проекта, так как сейчас дебажить нечего и финальный код в main-файле выглядит так:&lt;/p&gt;
  &lt;pre id=&quot;BLuv&quot; data-lang=&quot;python&quot;&gt;import pygame, sys #импортируем библиотеки PyGame и Sys
from settings import * #импорт из файла settings
from level import Level #+++ импорт из файла level класс Level +++

class Game: #основной класс игры
	def __init__(self): #создаём конструктор класса
		pygame.init() #конструктор использует конструкции из библиотеки PyGame
		self.screen = pygame.display.set_mode((WIDTH,HEIGTH)) #забирает из нашего проекта экран в виде размеров в ширину и высоту
		pygame.display.set_caption(&amp;quot;PyZelda&amp;quot;) #Устанавливаем название нашего окна
		self.clock = pygame.time.Clock() #а также, забирает из проекта время
		self.level = Level() #+++ объёвили Level +++

	def run(self): #функция запуска игры
		while True: #до выхода из игры она активна
			for event in pygame.event.get(): #просмотр событий в игре
				if event.type == pygame.QUIT: #сейчас мы можем только выйти и при выходе:
					pygame.quit() #вызываем метод закрытия игры
					sys.exit() #и закрываем окно системы
			self.screen.fill(&amp;#x27;green&amp;#x27;) #помимо событий, указываем цвет экрана
			self.level.run() #+++ запустили функцию run в файле level в классе Level +++
			pygame.display.update() #обновляем экран
			self.clock.tick(FPS) #запрашиваем FPS

if __name__ == &amp;#x27;__main__&amp;#x27;: #запуск игры только из main-файла
	game = Game() #Если файл main, то сама игра вызывает класс...
	game.run() #...и запускает функцию run из класса
&lt;/pre&gt;
  &lt;p id=&quot;1wLm&quot;&gt;Давайте далее, пропишем что-то в классе Level. Таким образом, мы создадим подложку из зелёного фона, а сверху наложим новые объекты. Для этого, мы воспользуемся простым методом, как в и в дебаге: &lt;code&gt;display_surface = pygame.display.get_surface()&lt;/code&gt;. В коде с Level оно выглядит так:&lt;/p&gt;
  &lt;pre id=&quot;eTzS&quot; data-lang=&quot;python&quot;&gt;import pygame

class Level: #создали класс
	def __init__(self): #базовые параметры
		self.display_surface = pygame.display.get_surface() #создали новый слой объектов
		self.visible_sprites = pygame.sprite.Group() #создали группу видимых элементов
		self.obstacle_sprites = pygame.sprite.Group() #создали группу технических элементов

	def run(self): #создали метод в классе
		pass&lt;/pre&gt;
  &lt;p id=&quot;F7Ea&quot;&gt;Сейчас ничего не поменяется, так как мы объявили что будем что-то рисовать, но ничего не нарисовали. Давайте приступим к процессу отрисовки. Для этого создадим новый файл &lt;code&gt;tile.py&lt;/code&gt;.&lt;/p&gt;
  &lt;pre id=&quot;57Wq&quot; data-lang=&quot;python&quot;&gt;import pygame
from settings import *

class Tile(pygame.sprite.Sprite):
	def __init__(self, pos, groups):
		super().__init__(groups) #наследуем все группы
		self.image = pygame.image.load(&amp;#x27;../graphic/box.png&amp;#x27;).convert_alpha() #указываем адрес картинки
		self.rect = self.image.get_rect(topleft = pos) #указываем позицию отрисовки (левый верхний угол)&lt;/pre&gt;
  &lt;p id=&quot;3yS6&quot;&gt;Интересного в этом коде мало. Мы просто импортируем сам pygame (снова и снова), из файла &lt;code&gt;settings.py&lt;/code&gt; мы берём всю информацию по разметке поля (потому, мы его и оставляем тут). Далее, мы создаём новый класс &lt;code&gt;Tile&lt;/code&gt;. В нём создаём параметры себя, позицию и группу наследования. Далее, командой &lt;code&gt;super()&lt;/code&gt; мы включаем &lt;a href=&quot;https://docs-python.ru/tutorial/vstroennye-funktsii-interpretatora-python/funktsija-super/&quot; target=&quot;_blank&quot;&gt;наследование&lt;/a&gt;. Далее, указываем картинки самих предметов и &lt;a href=&quot;https://younglinux.info/pygame/rect&quot; target=&quot;_blank&quot;&gt;&lt;code&gt;rect&lt;/code&gt;&lt;/a&gt; данных картинок. Из интересного, &lt;code&gt;convert_alpha()&lt;/code&gt;. Эта функция пайгейма создает новую копию поверхности с желаемым форматом пикселей. Суровая необходимость, чтобы пайгейм понял что мы делаем.&lt;/p&gt;
  &lt;p id=&quot;MU30&quot;&gt;Ровно такой же код создадим в файле &lt;code&gt;player.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;iJ6U&quot; data-lang=&quot;python&quot;&gt;import pygame
from settings import *

class Player(pygame.sprite.Sprite):
	def __init__(self, pos, groups):
		super().__init__(groups)
		self.image = pygame.image.load(&amp;#x27;../graphic/link.png&amp;#x27;).convert_alpha()
		self.rect = self.image.get_rect(topleft = pos)&lt;/pre&gt;
  &lt;p id=&quot;a9Zz&quot;&gt;Отличие данного кода лишь в двух местах:&lt;/p&gt;
  &lt;ul id=&quot;MEJH&quot;&gt;
    &lt;li id=&quot;eO6z&quot;&gt;Я создал класс &lt;code&gt;Player&lt;/code&gt; вместо Tile&lt;/li&gt;
    &lt;li id=&quot;JehW&quot;&gt;Заменили картинку с коробок на героя Хайрула :)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;bZHV&quot;&gt;Все пресеты картинок я взял из проекта &lt;a href=&quot;https://pixel-boy.itch.io/ninja-adventure-asset-pack&quot; target=&quot;_blank&quot;&gt;NinjaAdventure&lt;/a&gt;. Там есть способ скачать бесплатные сеты графики. Обрезал картики в фотошопе и получил мини-изображения.&lt;/p&gt;
  &lt;p id=&quot;YTRe&quot;&gt;Теперь, давайте отобразим нашу мировую карту. Делать мы это будем в файле &lt;code&gt;level.py&lt;/code&gt;, так как именно в нём мы храним всю нужную инфу про конкретный уровень. Сразу импортируем &lt;code&gt;settings.py&lt;/code&gt; и обратимся к карте. Финал работы будет выглядеть так:&lt;/p&gt;
  &lt;pre id=&quot;Akdy&quot; data-lang=&quot;python&quot;&gt;import pygame
from settings import *

class Level: #создали класс
	def __init__(self): #базовые параметры
		self.display_surface = pygame.display.get_surface() #создали новый слой объектов
		self.visible_sprites = pygame.sprite.Group() #создали группу видимых элементов
		self.obstacle_sprites = pygame.sprite.Group() #создали группу технических элементов
		self.create_map()

	def create_map(self):
		for row in WORLD_MAP:
			print(row)

	def run(self): #создали метод в классе
		pass&lt;/pre&gt;
  &lt;p id=&quot;GVKt&quot;&gt;После запуска main-файла, сама игра никак не поменялась, но мы в терминале отпечатали нашу карту.&lt;/p&gt;
  &lt;figure id=&quot;AtSM&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/w2/us/rl/w2usrlpqmue5az6n-t4q5dfqkmq.png&quot; width=&quot;1494&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;KrUN&quot;&gt;Про карту. Для упрощения работы, я создал клетку (напомню, что она размером 64 на 64 пикселя) и указываю символами что куда ставить. Поставил карту я так: &amp;#x27;x&amp;#x27; — это коробки, &amp;#x27;,&amp;#x27; — пустое место, а &amp;#x27;p&amp;#x27; — это наш герой.&lt;/p&gt;
  &lt;p id=&quot;o0dG&quot;&gt;Это, конечно, круто, но вот я хотел бы нарисовать карту в игре, а не в терминале. Для этого, модернизируем код. Работаем только с файлом &lt;code&gt;level.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;Li10&quot; data-lang=&quot;python&quot;&gt;import pygame
from settings import *
from tile import Tile
from player import Player

class Level: #создали класс
	def __init__(self): #базовые параметры
		self.display_surface = pygame.display.get_surface() #создали новый слой объектов
		self.visible_sprites = pygame.sprite.Group() #создали группу видимых элементов
		self.obstacle_sprites = pygame.sprite.Group() #создали группу технических элементов
		self.create_map()

	def create_map(self):
		for row_index, row in enumerate(WORLD_MAP):
			for col_index, col in enumerate(row):
				x = col_index * TILESIZE
				y = row_index * TILESIZE
				if col == &amp;#x27;x&amp;#x27;:
					Tile((x, y), [self.visible_sprites])
				if col == &amp;#x27;p&amp;#x27;:
					Player((x, y), [self.visible_sprites])

	def run(self): #создали метод в классе
		self.visible_sprites.draw(self.display_surface)&lt;/pre&gt;
  &lt;p id=&quot;LWmu&quot;&gt;Всё что я делаю — это прохожу массив данных и умножаю элемент на 64, так как размер моего тайла равен 64 пикселям. Далее, если элемент равен &lt;code&gt;&amp;#x27;x&amp;#x27;&lt;/code&gt; заменяю его на коробку, а если &lt;code&gt;&amp;#x27;p&amp;#x27;&lt;/code&gt;, то на героя. Далее, я прописал в методе запуска метод отрисовки поля. Также, на карте я заменил одну &lt;code&gt;&amp;#x27;,&amp;#x27;&lt;/code&gt; на &lt;code&gt;&amp;#x27;p&amp;#x27;&lt;/code&gt;. И результат:&lt;/p&gt;
  &lt;figure id=&quot;5KU0&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/yw/gu/s6/ywgus6g0r_afexbaexxmfjgvp3c.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Di3R&quot;&gt;В main-файле заменив цвет фона на чёрный, а размер тайла на 32 пикселя, я получил это:&lt;/p&gt;
  &lt;figure id=&quot;0mGp&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/aa/9f/wn/aa9fwnnikbo0j4titebgguazpuu.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;nCow&quot;&gt;&lt;a href=&quot;https://disk.yandex.ru/d/ZYjndkgFeRALkA&quot; target=&quot;_blank&quot;&gt;Файлы данного этапа для скачивания&lt;/a&gt;. Сразу оговорюсь, что отображение не совсем корректное из-за самих картинок. Я не подбивал их к размеру 64 на 64 пикселя. Далее я исправил это и вернул размер тайла в 64 на 64 пикселя.&lt;/p&gt;
  &lt;h3 id=&quot;Nalu&quot;&gt;Создаём игрока&lt;/h3&gt;
  &lt;p id=&quot;14nw&quot;&gt;Сам игрок должен мочь передвигаться и сталкиваться с существующими объектами. Для начала, запишем его движения. Переходим в &lt;code&gt;player.py&lt;/code&gt; и прописываем функцию перемещения. Код в &lt;code&gt;player.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;XbTo&quot; data-lang=&quot;python&quot;&gt;import pygame
from settings import *

class Player(pygame.sprite.Sprite):
	def __init__(self, pos, groups):
		super().__init__(groups)
		self.image = pygame.image.load(&amp;#x27;../graphic/link.png&amp;#x27;).convert_alpha()
		self.rect = self.image.get_rect(topleft = pos)

		self.direction = pygame.math.Vector2() #обращаемся к направлению через вектор

	def input(self): #варьируем кнопки
		keys = pygame.key.get_pressed()

		if keys[pygame.K_UP]:
			self.direction.y = -1
		elif keys[pygame.K_DOWN]:
			self.direction.y = 1
		else:
			self.direction.y = 0

		if keys[pygame.K_LEFT]:
			self.direction.x = -1
		elif keys[pygame.K_RIGHT]:
			self.direction.x = 1
		else:
			self.direction.x = 0

	def update(self):
		self.input()&lt;/pre&gt;
  &lt;p id=&quot;Gb97&quot;&gt;Тут с кодом достаточно просто. В функции &lt;code&gt;self.direction = pygame.math.Vector2()&lt;/code&gt; мы задаём вектор точке. Точка — это наш герой, а его вектор болтается в диапазоне от -1 до 1. Функция &lt;code&gt;keys = pygame.key.get_pressed()&lt;/code&gt; позволяет продолжать нажатие и тогда, герой должен разгоняться. Если нажатия нет — вектор равен 0 и герой тормозит. Это очень условное, но приписывание инерции.&lt;/p&gt;
  &lt;p id=&quot;Atjk&quot;&gt;Ещё в файле &lt;code&gt;level.py&lt;/code&gt; в функции &lt;code&gt;run&lt;/code&gt; я записал обновление всех спрайтов. Это строчка кода вида:&lt;/p&gt;
  &lt;pre id=&quot;8uif&quot; data-lang=&quot;python&quot;&gt;self.visible_sprites.update()&lt;/pre&gt;
  &lt;p id=&quot;4gUc&quot;&gt;Ещё, я переписал в том же файле вызов героя. Мне это нужно для глобализации позиции героя. Из строки&lt;/p&gt;
  &lt;pre id=&quot;qo2R&quot; data-lang=&quot;python&quot;&gt;Player((x, y), [self.visible_sprites])&lt;/pre&gt;
  &lt;p id=&quot;Ag28&quot;&gt;Я сделал&lt;/p&gt;
  &lt;pre id=&quot;lwo1&quot; data-lang=&quot;python&quot;&gt;self.player = Player((x, y), [self.visible_sprites])&lt;/pre&gt;
  &lt;p id=&quot;Umwg&quot;&gt;Продолжим прорисовку движений в файле &lt;code&gt;player.py&lt;/code&gt;. Создадим ещё один параметр — скорость. Для этого в глобальные параметры (&lt;code&gt;__init__&lt;/code&gt;) добавим строчку &lt;code&gt;self.speed = 5&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;RIoD&quot;&gt;Также напишем функцию &lt;code&gt;move&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;67uY&quot; data-lang=&quot;python&quot;&gt;def move(self, speed):
		self.rect.center += self.direction * speed&lt;/pre&gt;
  &lt;p id=&quot;6DSR&quot;&gt;И в update-функции пропишем движения персонажа: &lt;code&gt;self.move(self.speed)&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;iv6B&quot;&gt;Результат:&lt;/p&gt;
  &lt;figure id=&quot;ni2v&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/webt/9r/f5/kr/9rf5krne9ukw8zz-8mrbc2k1eho.gif&quot; width=&quot;600&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;mSRK&quot;&gt;Если приглядеться, то по диагонали, Линк бежит чуть быстрее. Дело в том, что он бежит по диагонали со скоростью корень из двух, что примерно равно 1.4. Мы прописали скорость вверх, вниз, влево и вправо равной 1, а вот по диагонали из правил математики, можно понять, что длина гипотенузы равна сумме квадратов длин оснований квадрата под корнем, то есть &lt;strong&gt;корень из (1^2 + 1^2)&lt;/strong&gt;. Исправим данный баг нормализацией от PyGame (да-да, как в Unity). Исправленная функция движения:&lt;/p&gt;
  &lt;pre id=&quot;PtzN&quot; data-lang=&quot;python&quot;&gt;def move(self, speed):
	if self.direction.magnitude() != 0:
	    self.direction = self.direction.normalize()
	self.rect.center += self.direction * speed&lt;/pre&gt;
  &lt;p id=&quot;kDIB&quot;&gt;Теперь вторая проблема. Линк — танк. Он сбивает всё на своём пути. Нам нужны объекты и прописать столкновения с ними. Не забывайте, что все объекты у нас — квадраты тайлами.&lt;/p&gt;
  &lt;p id=&quot;F1ZM&quot;&gt;Сейчас у нас есть проблема — файл &lt;code&gt;player.py&lt;/code&gt; не знает о наличии тайлов, которые отображаются через файл уровня. Поэтому, дадим нашему файлу новый аргумент. Добавим его в &lt;code&gt;init&lt;/code&gt; и назовём &lt;code&gt;obstacle_sprites&lt;/code&gt;. Также, не забудьте в файле самого уровня сослаться на &lt;code&gt;obstacle_sprites&lt;/code&gt; в отрисовке точки игрока. Для этого в файле &lt;code&gt;level.py&lt;/code&gt; замените строку:&lt;/p&gt;
  &lt;pre id=&quot;2YWt&quot; data-lang=&quot;python&quot;&gt;self.player = Player((x, y), [self.visible_sprites])&lt;/pre&gt;
  &lt;p id=&quot;Clco&quot;&gt;На строку:&lt;/p&gt;
  &lt;pre id=&quot;JUCx&quot; data-lang=&quot;python&quot;&gt;self.player = Player((x, y), [self.visible_sprites], self.obstacle_sprites)&lt;/pre&gt;
  &lt;p id=&quot;tIhi&quot;&gt;В самом файле игрока, создадим метод столкновений под название &lt;code&gt;collision&lt;/code&gt;. Сама функция:&lt;/p&gt;
  &lt;pre id=&quot;ODwp&quot; data-lang=&quot;python&quot;&gt;def collision(self, direction):
	if direction == &amp;#x27;horizontal&amp;#x27;:
		for sprite in self.obstacle_sprites:
			if sprite.rect.colliderect(self.rect):
				if self.direction.x &amp;gt; 0: #двигаем вправо
					self.rect.right = sprite.rect.left
				if self.direction.x &amp;lt; 0: #двигаем влево
					self.rect.left = sprite.rect.right

	if direction == &amp;#x27;vertical&amp;#x27;:
		for sprite in self.obstacle_sprites:
			if sprite.rect.colliderect(self.rect):
				if self.direction.y &amp;gt; 0: #двигаем вниз
					self.rect.bottom = sprite.rect.top
				if self.direction.y &amp;lt; 0: #двигаем вверх
					self.rect.top = sprite.rect.bottom&lt;/pre&gt;
  &lt;p id=&quot;puPk&quot;&gt;В ней всё разделено на две координаты. По горизонтальной оси — x, по вертикальной — y. Если столкновение произошло по горизонтали, то делаем смещения (вправо или влево). Тоже самое по вертикали, но там вниз и вверх. Последний шаг — разделить метод в движении на два варианта: вертикальный и горизонтальный. То есть, из строки:&lt;/p&gt;
  &lt;pre id=&quot;nLEO&quot; data-lang=&quot;python&quot;&gt;self.rect.center += self.direction * speed&lt;/pre&gt;
  &lt;p id=&quot;n4GT&quot;&gt;Делаем структуру:&lt;/p&gt;
  &lt;pre id=&quot;KsoR&quot; data-lang=&quot;python&quot;&gt;self.rect.x += self.direction.x * speed
self.collision(&amp;#x27;horizontal&amp;#x27;)
self.rect.y += self.direction.y * speed
self.collision(&amp;#x27;vertical&amp;#x27;)&lt;/pre&gt;
  &lt;p id=&quot;dozo&quot;&gt;Получаем героя Хайрула без наклонностей в приведение:&lt;/p&gt;
  &lt;figure id=&quot;1D1E&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/webt/cu/zc/0x/cuzc0x6xo2sy39hccbimhczo4pm.gif&quot; width=&quot;600&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;XqFF&quot;&gt;Из предыдущей гифки видна следующая задача — создать камеру. Этим и займёмся. &lt;a href=&quot;https://disk.yandex.ru/d/mpG1VH3zri3ioA&quot; target=&quot;_blank&quot;&gt;Ссылка на этот этап&lt;/a&gt;.&lt;/p&gt;
  &lt;h3 id=&quot;Mzdc&quot;&gt;Создание камеры&lt;/h3&gt;
  &lt;p id=&quot;M5K2&quot;&gt;Создать камеру я предлагаю с учётом вектора направления движения персонажа. Мы будем двигать камеру вместе с персонажем. Переходим к файлу уровня и создаём новый класс.&lt;/p&gt;
  &lt;pre id=&quot;Ec9v&quot; data-lang=&quot;python&quot;&gt;class YSortCameraGroup(pygame.sprite.Group):
	def __init__(self):
		super().__init__()&lt;/pre&gt;
  &lt;p id=&quot;pT77&quot;&gt;По сути, всё что я сделал сейчас — создал новый класс пустой и с наследованием всего и вся. Далее, применяем его вместо &lt;code&gt;pygame.sprite.Group()&lt;/code&gt; в &lt;code&gt;visible_sprites&lt;/code&gt;, дабы не тавтологироваться, а ссылаться на класс с более тонкими настройками. Теперь к тонкостям:&lt;/p&gt;
  &lt;pre id=&quot;JZez&quot; data-lang=&quot;python&quot;&gt;class YSortCameraGroup(pygame.sprite.Group):
	def __init__(self):
		super().__init__()
		self.display_surface = pygame.display.get_surface()

	def custom_draw(self):
		for sprite in self.sprites():
			self.display_surface.blit(sprite.image, sprite.rect) #прорисуем новую поверхность и отрисуем её&lt;/pre&gt;
  &lt;p id=&quot;e8fl&quot;&gt;Тут я добавил тех же отображений новых поверхностей в главного демона с наследованием и создал метод ручной отрисовки (&lt;code&gt;custom_draw&lt;/code&gt;). Там самый интересный пункт в &lt;code&gt;display_surface.blit&lt;/code&gt;. Сам Surface создаёт новый слой объектов, а blit отрисовывет их. Далее мы передаём сами картинки и фигуры. Скоро и это перепишем, так как нам нужны векторы. Этим и займёмся. Сам вектор знаком вам по ходьбе Линка. Далее, снова улучшим класс:&lt;/p&gt;
  &lt;pre id=&quot;ujzx&quot; data-lang=&quot;python&quot;&gt;class YSortCameraGroup(pygame.sprite.Group):
	def __init__(self):
		super().__init__()
		self.display_surface = pygame.display.get_surface()
		self.offset = pygame.math.Vector2()

	def custom_draw(self):
		for sprite in self.sprites():
			offset_pos = sprite.rect.topleft + self.offset #определяем позицию путём сравнения верхнего левого угла с вектором направления
			self.display_surface.blit(sprite.image, offset_pos) #прорисуем новую поверхность и отрисуем её&lt;/pre&gt;
  &lt;p id=&quot;RukG&quot;&gt;Тут из нового только одна конструкция в самом методе. Она направлена на определение верхнего левого угла, отрисовку и последующую сумму с вектором направления. Далее, в run-методе, не забудьте поменять отрисовку с базовой на нашу кастомную. Примерно так:&lt;/p&gt;
  &lt;pre id=&quot;9v38&quot; data-lang=&quot;python&quot;&gt;self.visible_sprites.custom_draw()&lt;/pre&gt;
  &lt;p id=&quot;VIcU&quot;&gt;Если вы сделали всё верно, вставив в вектор 2 значения (x и y), вы увидите перемещение карты. Я поставил -150 и -150 и получил это:&lt;/p&gt;
  &lt;figure id=&quot;F8U1&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/ax/va/h8/axvah8xksnzlgt3mdg7c8x5c32q.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;waMk&quot;&gt;Собственно, осталось перемещаться зацепившись за героя. Его мы оставим по центру экрана (да здравствует эпохе Dendy). Наш код по доработке:&lt;/p&gt;
  &lt;pre id=&quot;b3cV&quot; data-lang=&quot;python&quot;&gt;class YSortCameraGroup(pygame.sprite.Group):
	def __init__(self):
		super().__init__()
		self.display_surface = pygame.display.get_surface()
		self.half_width = self.display_surface.get_size()[0] // 2 #середина отрисованного экрана по ширине
		self.half_heigth = self.display_surface.get_size()[1] // 2 #середина отрисованного экрана по высоте
		self.offset = pygame.math.Vector2()

	def custom_draw(self, player):
		self.offset.x = player.rect.centerx - self.half_width #координата x Линка
		self.offset.y = player.rect.centery - self.half_heigth #координата y Линка
		for sprite in self.sprites():
			offset_pos = sprite.rect.topleft - self.offset #определяем позицию путём сравнения верхнего левого угла с вектором направления
			self.display_surface.blit(sprite.image, offset_pos) #прорисуем новую поверхность и отрисуем её&lt;/pre&gt;
  &lt;p id=&quot;SmgW&quot;&gt;В базовых демонов мы добавили размеры экрана и центр экрана (нацело делим пополам). В нашу кастомную рисовалку передадим координаты игрока и по x, y офсетам высчитаем их. Чтобы избавиться от &amp;quot;пьяной камеры&amp;quot;, я вычитаю вектор направления, а не прибавляю его. Не забудьте run-методе передать &lt;code&gt;self.player&lt;/code&gt;. Результат:&lt;/p&gt;
  &lt;figure id=&quot;i0OE&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/webt/1o/vl/fv/1ovlfv9bsetj4happytfcnep80o.gif&quot; width=&quot;600&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;odDT&quot;&gt;Теперь нужно разобраться с хитбоксами. Сейчас, у нас графика из Денди, где каждый объект стоит по конкретным клеткам (тайлам). Нужно это исправить. Для начала, перейдем к настройкам тайла и допишем один демон-элемент:&lt;/p&gt;
  &lt;pre id=&quot;aIm8&quot; data-lang=&quot;python&quot;&gt;self.hitbox = self.rect.inflate(0, -10)&lt;/pre&gt;
  &lt;p id=&quot;wSCj&quot;&gt;Таким образом, мы уменьшили хитбокс на 10 пикселей. Так как отрисовка идёт из центра — мы уменьшаем хитбокс сверху и снизу на 5 пикселей. В демонах игрока пропишем тот же код, но уменьшим хитбокс на 26 пикселей. Далее, наша задача двигаться и проверять коллизии через хитбоксы. Для этого объекты с &lt;code&gt;rect.x&lt;/code&gt; заменим на &lt;code&gt;hitbox.x&lt;/code&gt;. Тогда move-функция выглядит так:&lt;/p&gt;
  &lt;pre id=&quot;uTz7&quot; data-lang=&quot;python&quot;&gt;def move(self, speed):
	if self.direction.magnitude() != 0:
		self.direction = self.direction.normalize()
	self.hitbox.x += self.direction.x * speed
	self.collision(&amp;#x27;horizontal&amp;#x27;)
	self.hitbox.y += self.direction.y * speed
	self.collision(&amp;#x27;vertical&amp;#x27;)
	self.rect.center = self.hitbox.center&lt;/pre&gt;
  &lt;p id=&quot;cNxV&quot;&gt;Также, починим коллизии:&lt;/p&gt;
  &lt;pre id=&quot;mhb5&quot; data-lang=&quot;python&quot;&gt;def collision(self, direction):
	if direction == &amp;#x27;horizontal&amp;#x27;:
		for sprite in self.obstacle_sprites:
			if sprite.hitbox.colliderect(self.hitbox):
				if self.direction.x &amp;gt; 0: #двигаем вправо
					self.hitbox.right = sprite.hitbox.left
				if self.direction.x &amp;lt; 0: #двигаем влево
					self.hitbox.left = sprite.hitbox.right

	if direction == &amp;#x27;vertical&amp;#x27;:
		for sprite in self.obstacle_sprites:
			if sprite.hitbox.colliderect(self.hitbox):
				if self.direction.y &amp;gt; 0: #двигаем вниз
					self.hitbox.bottom = sprite.hitbox.top
				if self.direction.y &amp;lt; 0: #двигаем вверх
					self.hitbox.top = sprite.hitbox.bottom&lt;/pre&gt;
  &lt;p id=&quot;IQQj&quot;&gt;Результат:&lt;/p&gt;
  &lt;figure id=&quot;sPmS&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/webt/a8/og/um/a8ogumbvu9eyuwtraeiu6gegrjq.gif&quot; width=&quot;600&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;aMP2&quot;&gt;Линку отрывает шапку. Это происходит из-за того, что изображения рандомно находятся на поверхности. Какие-то выше, какие-то ниже. Нужно это исправить. Исправим это через класс YSort (не просто же так мы мы назвали класс YSortCameraGroup). Поправим только одну строку:&lt;/p&gt;
  &lt;pre id=&quot;Y5AD&quot; data-lang=&quot;python&quot;&gt;for sprite in self.sprites():&lt;/pre&gt;
  &lt;p id=&quot;ajSH&quot;&gt;На строку:&lt;/p&gt;
  &lt;pre id=&quot;ry9h&quot; data-lang=&quot;python&quot;&gt;for sprite in sorted(self.sprites(), key = lambda sprite: sprite.rect.centery):&lt;/pre&gt;
  &lt;p id=&quot;CHUU&quot;&gt;По сути, мы просто сделали сортировку по y-координате. Про лямбду можно отдельно &lt;a href=&quot;https://habr.com/ru/companies/piter/articles/674234/&quot; target=&quot;_blank&quot;&gt;почитать&lt;/a&gt;, но если сказать грубо — лямбда-функция — функция, которая работает в с анонимными функциями.&lt;/p&gt;
  &lt;p id=&quot;fQIa&quot;&gt;Итог:&lt;/p&gt;
  &lt;figure id=&quot;bgTV&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/ns/ll/7j/nsll7jsj49uhu6edhvwepn_lau0.png&quot; width=&quot;1187&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;NBEz&quot;&gt;&lt;a href=&quot;https://disk.yandex.ru/d/yQ82HKzPyOlTMw&quot; target=&quot;_blank&quot;&gt;Ссылка на этап проекта&lt;/a&gt;.&lt;/p&gt;
  &lt;h3 id=&quot;12uA&quot;&gt;Графика&lt;/h3&gt;
  &lt;p id=&quot;Vxh5&quot;&gt;Тут мне пришлось освоить для себя новую прогу. Она была очень дружелюбной и со второго раза, я смог нарисовать поле игры. Программа называется &lt;a href=&quot;https://www.mapeditor.org/&quot; target=&quot;_blank&quot;&gt;Tiled&lt;/a&gt;. В ней можно с лёгкости настраивать карты. Сразу оговорюсь, что это мой первый опыт работы с картами. Это сыграло со мной злую шутку. Дважды.&lt;/p&gt;
  &lt;p id=&quot;MBrj&quot;&gt;Чуть ранее я писал про проблемы с ассетами. Дело в том, что я выбрал размер тайла 64 пикселя. Это стандартное разрешение для игр в ряд, но я не учёл один момент — все ассеты, которые были у Ninja Adventure были в разрешении 16 на 16 пикселей. Это нормально для пиксельной графики. В общем, была задача поправить это расхождение. Поправка была простой — я увеличил размер нужных мне тайлов в 4 раза в фотошопе. В итоге, получилось из этого:&lt;/p&gt;
  &lt;figure id=&quot;DLya&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/n7/dx/g0/n7dxg0sqovm7qjtxmwfcmllmslw.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;90Yv&quot;&gt;Сделать это:&lt;/p&gt;
  &lt;figure id=&quot;QqFY&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/yn/ed/x_/ynedx_aereay58ujsm6-qi2f2pm.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;RAUM&quot;&gt;Для отрисовки самой карты, я взял 3 файла (TilesetFloor.png, TilesetFloorDetails.png и TilesetWater.png):&lt;/p&gt;
  &lt;figure id=&quot;NnE5&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/uv/j_/ry/uvj_rylxktzbe0rfsbuzrgyvzq0.png&quot; width=&quot;1381&quot; /&gt;
  &lt;/figure&gt;
  &lt;blockquote id=&quot;WpwF&quot;&gt;&lt;strong&gt;Что-то типа ворнинга&lt;/strong&gt;. Тут будьте осторожны. Мне пришлось перерисовать карту и сделать из разных картинок с тайлами одну. Не повторяйте моих ошибок и сначала прочитайте что происходит ниже в разделе &amp;quot;Монстры&amp;quot;.&lt;/blockquote&gt;
  &lt;p id=&quot;nBwr&quot;&gt;Помимо прочего, я создал зелёный квадрат 64 на 64 и красный такой же с прозрачностью в 20%, чтобы поставить точку спауна Линка и невидимые стены для него. Приступим к отрисовки карты.&lt;/p&gt;
  &lt;p id=&quot;J5sH&quot;&gt;Открываем Tiled и я выставил следующие настройки. Ортогональная карта лежит в координатах x и y, что нам и подходит. Слой будет выводиться в формате CSV и отрисовываться справа снизу. Размеры карты будут 80 на 60 тайлов, а это значит 80 на 64 = 5120 и 60 на 64 = 3840 пикселей.&lt;/p&gt;
  &lt;figure id=&quot;hd02&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/5z/kr/dh/5zkrdhqj5afln9a-ct1y-agpems.png&quot; width=&quot;594&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;lC2D&quot;&gt;Создав карту, получим своё рабочее поле и приступим к рисованию:&lt;/p&gt;
  &lt;figure id=&quot;a2QH&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/rx/ii/s2/rxiis2ufyukuxp3biikv5t80qzi.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;VPg2&quot;&gt;Час работы и результат:&lt;/p&gt;
  &lt;figure id=&quot;HMuN&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/pa/cx/qd/pacxqd-6ulljrztjabn2lqzwcde.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;J3dI&quot;&gt;Сейчас работа очень грубая. Нужно добавить деталей. Займёмся этим. Вот что получилось спустя минут 20:&lt;/p&gt;
  &lt;figure id=&quot;bg7S&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/qz/l1/ws/qzl1ws40mjt3x8cnwfrv_y5jxyq.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;zeB8&quot;&gt;Далее, я добавил тайлы-блоки, чтобы за них Линк не выбрался (куда ж без невидимых стен). Главное — все поля должны быть замкнуты, чтобы Линк внезапно не залетал. У меня получилось как-то так:&lt;/p&gt;
  &lt;figure id=&quot;aHu4&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/2c/60/gg/2c60ggttvct771gj8hn1r_fs0js.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;3YF6&quot;&gt;Потом я выключил данный слой, чтобы он не отвлекал. Далее, проставим места спауна врагов (бебов) и ГГ (Линка):&lt;/p&gt;
  &lt;figure id=&quot;vqNx&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/w_/kp/vm/w_kpvmg-n4zcalfx9zmkzdhjgru.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;88xT&quot;&gt;Добавим пару объектов:&lt;/p&gt;
  &lt;figure id=&quot;lShJ&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/hv/sd/gg/hvsdgggeq6l11hoibdj9fgkn5d0.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;wMsC&quot;&gt;Конечно, карта может быть детальнее проработана, ну да это не моя задача. Моя задача — проверить как там игродев на змейке.&lt;/p&gt;
  &lt;p id=&quot;7rkG&quot;&gt;Всю графику я перенёс в папку graphic, а также выгрузил карту в &lt;code&gt;.csv&lt;/code&gt;-формате в папку map.&lt;/p&gt;
  &lt;p id=&quot;v53C&quot;&gt;Приступим к коду. Для начала, я скинул в папку Test нашего Линка и коробку и поправил пути в проекте в файлах &lt;code&gt;player.py&lt;/code&gt; и &lt;code&gt;title.py&lt;/code&gt;. После запуска ничего не поменялось. Далее, я решил положить подложкой на чёрный экран нашу карту. Я просто экспортировал картинку без спауна и дополнительных объектов и установил её выше чёрного экрана, но ниже Линка с коробками. Для этого в файле &lt;code&gt;level.py&lt;/code&gt; я для начала объявил о наличии таких файлов двумя строками кода в демонах класса &lt;code&gt;YSortCameraGroup&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;2gYH&quot; data-lang=&quot;python&quot;&gt;self.floor_surf = pygame.image.load(&amp;#x27;../graphic/map+det.png&amp;#x27;).convert() #добавили задник карты
self.floor_rect = self.floor_surf.get_rect(topleft = (0, 0)) #отрисовка карты с левого верхнего угла&lt;/pre&gt;
  &lt;p id=&quot;StW6&quot;&gt;Далее в методе &lt;code&gt;custom_draw&lt;/code&gt; вычисляем отрисовку с офсетами для камерами (всё ровно также, как и ранее):&lt;/p&gt;
  &lt;pre id=&quot;el3u&quot; data-lang=&quot;python&quot;&gt;floor_offset_pos = self.floor_rect.topleft - self.offset
self.display_surface.blit(self.floor_surf, floor_offset_pos)&lt;/pre&gt;
  &lt;p id=&quot;Kbnn&quot;&gt;Результат:&lt;/p&gt;
  &lt;figure id=&quot;lU04&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/webt/p-/nv/wp/p-nvwpzivcfjtrzrmac6uexh46k.gif&quot; width=&quot;600&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;UWnR&quot;&gt;Происходит наслоение старой карты и новой. Исправим этою Удалим всё в методе &lt;code&gt;create_map&lt;/code&gt; в &lt;code&gt;level.py&lt;/code&gt;. Немного переписав метод, я привёл его к следующему виду:&lt;/p&gt;
  &lt;pre id=&quot;cgEb&quot; data-lang=&quot;python&quot;&gt;def create_map(self):
	self.player = Player((1000, 1000), [self.visible_sprites], self.obstacle_sprites)&lt;/pre&gt;
  &lt;p id=&quot;lPYn&quot;&gt;Всё что я оставил — это отрисовку места Линка на карте. Просто указал координату.&lt;/p&gt;
  &lt;figure id=&quot;nmKc&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/m9/un/o8/m9uno82jupl3b2zj2jcmckewahu.png&quot; width=&quot;912&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;z7Md&quot;&gt;Теперь наша задача провзаимодействовать с файлом &lt;code&gt;tile.py&lt;/code&gt; эму нужны настройки более детальные для прорисовки объектов и картинок конкретного размера. Приступим.&lt;/p&gt;
  &lt;p id=&quot;rg21&quot;&gt;Для начала, помимо прочих элементов, демонам нужно передавать новые два аргумента &lt;code&gt;sprite_type&lt;/code&gt; и &lt;code&gt;surface = pygame.Surface((TILESIZE, TILESIZE))&lt;/code&gt;. Думаю, по названия понятно, что они будут передавать сам тип спрайта и его размер из файла &lt;code&gt;settings.py&lt;/code&gt;. Ещё немного переработаем файл и получим упрощение конструкции с ссылкой на себя:&lt;/p&gt;
  &lt;pre id=&quot;9ihH&quot; data-lang=&quot;python&quot;&gt;import pygame
from settings import *

class Tile(pygame.sprite.Sprite):
	def __init__(self, pos, groups, sprite_type, surface = pygame.Surface((TILESIZE, TILESIZE))):
		super().__init__(groups) #наследуем все группы
		self.sprite_type = sprite_type
		self.image = surface
		self.rect = self.image.get_rect(topleft = pos) #указываем позицию отрисовки (левый верхний угол)
		self.hitbox = self.rect.inflate(0, -10) #делаем по 5 пискселей сверху и снизу от самого объекта, до хитбокса&lt;/pre&gt;
  &lt;p id=&quot;nHXR&quot;&gt;Вернёмся в &lt;code&gt;creat_map&lt;/code&gt;. Создадим новый словарь на основе csv-файлов:&lt;/p&gt;
  &lt;pre id=&quot;Czbx&quot; data-lang=&quot;python&quot;&gt;layout = {
		&amp;#x27;boundary&amp;#x27;: import_csv_layout(&amp;#x27;../map/map_Block.csv&amp;#x27;)
}&lt;/pre&gt;
  &lt;p id=&quot;5mAe&quot;&gt;Метод &lt;code&gt;import_csv_layout&lt;/code&gt; нам не знаком. Напишем его в новой файле &lt;code&gt;support.py&lt;/code&gt;.&lt;/p&gt;
  &lt;pre id=&quot;X1GL&quot; data-lang=&quot;python&quot;&gt;from csv import reader

def import_csv_layout(path):
	with open(path) as level_map:
		layout = reader(level_map, delimiter = &amp;#x27;,&amp;#x27;)
		for row in layout:
			print(row)

import_csv_layout(&amp;#x27;../map/map_Block.csv&amp;#x27;)&lt;/pre&gt;
  &lt;p id=&quot;C1aZ&quot;&gt;В данном коде идёт чтение csv-файла. А при чтении &amp;quot;1&amp;quot; — означает, что объект там есть, а &amp;quot;-1&amp;quot; — его там нет.&lt;/p&gt;
  &lt;p id=&quot;wLDk&quot;&gt;Результат вывода &lt;code&gt;support.py&lt;/code&gt;:&lt;/p&gt;
  &lt;figure id=&quot;r1Ad&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/3n/in/aa/3ninaaaabhjj56tkz55he6z7m5a.png&quot; width=&quot;1494&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Zlhu&quot;&gt;Чуть подправим, чтобы у нас на выходе была матрица (массив из выведенных строк) и функция готова:&lt;/p&gt;
  &lt;pre id=&quot;SWjD&quot; data-lang=&quot;python&quot;&gt;from csv import reader

def import_csv_layout(path):
	terrain_map = []
	with open(path) as level_map:
		layout = reader(level_map, delimiter = &amp;#x27;,&amp;#x27;)
		for row in layout:
			terrain_map.append(list(row))
		return terrain_map&lt;/pre&gt;
  &lt;p id=&quot;35a5&quot;&gt;Теперь, вернёмся к &lt;code&gt;creat_map&lt;/code&gt; и допишем функцию очень похожую на то, что было ранее (не забудьте импортировать support):&lt;/p&gt;
  &lt;pre id=&quot;jdSk&quot; data-lang=&quot;python&quot;&gt;def create_map(self):
	layout = {
			&amp;#x27;boundary&amp;#x27;: import_csv_layout(&amp;#x27;../map/map_Block.csv&amp;#x27;)
	}
	for style, layout in layout.items():
		for row_index, row in enumerate(layout):
			for col_index, col in enumerate(row):
				if col != &amp;#x27;-1&amp;#x27;:
					x = col_index * TILESIZE
					y = row_index * TILESIZE
					if style == &amp;#x27;boundary&amp;#x27;:
						Tile((x, y), [self.visible_sprites, self.obstacle_sprites], &amp;#x27;invisible&amp;#x27;)
	self.player = Player((1000, 1000), [self.visible_sprites], self.obstacle_sprites)&lt;/pre&gt;
  &lt;p id=&quot;oMuP&quot;&gt;Итог:&lt;/p&gt;
  &lt;figure id=&quot;r6J3&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/fq/cm/ew/fqcmewdiiqdrzhdd99epy1-kgwi.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ELQM&quot;&gt;Чёрные края — это невидимые стены. Осталось их только сделать невидимыми. Удалим &lt;code&gt;self.visible_sprites&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;ZJDf&quot;&gt;Создадим ещё один вариант стиля — &lt;code&gt;objects&lt;/code&gt;. Тут нам потребуется сразу несколько картинок. Чтобы не перебирать их вручную в &lt;code&gt;support.py&lt;/code&gt; создадим новый метод поиска картинок при помощи знакомым многим функции walk:&lt;/p&gt;
  &lt;pre id=&quot;Abz1&quot; data-lang=&quot;python&quot;&gt;def import_folder(path):
	for _, __, img_files in walk(path):
		for image in img_files:
			full_path = path + &amp;#x27;/&amp;#x27; + image
			print(full_path)&lt;/pre&gt;
  &lt;p id=&quot;f6s5&quot;&gt;Получим вывод:&lt;/p&gt;
  &lt;figure id=&quot;LIXS&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/nr/5i/zt/nr5iztoplq3uepre60axndgtsrq.png&quot; width=&quot;1494&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;MlVY&quot;&gt;Немного перепишем метод под pygame:&lt;/p&gt;
  &lt;pre id=&quot;IexW&quot; data-lang=&quot;python&quot;&gt;def import_folder(path):
	surface_list = []
	for _, __, img_files in walk(path):
		for image in img_files:
			full_path = path + &amp;#x27;/&amp;#x27; + image
			image_surf = pygame.image.load(full_path).convert_alpha()
			surface_list.append(image_surf)
	return surface_list&lt;/pre&gt;
  &lt;p id=&quot;y5QI&quot;&gt;Сам метод отрисовки объектов:&lt;/p&gt;
  &lt;pre id=&quot;kFgO&quot; data-lang=&quot;python&quot;&gt;if style == &amp;#x27;objects&amp;#x27;:
	surf = graphics[&amp;#x27;objects&amp;#x27;][int(col)]
	Tile((x, y), [self.visible_sprites, self.obstacle_sprites], &amp;#x27;object&amp;#x27;, surf)&lt;/pre&gt;
  &lt;p id=&quot;l5aP&quot;&gt;Тут мы просто перебором по всем файлам выставляем объекты. Есть только одна проблема. Если объекты были друг за другом — они рандомно ставятся. Нужно это исправить. Исправим это в &lt;code&gt;tile.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;GqXF&quot; data-lang=&quot;python&quot;&gt;if sprite_type == &amp;#x27;object&amp;#x27;:
	self.rect = self.image.get_rect(topleft = (pos[0], pos[1] - TILESIZE))
else:
	self.rect = self.image.get_rect(topleft = pos) #указываем позицию отрисовки (левый верхний угол)&lt;/pre&gt;
  &lt;p id=&quot;2eP8&quot;&gt;В этом моменте мы отключили перекрытие объектом других объектов. Итого, Линк гуляет в лесу!&lt;/p&gt;
  &lt;p id=&quot;2S8d&quot;&gt;&lt;a href=&quot;https://disk.yandex.ru/d/eKerCcYDe7tTqA&quot; target=&quot;_blank&quot;&gt;Результат работы по ссылке&lt;/a&gt;. Помимо прочего, я оставил проект в Tiled, чтобы вы сами могли &amp;quot;поиграться&amp;quot; с ним. Далее, мы поговорим об анимации.&lt;/p&gt;
  &lt;h3 id=&quot;qRms&quot;&gt;Анимация Линка&lt;/h3&gt;
  &lt;p id=&quot;GYqh&quot;&gt;Для начала, нужно добавить действие и кнопку. На атаку будет стоять кнопка &amp;quot;Пробел&amp;quot;. Пропишем это в &lt;code&gt;player.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;6kLn&quot; data-lang=&quot;python&quot;&gt;if keys[pygame.K_SPACE] and not self.attacking:
	self.attacking = True&lt;/pre&gt;
  &lt;p id=&quot;RCWV&quot;&gt;Тут непонятно что такое &lt;code&gt;self.attacking&lt;/code&gt;. В демоны файла я добавил три параметра: статус атаки (&lt;code&gt;self.attacking = False&lt;/code&gt;), кулдаун после атаки (&lt;code&gt;self.attack_cooldown = 400&lt;/code&gt;) и время атаки (&lt;code&gt;self.attack_time = None&lt;/code&gt;).&lt;/p&gt;
  &lt;p id=&quot;gkic&quot;&gt;Добавим время между атаками. Для этого, после успешной атаки, создадим конструкцию: &lt;code&gt;self.attack_time = pygame.time.get_ticks()&lt;/code&gt; сразу после объявление атаки флагом &lt;code&gt;True&lt;/code&gt;. Далее, перейдём к настройке нового метода &lt;code&gt;cooldowns&lt;/code&gt;. Сам метод:&lt;/p&gt;
  &lt;pre id=&quot;ECoh&quot; data-lang=&quot;python&quot;&gt;def cooldowns(self):
	current_time = pygame.time.get_ticks()

	if self.attacking:
		if current_time - self.attack_time &amp;gt;= self.attack_cooldown:
			self.attacking = False&lt;/pre&gt;
  &lt;p id=&quot;8xf1&quot;&gt;На самом деле конструкция очень проста. Если разница во времени после нажатия меньше кулдауна атаки (в моём случае 400 мс), запрещать атаку. Не забудьте закинуть функцию cooldowns в update-функцию.&lt;/p&gt;
  &lt;p id=&quot;9Ygf&quot;&gt;Далее, пропишем метод &lt;code&gt;import_player_assets&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;t05Y&quot; data-lang=&quot;python&quot;&gt;def import_player_assets(self):
	character_path = &amp;#x27;../graphic/Link/&amp;#x27;
	self.animations = {&amp;#x27;up&amp;#x27;: [], &amp;#x27;down&amp;#x27;: [], &amp;#x27;left&amp;#x27;: [], &amp;#x27;right&amp;#x27;: [],
	&amp;#x27;right_idle&amp;#x27;: [], &amp;#x27;left_idle&amp;#x27;: [], &amp;#x27;up_idle&amp;#x27;: [], &amp;#x27;down_idle&amp;#x27;: [],
	&amp;#x27;right_attack&amp;#x27;: [], &amp;#x27;left_attack&amp;#x27;: [], &amp;#x27;up_attack&amp;#x27;: [], &amp;#x27;down_attack&amp;#x27;: []}&lt;/pre&gt;
  &lt;p id=&quot;NFRz&quot;&gt;В нём прописаны все возможности передвижения. Они лежат в папке &amp;quot;Link&amp;quot;:&lt;/p&gt;
  &lt;figure id=&quot;rtpg&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/dv/bz/7r/dvbz7r9mulkwm_hifbrckujnmre.png&quot; width=&quot;1381&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;N9Ud&quot;&gt;Не забудьте закинуть в базовых демонов Player-класса наши ассеты: &lt;code&gt;self.import_player_assets()&lt;/code&gt;. Далее, &amp;quot;пробежимся&amp;quot; по нашим папкам благодаря методу &lt;code&gt;import_folder&lt;/code&gt; в &lt;code&gt;support.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;nFXO&quot; data-lang=&quot;python&quot;&gt;for animation in self.animations.keys():
	full_path = character_path + animation
	self.animations[animation] = import_folder(full_path)&lt;/pre&gt;
  &lt;p id=&quot;0UKH&quot;&gt;Теперь мы модем открыть все файлы, но есть дополнительная проблема — нужно прописать статусы и анимации при нажатии на кнопку. Статус по умолчанию укажем в демоне и по умолчанию Линк будет смотреть вниз (&lt;code&gt;self.status = &amp;#x27;down&amp;#x27;&lt;/code&gt;). Но этого мало. Нужно получать статус автоматически, а это значит новый метод:&lt;/p&gt;
  &lt;pre id=&quot;1tjJ&quot; data-lang=&quot;python&quot;&gt;def get_status(self):
	if self.direction.x == 0 and self.direction.y == 0:
		self.status = self.status + &amp;#x27;_idle&amp;#x27;&lt;/pre&gt;
  &lt;p id=&quot;FJ1f&quot;&gt;Тут мы прописываем название файла &amp;quot;стояния&amp;quot; героя. Стояние — &lt;code&gt;_idle&lt;/code&gt;, а статус будет меняться от нажатия кнопок. Закидываем &lt;code&gt;get_status()&lt;/code&gt; в update-метод.&lt;/p&gt;
  &lt;p id=&quot;b0U1&quot;&gt;Далее, пропишем статусы для наших методов хождения:&lt;/p&gt;
  &lt;pre id=&quot;OY27&quot; data-lang=&quot;python&quot;&gt;if keys[pygame.K_UP]:
	self.direction.y = -1
	self.status = &amp;#x27;up&amp;#x27;
elif keys[pygame.K_DOWN]:
	self.direction.y = 1
	self.status = &amp;#x27;down&amp;#x27;
else:
	self.direction.y = 0

if keys[pygame.K_LEFT]:
	self.direction.x = -1
	self.status = &amp;#x27;left&amp;#x27;
elif keys[pygame.K_RIGHT]:
	self.direction.x = 1
	self.status = &amp;#x27;right&amp;#x27;&lt;/pre&gt;
  &lt;p id=&quot;hYTF&quot;&gt;Тут всё достаточно прозрачно. Движение = статусу. Подправим функцию статуса:&lt;/p&gt;
  &lt;pre id=&quot;cLzF&quot; data-lang=&quot;python&quot;&gt;if not &amp;#x27;idle&amp;#x27; in self.status:
	self.status = self.status + &amp;#x27;_idle&amp;#x27;&lt;/pre&gt;
  &lt;p id=&quot;P6Cv&quot;&gt;Теперь, если мы отпускаем кнопку — статус равен idle, а если держим просто название направления.&lt;/p&gt;
  &lt;p id=&quot;VFCb&quot;&gt;Теперь окончательно проапгрейдим код для атак и комбинаций с &amp;quot;_idle&amp;quot;:&lt;/p&gt;
  &lt;pre id=&quot;Mpsh&quot; data-lang=&quot;python&quot;&gt;def get_status(self):
	if self.direction.x == 0 and self.direction.y == 0:
		if not &amp;#x27;idle&amp;#x27; in self.status and not &amp;#x27;attack&amp;#x27; in self.status:
			self.status = self.status + &amp;#x27;_idle&amp;#x27;
	if self.attacking:
		self.direction.x = 0 #координаты по x
		self.direction.y = 0 #координаты по y
		if not &amp;#x27;attack&amp;#x27; in self.status: #если нет подписи &amp;quot;attack&amp;quot;
			if &amp;#x27;idle&amp;#x27; in self.status: #но есть &amp;quot;idle&amp;quot;
				self.status = self.status.replace(&amp;#x27;_idle&amp;#x27;, &amp;#x27;_attack&amp;#x27;) #убираем _idle, но оставляем _attack
			else:
				self.status = self.status + &amp;#x27;_attack&amp;#x27; #если idle не было, просто стави attack
	else:
		if &amp;#x27;attack&amp;#x27; in self.status:
			self.status = self.status.replace(&amp;#x27;_attack&amp;#x27;, &amp;#x27;&amp;#x27;) #удаляем attack при завершении статуса&lt;/pre&gt;
  &lt;p id=&quot;h3wC&quot;&gt;Наконец, заанимируем Линка. Установим два новых демона &lt;code&gt;self.frame_index = 0&lt;/code&gt; — индекс первой картинки и скорость смены картинок — &lt;code&gt;self.animation_speed = 0.15&lt;/code&gt;. Далее, создадим метод &lt;code&gt;animate()&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;mBDR&quot; data-lang=&quot;python&quot;&gt;def animate(self):
	animation = self.animations[self.status] #узнаём статус для ссылки на нужный файл
	self.frame_index += self.animation_speed #добовляем нашу скорость и когда добавится единица (из 0.15), сменяем картинку
	if self.frame_index &amp;gt;= len(animation): #при вылете из массива
		self.frame_index = 0 #возвращаемся к начальной картинке и тем самым зацикливаемся
	self.image = animation[int(self.frame_index)] #указываем картику
	self.rect = self.image.get_rect(center = self.hitbox.center) #указываем хитбокс&lt;/pre&gt;
  &lt;p id=&quot;NTe8&quot;&gt;Всё что тут происходит, мы перебираем все наши картинки и главное — их зациклить, как в рилсах. Не забываем в update-функцию &lt;code&gt;self.animate()&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;dXDh&quot;&gt;Тут у меня залогала анимация атаки, так как кнопка продолжала нажиматься. Исправим это в input-методе:&lt;/p&gt;
  &lt;pre id=&quot;Rb37&quot; data-lang=&quot;python&quot;&gt;def input(self): #варьируем кнопки
	if not self.attacking:
		keys = pygame.key.get_pressed()

		if keys[pygame.K_UP]:
			self.direction.y = -1
			self.status = &amp;#x27;up&amp;#x27;
		elif keys[pygame.K_DOWN]:
			self.direction.y = 1
			self.status = &amp;#x27;down&amp;#x27;
		else:
			self.direction.y = 0

		if keys[pygame.K_LEFT]:
			self.direction.x = -1
			self.status = &amp;#x27;left&amp;#x27;
		elif keys[pygame.K_RIGHT]:
			self.direction.x = 1
			self.status = &amp;#x27;right&amp;#x27;
		else:
			self.direction.x = 0

		if keys[pygame.K_SPACE]:
			self.attacking = True
			self.attack_time = pygame.time.get_ticks()&lt;/pre&gt;
  &lt;p id=&quot;zSG5&quot;&gt;Итог:&lt;/p&gt;
  &lt;figure id=&quot;95Pl&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/webt/mm/r7/pw/mmr7pwjcipk6fzlcmnanaclguye.gif&quot; width=&quot;600&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;yEFB&quot;&gt;Далее, прорисуем оружие. &lt;a href=&quot;https://disk.yandex.ru/d/VVjRMFfvxHqLHg&quot; target=&quot;_blank&quot;&gt;Файлы этого этапа&lt;/a&gt;.&lt;/p&gt;
  &lt;h3 id=&quot;nWXi&quot;&gt;Оружие героя&lt;/h3&gt;
  &lt;p id=&quot;4dmy&quot;&gt;Тут я немного поменял карту, так как Линк врезался в мосты, которые соединяют нижние острова. Изменения делала непосредственно в Tiles и сохранял карту и csv-файлы. Чтобы всё было канонично, Линку выдадим меч. Спрайты на мечи я тоже отрисовал. Он лежит в папке weapons/sword. Там 5 картинок, где full обозначает сам меч, а остальные 4 — направления меча. Приступим к коду.&lt;/p&gt;
  &lt;p id=&quot;R7c7&quot;&gt;В файле &lt;a href=&quot;http://setting.py/&quot; target=&quot;_blank&quot;&gt;setting.py&lt;/a&gt;, я создал словарь из оружий. У меня будет только один меч, но вы можете добавить больше оружия. Сам словарь:&lt;/p&gt;
  &lt;pre id=&quot;nA9S&quot; data-lang=&quot;python&quot;&gt;weapon_data = {&amp;#x27;sword&amp;#x27;: {&amp;#x27;cooldown&amp;#x27;: 300, &amp;#x27;damage&amp;#x27;: 15, &amp;#x27;graphic&amp;#x27;:&amp;#x27;../graphic/weapons/sword/full.png&amp;#x27;}}&lt;/pre&gt;
  &lt;p id=&quot;8vL0&quot;&gt;Далее, создадим новый файл с настойкой оружия &lt;code&gt;weapon.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;9ndr&quot; data-lang=&quot;python&quot;&gt;import pygame

class Weapon(pygame.sprite.Sprite):
	def __init__(self, player, groups):
		super().__init__(groups)
		self.image = pygame.Surface((40, 40)) #сама графика
		self.rect = self.image.get_rect(center = player.rect.center) #место отрисовки&lt;/pre&gt;
  &lt;p id=&quot;OPKa&quot;&gt;Тут всё традиционно и без нового. Мы центруемся от самого игрока последней строкой в коде. Сейчас посередине будет рисоваться чёрный квадрат 40 на 40 пикселей. Импортируем новый файл в Level и создаём новый метод &lt;code&gt;create_attack&lt;/code&gt;.&lt;/p&gt;
  &lt;pre id=&quot;6BXe&quot; data-lang=&quot;python&quot;&gt;def create_attack(self):
	Weapon(self.player, [self.visible_sprites])	&lt;/pre&gt;
  &lt;p id=&quot;wE7c&quot;&gt;Далее, в самой отрисовке игрока, добавим наш метод как ссылку на него:&lt;/p&gt;
  &lt;pre id=&quot;64L8&quot; data-lang=&quot;python&quot;&gt;self.player = Player((1000, 1000), [self.visible_sprites], self.obstacle_sprites, self.create_attack)&lt;/pre&gt;
  &lt;p id=&quot;0yIZ&quot;&gt;Далее, перейдём в файл &lt;a href=&quot;http://player.py/&quot; target=&quot;_blank&quot;&gt;player.py&lt;/a&gt; и там передадим create_attack и создадим демона. Также, при нажатии на пробел, добавим метод &lt;code&gt;self.create_attak()&lt;/code&gt;. Теперь можем вернуться к отрисовке нашего оружия:&lt;/p&gt;
  &lt;pre id=&quot;seAf&quot; data-lang=&quot;python&quot;&gt;import pygame

class Weapon(pygame.sprite.Sprite):
	def __init__(self, player, groups):
		super().__init__(groups)
		direction = player.status.split(&amp;#x27;_&amp;#x27;)[0] #обрезаем строку по &amp;quot;_&amp;quot; чтобы понимать куда он смотрит
		full_path = f&amp;#x27;../graphic/weapons/{player.weapon}/{direction}.png&amp;#x27; #адрес оружия
		self.image = pygame.image.load(full_path).convert_alpha() #сама графика
		if direction == &amp;#x27;right&amp;#x27;:
			self.rect = self.image.get_rect(midleft = player.rect.midright + pygame.math.Vector2(-10, 16))
		elif direction == &amp;#x27;left&amp;#x27;:
			self.rect = self.image.get_rect(midright = player.rect.midleft + pygame.math.Vector2(10, 16))
		elif direction == &amp;#x27;down&amp;#x27;:
			self.rect = self.image.get_rect(midtop = player.rect.midbottom + pygame.math.Vector2(-15, 0))
		else:
			self.rect = self.image.get_rect(midbottom = player.rect.midtop + pygame.math.Vector2(-15, 0))&lt;/pre&gt;
  &lt;p id=&quot;5ePy&quot;&gt;Тут появилось несколько интересного. Во-первых, мы обрезаем строку по &amp;quot;_&amp;quot; чтобы понять куда смотрит герой (неважно с &amp;quot;attack&amp;quot; или без). Далее, отрисовка. Нам нужно чтобы меч рисовался в руке у Линка. Я выбрал следующий метод, если меч слева, то &amp;quot;приклеиться&amp;quot; он должен справа от Линка, то есть &lt;code&gt;midleft = player.rect.midright + pygame.math.Vector2(-10, 16)&lt;/code&gt;. Далее, плюсуем вектор направления чтобы меч был ровно в руке. Далее, всё повторяется в зависимости от направления.&lt;/p&gt;
  &lt;p id=&quot;6h9Q&quot;&gt;Добавим в &lt;a href=&quot;http://player.py/&quot; target=&quot;_blank&quot;&gt;player.py&lt;/a&gt; новых демонов:&lt;/p&gt;
  &lt;pre id=&quot;Yu5A&quot; data-lang=&quot;python&quot;&gt;self.create_attak = create_attak #создали атаку
self.weapon_index = 0 #номер оружия (если у вас будет несколько орудий пыток монстров)
self.weapon = list(weapon_data.keys())[self.weapon_index] #выбрали конкретное оружие и все его параметры= None&lt;/pre&gt;
  &lt;p id=&quot;VA8X&quot;&gt;Теперь есть меч, но есть проблема. Мечи не исчезают:&lt;/p&gt;
  &lt;figure id=&quot;EF5B&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/-q/pj/7k/-qpj7kfcf-hjzxg_qyjvekzbeye.png&quot; width=&quot;487&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;AK90&quot;&gt;Что ж, создадим новый метод в &lt;code&gt;level.py&lt;/code&gt;: &lt;code&gt;destroy_weapon&lt;/code&gt;. Помимо прочего, нужно немного переработать код в самом &lt;code&gt;level.py&lt;/code&gt;. Создадим нового демона &lt;code&gt;self.current_attack = None&lt;/code&gt;, а также переработаем метод &lt;code&gt;create_attack&lt;/code&gt;.&lt;/p&gt;
  &lt;pre id=&quot;QNKu&quot; data-lang=&quot;python&quot;&gt;def create_attack(self):
	self.current_attack = Weapon(self.player, [self.visible_sprites])	

def destroy_weapon(self):
	if self.current_attack:
		self.current_attack.kill()
	self.current_attack = None&lt;/pre&gt;
  &lt;p id=&quot;8Wsf&quot;&gt;Таким образом, при наличии атаки, мы убиваем процесс и обнуляем указатель атаки (&lt;code&gt;current_attak&lt;/code&gt;). Нужен ещё кулдаун. Также, не забудьте сослаться на &lt;code&gt;self.destroy_weapon&lt;/code&gt; в player:&lt;/p&gt;
  &lt;pre id=&quot;epSb&quot; data-lang=&quot;python&quot;&gt;self.player = Player((1000, 1000), [self.visible_sprites], self.obstacle_sprites, self.create_attack, self.destroy_weapon)&lt;/pre&gt;
  &lt;p id=&quot;BGXL&quot;&gt;Далее пропишем метод в &lt;a href=&quot;http://player.py/&quot; target=&quot;_blank&quot;&gt;player.py&lt;/a&gt; и внесём в кулдаун новую функцию: &lt;code&gt;self.destroy_weapon()&lt;/code&gt;. Результат:&lt;/p&gt;
  &lt;figure id=&quot;wMHp&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/webt/hx/uz/cf/hxuzcfzagyusjhvnw6dqnlnzn2w.gif&quot; width=&quot;600&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;rKX1&quot;&gt;&lt;a href=&quot;https://disk.yandex.ru/d/iNPvgc6Yu52cGg&quot; target=&quot;_blank&quot;&gt;Файлы этапа можно скачать здесь&lt;/a&gt;. Далее, настроим интерфейс.&lt;/p&gt;
  &lt;h3 id=&quot;0kCm&quot;&gt;Интерфейс&lt;/h3&gt;
  &lt;p id=&quot;ZSdy&quot;&gt;Наша задача — сделать интерфейс игры. Первым делом, нужно создать такие простые вещи как базовые параметры. У нас уже есть один параметр. Это скорость. Сейчас допишем остальные параметры. В демоны в файле &lt;code&gt;player.py&lt;/code&gt; запишем следующие параметры:&lt;/p&gt;
  &lt;pre id=&quot;of7E&quot; data-lang=&quot;python&quot;&gt;self.stats = {&amp;#x27;health&amp;#x27;: 100, &amp;#x27;energy&amp;#x27;: 60, &amp;#x27;attack&amp;#x27;: 10, &amp;#x27;speed&amp;#x27;: 5} #все параметры героя
self.health = self.stats[&amp;#x27;health&amp;#x27;] #соотношение со здоровьем
self.energy = self.stats[&amp;#x27;energy&amp;#x27;] #соотношение с энергией
self.exp = 4221 #количество очков
self.speed = self.stats[&amp;#x27;speed&amp;#x27;] #скорость игрока&lt;/pre&gt;
  &lt;p id=&quot;On8L&quot;&gt;Все параметры указаны и можно удалить параметр скорости из демона ранее. Особенно хорошо, что Линк уже набрал 4221 очка за просмотр себя на ютюбе у Артура из Уфы. В файле &lt;a href=&quot;http://settings.py/&quot; target=&quot;_blank&quot;&gt;settings.py&lt;/a&gt; Добавим немного параметров отображения:&lt;/p&gt;
  &lt;pre id=&quot;pvyh&quot; data-lang=&quot;python&quot;&gt;BAR_HEIGHT = 20 #толщина всех панелек
HEALTH_BAR_WIDTH = 200  #длина панельки здоровья
ENERGY_BAR_WIDTH = 140 #длина панельки энергии
ITEM_BOX_SIZE = 80 #размер значка под предмет
UI_FONT = &amp;#x27;../graphic/font/joystix.ttf&amp;#x27; #основной шрифт
UI_FONT_SIZE = 18 #кегель шрифта

UI_BG_COLOR = &amp;#x27;#222222&amp;#x27; #цвет задника
UI_BORDER_COLOR = &amp;#x27;#111111&amp;#x27; #цвет обводки
TEXT_COLOR = &amp;#x27;#EEEEEE&amp;#x27; #цвет текста

HEALTH_COLOR = &amp;#x27;red&amp;#x27; #цвет здоровья
ENERGY_COLOR = &amp;#x27;green&amp;#x27; #цвет энергии&lt;/pre&gt;
  &lt;p id=&quot;9OBL&quot;&gt;Тут самый важный момент — добавить шрифт. Самый его большой плюс это то, что он поддерживает русский язык. Теперь, в настройках уровня укажем нового демона &lt;code&gt;self.ui = UI()&lt;/code&gt; и импортируем сам файл в проект. Под конец, добавим в run-метод правило отрисовки:&lt;/p&gt;
  &lt;pre id=&quot;D3Mz&quot; data-lang=&quot;python&quot;&gt;self.ui.display(self.player)&lt;/pre&gt;
  &lt;p id=&quot;Rm7w&quot;&gt;Теперь создадим новый файл &lt;code&gt;ui.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;ppfg&quot; data-lang=&quot;python&quot;&gt;import pygame
from settings import *

class UI:
	def __init__(self):
		self.display_surface = pygame.display.get_surface() #прорисовка самого экрана
		self.font = pygame.font.Font(UI_FONT, UI_FONT_SIZE) #добавление стандартного шрифта
		self.healt_bar_rect = pygame.Rect(10, 10, HEALTH_BAR_WIDTH, BAR_HEIGHT) #панелька для здоровья
		self.energy_bar_rect = pygame.Rect(10, 34, ENERGY_BAR_WIDTH, BAR_HEIGHT) #панелька для энергии

	def show_bar(self, current, max_amountm, bg_rect, color):
		pygame.draw.rect(self.display_surface, UI_BG_COLOR, bg_rect) #отрисовка задника панельки
		ratio = current / max_amountm
		current_with = bg_rect.width * ratio
		current_rect = bg_rect.copy()
		current_rect.width = current_with
		pygame.draw.rect(self.display_surface, color, current_rect) #рисование панельки
		pygame.draw.rect(self.display_surface, UI_BORDER_COLOR, bg_rect, 3) #рисование обводки панельки

	def display(self, player):
		self.show_bar(player.health, player.stats[&amp;#x27;health&amp;#x27;], self.healt_bar_rect, HEALTH_COLOR) #обращение к отрисовке панели здоровья
		self.show_bar(player.energy, player.stats[&amp;#x27;energy&amp;#x27;], self.energy_bar_rect, ENERGY_COLOR) #обращение к отрисовке панели энергии&lt;/pre&gt;
  &lt;p id=&quot;sNhI&quot;&gt;Из интересного, тут есть строки расчётов:&lt;/p&gt;
  &lt;pre id=&quot;WbVO&quot; data-lang=&quot;python&quot;&gt;ratio = current / max_amountm
current_with = bg_rect.width * ratio
current_rect = bg_rect.copy()
current_rect.width = current_with&lt;/pre&gt;
  &lt;p id=&quot;PDYS&quot;&gt;Тут мы переводим значения нашего здоровья в проценты прорисовки в поле пикселей. Нам нужно перевести даже 140 очков здоровья в 100%. Для этого, мы запрашиваем &lt;code&gt;current&lt;/code&gt; — очки здоровья и делим их на длину нашего поля здоровья (&lt;code&gt;max_amountm&lt;/code&gt;), далее перемножаем это с &lt;code&gt;bg_rect.width&lt;/code&gt; для отображения в поле. Я поставил в &lt;a href=&quot;http://player.py/&quot; target=&quot;_blank&quot;&gt;player.py&lt;/a&gt; значение здоровья на -10 и -50 на энергию:&lt;/p&gt;
  &lt;pre id=&quot;TUun&quot; data-lang=&quot;python&quot;&gt;self.health = self.stats[&amp;#x27;health&amp;#x27;] - 10 #соотношение со здоровьем
self.energy = self.stats[&amp;#x27;energy&amp;#x27;] - 50 #соотношение с энергией&lt;/pre&gt;
  &lt;p id=&quot;s1kl&quot;&gt;Результат:&lt;/p&gt;
  &lt;figure id=&quot;zh6p&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/lo/m-/mx/lom-mxxf6k8obbhxd6tbl8547qc.png&quot; width=&quot;344&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;xbq6&quot;&gt;Нарисуем же наши очки. Переходим опять к &lt;code&gt;ui.py&lt;/code&gt; и создадим новый метод &lt;code&gt;show_exp&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;Cwlq&quot; data-lang=&quot;python&quot;&gt;def show_exp(self, exp):
	text_surf = self.font.render(str(int(exp)), False, TEXT_COLOR) #рендер шрифта с экспой, без сглаживания и с цветом
	x = self.display_surface.get_size()[0] - 20 #отступ снизу на 20 пикселей по x
	y = self.display_surface.get_size()[1] - 20 #отступ снизу на 20 пикселей по y
	text_rect = text_surf.get_rect(bottomright = (x, y)) #цепляемся за низ экрана справа

	pygame.draw.rect(self.display_surface, UI_BG_COLOR, text_rect.inflate(20, 20)) #цепляемся за низ экрана справа
	self.display_surface.blit(text_surf, text_rect) #отображаем панельку
	pygame.draw.rect(self.display_surface, UI_BORDER_COLOR, text_rect.inflate(20, 20), 3) #обводка панели&lt;/pre&gt;
  &lt;p id=&quot;j49t&quot;&gt;Из интересного, тут стоит False в методе &lt;code&gt;self.font.render&lt;/code&gt;. Данный метод выключает сглаживание, так как у меня пиксельный шрифт. А также, pygame сделали крутой метод &lt;code&gt;text_rect.inflate&lt;/code&gt;, который помогает вписать текст в панельку. Результат удивительно прекрасен:&lt;/p&gt;
  &lt;figure id=&quot;2l4Q&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/nh/ho/oe/nhhooenw_zub2mrxxsbbibq2hrc.png&quot; width=&quot;148&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;nBnl&quot;&gt;Последний шаг — прорисовка меча Линка. Для начала, нужно прописать в базовых демонов наш список оружия. У меня в наличии только одно оружие, так что этот кусок кода можно упростить, но я оставил возможность подбирать оружие и добавить его в словарь оружия, а затем и в этот список:&lt;/p&gt;
  &lt;pre id=&quot;BKGw&quot; data-lang=&quot;python&quot;&gt;self.weapon_graphics = []
for weapon in weapon_data.values():
	path = weapon[&amp;#x27;graphic&amp;#x27;]
	weapon = pygame.image.load(path).convert_alpha()
	self.weapon_graphics.append(weapon)&lt;/pre&gt;
  &lt;p id=&quot;7JS0&quot;&gt;Далее, пишем простой метод для отображения предметов:&lt;/p&gt;
  &lt;pre id=&quot;UrqR&quot; data-lang=&quot;python&quot;&gt;def weapon_overlay(self, weapon_index):
	bg_rect = pygame.Rect(10, 630, ITEM_BOX_SIZE, ITEM_BOX_SIZE)
	pygame.draw.rect(self.display_surface, UI_BG_COLOR, bg_rect)
	weapon_surf = self.weapon_graphics[weapon_index]
	weapon_rect = weapon_surf.get_rect(center = bg_rect.center)

	self.display_surface.blit(weapon_surf, weapon_rect)&lt;/pre&gt;
  &lt;p id=&quot;mT2m&quot;&gt;В конце не забудьте добавить отображение оружия в display-методе: &lt;code&gt;self.weapon_overlay(player.weapon_index)&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;wh83&quot;&gt;Результат:&lt;/p&gt;
  &lt;figure id=&quot;QWjD&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/jy/te/cr/jytecrdqzdmwjgtqv9jiacewklg.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;WUuv&quot;&gt;&lt;a href=&quot;https://disk.yandex.ru/d/WwhG3l8y5LrT5A&quot; target=&quot;_blank&quot;&gt;Файлы проекта&lt;/a&gt; и дальше будем писать монстров (более известных как бебы).&lt;/p&gt;
  &lt;h3 id=&quot;3tPc&quot;&gt;Монстры&lt;/h3&gt;
  &lt;p id=&quot;BUix&quot;&gt;Для начала, я прописал референсы для монстров. Они хранятся в папке &lt;code&gt;graphic/monsters&lt;/code&gt;. Также, я добавил звуки ударов и закинул их в папку &lt;code&gt;audio/attack&lt;/code&gt; Далее, в &lt;a href=&quot;http://setting.py/&quot; target=&quot;_blank&quot;&gt;setting.py&lt;/a&gt; прописаны их входные данные:&lt;/p&gt;
  &lt;pre id=&quot;IDuA&quot; data-lang=&quot;python&quot;&gt;monster_data = {
	&amp;#x27;axalot&amp;#x27;: {&amp;#x27;health&amp;#x27;: 200, &amp;#x27;exp&amp;#x27;: 400, &amp;#x27;damage&amp;#x27;: 40, &amp;#x27;attack_type&amp;#x27;: &amp;#x27;slash&amp;#x27;, &amp;#x27;attack_sound&amp;#x27;: &amp;#x27;../audio/attack/slash.wav&amp;#x27;, &amp;#x27;speed&amp;#x27;: 3, &amp;#x27;resistance&amp;#x27;: 3, &amp;#x27;attack_radius&amp;#x27;: 80, &amp;#x27;notice_radius&amp;#x27;: 300},
	&amp;#x27;lizard&amp;#x27;: {&amp;#x27;health&amp;#x27;: 50, &amp;#x27;exp&amp;#x27;: 100, &amp;#x27;damage&amp;#x27;: 15,&amp;#x27;attack_type&amp;#x27;: &amp;#x27;claw&amp;#x27;,  &amp;#x27;attack_sound&amp;#x27;: &amp;#x27;../audio/attack/claw.wav&amp;#x27;, &amp;#x27;speed&amp;#x27;: 2, &amp;#x27;resistance&amp;#x27;: 3, &amp;#x27;attack_radius&amp;#x27;: 100, &amp;#x27;notice_radius&amp;#x27;: 400},
	&amp;#x27;snake&amp;#x27;: {&amp;#x27;health&amp;#x27;: 100,&amp;#x27;exp&amp;#x27;:100,&amp;#x27;damage&amp;#x27;: 10,&amp;#x27;attack_type&amp;#x27;: &amp;#x27;claw&amp;#x27;, &amp;#x27;attack_sound&amp;#x27;: &amp;#x27;../audio/attack/claw.wav&amp;#x27;, &amp;#x27;speed&amp;#x27;: 4, &amp;#x27;resistance&amp;#x27;: 3, &amp;#x27;attack_radius&amp;#x27;: 80, &amp;#x27;notice_radius&amp;#x27;: 350},
	&amp;#x27;spirit&amp;#x27;: {&amp;#x27;health&amp;#x27;: 150,&amp;#x27;exp&amp;#x27;:200,&amp;#x27;damage&amp;#x27;: 15,&amp;#x27;attack_type&amp;#x27;: &amp;#x27;claw&amp;#x27;, &amp;#x27;attack_sound&amp;#x27;: &amp;#x27;../audio/attack/claw.wav&amp;#x27;, &amp;#x27;speed&amp;#x27;: 3, &amp;#x27;resistance&amp;#x27;: 3, &amp;#x27;attack_radius&amp;#x27;: 100, &amp;#x27;notice_radius&amp;#x27;: 400}}&lt;/pre&gt;
  &lt;p id=&quot;sXGd&quot;&gt;Давайте пробежимся по параметрам:&lt;/p&gt;
  &lt;ul id=&quot;Ho3w&quot;&gt;
    &lt;li id=&quot;onZg&quot;&gt;&lt;code&gt;health&lt;/code&gt; — здоровье беба&lt;/li&gt;
    &lt;li id=&quot;shxx&quot;&gt;&lt;code&gt;exp&lt;/code&gt; — сколько очков за смерть беба&lt;/li&gt;
    &lt;li id=&quot;x6gd&quot;&gt;&lt;code&gt;damage&lt;/code&gt; — какой урон он нанесёт герою&lt;/li&gt;
    &lt;li id=&quot;Tpzc&quot;&gt;&lt;code&gt;attack_type&lt;/code&gt; — тип атаки&lt;/li&gt;
    &lt;li id=&quot;bCkp&quot;&gt;&lt;code&gt;attack_sound&lt;/code&gt; — звук удара&lt;/li&gt;
    &lt;li id=&quot;p6hu&quot;&gt;&lt;code&gt;speed&lt;/code&gt; — скорость зверька&lt;/li&gt;
    &lt;li id=&quot;ICiE&quot;&gt;&lt;code&gt;resistance&lt;/code&gt; — на сколько враг отлетит после нашего удара&lt;/li&gt;
    &lt;li id=&quot;uCSh&quot;&gt;&lt;code&gt;attack_radius&lt;/code&gt; — радиус, с которого беб опасен и может ударить&lt;/li&gt;
    &lt;li id=&quot;Zrqx&quot;&gt;&lt;code&gt;notice_radius&lt;/code&gt; — радиус зрения вражины&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;oi9g&quot;&gt;Далее, создадим новый файл сущностей (&lt;code&gt;entity.py&lt;/code&gt;) и добавим туда супер демона с наследованием групп:&lt;/p&gt;
  &lt;pre id=&quot;UKD5&quot; data-lang=&quot;python&quot;&gt;import pygame

class Entity(pygame.sprite.Sprite):
	def __init__(self, groups):
		super().__init__(groups)&lt;/pre&gt;
  &lt;p id=&quot;5uUg&quot;&gt;Скопируем методы &lt;code&gt;move&lt;/code&gt; и &lt;code&gt;collision&lt;/code&gt; из &lt;code&gt;player.py&lt;/code&gt;. Теперь удаляем из &lt;code&gt;player.py&lt;/code&gt; эти методы и ссылаться будем в классе не на &lt;code&gt;pygame.sprite.Sprite&lt;/code&gt;, а на &lt;code&gt;Entity&lt;/code&gt; (не забывайте импортировать файл). Эти небольшие танцы с бубном нужны для того, чтобы не переписывать каждый раз правила движений для нашего героя и врагов. Все они — одинаковые сущности. Также я перенёс демонов скорости анимации, фрейма и определения вектора скорости. Когда всё сделаете, перепроверьте, что всё работает.&lt;/p&gt;
  &lt;p id=&quot;EdNe&quot;&gt;Затем, наконец, создадим файл &lt;code&gt;enemy.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;cvQb&quot; data-lang=&quot;python&quot;&gt;import pygame
from settings import *
from entity import Entity

class Enemy(Entity):
	def __init__(self, monster_name, pos, groups):
		super().__init__(groups)
		self.sprite_type = &amp;#x27;enemy&amp;#x27; #новый тип спрайтов — враги
		self.image = pygame.Surface((64, 64)) #наш традиционный размер тайла
		self.rect = self.image.get_rect(topleft = pos) #традиционная отрисовка&lt;/pre&gt;
  &lt;p id=&quot;n76C&quot;&gt;Перейдём к настройке уровня. Для начала, сделаем так, чтобы наш герой спаунился там, где надо (зелёный квадрат на карте). Для этого, нам нужно импортировать новый csv-файл из уже созданной карты &lt;code&gt;&amp;#x27;entities&amp;#x27;: import_csv_layout(&amp;#x27;../map/map_Spawn.csv&amp;#x27;)&lt;/code&gt;. И пропишем в методе &lt;code&gt;creat_map&lt;/code&gt; новый объект:&lt;/p&gt;
  &lt;pre id=&quot;hS66&quot; data-lang=&quot;python&quot;&gt;if style == &amp;#x27;entities&amp;#x27;:
	if col == &amp;#x27;8&amp;#x27;:
	self.player = Player((x, y), [self.visible_sprites], self.obstacle_sprites, self.create_attack, self.destroy_weapon)&lt;/pre&gt;
  &lt;p id=&quot;ffLg&quot;&gt;Результат вас удивит:&lt;/p&gt;
  &lt;figure id=&quot;zA3S&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/dz/bb/m4/dzbbm4lxnmod4ucsux9yj2etg08.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;YSFm&quot;&gt;Герои Хайрула размножились. Проблема в том, что я прорисовывал карту разными наборами элементов. Не повторяйте моих ошибок и давайте всё исправлять. Дело в том, что номер тайла автоматически рассчитывается программой Tiles, а я указал, разные тайлы и номера задублировались, так как у меня был отдельный файл Bebs.png для спауна врагов и Link_and_block.png для Линка и блоков-стен. Теперь я объединил два набора тайлов и присвоил линку номер 16. Результат:&lt;/p&gt;
  &lt;figure id=&quot;vFNL&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/cf/6z/pz/cf6zpzgvogebhablacrdfavisqs.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;iH2E&quot;&gt;Линк на своём законном месте. Давайте заспаумим врагов, добавив лишь один else:&lt;/p&gt;
  &lt;pre id=&quot;gEoY&quot; data-lang=&quot;python&quot;&gt;else:
	Enemy(&amp;#x27;monster&amp;#x27;, (x, y), [self.visible_sprites])&lt;/pre&gt;
  &lt;figure id=&quot;f7Wj&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/ey/ed/ql/eyedqlpnxark47ej0p1ztoi8y3a.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Tzie&quot;&gt;Монстры отобразились, но теперь нужно отобразить их верно. Работаем с файлом &lt;code&gt;enemy.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;LUlP&quot; data-lang=&quot;python&quot;&gt;import pygame
from settings import *
from entity import Entity
from support import *

class Enemy(Entity):
	def __init__(self, monster_name, pos, groups):
		super().__init__(groups)
		self.sprite_type = &amp;#x27;enemy&amp;#x27; #новый тип спрайтов — враги
		self.import_graphics(monster_name) #обращаемся к новой функции перебора картинок
		self.status = &amp;#x27;idle&amp;#x27; #установим базовый статус
		self.image = self.animations[self.status][self.frame_index] #перебираем номер фрейма в папке из функции ниже
		self.rect = self.image.get_rect(topleft = pos) #традиционная отрисовка

	def import_graphics(self, monster_name):
		self.animations = {&amp;#x27;idle&amp;#x27;: [], &amp;#x27;move&amp;#x27;: [], &amp;#x27;attack&amp;#x27;: []} #перебираем возможные варианты анимаций в папках
		main_path = f&amp;#x27;../graphic/monsters/{monster_name}/&amp;#x27; #обращаемся к монстру по имени :)
		for animation in self.animations.keys(): #перебираем все картинки
			self.animations[animation] = import_folder(main_path + animation) #перебор благодаря support-файлу&lt;/pre&gt;
  &lt;p id=&quot;rz6V&quot;&gt;Тут мы делаем всё ровно также, как и ранее, но если в файле &lt;code&gt;level.py&lt;/code&gt; мы внесём имя любого монстра, то получим картинку монстра на карте:&lt;/p&gt;
  &lt;figure id=&quot;J7dP&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/8c/qp/nt/8cqpntdcv9af2s9txpo8x6b9e2a.png&quot; width=&quot;302&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;e4HB&quot;&gt;Осталось только перебрать монстров по их номерам тайлов на карте:&lt;/p&gt;
  &lt;pre id=&quot;ylGO&quot; data-lang=&quot;python&quot;&gt;else:
	if col == &amp;#x27;0&amp;#x27;:
		monster_name = &amp;#x27;axolot&amp;#x27;
	elif col == &amp;#x27;4&amp;#x27;:
		monster_name = &amp;#x27;lizard&amp;#x27;
	elif col == &amp;#x27;8&amp;#x27;:
		monster_name = &amp;#x27;snake&amp;#x27;
	else:
	monster_name = &amp;#x27;spirit&amp;#x27;

	Enemy(monster_name, (x, y), [self.visible_sprites])&lt;/pre&gt;
  &lt;figure id=&quot;wU7U&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/0d/bx/2v/0dbx2vpdvrznqapup6a0dilsiji.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;VtR7&quot;&gt;Теперь, добавим аргумент &lt;code&gt;obstacle_sprites&lt;/code&gt; в нашу конструкцию, что бебы могли взаимодействовать с Линком. Далее, создадим update-метод для файла &lt;code&gt;enemy.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;7Od5&quot; data-lang=&quot;python&quot;&gt;def update(self):
	self.move(self.speed)&lt;/pre&gt;
  &lt;p id=&quot;HGx9&quot;&gt;Далее, нужно прописать несколько статусов для наших плохишей. Добавим их в демонов данного файла:&lt;/p&gt;
  &lt;pre id=&quot;wqcc&quot; data-lang=&quot;python&quot;&gt;self.monster_name = monster_name #имя монстра
monster_info = monster_data[self.monster_name] #перехват данных монстра по имени
self.health = monster_info[&amp;#x27;health&amp;#x27;]
self.exp = monster_info[&amp;#x27;exp&amp;#x27;]
self.speed = monster_info[&amp;#x27;speed&amp;#x27;]
self.attack_damage = monster_info[&amp;#x27;damage&amp;#x27;]
self.resistance = monster_info[&amp;#x27;resistance&amp;#x27;]
self.attack_radius = monster_info[&amp;#x27;attack_radius&amp;#x27;]
self.notice_radius = monster_info[&amp;#x27;notice_radius&amp;#x27;]
self.attack_type = monster_info[&amp;#x27;attack_type&amp;#x27;]&lt;/pre&gt;
  &lt;p id=&quot;nU0P&quot;&gt;Тут мы ссылаемся на файл &lt;a href=&quot;http://settings.py/&quot; target=&quot;_blank&quot;&gt;settings.py&lt;/a&gt; и перехватываем все параметры монстров оттуда. Теперь наша задача прописать метод определения дистанции до объекта. Я думал, что эта задача непроста, так как координаты объекта рассчитываются с верхнего левого угла, у них есть свои вектора (скорости), да ещё и нужна нормализация для предотвращения &amp;quot;диагонального чита&amp;quot; (как это было у Линка). Собственно весь метод:&lt;/p&gt;
  &lt;pre id=&quot;ADrG&quot; data-lang=&quot;python&quot;&gt;def get_player_distance_direction(self, player):
	enemy_vec = pygame.math.Vector2(self.rect.center) #координата врага
	player_vec = pygame.math.Vector2(player.rect.center) #координата Линка
	distance = (player_vec - enemy_vec).magnitude() #Евклидова величина
	if distance &amp;gt; 0:
		direction = (player_vec - enemy_vec).normalize() #вычисление вектора сближения
	else:
		direction = pygame.math.Vector2() #точка, мы друг в друге
	return(distance, direction)&lt;/pre&gt;
  &lt;p id=&quot;JSax&quot;&gt;Я искренне не ожидал, что это &lt;strong&gt;так&lt;/strong&gt; просто. По сути, все сложные методы вычисления Евклидовой величины по поиску дистанции мы переложили на функцию &lt;code&gt;magnitude()&lt;/code&gt;, а с читерской функцией &lt;code&gt;normalize()&lt;/code&gt; вы уже знакомы. И зачем я учил математику? Далее, пропишем метод определения статуса беба по отношению к Линку:&lt;/p&gt;
  &lt;pre id=&quot;q4FP&quot; data-lang=&quot;python&quot;&gt;def get_status(self, player):
	distance = self.get_player_distance_direction(player)[0]
	if distance &amp;lt;= self.attack_radius:
		self.status = &amp;#x27;attack&amp;#x27;
	elif distance &amp;lt;= self.notice_radius:
		self.status = &amp;#x27;move&amp;#x27;
	else:
		self.status = &amp;#x27;idle&amp;#x27;&lt;/pre&gt;
  &lt;p id=&quot;vzFt&quot;&gt;Тут мы отсекаем изнутри во вне &amp;quot;окружности&amp;quot; зрения (близко — атака, средняя дистанция — преследование, далеко — idle), но чтобы оно заработало, нам нужно обновлять данные в фале &lt;code&gt;level.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;g4lb&quot; data-lang=&quot;python&quot;&gt;def enemy_update(self, player):
	enemy_sprites = [sprite for sprite in self.sprites() if hasattr(sprite,&amp;#x27;sprite_type&amp;#x27;) and sprite.sprite_type == &amp;#x27;enemy&amp;#x27;]
	for enemy in enemy_sprites:
		enemy.enemy_update(player)&lt;/pre&gt;
  &lt;p id=&quot;HXez&quot;&gt;Тут самая интересная строка — строка прорисовывания спрайтов для врага. Тут можно как в анекдоте: &amp;quot;Потерядлся атрибут? Ничего страшного! Всегда есть метод &lt;code&gt;hasattr&lt;/code&gt;&amp;quot;. Далее, в run-методе пропишем отрисовку спрайтов врага:&lt;/p&gt;
  &lt;pre id=&quot;hT3a&quot; data-lang=&quot;python&quot;&gt;self.visible_sprites.enemy_update(self.player)&lt;/pre&gt;
  &lt;p id=&quot;3hd9&quot;&gt;Теперь мы сможем замкнуть врага на игрока, а игрока на уровень. Для этого пропишем новый метод в &lt;code&gt;enemy.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;hmT2&quot; data-lang=&quot;python&quot;&gt;def enemy_update(self, player):
	self.get_status(player)&lt;/pre&gt;
  &lt;p id=&quot;7n3e&quot;&gt;Теперь, у нас есть способ получения методов, но мы с ними не взаимодействуем. Исправим это новым методом:&lt;/p&gt;
  &lt;pre id=&quot;8Cre&quot; data-lang=&quot;python&quot;&gt;def actions(self, player):
	if self.status == &amp;#x27;attack&amp;#x27;:
		print(&amp;#x27;attack&amp;#x27;) #тут мы только пишем в терминале атаку
	elif self.status == &amp;#x27;move&amp;#x27;:
		self.direction = self.get_player_distance_direction(player)[1] #нанюхивать Линка
	else:
		self.direction = pygame.math.Vector2() #остановиться по координатам&lt;/pre&gt;
  &lt;p id=&quot;yzQs&quot;&gt;В этом методе всё ровно также как мы работали ранее, но не забудьте закинуть его вызов в &lt;code&gt;enemy_update&lt;/code&gt;-функцию командой &lt;code&gt;self.actions(player)&lt;/code&gt;. Тетерь пропишем анимацию. Она полностью аналогична анимации Линка:&lt;/p&gt;
  &lt;pre id=&quot;NUI7&quot; data-lang=&quot;python&quot;&gt;def animate(self):
	animation = self.animations[self.status]
	self.frame_index += self.animation_speed
	if self.frame_index &amp;gt;= len(animation):
		self.frame_index = 0
	self.image = animation[int(self.frame_index)]
	self.rect = self.image.get_rect(center = self.hitbox.center)&lt;/pre&gt;
  &lt;p id=&quot;g0MX&quot;&gt;Также, добавьте animate в update-функцию. Теперь можно получить ачивку: &amp;quot;Собрал всех чушпанов с района&amp;quot;:&lt;/p&gt;
  &lt;figure id=&quot;85sF&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/webt/qz/kv/np/qzkvnpmic_-_zq9edveqno6-dhg.png&quot; width=&quot;1560&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;hTMu&quot;&gt;Но есть проблема. Они атакуют несчастного Линка толпой без остановки. Это нужно исправить, а значит время нового метода и нового кулдауна. Для начала, я добавил нового демона &lt;code&gt;self.can_attack = True&lt;/code&gt;. Это флаг, который будет указывать на то, что беб может пнуть Линка. Соответственно, нужно подправить условие атаки и помимо дистанции, указать данный флаг. Если вы добавили флаг на &lt;code&gt;True&lt;/code&gt;, то обязательно сразу нужно прописать ситуацию, когда он будет опускаться (положение &lt;code&gt;False&lt;/code&gt;). Запишем этот пункт в методе анимации:&lt;/p&gt;
  &lt;pre id=&quot;cfcp&quot; data-lang=&quot;python&quot;&gt;if self.frame_index &amp;gt;= len(animation):
	if self.status == &amp;#x27;attack&amp;#x27;:
		self.can_attack = False&lt;/pre&gt;
  &lt;p id=&quot;7jIg&quot;&gt;Немного объясню происходящее. Анимация атаки не должна прерывать анимацию перехода и если мы завершили весь цикл из переходов от картинки к картинке, то только тогда можно менять флаг на опущенное состояние. Простыми словами, все враги могут ударить нас только 1 раз, так как флаг не поднимается обратно. Поднимать тот самый флаг мы будем по кулдауну через паузу. То есть, я дабалвю два демона, которые будут обозначать время атаки и кулдаун после атаки:&lt;/p&gt;
  &lt;pre id=&quot;11TK&quot; data-lang=&quot;python&quot;&gt;self.attack_time = None
self.attack_cooldown = 400&lt;/pre&gt;
  &lt;p id=&quot;x19x&quot;&gt;Теперь пропишем сам метод кулдауна по вычислению разницы текущего времени и времени задержки:&lt;/p&gt;
  &lt;pre id=&quot;fpCm&quot; data-lang=&quot;python&quot;&gt;def cooldown(self):
	if not self.can_attack:
		current_time = pygame.time.get_ticks()
		if current_time - self.attack_time &amp;gt;= self.attack_cooldown:
			self.can_attack = True&lt;/pre&gt;
  &lt;p id=&quot;zFoQ&quot;&gt;Тут самое главное, не забыть про место старта времени, то есть про установку времени на момент атаки:&lt;/p&gt;
  &lt;pre id=&quot;tEid&quot; data-lang=&quot;python&quot;&gt;self.attack_time = pygame.time.get_ticks()&lt;/pre&gt;
  &lt;p id=&quot;geg5&quot;&gt;После этого, не забудьте закинуть метод в update-метод. Результат:&lt;/p&gt;
  &lt;figure id=&quot;NGQM&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/webt/8y/oj/p7/8yojp7whdb3ugbn1mdkc3fxtody.gif&quot; width=&quot;600&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;P9g7&quot;&gt;Мы не закончили работу с врагами, но давайте оставлю &lt;a href=&quot;https://disk.yandex.ru/d/R_we7k1uGvTW7Q&quot; target=&quot;_blank&quot;&gt;бэкап проекта&lt;/a&gt; сейчас и в следующей части создадим методы взаимодействия нас с врагами и врагов с нами.&lt;/p&gt;
  &lt;h3 id=&quot;XH8l&quot;&gt;Драки с бебами&lt;/h3&gt;
  &lt;p id=&quot;sXRd&quot;&gt;Итак, для начала создадим два новых демона для атак в &lt;code&gt;level.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;5AQE&quot; data-lang=&quot;python&quot;&gt;self.attack_sprites = pygame.sprite.Group() #атакующий спрайт
self.attackable_sprites = pygame.sprite.Group() #атакуемый спрайт&lt;/pre&gt;
  &lt;p id=&quot;n0EC&quot;&gt;Думаю, по названиям понятно, что демоны нужны для обозначения процесса атаки. Дополним метод вызова врагов помимо видимых спрайтов, атакуемыми спрайтами (&lt;code&gt;self.attack_sprites&lt;/code&gt;):&lt;/p&gt;
  &lt;pre id=&quot;RHSt&quot; data-lang=&quot;python&quot;&gt;Enemy(monster_name, (x, y), [self.visible_sprites, self.attackable_sprites], self.obstacle_sprites)&lt;/pre&gt;
  &lt;p id=&quot;1LR1&quot;&gt;Также, дополним метод &lt;code&gt;create_attack&lt;/code&gt; атакующим спрайтом (&lt;code&gt;self.attack_sprites&lt;/code&gt;) :&lt;/p&gt;
  &lt;pre id=&quot;QOvF&quot; data-lang=&quot;python&quot;&gt;def create_attack(self):
	self.current_attack = Weapon(self.player, [self.visible_sprites, self.attack_sprites])&lt;/pre&gt;
  &lt;p id=&quot;hOaJ&quot;&gt;Далее, пропишем новый метод с логикой атаки игрока:&lt;/p&gt;
  &lt;pre id=&quot;ivxC&quot; data-lang=&quot;python&quot;&gt;def player_attack_logic(self):
	if self.attack_sprites:
		for attack_sprites in self.attack_sprites:
			collision_sprites = pygame.sprite.spritecollide(attack_sprites, self.attackable_sprites, False)
			if collision_sprites:
				for target_sprite in collision_sprites:
					target_sprite.kill()&lt;/pre&gt;
  &lt;p id=&quot;jXzo&quot;&gt;Самая интересная строка тут, это строка с методом пайгейма &lt;code&gt;pygame.sprite.spritecollide&lt;/code&gt;. Данный метод позволяет удалять спрайт из группы. Первый аргумент функции — спрайты для атаки, второй — группа спрайтов из которой мы будем удалять спрайт, третий — DoKill. Если у DoKill установлено значение &lt;code&gt;True&lt;/code&gt;, все спрайты, которые сталкиваются, будут удалены из группы. Далее, в run-методе пропишем наш метод. Исход:&lt;/p&gt;
  &lt;figure id=&quot;QS3E&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/webt/jq/ev/w0/jqevw0gvyg0lioewqm7ddg_pu_k.gif&quot; width=&quot;600&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Vz8p&quot;&gt;Немного улучшим метод &lt;code&gt;player_attack_logic&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;DOVD&quot; data-lang=&quot;python&quot;&gt;if target_sprite.sprite_type == &amp;#x27;enemy&amp;#x27;:
	target_sprite.get_damage(self.player, attack_sprites.sprite_type)&lt;/pre&gt;
  &lt;p id=&quot;uWbv&quot;&gt;Мы стали сопоставлять наши спрайты по типам. В моём проекте, типов только два (enemy и weapon). Я прописал в файле &lt;code&gt;weapon.py&lt;/code&gt; в демоне строку для присваивания ему нового типа:&lt;/p&gt;
  &lt;pre id=&quot;l4V5&quot; data-lang=&quot;python&quot;&gt;self.sprite_type = &amp;#x27;weapon&amp;#x27;&lt;/pre&gt;
  &lt;p id=&quot;d7tn&quot;&gt;Далее, нам не нужно удалять врага при ударе. Нам нужно прописывать ему урон от нашего оружия. Собственно, теперь нужно в файле &lt;a href=&quot;http://enemy.py/&quot; target=&quot;_blank&quot;&gt;enemy.py&lt;/a&gt; прописать новый метод — &lt;code&gt;get_damage&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;GaO0&quot; data-lang=&quot;python&quot;&gt;def get_damage(player, attack_type):
	if attack_type == &amp;#x27;weapon&amp;#x27;:
	    self.health -= player.get_full_weapon_damage()&lt;/pre&gt;
  &lt;p id=&quot;vqnG&quot;&gt;Тут мы прописываем новый метод (&lt;code&gt;get_full_weapon_damage&lt;/code&gt;), который должен высчитывать сумму урона от оружия и от силы самого Линка (прямо как в Dark Souls). Пропишем же данный метод в &lt;code&gt;player.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;lbKI&quot; data-lang=&quot;python&quot;&gt;def get_full_weapon_damage(self):
	base_damage = self.stats[&amp;#x27;attack&amp;#x27;] #урон самого Линка
	weapon_damage = weapon_data[self.weapon][&amp;#x27;damage&amp;#x27;] #урон от выбранного оружия
	return base_damage + weapon_damage&lt;/pre&gt;
  &lt;p id=&quot;nWjN&quot;&gt;Тут мы находим и складываем уроны их наших списков. Возможно, тут встанет вопрос: &amp;quot;Зачем так сложно, если у нас только один меч и всё?&amp;quot;. Я хотел бы сделать проект так, чтобы вы могли самостоятельно с ним &amp;quot;поиграться&amp;quot;. Собственно и цель статьи не номинация &amp;quot;Игра года&amp;quot; в The Game Awards, а лишь попытка продемонстрировать работоспособность языка Python как неплохого движка. Ну да вернёмся к коду. Помимо урона, я решил сразу прописать кулдаун оружия и заменил строку:&lt;/p&gt;
  &lt;pre id=&quot;aL6n&quot; data-lang=&quot;python&quot;&gt;if current_time - self.attack_time &amp;gt;= self.attack_cooldown&lt;/pre&gt;
  &lt;p id=&quot;KQK5&quot;&gt;На строку:&lt;/p&gt;
  &lt;pre id=&quot;3rfe&quot; data-lang=&quot;python&quot;&gt;if current_time - self.attack_time &amp;gt;= self.attack_cooldown + weapon_data[self.weapon][&amp;#x27;cooldown&amp;#x27;]&lt;/pre&gt;
  &lt;p id=&quot;oyVX&quot;&gt;Напишем новый метод в &lt;code&gt;enemy.py&lt;/code&gt; на проверку смерти вражины:&lt;/p&gt;
  &lt;pre id=&quot;5GwH&quot; data-lang=&quot;python&quot;&gt;def check_death(self):
	if self.health &amp;lt;= 0:
		self.kill()&lt;/pre&gt;
  &lt;p id=&quot;YjcA&quot;&gt;Тут я даже не знаю что ещё подсветить в коде :) Не забудьте добавить данный метод в update-метод. Теперь один удар приводит к смерти врага. Таким образов, PyGame считает, что пока оружие соприкасается с врагом (вызывается метод коллизий), удары наносятся один за другим. Как итог — Линк танк, который уничтожает всё на своём пути. Исправим это. Для начала, создадим новых демонов &lt;code&gt;enemy.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;s7Tm&quot; data-lang=&quot;python&quot;&gt;self.vulnerable = True #флаг уязвимости
self.hit_time = None #время удара
self.invincibility_duration = 300 #продолжительность неуязвимости&lt;/pre&gt;
  &lt;p id=&quot;oWv6&quot;&gt;Тут достаточно прозрачные демоны. Важный момент — флаг уязвимости. Если он поднят — враг может получать урон. Теперь встроим их в &lt;code&gt;get_damage&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;iWUF&quot; data-lang=&quot;python&quot;&gt;def get_damage(self, player, attack_type):
	if self.vulnerable:	
		if attack_type == &amp;#x27;weapon&amp;#x27;:
			self.health -= player.get_full_weapon_damage()
		self.hit_time = pygame.time&lt;/pre&gt;
  &lt;p id=&quot;Y0fl&quot;&gt;Далее, необходимо дополнить код cooldown-метода:&lt;/p&gt;
  &lt;pre id=&quot;B09X&quot; data-lang=&quot;python&quot;&gt;if not self.vulnerable:
	if current_time - self.hit_time &amp;gt;= self.invincibility_duration:
		self.vulnerable = True&lt;/pre&gt;
  &lt;p id=&quot;WN8w&quot;&gt;Тут, как я говорил ранее, мы сразу добавляем вариацию флага. У нас было место, где флаг опускается и теперь в cooldown-методе он поднимается по истечению указанного времени неуязвимости. Теперь все враги убиваются весьма приятно. Теперь, нужно добавить отбивание врага на дистанцию, которая указана у каждого врага. Создадим ещё метод:&lt;/p&gt;
  &lt;pre id=&quot;vKBn&quot; data-lang=&quot;python&quot;&gt;def hit_reaction(self):
	if not self.vulnerable:
		self.direction *= -self.resistance&lt;/pre&gt;
  &lt;p id=&quot;I1eW&quot;&gt;Осталось вычислить положение в методе &lt;code&gt;get_damage&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;2NuT&quot; data-lang=&quot;python&quot;&gt;self.direction = self.get_player_distance_direction(player)[1]&lt;/pre&gt;
  &lt;p id=&quot;Jk8Z&quot;&gt;Теперь добавим мерцание во время удара, чтобы понять что удар был сделан. В PyGame все сигнатуры (синусоидные функции) лежат в диапазоне от -255 до 255, а позиции удобно брать из синусоид, так как интерпретация в Python будет работать на основе степеней (как и любой калькулятор), а затем будет процесс получения точки на синусоиде. Этот процесс я описывал дольше, чем будет писаться метод отображения пульсации:&lt;/p&gt;
  &lt;pre id=&quot;2qG8&quot; data-lang=&quot;python&quot;&gt;def wave_value(self):
	value = sin(pygame.time.get_ticks())
	if value &amp;gt;= 0:
		return 255
	else:
		return 0&lt;/pre&gt;
  &lt;p id=&quot;CSXU&quot;&gt;Данный метод написан в &lt;code&gt;entity.py&lt;/code&gt;. Не забудьте импортировать sin-метод из библиотеки math. Теперь вызовем данный метод при ударе по врагу в методе &lt;code&gt;animate&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;3twl&quot; data-lang=&quot;python&quot;&gt;if not self.vulnerable:
	alpha = self.wave_value()
	self.image.set_alpha(alpha)
else:
	self.image.set_alpha(255)&lt;/pre&gt;
  &lt;p id=&quot;XiVQ&quot;&gt;Итак, сейчас мы бьём врагов абсолютно верно и можем отследить когда враги атакуют нас (в терминал приходит сообщение &amp;quot;attack&amp;quot;). Осталось сделать метод, который коцает нашего Линка. Пропишем его в &lt;code&gt;level.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;1YEB&quot; data-lang=&quot;python&quot;&gt;def damage_player(self, amount, attack_type):
	if self.player.vulnerable:
		self.player.health -= amount
		self.player.vulnerable = False
		self.player.hurt_time = pygame.time.get_ticks()&lt;/pre&gt;
  &lt;p id=&quot;R2jb&quot;&gt;Дополним в &lt;code&gt;create_map&lt;/code&gt; в строку вызова врагов нанесение урона Линку:&lt;/p&gt;
  &lt;pre id=&quot;7CDQ&quot; data-lang=&quot;python&quot;&gt;Enemy(monster_name, (x, y), [self.visible_sprites, self.attackable_sprites], self.obstacle_sprites, self.damage_player)&lt;/pre&gt;
  &lt;p id=&quot;vozE&quot;&gt;Добавим в Enemy-класс наш новый только созданный параметр (&lt;code&gt;damage_player&lt;/code&gt;) и пропишем нового демона — &lt;code&gt;self.damage_player = damage_player&lt;/code&gt;. Теперь вместо простого вывода сообщения &amp;quot;attack&amp;quot; выполним вызов нашего метода:&lt;/p&gt;
  &lt;pre id=&quot;iAw0&quot; data-lang=&quot;python&quot;&gt;self.damage_player(amount, attack_type)&lt;/pre&gt;
  &lt;p id=&quot;Ev8d&quot;&gt;Добавим параметры таймеров в демонов нашего player-класса:&lt;/p&gt;
  &lt;pre id=&quot;RnUm&quot; data-lang=&quot;python&quot;&gt;self.vulnerable = True
self.hurt_time = None
self.invulnerablity_duration = 500&lt;/pre&gt;
  &lt;p id=&quot;lCl3&quot;&gt;Они аналогичны демонам в &lt;code&gt;enemy.py&lt;/code&gt;. Далее, традиционно пропишем смену флага в наш кулдаун-метод:&lt;/p&gt;
  &lt;pre id=&quot;MRqT&quot; data-lang=&quot;python&quot;&gt;if not self.vulnerable:
	if current_time - self.hurt_time &amp;gt;= self.invulnerablity_duration:
		self.vulnerable = True&lt;/pre&gt;
  &lt;p id=&quot;KPut&quot;&gt;Теперь пропишем наше мерцание. Тут всё также, как и ранее. Прописывать будем в animate-методе:&lt;/p&gt;
  &lt;pre id=&quot;62m9&quot; data-lang=&quot;python&quot;&gt;if not self.vulnerable:
	alpha = self.wave_value()
	self.image.set_alpha(alpha)
else:
	self.image.set_alpha(255)&lt;/pre&gt;
  &lt;p id=&quot;ZBO6&quot;&gt;Теперь нам нужно восстанавливать энергию (повторим механику из Dark Souls). Для этого создадим метод &lt;code&gt;energy_recover&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;IHAy&quot; data-lang=&quot;python&quot;&gt;def energy_recover(self):
	if self.energy &amp;lt; self.stats[&amp;#x27;energy&amp;#x27;]:
		self.energy += 0.1
	else:
		self.energy = self.stats[&amp;#x27;energy&amp;#x27;]&lt;/pre&gt;
  &lt;p id=&quot;sDFP&quot;&gt;Далее, пропишем, что при ударе у нас теряется 10 очков стамины, а если её не хватает — атака не проходит:&lt;/p&gt;
  &lt;pre id=&quot;uKyD&quot; data-lang=&quot;python&quot;&gt;if keys[pygame.K_SPACE]:
	if self.energy &amp;gt;= 10:
		self.energy -= 10
		self.attacking = True
		self.attack_time = pygame.time.get_ticks()
		self.create_attak()
		self.weapon_attack_sound.play()&lt;/pre&gt;
  &lt;p id=&quot;iqQ3&quot;&gt;Последнее, что я хотел бы сделать — добавить экспу за убийство врага в &lt;code&gt;level.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;4mGW&quot; data-lang=&quot;python&quot;&gt;def add_xp(self, amount):
	self.player.exp += amount&lt;/pre&gt;
  &lt;p id=&quot;9O1P&quot;&gt;Добавим этот же метод для &lt;code&gt;create_map&lt;/code&gt; в &lt;code&gt;Enemy&lt;/code&gt;. Далее, повторим всё, что делали ранее с &lt;code&gt;damage_player&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;yKo9&quot;&gt;&lt;a href=&quot;https://disk.yandex.ru/d/fH7ArtoIx-sQSw&quot; target=&quot;_blank&quot;&gt;Файлы данного шага тут&lt;/a&gt; и давайте приступим к последнему шагу — музыке.&lt;/p&gt;
  &lt;h3 id=&quot;ZfxM&quot;&gt;Музыка&lt;/h3&gt;
  &lt;p id=&quot;ea3q&quot;&gt;Мы на финишной прямой. В нашего &lt;code&gt;player.py&lt;/code&gt; добавим демонов:&lt;/p&gt;
  &lt;pre id=&quot;6Vrs&quot; data-lang=&quot;python&quot;&gt;self.weapon_attack_sound = pygame.mixer.Sound(&amp;#x27;../audio/attack/slash.wav&amp;#x27;)
self.weapon_attack_sound.set_volume(0.4)&lt;/pre&gt;
  &lt;p id=&quot;MpWC&quot;&gt;Первый демон укажет на название файла, а второй на громкость. Далее, вызовем звук при нажатии на клавишу:&lt;/p&gt;
  &lt;pre id=&quot;EEq5&quot; data-lang=&quot;python&quot;&gt;self.weapon_attack_sound.play()&lt;/pre&gt;
  &lt;p id=&quot;Rlp9&quot;&gt;Повторим успех с ударом от монстра:&lt;/p&gt;
  &lt;pre id=&quot;WQZC&quot; data-lang=&quot;python&quot;&gt;self.hit_sound = pygame.mixer.Sound(&amp;#x27;../audio/attack/claw.wav&amp;#x27;)
self.hit_sound.set_volume(0.4)&lt;/pre&gt;
  &lt;pre id=&quot;r54I&quot; data-lang=&quot;python&quot;&gt;self.hit_sound.play()&lt;/pre&gt;
  &lt;p id=&quot;zZdZ&quot;&gt;Данный метод я вызвал в get_damage после успешного попадания. Теперь мы слышим попадания при ударе. А враг? Сейчас сделаем. Добавим ещё пару демонов и вызов:&lt;/p&gt;
  &lt;pre id=&quot;0D70&quot; data-lang=&quot;python&quot;&gt;self.attack_sound = pygame.mixer.Sound(monster_info[&amp;#x27;attack_sound&amp;#x27;])
self.attack_sound.set_volume(0.3)&lt;/pre&gt;
  &lt;pre id=&quot;IrSc&quot; data-lang=&quot;python&quot;&gt;self.attack_sound.play()&lt;/pre&gt;
  &lt;p id=&quot;luKT&quot;&gt;Вызов функции в методе actions-методе в &lt;code&gt;enemy.py&lt;/code&gt;. Осталось только главная музыка игры. Переходим в &lt;code&gt;main.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;6EcB&quot; data-lang=&quot;python&quot;&gt;main_sound = pygame.mixer.Sound(&amp;#x27;../audio/main.wav&amp;#x27;)
main_sound.play(loops = -1)&lt;/pre&gt;
  &lt;p id=&quot;vMDH&quot;&gt;Это два новых демона. Отличие только одно — метод &lt;code&gt;play(loops = -1)&lt;/code&gt;. Тут мы создаём музыку, которая будет играть снова и снова во время игры и не закончится до выхода.&lt;/p&gt;
  &lt;p id=&quot;Eo5w&quot;&gt;В конце, я забыл, что игра не заканчивается. Я исправил это функцией &lt;code&gt;final&lt;/code&gt; в &lt;code&gt;level.py&lt;/code&gt;:&lt;/p&gt;
  &lt;pre id=&quot;dFX5&quot; data-lang=&quot;python&quot;&gt;def final(self):
	if self.player.health &amp;lt;= 0:
		print(&amp;#x27;\n&amp;#x27;, &amp;#x27;\n&amp;#x27;, &amp;#x27;Линк умер. Хана Хайрулу&amp;#x27;)
		exit()
	if self.player.exp &amp;gt; 5000:
		print(&amp;#x27;\n&amp;#x27;, &amp;#x27;\n&amp;#x27;, &amp;#x27;Линк победил&amp;#x27;)
		exit()&lt;/pre&gt;
  &lt;p id=&quot;SB5O&quot;&gt;Тут всё просто. При получении более 5000 очков — вы победили, менее — проиграли. Ну и конечно, вернул здоровье и энергию на 100%, а экспу на 0. &lt;a href=&quot;https://disk.yandex.ru/d/iTkKdIS_vjVurA&quot; target=&quot;_blank&quot;&gt;Все файлы с доработками оставлю тут&lt;/a&gt;. Вот что получилось:&lt;/p&gt;
  &lt;figure id=&quot;666ab0e8d1b5b66d8de0caa6&quot; class=&quot;m_16x9&quot;&gt;
    &lt;iframe src=&quot;https://embedd.srv.habr.com/iframe/666ab0e8d1b5b66d8de0caa6&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;MkTs&quot;&gt;Итоги&lt;/h3&gt;
  &lt;p id=&quot;4ujC&quot;&gt;В результате работы мы создали игру на голом Python только с библиотекой PyGame. Было использовано ещё парочка для обхода директорий, но можно было и без них. Выводы данной статьи, которые я хотел бы сделать не заключаются в том, чтобы подчёркивать мысль о том, что Python скоро заменит C# с Unity и Unreal. Цель статьи — продемонстрировать возможность работы с Python как с движком для программирования игр. В России, я думаю, этот вариант написания игр будет популярен. Не из-за World Of Tanks, который написан на Python, а из-за мультиплатформенности интерпретируемого языка программирования. Данный код я могу спокойно запускать из любой Unix-системы и это круто. Но встаёт пара вопросов:&lt;/p&gt;
  &lt;ol id=&quot;qGec&quot;&gt;
    &lt;li id=&quot;AYou&quot;&gt;&lt;strong&gt;Насколько сложно написать игру самому с нуля?&lt;/strong&gt; Если вы только входите в геймдев и вообще не понимаете что происходит с играми — не используйте питон. Данный сектор сейчас очень узок и вряд ли вы сможете быстро найти работу (как и вообще в геймдеве). Выбирайте Unity. Он проще Unreal Engine, но при этом весьма работоспособен. Если же вы понимаете язык программирования Python и хотите сделать игру — делайте её на Python. Нет смысла выучивать новый язык только для создания игры. Python весьма на многое способен. В качестве доказательств моих слов, могу сослаться на игры написанные на Python, а могу и на 3D-движок, который набирает обороты под название &lt;a href=&quot;https://www.harfang3d.com/en_US/&quot; target=&quot;_blank&quot;&gt;HARFANG&lt;/a&gt;. Он ничем не хуже Unity.&lt;/li&gt;
    &lt;li id=&quot;WQVV&quot;&gt;&lt;strong&gt;Ну а как быть с опытом разработчиков?&lt;/strong&gt; На Unity и Unreal много пресетов. Это правда. Но и на Python не меньше. Я не геймдевер, как можно было понять из введения в статью. Я системный администратор со знанием Python на +/- Middle-уровне (да простят меня разрабы). Я писал код для оптимизации работы в сетях, а вот с играми знаком только как игрок со стажем или программист крестиков-ноликов. Всё что я сделал — я начал изучать вопрос. И каково было моё удивление в том, что есть куча людей, которые помогают написать игру на Python. Лично я пользовался гайдами от &lt;a href=&quot;https://www.youtube.com/@ClearCode&quot; target=&quot;_blank&quot;&gt;Clear Code&lt;/a&gt; (чувак очень подробно рассказывает на какие библиотеки в PyGame ссылаться), собственно, &lt;a href=&quot;https://www.pygame.org/&quot; target=&quot;_blank&quot;&gt;официальным мануалом по PyGame&lt;/a&gt; и книгой Making Games with Python &amp;amp; Pygame (внутри базовые математические концепции игр). Эти три элемента позволили мне написать игру меньше чем за месяц.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;G1Ml&quot;&gt;Конечно, мой проект по ПуЗельде можно долго дорабатывать. Можно сделать фон из деревьев, чтобы экран не оставался чёрным, добавить оружия, подбираемых предметов. Можно сделать больших боссов. Можно создать менюшку с перезапуском и выходом из игры. В общем, есть много точек роста. Весь проект я &lt;a href=&quot;https://disk.yandex.ru/d/6FQ_XjY2nwg5LQ&quot; target=&quot;_blank&quot;&gt;оставляю&lt;/a&gt; вам на обсуждение и возможные доработки. Надеюсь было интересно! Закончу как один известный выпускник 13 школы.&lt;/p&gt;
  &lt;p id=&quot;Iawx&quot;&gt;Последние коммиты на &lt;a href=&quot;https://gitverse.ru/montirovka/The-Legend-of-PyZelda-Breath-of-the-Snakes&quot; target=&quot;_blank&quot;&gt;GitVerse&lt;/a&gt;!&lt;/p&gt;
  &lt;p id=&quot;fVao&quot;&gt;Ииииииииииииииииииииииииии помните! Питон — игривая змея!&lt;/p&gt;

</content></entry><entry><id>valerylinkov:oYL7TTVllqI</id><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov/oYL7TTVllqI?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><title>Что такое Flipper и почему он Zero. Разбираемся в тамагочи для гиков руками чайника</title><published>2024-10-30T15:33:18.311Z</published><updated>2024-10-30T16:53:18.806Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/3e/00/3e004a61-c341-4508-8c8f-07e66bf29e25.png"></media:thumbnail><category term="ed-tech" label="EdTech 🎓"></category><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/8b/28/8b28f2ea-b726-4c3f-a936-385dcef7786e.png&quot;&gt;Не так давно, примерно год назад я наконец получил свою долгожданную посылку. Flipper Zero. Для тех кто не знает, Flipper Zero - это небольшое устройство, которое позволяет заниматься всякими весёлыми затеями в жизни. Веселье начинается с Sub-1 GHz антенны и продолжается микро-скриптами для ПК. Интересующихся, прошу под кат.</summary><content type="html">
  &lt;nav&gt;
    &lt;ul&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#oTYG&quot;&gt;Приложения&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#VWnJ&quot;&gt;Sub-GHz&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#RS0F&quot;&gt;125 кГц RFID&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#EEUW&quot;&gt;NFC&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#kB0W&quot;&gt;Инфракрасный порт&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#4msR&quot;&gt;GPIO&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#WogL&quot;&gt;iButton&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#At0p&quot;&gt;Bad USB&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#8uSs&quot;&gt;U2F&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#7FRk&quot;&gt;Часы и настройки&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#sjvB&quot;&gt;Прошивки&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#lQCE&quot;&gt;Где, что и как купить?&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#fvG4&quot;&gt;А кому оно надо?&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/nav&gt;
  &lt;p id=&quot;LaFL&quot;&gt;Не так давно, примерно год назад я наконец получил свою долгожданную посылку. Flipper Zero. Для тех кто не знает, Flipper Zero - это небольшое устройство, которое позволяет заниматься всякими весёлыми затеями в жизни. Веселье начинается с Sub-1 GHz антенны и продолжается микро-скриптами для ПК. Интересующихся, прошу под кат.&lt;/p&gt;
  &lt;p id=&quot;ZD0y&quot;&gt;Ваше знакомство буду выполнять в хронологическом порядке разделов в меню самого флипера.&lt;/p&gt;
  &lt;h2 id=&quot;oTYG&quot;&gt;Приложения&lt;/h2&gt;
  &lt;figure id=&quot;Vl7W&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/73d/d74/591/73dd745915f8b6d87806c599e7fc7038.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;W1VO&quot;&gt;Я бы не стал выбирать самым основным пунктом данный, так как задача флипера, на мой взгляд, работа с физическим миром вокруг нас, а не программные приколюхи внутри устройства. Как устройство по работе с приложениями - флипер не лучший вариант. Я бы рекомендовал использовать Raspberry Pi или на худой конец Arduino.&lt;/p&gt;
  &lt;p id=&quot;g5lk&quot;&gt;Тем не менее, внутри достаточно много приложений уже написанных прекрасными пользователями интернета. Скажу сразу, я установил себе кастомную прошивку DarkFlipper. Об этом позже.&lt;/p&gt;
  &lt;figure id=&quot;B5iA&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/4b8/331/0d7/4b83310d7b27b8394fe3dce37b9ba6a2.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;figure id=&quot;RuIN&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/86f/a75/092/86fa7509290b5c63c6f21314003b130a.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;NU6x&quot;&gt;Из предустановок - 8-битные игры типа DOOM, надстройки для распиновки GPIO, аудио-проигрыватель, калькуляторы и доп. приложения и доп. приложения для антенны в 1 ГГц.&lt;/p&gt;
  &lt;figure id=&quot;wEBq&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/85a/397/406/85a39740622b5ccf423105dcd29c0edc.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;FRr4&quot;&gt;Повторюсь, данный раздел совсем не самый интересный.&lt;/p&gt;
  &lt;h2 id=&quot;VWnJ&quot;&gt;Sub-GHz&lt;/h2&gt;
  &lt;figure id=&quot;M4W0&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/343/c53/140/343c5314012d64674b326e531f58a939.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;M8lP&quot;&gt;Тут всё просто. В диапазоне от 300 до 928 МГц в AM и FM модификациях можно сканировать все сырые и не сырые данные.&lt;/p&gt;
  &lt;figure id=&quot;tZUH&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/2c6/75b/3db/2c675b3db2068f28eae9f80ee48428f4.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;figure id=&quot;krHt&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b22/e80/2b2/b22e802b2a051671be24e39901b8c5e6.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;uAc8&quot;&gt;Для тех, кто не очень понимает зачем, могу привести простой пример - коды шлагбаумов. В данном диапазоне передаются данные в шлагбаумы. Как пример, я смог скопировать свой ключ от шлагбаума. Любых шлагбаумов и ворот.&lt;/p&gt;
  &lt;p id=&quot;1Cke&quot;&gt;Как это можно реализовать? Расскажу свою историю. Я живу в центре города, где есть такое поверие: &amp;quot;нет шлагбаума - нет парковки&amp;quot;. Живя в уникальном, не побоюсь этого слова, доме, где в один небольшой двор размером с небольшой &amp;quot;плевочек&amp;quot; с детской площадкой и местом для парковки примерно на 30 машин установили аж 3 шлагбаума. Три, Карл!&lt;/p&gt;
  &lt;p id=&quot;ujyH&quot;&gt;Боль данного пункта заключается в том, что шлагбаумы были установлены трёх разных фирм, трёх разных диапазонов, да ещё и двух типов закрытия. Будучи законопослушным гражданином, я решил запросить данный пульт для парковки своего авто. Позвонив по номерам, которые были упорно замазаны на шлагбауме, я попал не много, не мало в город Реутов (сам нахожусь я в Москве). Там, мне сказали, что сделать можно, но без физического ключа - ничего не получится. На вопрос где его добыть, я получил неутешительный ответ: &amp;quot;Не знаю&amp;quot;. Месяц поисков и чудом я выяснил у соседей, что данный ключ находится у &amp;quot;старшей по подъезду&amp;quot; (рубрика &amp;quot;Центр Москвы&amp;quot;). Старшая по подъезду переехала, а подъезд остался. Не ленясь, я дозвонился до данной хозяйки медного шлагбаума. Выяснилось, что данные три шлагбаума были установлены до закона о централизованной установке шлагбаумов и каждый подъезд поставил то что хочет и то как хочет данный аппарат. Каждый шлагбаум - совместная собственность, где все бумаги носит при себе старшая по подъезду. Цирк продолжился. Требования для получения заветного ключа были следующие:&lt;/p&gt;
  &lt;ol id=&quot;wSF6&quot;&gt;
    &lt;li id=&quot;9yHV&quot;&gt;Заплатить 7 тысяч рублей за вызов бригады (оно и понятно, из Реутова-то ехать)&lt;/li&gt;
    &lt;li id=&quot;w1qf&quot;&gt;Купить резидентную парковку для бесплатной парковки в районе дома, что стоило 3 тысячи рублей в год. Она у меня была, так как ставить машину у дома я не мог.&lt;/li&gt;
    &lt;li id=&quot;9f2R&quot;&gt;Отдать &amp;quot;на сканирование в архив&amp;quot; старшей по подъезду, проживающей в другом доме все документы на машину и меня.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;I0v7&quot;&gt;Если первые два пункта были хотя бы понятны и хоть на сколько-то разумны (хотя сейчас резидентной парковки сейчас у меня нет, так как ставя машину в дворовой территории, она не нужна), то последний пункт меня возмутил. И я бы не против был бы и купить за 10 тысяч &amp;quot;ключик от домика&amp;quot;, даже был бы не против купить данную подписку у женщины, которая поставила данный шлагбаум, ведь благодаря ней, во дворе уменьшилось количество такси и сторонних машин. Но вот отдавать документы куда-то в другой дом незнакомому человеку, как-то не хотелось. Я любезно отказался от данного предложения.&lt;/p&gt;
  &lt;p id=&quot;6jew&quot;&gt;Шаг в сторону парковки подарила мне компания &lt;a href=&quot;https://prime-pult.ru/&quot; target=&quot;_blank&quot;&gt;Прайм Пульт&lt;/a&gt;. Вопрос решился просто.&lt;/p&gt;
  &lt;figure id=&quot;LEgf&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b9a/039/799/b9a039799691be00f6bddeb8b3a373e6.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Jqls&quot;&gt;Кто не понял - это ключ, который копирует сигнал. Нужно было просто понять в каком диапазоне работает ключ. Цена вопроса за 10 ключей была 3 тысячи рублей.&lt;/p&gt;
  &lt;p id=&quot;j1lC&quot;&gt;Зная фирму производителя (в моём случае Nice Flor-S), можно узнать герцовку данного производителя (в моём случае 433,92 МГц). Далее - всё просто.&lt;/p&gt;
  &lt;p id=&quot;8J9d&quot;&gt;Флиппер же помог мне сделать то же самое, но не в отдельном шлагбауме, а на всех трёх простым чтением сырых (RAW) данных. Также, в кастомной прошивке есть подбор ключей по диапазону (приложение находится в отдельной папке в меню Applications).&lt;/p&gt;
  &lt;figure id=&quot;MICl&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/d41/c14/fe2/d41c14fe2458a80832bbecef04cb4450.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;RS0F&quot;&gt;125 кГц RFID&lt;/h2&gt;
  &lt;figure id=&quot;wwqO&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/9a9/359/abb/9a9359abb9e85de3a46e7cbad0c7b514.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;p4Nx&quot;&gt;Переводя с русского на русский, данный раздел нужен для чтения ключей и смарт карт доступа.&lt;/p&gt;
  &lt;figure id=&quot;5a8H&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/87f/5e7/9fb/87f5e79fb72847a5706936b0c2278c2e.png&quot; width=&quot;1020&quot; /&gt;
    &lt;figcaption&gt;Ключики на 125 кГц&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;S08p&quot;&gt;Данные ключи сейчас активно используются в новостройках для открытия балконов или (простите) комнат для мусора. В многих учреждениях, открывается турникеты для входа в помещения.&lt;/p&gt;
  &lt;p id=&quot;hyAl&quot;&gt;Я работаю в университете и у нас такие же ключи доступа. Как прочитать её - просто. Нажать кнопку &amp;quot;Read&amp;quot; и положить её под флипер. Примерно так:&lt;/p&gt;
  &lt;figure id=&quot;wsdS&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/901/b1d/877/901b1d877d7c6e48ddb4bce39e8a53d2.png&quot; width=&quot;1280&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;EEUW&quot;&gt;NFC&lt;/h2&gt;
  &lt;figure id=&quot;j8EH&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/4dc/855/e2c/4dc855e2c25c1cd32944ce49261bc447.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;I4Br&quot;&gt;Аналог ключей, но с большей защитой. Бывает два типа защиты - PSK. В нём - всё также как и в 125 кГц ключах.&lt;/p&gt;
  &lt;figure id=&quot;645aa928ba194ffbd3482e5b&quot; class=&quot;m_16x9&quot;&gt;
    &lt;iframe src=&quot;https://embedd.srv.habr.com/iframe/645aa928ba194ffbd3482e5b&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;7dMU&quot;&gt;Второй вариант - ASK.&lt;/p&gt;
  &lt;p id=&quot;NrbV&quot;&gt;Тут нужно сделать 2 пункта - записать ключ и считыватель. Мужчина на видео по ASK - создатель флипера &lt;strong&gt;Павел Жовнер&lt;/strong&gt; &lt;a href=&quot;https://habr.com/users/zhovner&quot; target=&quot;_blank&quot;&gt;@zhovner&lt;/a&gt;&lt;/p&gt;
  &lt;figure id=&quot;645aa8e449a83800dcce55b8&quot; class=&quot;m_16x9&quot;&gt;
    &lt;iframe src=&quot;https://embedd.srv.habr.com/iframe/645aa8e449a83800dcce55b8&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;kB0W&quot;&gt;Инфракрасный порт&lt;/h2&gt;
  &lt;figure id=&quot;6ta6&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/93c/b81/485/93cb8148574b8fc9f70bfbdb696208f2.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;o8zO&quot;&gt;Инфракрасный излучатель позволяет управлять всем с ИК-приёмником. Тут справится даже ребёнок. Выбираем универсальный пульт:&lt;/p&gt;
  &lt;figure id=&quot;mRwA&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/760/014/6aa/7600146aad437f2df9bbe473cbcb83e6.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;dxId&quot;&gt;Затем, выбираем конкретный тип прибора:&lt;/p&gt;
  &lt;figure id=&quot;hTI5&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/15b/395/12d/15b39512d413c8d389475b252da7b8da.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;sben&quot;&gt;Далее, переворачиваем флипер, так чтобы сверху оказался ИК-передатчик и после нажатия на кнопку - отправляются все типы ИК-сигналов.&lt;/p&gt;
  &lt;figure id=&quot;7qo6&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/d06/ea1/c6e/d06ea1c6e5e598336fb4866951ba3ea1.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;4msR&quot;&gt;GPIO&lt;/h2&gt;
  &lt;p id=&quot;D0gp&quot;&gt;Жаба меня задушила купить Wi-Fi модуль для флипера. По нему не смогу ничего рассказать. Спасибо YouTube за контент.&lt;/p&gt;
  &lt;figure id=&quot;645aab3b1a7f54fbab01d4bf&quot; class=&quot;m_16x9&quot;&gt;
    &lt;iframe src=&quot;https://embedd.srv.habr.com/iframe/645aab3b1a7f54fbab01d4bf&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;c5ck&quot;&gt;Как дополнение, распиновка:&lt;/p&gt;
  &lt;figure id=&quot;tIE3&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/5d0/07a/000/5d007a000230a8706370666f75690df9.png&quot; width=&quot;1680&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;WogL&quot;&gt;iButton&lt;/h2&gt;
  &lt;figure id=&quot;FUxT&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/5c7/918/f47/5c7918f47c22c02bb1e5e21ce71014e1.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;dGYA&quot;&gt;Под надписью iButton спрятался сканнер ключей. Работает всё просто. Сканируем ключ на + и - к разным выпирающим точкам:&lt;/p&gt;
  &lt;figure id=&quot;vyH6&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/303/639/8b6/3036398b6c9786589c0bdbf7c50c7faf.png&quot; width=&quot;1680&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;lMAi&quot;&gt;Далее, эмулируем их же и подносим к домофону:&lt;/p&gt;
  &lt;figure id=&quot;lQ4y&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/7c7/03d/6f3/7c703d6f30a4dc6ab6338d85134ae414.png&quot; width=&quot;1680&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;At0p&quot;&gt;Bad USB&lt;/h2&gt;
  &lt;figure id=&quot;HgTu&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/c88/34d/d7c/c8834dd7cb1c4d0cb859886d92a145f4.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;BNAx&quot;&gt;Мой любимый раздел. По умолчанию, доступно всего 2 демо для Mac и Windows. Так как сижу на винде, скриншот вывода:&lt;/p&gt;
  &lt;figure id=&quot;ZXFe&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/925/5ae/984/9255ae984438164a011db55d6e823dd1.png&quot; width=&quot;1426&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;7g6t&quot;&gt;Конечно, этим всё не заканчивается. Далеко не заканчивается. Из моих любимых уже готовых скриптов под винду на PowerShell - разработка от &lt;a href=&quot;https://github.com/I-Am-Jakoby/Flipper-Zero-BadUSB&quot; target=&quot;_blank&quot;&gt;Jakoby&lt;/a&gt;. Там много различных вариаций использования от простой смены обоев, до Wi-Fi стиллера.&lt;/p&gt;
  &lt;h2 id=&quot;8uSs&quot;&gt;U2F&lt;/h2&gt;
  &lt;figure id=&quot;h4V1&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/507/3bd/07c/5073bd07c58ce9b3809341c4332a8b63.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;VvyC&quot;&gt;Двухфакторная аутентификация возможна и на флипере. Всё что нужно - подключить его без утилиты qFlipper.&lt;/p&gt;
  &lt;p id=&quot;DRCk&quot;&gt;К слову про qFlipper. Приложение можно скачать &lt;a href=&quot;https://flipperzero.one/update&quot; target=&quot;_blank&quot;&gt;здесь&lt;/a&gt;. Смысл приложения прост - работа со сторонним устройством (ПК или же телефоном). Также есть работа через блютуз.&lt;/p&gt;
  &lt;figure id=&quot;c28q&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/7f3/341/c00/7f3341c00adfd7216f1b0f67f4be32d2.png&quot; width=&quot;1724&quot; /&gt;
    &lt;figcaption&gt;Десктопное приложение&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;figure id=&quot;2tZQ&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/dae/ee6/146/daeee61460c77bb6e0a359366386bd79.png&quot; width=&quot;591&quot; /&gt;
    &lt;figcaption&gt;Мобильное приложение&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;7FRk&quot;&gt;Часы и настройки&lt;/h2&gt;
  &lt;figure id=&quot;qHYZ&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b5f/39a/5ba/b5f39a5baa861905cd900ba7f68b2f60.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ZaYH&quot;&gt;Тут что-то добавить сложно. Часы необходимы, если хотите узнать время, а в настройках можно доработать ваш флипер.&lt;/p&gt;
  &lt;h2 id=&quot;sjvB&quot;&gt;Прошивки&lt;/h2&gt;
  &lt;p id=&quot;S9O7&quot;&gt;Из моих фаворитов кастомных прошивок - &lt;a href=&quot;https://github.com/DarkFlippers&quot; target=&quot;_blank&quot;&gt;DarkFlippers&lt;/a&gt;.&lt;/p&gt;
  &lt;figure id=&quot;ZXNz&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/1af/27a/9eb/1af27a9ebd6794841af531a8fd582c4c.png&quot; width=&quot;600&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ZbYV&quot;&gt;На мой взгляд, данная прошивка самая стабильная из кастомных. Изменений довольно много. Все они описаны по ссылке на репозиторий гитхаба.&lt;/p&gt;
  &lt;p id=&quot;pZ59&quot;&gt;Второй крутой вариант - вариант от &lt;a href=&quot;https://github.com/skizzophrenic/awesome-flipperzero-withModules&quot; target=&quot;_blank&quot;&gt;TalkingSasquach&lt;/a&gt;. Там также есть крутые &lt;a href=&quot;https://github.com/skizzophrenic/Talking-Sasquach/tree/main&quot; target=&quot;_blank&quot;&gt;обои&lt;/a&gt; такого типа:&lt;/p&gt;
  &lt;figure id=&quot;645bddc8d2201800a1b42a7f&quot; class=&quot;m_16x9&quot;&gt;
    &lt;iframe src=&quot;https://embedd.srv.habr.com/iframe/645bddc8d2201800a1b42a7f&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;lQCE&quot;&gt;Где, что и как купить?&lt;/h2&gt;
  &lt;p id=&quot;9YW2&quot;&gt;Сейчас с поставками флипера сложности. Я свой флипер получил спустя почти год после его официального выхода, как пользователь поддерживающий проект на кикстарте. В комплекте: коробочка, USB type-C, стикер и инструкция по быстрому старту.&lt;/p&gt;
  &lt;figure id=&quot;1rWp&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/352/8d9/8b6/3528d98b699021085f70740a5f61b13a.png&quot; width=&quot;1280&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;9QRU&quot;&gt;Сам флипер, как сказано в &lt;a href=&quot;https://t.me/zhovner_hub&quot; target=&quot;_blank&quot;&gt;официальном телеграмм-канале Павла&lt;/a&gt;, купить можно &lt;a href=&quot;https://www.joom.com/ru/products/6448f04bf29f0401729eed7f&quot; target=&quot;_blank&quot;&gt;через Joom&lt;/a&gt;. Всё остальное (чехол, Wi-Fi модуль, плату) можно купить в &lt;a href=&quot;https://amperka.ru/search?q=flipper+zero&quot; target=&quot;_blank&quot;&gt;Амперке&lt;/a&gt;.&lt;/p&gt;
  &lt;h2 id=&quot;fvG4&quot;&gt;А кому оно надо?&lt;/h2&gt;
  &lt;p id=&quot;NMBU&quot;&gt;Как итог моего использования, могу сказать следующее (учтите, это только моё мнение): устройство прикольное, но нужно &amp;quot;понимающим&amp;quot; пользователям или тем, у кого много ключ-карт и всякого рода пультов.&lt;/p&gt;
  &lt;p id=&quot;uBsV&quot;&gt;В реальной жизни я использовал флипер порой и веселее включая кондиционеры и проекторы в кабинетах, где оно всё терялось. Ну и конечно, убивалка времени - классная. Лично для меня - устройство очень удобно и главное - приятно. Однако, есть два момента. Первый - я гик и кайфую с этого. Второй - купил я устройство в хорошие годы за 8 000 - 10 000 тысяч рублей (в зависимости от курса банка за евробаксы). Особые весельчаки взламывают лючки теслы.&lt;/p&gt;
  &lt;figure id=&quot;645be2a37942b7fb9d1cc755&quot; class=&quot;m_16x9&quot;&gt;
    &lt;iframe src=&quot;https://embedd.srv.habr.com/iframe/645be2a37942b7fb9d1cc755&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;s8Rp&quot;&gt;Потенциал у устройства есть. Об этом потенциале говорит Линус Себастьян (канал Linus Tech Tips). По мнению Себастьяна, Flipper Zero — это на самом деле это один из самых универсальных хакерских инструментов, которые когда-либо появлялись на рынке.&lt;/p&gt;
  &lt;figure id=&quot;645be15a7942b7fb9d1cc675&quot; class=&quot;m_16x9&quot;&gt;
    &lt;iframe src=&quot;https://embedd.srv.habr.com/iframe/645be15a7942b7fb9d1cc675&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Ftwp&quot;&gt;Как всегда, выбор остаётся за вами. Я же пойду дальше юзать свой флипер и играться с новыми и новыми прошивками.&lt;/p&gt;
  &lt;figure id=&quot;NbfL&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b48/b20/000/b48b200003362d379c3b6a7a27b23f23.png&quot; width=&quot;512&quot; /&gt;
  &lt;/figure&gt;

</content></entry><entry><id>valerylinkov:k6BVC-BWN-T</id><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov/k6BVC-BWN-T?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><title>Проблематика текущей концепции мировой сетевой инфраструктуры и решение при помощи децентрализованного детерминизма</title><published>2024-10-30T15:31:17.313Z</published><updated>2024-10-30T16:53:42.123Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/06/42/0642a6bc-7533-458d-afa1-64ba3604222b.png"></media:thumbnail><category term="seti" label="Сети 🕸️"></category><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/cc/eb/cceb262e-7220-49f5-b96a-388ac6495661.png&quot;&gt;Пишу вам о наболевшем. О WEB 3.0. Понимаю, что и информация была много где и много разрозненной информации, но в этой статье я постарался рассказать всю основную информацию по всем основным понятиям. Часть из информации понятна мастодонтам в области, часть очень ознакомительна, однако, думаю, информация будет интересна многим и надеюсь весьма понятна. Не будем откладывать вопрос в долгий ящик и приступим.</summary><content type="html">
  &lt;nav&gt;
    &lt;ul&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#Bkgx&quot;&gt;Проблематика концепции мировой сети&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#pGUv&quot;&gt;WWW&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#E3Dr&quot;&gt;WEB 1.0&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#D9W2&quot;&gt;WEB 2.0&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#5DFL&quot;&gt;Теория детерминизма&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#D6DY&quot;&gt;Криптовалюта&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#KNmV&quot;&gt;WEB 3.0&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#cQxb&quot;&gt;Необходимость WEB 3.0&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#i0E1&quot;&gt;(Не)возможность WEB 3.0&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/nav&gt;
  &lt;p id=&quot;VnFs&quot;&gt;Пишу вам о наболевшем. О WEB 3.0. Понимаю, что и информация была много где и много разрозненной информации, но в этой статье я постарался рассказать всю основную информацию по всем основным понятиям. Часть из информации понятна мастодонтам в области, часть очень ознакомительна, однако, думаю, информация будет интересна многим и надеюсь весьма понятна. Не будем откладывать вопрос в долгий ящик и приступим.&lt;/p&gt;
  &lt;h2 id=&quot;Bkgx&quot;&gt;Проблематика концепции мировой сети&lt;/h2&gt;
  &lt;p id=&quot;p5qq&quot;&gt;Для обсуждения вопроса мировой сети, нужно дать определение сети, а также сказать о том, как сеть стала мировой паутиной, хотя изначально предполагалась библиотечным хранилищем.&lt;/p&gt;
  &lt;p id=&quot;pJTo&quot;&gt;Информационная сеть – коммуникационная сеть, в которой информация выступает в качестве продукта создания, переработки, хранения и использования. С появлением персональных компьютеров стали широко распространятся компьютерные сети. Начиная с Тима-Бёрнса Ли, более известного как основателя Интернета, была ключевая концепция Интернета как киберпространства. Под киберпространством в данном контексте подразумевается виртуальная реальность, т.е. второй мир как «внутри» компьютеров, так и «внутри» компьютерных сетей. Было понятие сеть и Интернет (от англ. InterNet, где Inter - интернациональная, Net - сеть). Интернет был ключевым разделом в системе связанных воедино устройств. Смысл данного раздела, который получил своё название уже после создания 29 октября 1969 на базе ARPANET, был в хранении, передачи и работе с информацией. Соответственно, было необходимо создать систему, которая будет хранить информацию и прописывать доступ к ней путём иерархических подходов (аутентификации по ассиметричному или же симметричному шифрованию). Концепция разрасталась и ARPANET стал Интернетом, который правильно писать именно с заглавной буквы как название, а не с прописной как устоявшийся объект в реальной жизни.&lt;/p&gt;
  &lt;p id=&quot;PBAj&quot;&gt;Изначальная концепция предполагала, что сеть станет подобием цифровой библиотеки с множеством разветвлений и простыми алгоритмами поиска как по тексту, так и по более сложному содержанию. Можно сказать, что концепция не поменялась, однако на практике нынешний Интернет не используется по назначению и концепция требовала тотального пересмотра и расширения.&lt;/p&gt;
  &lt;p id=&quot;Yke0&quot;&gt;Сейчас не существует общепринятого определения Интернета, поэтому мною дается не само понятие, а концепция, в которой описано какие идеи вкладывали в это создатели сайтов и технологий. Даже само понимание «Отец» Интернета – звучит очень странно. Тим-Бёрнс Ли создал протоколы (правила) работы библиотечной системы отправки и получения данных, пользователи же вместе с инженерами изменили привычную идею (концепцию), после чего родилось новое виденье сети в целом и Интернета в частности.&lt;/p&gt;
  &lt;h2 id=&quot;pGUv&quot;&gt;WWW&lt;/h2&gt;
  &lt;p id=&quot;hHhm&quot;&gt;В сетях и Интернете, в частности, используется аббревиатура Всемирной паутины - WWW или World Wide Web. Всемирная паутина — это распределённая система, предоставляющая доступ к связанным между собой документам, расположенным на различных компьютерах, подключённых к сети Интернет. Для обозначения Всемирной паутины также используют слово веб (англ. &lt;em&gt;web&lt;/em&gt; «паутина»). К этому слову мы вернёмся в следующем разделе данной работы.&lt;/p&gt;
  &lt;figure id=&quot;8qLI&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/d40/7c5/526/d407c5526588cd06ad1fc48a2d62f71b.png&quot; width=&quot;1024&quot; /&gt;
    &lt;figcaption&gt;Ключевые уровни Интернета&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;SYuN&quot;&gt;Мировая паутина представляет из себя сложную систему, и как любую сложную систему её разбили на более простые уровни для удобства работы. Разбитие было названо моделью OSI или ISO, так как читать её можно сверху вниз и снизу вверх, не боясь потерять смысл. Сетевая модель OSI (The Open Systems Interconnection model) — сетевая модель стека (набора) сетевых протоколов OSI/ISO. Сама модель выглядит сейчас концептуально иначе:&lt;/p&gt;
  &lt;figure id=&quot;ck1F&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/4ba/99b/9ef/4ba99b9ef50ba2e53fe57cd5ce443b60.jpg&quot; width=&quot;512&quot; /&gt;
    &lt;figcaption&gt;Модель OSI&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;0Z5F&quot;&gt;Разница заключается в отступлении от стандартных приложений и протоколов, но переход к новым стандартам логического мышления, дабы открыть доступ инженерам нового времени к созданию совершенно других технологий, которые базировались бы на старой логике. Проблема в том, что модель OSI описывает логистику, а уровни Интернета демонстрируют технологию, разработанную на том или ином уровне. Как бы то ни было, нас волнует технология Всемирной паутины и её концептуальное представление ранее и сейчас.&lt;/p&gt;
  &lt;h2 id=&quot;E3Dr&quot;&gt;WEB 1.0&lt;/h2&gt;
  &lt;p id=&quot;5DWS&quot;&gt;Концепция WEB 1.0 появилась не сразу, а после появления в 2005 году концепции WEB 2.0. С приходом нового устарело то, что было ранее (иными словами, появление WEB 2.0 породило WEB 1.0, как предшественника), и получило своё название на полках истории. О WEB 2.0 мы поговорим в следующем разделе, а про ретроспективно созданную WEB 1.0 необходимо расписать ключевые данные в этом разделе.&lt;/p&gt;
  &lt;p id=&quot;03UX&quot;&gt;WEB 1.0 продлился с 1991 по 2004 год. Работа велась следующим образом: в случае, если был инженер, который хотел поделиться с миром своим сайтом, он писал его самостоятельно и после чего выгружал его на удалённый сервер, затем пользователь, обладающий компьютером и браузером (программный продукт для просмотра страниц в Интернете) на нём, а также купленным у провайдера доступом к Интернету, мог открыть и посмотреть содержимое сайта инженера.&lt;/p&gt;
  &lt;figure id=&quot;HFOR&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/98c/446/0f3/98c4460f3068a71ef8dd209619dc2d0f.png&quot; width=&quot;900&quot; /&gt;
    &lt;figcaption&gt;WEB 1.0&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;7kK0&quot;&gt;Сайты выглядели тоже весьма посредственно, так как доработка требовала большое количество итерационных действий, и для введения одного нового слова на страницу, приходилось переписывать сайт полностью.&lt;/p&gt;
  &lt;figure id=&quot;vmr2&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/230/ba3/5cb/230ba35cb6e689ec1ba626407f64485f.jpeg&quot; width=&quot;900&quot; /&gt;
    &lt;figcaption&gt;Вид сайта WEB 1.0&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;cjL0&quot;&gt;Альтернативное название сети WEB 1.0 было Read-Only Web (от англ. только для чтения). Это был ключевой и фатальный недостаток технологии (речь идёт о наборе технологий WEB 1.0, а не о конкретном протоколе), так как люди делились на тех, кто может только писать книги и тех, кто мог только читать. Также было с реальными книгами логично поначалу, но весьма неудобно в результате, так как многие читатели хотели также доработать контент на сайте, написать свой сайт или вообще сделать иной сервис, а сделать это было весьма проблематично. Проблема была не столько в цене (за данную услугу платили неохотно и не много), сколько в отсутствии необходимости и логичности, так как Интернет в то время был малопопулярен с точки зрения самопродвигающейся социальной площадки. Как итог, в WEB 1.0 получилось: отсутствие интерактивности и автоматизации, минимальное участие пользователей в формировании контента и примитивный дизайн.&lt;/p&gt;
  &lt;h2 id=&quot;D9W2&quot;&gt;WEB 2.0&lt;/h2&gt;
  &lt;p id=&quot;wl5D&quot;&gt;Всё поменял Тим О’Райли. В 2005 году американский издатель и активист движения за свободное программное обеспечение опубликовал статью &lt;a href=&quot;https://www.oreilly.com/pub/a/web2/archive/what-is-web-20.html&quot; target=&quot;_blank&quot;&gt;What Is Web 2.0&lt;/a&gt;, которая датируется 30 сентября 2005 года. В ней изложены все основные изменения концепции по сравнению с WEB 1.0. К основным изменениям относят: пользователи могут сами участвовать в жизни Интернета и наполнять его контентом, появились тренды на рынке и крупные корпорации стали их негласными законодателями (всё это произошло в результате капиталистического подхода к сетям), исходя из предыдущего пункта, пользовательские данные стали «товаром» для рекламодателей. Ключевой неизменный пункт - информация по-прежнему хранится на единых серверах и выдается по требованию. Схема подключения аналогична схеме ниже.&lt;/p&gt;
  &lt;figure id=&quot;2H0a&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/1fe/069/773/1fe069773bf9fdd1b95699aea79e285e.png&quot; width=&quot;900&quot; /&gt;
    &lt;figcaption&gt;WEB 2.0&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;zPKL&quot;&gt;Чтобы увидеть сайт исконно WEB 2.0 - откройте сайты типа Instagram.com или, например habr.com. Все пользователи могу писать статьи, выдавать контент и писать комментарии, однако они не стали сетевыми мастерами и не стали владеть индустрией. Сейчас происходит мировой апокалипсис WEB 2.0.&lt;/p&gt;
  &lt;p id=&quot;9wHE&quot;&gt;Апокалипсис можно условно назвать так: &amp;quot;Эра таргетированной рекламы и недостатка приватности&amp;quot;. Произошло это по двум причинам: развитие социальных функций Сети и потеря контроля пользователями своих данных. Как результат: корпорации могут удалять, сохранять, изменять, приватизировать и патентовать любой контент. Для упрощения контроля появилась технология RSS.&lt;/p&gt;
  &lt;p id=&quot;gIQa&quot;&gt;Из определения: RSS (англ. Rich Site Summary — обогащённая сводка сайта) — семейство XML-форматов, предназначенных для описания лент новостей, анонсов статей, изменений в блогах и т. п. Информация из различных источников, представленная в формате RSS, может быть собрана, обработана и представлена пользователю в удобном для него виде специальными программами-агрегаторами или-сервисами.&lt;/p&gt;
  &lt;p id=&quot;msTP&quot;&gt;Таким образом - &lt;strong&gt;все стали знать всё про всех&lt;/strong&gt;. Конечно, вопрос в том, что можно не вылезать в Интернет и/или ничего там не выкладывать, но тогда получается жесточайшая цензура путём запугивания людей открытостью их жизни. Появилась ценность приватности. За переписки или фото опубликованные заранее стали платить астрономические суммы.&lt;/p&gt;
  &lt;p id=&quot;jSXu&quot;&gt;Пример от 7 марта 2023 года. Русскоязычные хакеры BlackСat опубликовали в даркнете интимные фото больных раком, после того как группа здравоохранения Пенсильвании отказалась платить выкуп. LVHN заявляет, что этот поступок является отвратительным и жестоким по отношению к пациентам, которые получают лечение от онкологии.&lt;/p&gt;
  &lt;p id=&quot;Euur&quot;&gt;Или другой пример от 23 марта 2022 года. Крупная база данных клиентов «Яндекс.Еды» была опубликована в интернете. В ней указаны местоположение заказчика, электронная почта, номера телефонов и еще несколько строк информации. Самый полный список данных содержит: Ф.И.О; адрес местоположения, этаж, квартира, электронная почта, модель телефона (iOS или Android), код домофона и сумма, потраченная на заказы за последние полгода.&lt;/p&gt;
  &lt;p id=&quot;SSYz&quot;&gt;Проблема сейчас встала очень остро и решение было предложено философским сообществом в далёком 2007 году.&lt;/p&gt;
  &lt;h2 id=&quot;5DFL&quot;&gt;Теория детерминизма&lt;/h2&gt;
  &lt;p id=&quot;2Yda&quot;&gt;Детерминизм — это философское учение о закономерной универсальной взаимосвязи и взаимообусловленности явлений объективной действительности. Понятие &amp;quot;детерминизм&amp;quot; в философском поле сформулировали в древней Греции. Его изучали материалисты-атомисты. Позже, понятие детерминизма начинает приобретать новый смысл — смысл обусловленности — и употребляется в этике для выражения позиции, противостоящей «свободе воли». В XVII веке в период выработки элементарных понятий механики происходит сближение понятия детерминизма и причинности, устанавливается тесная связь категории закономерности и причинности, закладываются основы механистического детерминизма. Успехи механики закрепляют представления об исключительно динамическом характере закономерностей, об универсальности причинной обусловленности.&lt;/p&gt;
  &lt;p id=&quot;Z4Lv&quot;&gt;Таким образом, если извлечь из философского учения нужное для технологий знание, можно извлечь следующую мысль. Детерминизм — это условные рельсы, по которым движется технологический прогресс. Другого варианта, как сделать ровно так как есть сейчас быть не могло и не может. Было только &amp;quot;до&amp;quot; и есть только &amp;quot;после&amp;quot;. На каждое &amp;quot;после&amp;quot; влияет своё &amp;quot;до&amp;quot;.&lt;/p&gt;
  &lt;p id=&quot;tnaM&quot;&gt;Взяв это умозаключение за основу, можно дойти до очень интересных процессов. Например, как появились нейронные сети - вполне объяснимо, однако почему они работают именно так, как работают - понять до сих пор не удаётся. Значит можно изучить всё прошлое и восстановить точную картину вплоть до Иисуса Христа или даже динозавров, лишь при достаточно больших вычислительных мощностях (данная концепция была описана в сериале &amp;quot;Devs&amp;quot;). Раз так, то почему нельзя структурировать данные в детерминистическом поле путём банальной реверс-инженерии рельс жизни? Данные есть, но существует проблема вычислительных мощностей, которые сейчас весьма развиты, но недостаточно для того, чтобы сотворить такое. Итог - развитие квантовых компьютеров, которые кратно быстрее всех ныне изученных компьютеров. В сентябре 2019 года Google удалось достичь квантового превосходства — квантовый компьютер выполнил за 200 секунд вычисления, на которые у мощнейшего обычного компьютера ушло бы 10 тысячелетий. В декабре 2020 года о достижении квантового превосходства заявили и китайские исследователи. Прототип квантового компьютера из Поднебесной сумел за три минуты решить задачу, на которую у самого быстрого в мире компьютера уйдет более 600 млн лет. И снова недостаток мощностей и слишком большая цена разработки. Однако данная проблема целиком и полностью придумана маркетингом.&lt;/p&gt;
  &lt;h2 id=&quot;D6DY&quot;&gt;Криптовалюта&lt;/h2&gt;
  &lt;p id=&quot;n12O&quot;&gt;Кто разогнал и &amp;quot;обжил&amp;quot; квантовый компьютер до скоростей, что описаны выше? Мировой лидер в области IT - копания Google. На момент 26 октября 2006 г.; 22:52 МСК тройка лидеров мирового технологического рынка выглядела так: 1 место. Microsoft ($281,85 млрд), 2 место. Google ($147,77 млрд), 3 место. Cisco ($147,08 млрд). Компании Microsoft и Cisco также применяют технологии квантовых вычислений, и весь мир надеется на их успех. Но он вовсе не нужен. Это было активно продемонстрировано в 2018-19 годах майнингом криптовалют в России и мире. Впервые о добыче цифровой валюты заговорили более десяти лет назад. С того момента курс биткоина вырос в сотни раз, а за криптовалютой начали охотиться тысячи людей со всего мира.&lt;/p&gt;
  &lt;p id=&quot;q9Z4&quot;&gt;Слово «майнинг» (от англ. mining — добыча полезных ископаемых) в контексте финансов и информационных технологий добывается криптовалюта. Майнинг – это добыча цифровой валюты с помощью специального оборудования. Криптовалюта — разновидность цифровой валюты, учёт внутренних расчётных единиц которой обеспечивает децентрализованная платёжная система, работающая в полностью автоматическом режиме.&lt;/p&gt;
  &lt;p id=&quot;FvDh&quot;&gt;Таким образом, майнинг - инструмент добычи некой субстанции, которая не существует в реальной природе, однако стоит реальных денег. Всё дело в вычислительных мощностях. Криптовалюта - цена за вычисление (точнее за железо). Как только в мире появилась реальная цена за железку, на которой работает человек - появилась ферма по майнингу криптовалюты, а соответственно и денег &amp;quot;из воздуха&amp;quot;. Многие люди, которые были далеки от науки, но близки к понятию &amp;quot;деньги&amp;quot; были в диком восторге от идеи и начали создавать фермы валют в каждом подъезде. Итог - дикий прирост биткоина (главной криптовалюты) в несколько раз (см. скриншот ниже).&lt;/p&gt;
  &lt;figure id=&quot;oXXG&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/f18/509/1f4/f185091f49a549b46ee4ed2aa1645ad1.png&quot; width=&quot;1902&quot; /&gt;
    &lt;figcaption&gt;Данные с сайта &lt;a href=&quot;https://investfunds.ru/indexes/9021/&quot; target=&quot;_blank&quot;&gt;investfunds.ru&lt;/a&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;3xjO&quot;&gt;Смысл технологии майнинговых ферм заключался в том, чтобы объединить несколько устройств и благодаря большому количеству мощных устройств добиться большой мощности. В то время, как компании создают одну и супермощную систему – квантовый компьютер. Если же объединить даже двадцатую часть мощностей носимой электроники, получится устройство (или система устройств) в разы, обгоняющая один квантовый компьютер.&lt;/p&gt;
  &lt;p id=&quot;v9Yl&quot;&gt;О чём можно судить, заводя разговор про криптовалютный рынок? Вычислительные мощности необходимы для ряда техник в реальной жизни и бой за очередной капиталистический рынок (теперь под названием &amp;quot;Биткойн&amp;quot;). А что, если применить все эти вычисления не только в Биткойн, но и во все криптовалюты? А что, если объединять не специально созданные фермы, а просто все устройства? Последний iPhone 14 Pro Max мощнее любого компьютера 2007 года. А если их объединить?&lt;/p&gt;
  &lt;h2 id=&quot;KNmV&quot;&gt;WEB 3.0&lt;/h2&gt;
  &lt;p id=&quot;RIYC&quot;&gt;Если объединить все устройства - получится WEB 3.0 или бессерверная архитектура Интернета, более известная как децентрализованная сеть (сеть без почти центра).&lt;/p&gt;
  &lt;figure id=&quot;ShOf&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/905/234/aa2/905234aa23f868ca588a19f12b1d17e8.png&quot; width=&quot;900&quot; /&gt;
    &lt;figcaption&gt;WEB 3.0&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Aqyg&quot;&gt;Основные концепции Web 3.0 обозначил руководитель компании Netscape Джейсон Калаканис (Jason Calacanis). Основной проблемой руководитель считает обесценивание ресурсов и сервисов: относительная простота создания сайтов повлияла на возникновение однообразия. Тим О’Райли поддержал в свое время идеи Калаканиса, а также отметил, что Web 3.0 должен выйти за рамки привычного понимания Сети и начать «взаимодействовать с физическим миром».&lt;/p&gt;
  &lt;p id=&quot;OnN7&quot;&gt;Концепция децентрализованного Интернета базируется на следующих идеях:&lt;/p&gt;
  &lt;ul id=&quot;MfHB&quot;&gt;
    &lt;li id=&quot;aooV&quot;&gt;&lt;strong&gt;Данные хранятся децентрализовано&lt;/strong&gt;. Данные хранятся на всех устройствах частично, и никто не может прочитать данные друг друга, так как нет единого центра. Только ссылки друг на друга. Помимо этого - нет ценности красть ссылку, так как вашу можно также без проблем украсть. Отсутствует неравенство систем безопасности.Для примера возьмём две компании. Компания «Один» будет иметь кучу сложных и дорогостоящих устройств (Cisco ASA как межсетевой экран, новейшие маршрутизаторы и т.п.). Компания «Два» будет иметь один самый дешёвый роутер от провайдера. Понятно, что для взлома компании «Один» потребуется гораздо больше времени и сил, однако цена устройств разительно выше, в то время как компания «Два» - лёгкая «добыча». В случае, когда все компании (в том числе «Один» и «Два» работают в одной сети – безопасность будет на одном уровне и иерархии. Для одной компании технологии станут сильно дешевле, для другой – надёжнее.&lt;/li&gt;
    &lt;li id=&quot;bRPB&quot;&gt;&lt;strong&gt;Наполнение контентом - дело человека&lt;/strong&gt;. В отсутствии машинных сайтов, сайтов компании - нет разницы в цене и нет отличий в дизайне. Каждый пользователь создаёт свой уникальный контент, а это значит, что будет оплата не за дизайн сайта, а за работу (постоянную работу) дизайнера.В идеальном мире WEB 3.0 – сайты не необходимость, а желание и искусство. Как сейчас стало искусством – картины. Есть именитый художник, а есть начинающий, оба создают работы и оба продают их на условном аукционе и как итог – деньги и слава художнику, чья работа лучше.&lt;/li&gt;
    &lt;li id=&quot;CgYz&quot;&gt;&lt;strong&gt;Открытая архитектура&lt;/strong&gt;. Всё, что есть в Интернете не зашифровано, а значит открыто как для преступников, так и для правозащитников. Всё как в жизни.&lt;/li&gt;
    &lt;li id=&quot;yYhW&quot;&gt;&lt;strong&gt;Модерацией контента будут заниматься сообщества&lt;/strong&gt;. Правила сообщества - правила участия в нём и публикации в сети сообщества.Наглядный пример предыдущих двух пунктов – открытое общество с членством. Если вы живёте в городе – вы существуете и занимаетесь своими делами. Если вы захотите стать частью какого-то ни было клуба – придётся выполнить ряд его условий. При принадлежности к клубу – будет ряд условий, по которым вы сможете лишиться членства в клубе по внутренним правилам сообщества.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;bcHF&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/507/d00/7b1/507d007b14409890db68d13f616fa1a0.png&quot; width=&quot;612&quot; /&gt;
    &lt;figcaption&gt;Децентрализация наглядно&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;tAYM&quot;&gt;В сети можно найти &lt;a href=&quot;https://www.seocheckin.com/web-3-0-sites-list/&quot; target=&quot;_blank&quot;&gt;список&lt;/a&gt; сайтов, децентрализованных приложений dApps и сервисов, которые устроены по принципу Web 3.0. Вот некоторые из них:&lt;/p&gt;
  &lt;ul id=&quot;RV6x&quot;&gt;
    &lt;li id=&quot;mKxY&quot;&gt;&lt;a href=&quot;https://decenternet.com/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Браузер Decenternet&lt;/strong&gt;&lt;/a&gt;. Использует технологию блокчейна для создания бесшовной архитектуры. В нем есть встроенный VPN, он устраняет навязчивую рекламу, обеспечивает более высокую скорость просмотра и не отслеживает поведение пользователей в интернете.&lt;/li&gt;
    &lt;li id=&quot;sLBM&quot;&gt;&lt;a href=&quot;https://www.mysterium.network/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Маркетплейс Mysterium Network&lt;/strong&gt;&lt;/a&gt;. Платформа peer-to-peer, где пользователи могут обмениваться данными. Платформа защищена от несанкционированного доступа, анонимная и зашифрованная, но с удобным интерфейсом для пользователя.&lt;/li&gt;
    &lt;li id=&quot;8B94&quot;&gt;&lt;a href=&quot;https://steemit.com/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Платформа Steemit&lt;/strong&gt;&lt;/a&gt;. Аналог Reddit, где пользователи могут создавать аккаунты и обмениваться сообщениями. Ценный контент вознаграждается криптовалютой Steem.&lt;/li&gt;
    &lt;li id=&quot;4jMc&quot;&gt;&lt;a href=&quot;https://www.atlas.work/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Платформа фрилансеров Atlas Work&lt;/strong&gt;&lt;/a&gt;. Работодатели могут размещать на платформе разные задания и оплачивать их криптовалютой. Алгоритмы машинного обучения предлагают кандидатуры работодателей и исполнителей друг другу.&lt;/li&gt;
    &lt;li id=&quot;ZT9U&quot;&gt;&lt;a href=&quot;https://d.tube/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Платформа для потокового видео DTube&lt;/strong&gt;&lt;/a&gt;. Аналог YouTube: пользователи могут загружать на платформу свои видео. Платформа предлагает инструменты поощрения за загрузки и количество просмотров криптовалютой.&lt;/li&gt;
    &lt;li id=&quot;gpvY&quot;&gt;&lt;a href=&quot;https://audius.co/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Плеер Audius&lt;/strong&gt;&lt;/a&gt;. Сервис позволяет артистам монетизировать музыку с помощью криптовалюты и общаться со своими слушателями.&lt;/li&gt;
    &lt;li id=&quot;13Be&quot;&gt;&lt;a href=&quot;https://www.biconomy.io/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Платежный сервис Biconomy&lt;/strong&gt;&lt;/a&gt;. Предлагает возможность оплаты несколькими криптовалютами, его можно интегрировать в свою систему с помощью API.&lt;/li&gt;
    &lt;li id=&quot;CBtJ&quot;&gt;&lt;a href=&quot;https://www.huddle01.com/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Сервис конференций Huddle01&lt;/strong&gt;&lt;/a&gt;. В нем реализована децентрализованная система видеозвонков — это помогает контролировать нагрузку и улучшает качество конференций.&lt;/li&gt;
    &lt;li id=&quot;S3eY&quot;&gt;&lt;a href=&quot;https://brave.com/ru/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Браузер Brave&lt;/strong&gt;&lt;/a&gt;. В браузер встроена технология быстрого просмотра и блокировки рекламы, есть интеграция с блокчейном и собственная криптовалюта BAT.&lt;/li&gt;
    &lt;li id=&quot;oQuY&quot;&gt;&lt;a href=&quot;https://bitpay.com/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Криптоприложение BitPay&lt;/strong&gt;&lt;/a&gt;. Пользователи могут покупать, хранить, обменивать и тратить криптовалюту. Могут превратить биткоин в доллары и расплачиваться валютой с помощью криптовалютной дебетовой карты.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;K33N&quot;&gt;Для поддержки интернета будущего был создан специальный фонд и инструменты разработчика Web 3.0:&lt;/p&gt;
  &lt;ul id=&quot;Bj1o&quot;&gt;
    &lt;li id=&quot;KP6M&quot;&gt;&lt;a href=&quot;https://web3.foundation/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Фонд поддержки Web 3.0&lt;/strong&gt;&lt;/a&gt;. Он финансирует проекты, освещает и продвигает их в СМИ, предлагает консультации экспертов.&lt;/li&gt;
    &lt;li id=&quot;nHpe&quot;&gt;&lt;a href=&quot;https://moralis.io/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Платформа для разработки Moralis&lt;/strong&gt;&lt;/a&gt;. Большая часть проектов для блокчейна создана с помощью Moralis.&lt;/li&gt;
    &lt;li id=&quot;sp94&quot;&gt;&lt;a href=&quot;https://hardhat.org/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Платформа для создания приложений Hardhat&lt;/strong&gt;&lt;/a&gt;. Масштабируемая платформа, которая позволяет разработчикам создавать dApps c низкими комиссиями за транзакции без ущерба для безопасности.&lt;/li&gt;
    &lt;li id=&quot;8CZA&quot;&gt;&lt;a href=&quot;https://polygon.technology/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Платформа Polygon&lt;/strong&gt;&lt;/a&gt;. Разные решения для работы с Etherium.&lt;/li&gt;
    &lt;li id=&quot;DLhQ&quot;&gt;&lt;a href=&quot;https://consensys.net/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Инструмент ConsenSys&lt;/strong&gt;&lt;/a&gt;. Позволяет создавать децентрализованные приложения и инструменты для конечных пользователей.&lt;/li&gt;
    &lt;li id=&quot;keWx&quot;&gt;&lt;a href=&quot;https://www.koinearth.com/&quot; target=&quot;_blank&quot;&gt;&lt;strong&gt;Инструмент KoineArth&lt;/strong&gt;&lt;/a&gt;. Помогает преобразовывать физические продукты, материалы и документы в NFT, чтобы отслеживать их по всей цепочке поставок.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;cQxb&quot;&gt;Необходимость WEB 3.0&lt;/h2&gt;
  &lt;p id=&quot;hnUq&quot;&gt;Говоря о самой технологии WEB 3.0, технические специалисты начинают впадать в мир грёз о лучшем мире, однако обычным пользователям не понятно, с чем это связано. Связано это с концептуально иным подходом к технологиям. Если объяснить простыми словами, то WEB 3.0 – это технология (или набор технологий), к которому стремилось мировое IT-сообщество. А именно:&lt;/p&gt;
  &lt;ul id=&quot;0V2m&quot;&gt;
    &lt;li id=&quot;MJc8&quot;&gt;Доступность Интернета. Входной билет в сеть – устройство с антенной или сетевой картой.&lt;/li&gt;
    &lt;li id=&quot;mMx8&quot;&gt;Свобода слова. Свобода всего, так как не будет каких-либо регуляторных инструментов со стороны «крупных игроков» на рынке.&lt;/li&gt;
    &lt;li id=&quot;MGhv&quot;&gt;Полная анонимность и защищённость. Нет разницы в цене устройств и в правилах настройки – тотальная анонимность.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;i0E1&quot;&gt;(Не)возможность WEB 3.0&lt;/h2&gt;
  &lt;p id=&quot;dntO&quot;&gt;Данная концепция при всех плюсах, возможности продемонстрированной криптовалютой и выгодах для человечества на пути к мировым идеалам не поддерживается ни одной крупной компанией в мире. Поддержка компании чаще всего выражается в количестве инвестиций. Инвестиции должны приносить обратные инвестиции (откат), а при развитии WEB 3.0 компании потеряют статусность и необходимость и автоматически станут банкротами.&lt;/p&gt;
  &lt;p id=&quot;MMPf&quot;&gt;Обратная сторона медали - не противление идеям, так как многие IT-специалисты готовы работать с WEB 3.0, так как понимают ценность данный технологии для человека и человечества. Итог один - всё в наших руках.&lt;/p&gt;

</content></entry><entry><id>valerylinkov:u0aW3tLQZKS</id><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov/u0aW3tLQZKS?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><title>Разговор о самих себе или кто такие IT-шники</title><published>2024-10-30T15:24:28.937Z</published><updated>2024-10-30T15:30:28.075Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/4f/7b/4f7b3f33-b1fc-4501-8b16-19e17fe42aae.png"></media:thumbnail><category term="bombyozh" label="Бомбёж 🔥"></category><summary type="html">&lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/9c1/55d/0b8/9c155d0b89006a333c26ed44df003ebb.jpg&quot;&gt;Доброго времени суток, прекрасные покорители гор знаний Хабра! Сегодня я пришёл с размышлениями о простом вопросе к себе - &quot;Кто такой ITшник?&quot;. Вопрос кажется простым, пока не начинаешь его обсуждать. Собственно, я постараюсь начать отвечать на данный вопрос, а что вышло - сейчас расскажу. Милости прошу под кат!</summary><content type="html">
  &lt;nav&gt;
    &lt;ul&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#EA0Y&quot;&gt;Главные файндеры IT профессий&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#rb22&quot;&gt;Карта IT&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#Z4Pd&quot;&gt;Юзверь&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#vQT0&quot;&gt;Эникейщик&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#Bang&quot;&gt;Сетевик&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#VjS1&quot;&gt;ИБшник&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#sMqh&quot;&gt;Хелпдеск&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#4ciB&quot;&gt;Админ&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#j5eE&quot;&gt;Юрист&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#Qojg&quot;&gt;Аналитик&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#ysT9&quot;&gt;Программисты&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#DU6E&quot;&gt;И это всё?!&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#I3bA&quot;&gt;Почему стоит слушать нас?&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/nav&gt;
  &lt;p id=&quot;2OAh&quot;&gt;Доброго времени суток, прекрасные покорители гор знаний! Сегодня я пришёл с размышлениями о простом вопросе к себе - &amp;quot;Кто такой ITшник?&amp;quot;. Вопрос кажется простым, пока не начинаешь его обсуждать. Собственно, я постараюсь начать отвечать на данный вопрос, а что вышло - сейчас расскажу. Милости прошу под кат!&lt;/p&gt;
  &lt;figure id=&quot;Thmp&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/9c1/55d/0b8/9c155d0b89006a333c26ed44df003ebb.jpg&quot; width=&quot;649&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;gZCg&quot;&gt;Стоит начать с того, откуда взялся вопрос. Мне задала его жена. Она философ. Дело в том, что философы - такие люди, которые задают вопросы про все базовые понятия. Например: &amp;quot;Что такое любовь?&amp;quot;, &amp;quot;В чём смысл смысла?&amp;quot;, &amp;quot;Создатель и Бог - в чём принципиальное отличие?&amp;quot;. В общем, люди интересующиеся миром. И вот как-то раз Настя спросила меня &amp;quot;Валер, а кем ты работаешь?&amp;quot;. Я встал в ступор, услышав такой вопрос от жены. Когда я немного смутившись ответил на вопрос: &amp;quot;Айтишником...&amp;quot;, Настя продолжила: &amp;quot;А кто это?&amp;quot;. Собственно, с результатами я и пришёл.&lt;/p&gt;
  &lt;h2 id=&quot;EA0Y&quot;&gt;Главные файндеры IT профессий&lt;/h2&gt;
  &lt;figure id=&quot;9Wcc&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/680/46f/597/68046f597f2f4c4510b8b14571f64dad.png&quot; width=&quot;640&quot; /&gt;
    &lt;figcaption&gt;Валерий Линьков&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;bk2F&quot;&gt;Ваш покорный слуга, которые вот уже 7 лет работает в IT сфере и где &lt;s&gt;его&lt;/s&gt; (то есть меня) только черти не душили. От эникейщика до ген. директора компании, через инженера ИБ Cisco.&lt;/p&gt;
  &lt;figure id=&quot;T2CV&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/aca/1bc/1f6/aca1bc1f61c21271a8f1454d580ada7f.png&quot; width=&quot;960&quot; /&gt;
    &lt;figcaption&gt;Анастасия Линькова&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;aGNe&quot;&gt;Моя любимая супруга. Человек, который обожает задавать вопросы, на которые сложно дать простые односложные ответы. Магистр философских наук в МГУ, автор ряда статей по этике и IT-этике.&lt;/p&gt;
  &lt;p id=&quot;SOSW&quot;&gt;Мы поставили себе задачу понять кто такой IT-специалист и выработать какую-то дорожную карту всех IT-шников.&lt;/p&gt;
  &lt;p id=&quot;tiM1&quot;&gt;Необходимо обсудить один момент. Каждый айтишник понимает чем он занимается и чем занимается его коллега, который скажет простую для него фразу: &amp;quot;Ну я на фулстеке с пыхой и явой сижу&amp;quot;. Для обычного человека (даже понимающего английский, что уже не минимум) фраза будет звучать типа &amp;quot;Ну он полностью прокурен сигаретами &amp;quot;Ява&amp;quot;&amp;quot;. И теперь становиться понятно, что человек вообще не от мира сего и делает он что-то нереальное. Когда же обычный человек переспросит чем же занимается его друг, он получит ответ типа &amp;quot;Ну сайты пишу&amp;quot;...&lt;/p&gt;
  &lt;figure id=&quot;CZ0Z&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/2e9/b05/430/2e9b054304f14d61fca329ab14790e50.png&quot; width=&quot;998&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;rb22&quot;&gt;Карта IT&lt;/h2&gt;
  &lt;p id=&quot;0jtH&quot;&gt;Чтобы упростить себе задачу рассказывания, а вам чтения, позвольте продемонстрировать условную карту, которую я позволил себе предположить. Она описывает моё виденье IT. Это не истина, но и не абсолютно далёкая от реальности картина. Схему можно читать сверху вниз и снизу вверх.&lt;/p&gt;
  &lt;figure id=&quot;kSwN&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/afd/16f/82a/afd16f82ac51bbad4fefe0a248361a4b.png&quot; width=&quot;1610&quot; /&gt;
    &lt;figcaption&gt;Карта IT&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;8Rsq&quot;&gt;Итак, давайте расскажу как устроена схема. Я буду рассказывать про неё снизу вверх.&lt;/p&gt;
  &lt;h2 id=&quot;Z4Pd&quot;&gt;Юзверь&lt;/h2&gt;
  &lt;p id=&quot;8cSk&quot;&gt;Есть обычный человек. Если он не пользуется технологиями он не очень интересен нам, так как мы IT-шники, то есть специалисты Information Technologies (И-информация, Т-технология), работаем с &lt;strong&gt;технологиями&lt;/strong&gt;. Когда человек хочет узнать что-то новое, поработать с информацией и он пользуется каким-либо технологическим устройством, он приобретает статус - &lt;em&gt;пользователь.&lt;/em&gt;&lt;/p&gt;
  &lt;p id=&quot;dsh1&quot;&gt;Пользователи ничего не понимают в IT. И не должны они только пользуются технологиями, которые мы им поставляем. Однако, есть пара оговорок, которые я хотел бы рассказать каждому пользователю, которые читает данную статью. Есть несколько основных пунктов:&lt;/p&gt;
  &lt;ol id=&quot;5H5J&quot;&gt;
    &lt;li id=&quot;WywO&quot;&gt;Наши услуги стоят &lt;strong&gt;денег&lt;/strong&gt;. Пользователи платят IT-шникам не за условное время потраченное на фрилансе (хотя и это тоже), а за своё &lt;strong&gt;знание&lt;/strong&gt;. Знание мы получаем не с неба, и применить это большая проблема. Дети с начальной школы идут в программисты, и далеко не все &amp;quot;доходят&amp;quot; до конца обучения в институте. Одно &lt;a href=&quot;https://habr.com/ru/post/585718/&quot; target=&quot;_blank&quot;&gt;ЕГЭ по информатике&lt;/a&gt; до сих пор считается одним из самых сложных (после обществознания).&lt;/li&gt;
    &lt;li id=&quot;NTHj&quot;&gt;Вы должны выполнять наши указания в системах &lt;strong&gt;в точности, как мы описали&lt;/strong&gt;. Конечно, если хотите, чтобы система работала как надо. Пользователи же, которые не выполняют это условия сразу окрещаются IT-спецами как &amp;quot;&lt;strong&gt;юзверь&lt;/strong&gt;&amp;quot; (от слова User - пользователь и зверь).&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;tSkD&quot;&gt;Почему я так резок? Сейчас поясню. Первый пункт пошёл от умозаключения: &amp;quot;Ну айтишник - куча бабла из воздуха&amp;quot;. Во-первых, далеко не куча, во-вторых, не из воздуха. Давайте в цифрах.&lt;/p&gt;
  &lt;p id=&quot;u3Hz&quot;&gt;Согласно данным Росстата, по итогам 2021 года средняя заработная плата в Москве составила 111 092 рубля. По промежуточным результатам 2022 года (январь — май) средняя зарплата в Москве составляет &lt;strong&gt;116 354 рубля &lt;/strong&gt;(&lt;a href=&quot;https://sovcombank.ru/blog/umnii-potrebitel/srednyaya-zarplata-v-moskve-v-2022-godu&quot; target=&quot;_blank&quot;&gt;источник&lt;/a&gt;). Понимаю, что данные очень расплывчаты и могут быть не точны, но тем не менее - чем не мерило? По данным сайта zarplan.com средняя зарплата по должности &amp;#x27;IT-инженер&amp;#x27; составляет &lt;strong&gt;109 857 рублей&lt;/strong&gt; (&lt;a href=&quot;https://zarplan.com/zarplata/IT-%D0%98%D0%9D%D0%96%D0%95%D0%9D%D0%95%D0%A0/%D0%A0%D0%9E%D0%A1%D0%A1%D0%98%D0%AF/&quot; target=&quot;_blank&quot;&gt;источник&lt;/a&gt;) по Москве. Получается ниже средней. К слову, сам сайт имеет оговорку.&lt;/p&gt;
  &lt;blockquote id=&quot;ly6f&quot;&gt;&lt;strong&gt;Как мы считали&lt;/strong&gt;. Средние и медианные зарплаты рассчитаны на основе найденных свежих вакансий с указанной предлагаемой заработной платой. Таким образом, рассчитанные зарплаты характеризуют в большей степени предложение рынка труда (на основе вакансий), а НЕ реальные зарплаты, которые получают работники. Рассчитанные зарплаты имеют приблизительные значения.&lt;/blockquote&gt;
  &lt;p id=&quot;MBWk&quot;&gt;Становится понятно, что всё не так однозначно.&lt;/p&gt;
  &lt;p id=&quot;OkEm&quot;&gt;На счёт юзверей и второго пункта. Мы, конечно, понимаем, что работаем с пользователями, которые не знают как пользоваться новейшими решениями и просим что-то запускать, а что-то не трогать, но юзверь - везде юзверь.&lt;/p&gt;
  &lt;p id=&quot;Lq5Q&quot;&gt;История из реальной практики, которая произошла со мной буквально 2 месяца назад. Меня попросили починить сайт на Битриксе. Сайт работал исправно, но часть функционала была ограничена. Я залез на сайт и понял, что проблема была связана со стилем, который съел этот функционал. Починил и попросил не трогать стилистическое оформление до демонстрации директору (разговаривал с заказчиком в лице &lt;em&gt;маркетолога&lt;/em&gt;). Итог - чуть не сломали сайт играя со шрифтами и внося изменения в стиль. Вопрос: &lt;strong&gt;Зачем?!&lt;/strong&gt;.&lt;/p&gt;
  &lt;p id=&quot;qWHb&quot;&gt;Юзверь - это не человек, это - состояние души. Когда слушать исполнителя - не важно. И когда можно потестить &amp;quot;как бы систему сломать&amp;quot; и маяться с кучей проблем.&lt;/p&gt;
  &lt;figure id=&quot;zXLx&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/f45/658/cf3/f45658cf38cc05f3e519ff93e2dc702e.jpeg&quot; width=&quot;500&quot; /&gt;
    &lt;figcaption&gt;Маркетолог&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;mfKt&quot;&gt;Если говорить серьёзно, то пользователи в большинстве своём приятные люди, которые не являются диванными анархистами, а просто хотят получить качественный продукт. Соответственно, наша задача - им помочь.&lt;/p&gt;
  &lt;h2 id=&quot;vQT0&quot;&gt;Эникейщик&lt;/h2&gt;
  &lt;p id=&quot;vgcF&quot;&gt;Первый помощник - это человек-швейцарский нож, более известный как эникейщик. Он способен сделать всё (от настройки ПК, до сборки сервера и написания сайтов). Одна оговорка. Он способен на всё, но &lt;em&gt;плохо&lt;/em&gt;. Плохо не в том плане, что человек плохой работник, а в том плане, что он знает IT сферы поверхностно. Потом из эникейщика вырастает специалист в конкретной области, исходя из своих предпочтений.&lt;/p&gt;
  &lt;p id=&quot;fioF&quot;&gt;Эникейщик самый младший специалист в нашей сфере, поэтому его не очень уважают, однако, он - очень важен, так как благодаря ему пользователи понимают что и как делать с созданной нами же системой. Но чаще всего, они завалены бумагой, деталями и работой в целом.&lt;/p&gt;
  &lt;figure id=&quot;ZA3w&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/58a/928/54c/58a92854c2d775097faee177026035d4.jpeg&quot; width=&quot;750&quot; /&gt;
    &lt;figcaption&gt;Будни эникейщика&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;Bang&quot;&gt;Сетевик&lt;/h2&gt;
  &lt;p id=&quot;cuFf&quot;&gt;Самый частый рост эникейщика - это сетевой инженер. Это человек, который работает с передачей информации. Он занимается связкой сетей, их настройкой и общей коммутацией с новыми устройствами и новыми пользователями. Также его задача работать с подключениями всего и вся и настройкой интернета. Сайт он не пишет, он делает его доступным.&lt;/p&gt;
  &lt;figure id=&quot;Wb9P&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/post_images/62a/116/6d7/62a1166d7c5cacc397bf449309055277.jpg&quot; width=&quot;600&quot; /&gt;
    &lt;figcaption&gt;Сетевой будда&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;VjS1&quot;&gt;ИБшник&lt;/h2&gt;
  &lt;p id=&quot;x7ov&quot;&gt;Специалист информационной безопасности. Этого человека также называют хакером. Он работает над технической защитой информации. Как с железом, так и с программами. Профессия своеобразная (к ней я себя причисляю уже давно). Своеобразие в том, что кто-то будет систему защищать, а кто-то прибегнет к древней мудрости: лучшая защита - это нападение, и станет хакером. Хакер - специалист по взлому систем. Ну а сериал про эту прекрасную профессию - &lt;a href=&quot;https://habr.com/ru/post/491512/&quot; target=&quot;_blank&quot;&gt;Мистер Робот&lt;/a&gt;. В нём и расскажут как работает специалист по безопасности одной компании.&lt;/p&gt;
  &lt;figure id=&quot;rfBH&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/875/146/ddc/875146ddc994aef6687731454b517a80.jpeg&quot; width=&quot;640&quot; /&gt;
    &lt;figcaption&gt;Хакер/ИБшник&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;sMqh&quot;&gt;Хелпдеск&lt;/h2&gt;
  &lt;p id=&quot;NeIf&quot;&gt;Человек помогающий пользователям уже удалённо и по конкретному вопросу. Грубо говоря эникейщик, но на своей системе. Он выше эникейщика за счёт того, что должен разбираться в конкретной системе и работе с ней. Им посвящён целый сериал - &lt;a href=&quot;https://habr.com/ru/post/498766/&quot; target=&quot;_blank&quot;&gt;Компьютерщики (The IT Crowd)&lt;/a&gt;.&lt;/p&gt;
  &lt;figure id=&quot;pcZP&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/529/b01/8b4/529b018b405084f9106dc997a2fcd621.png&quot; width=&quot;1024&quot; /&gt;
    &lt;figcaption&gt;Хелпдеск&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;4ciB&quot;&gt;Админ&lt;/h2&gt;
  &lt;p id=&quot;UzzE&quot;&gt;Сетевой или системный администратор. Человек, занимающийся продумыванием крупных сетей и систем. Он является своего рода архитектором сетей/систем. Если вы являетесь бизнесменом, то ваш прямой путь - к нему. Он поможет и расскажет, что и как делать на старте, рассчитает и расскажет, как сетевику собрать, что он придумал. К слову, про него есть отдельная бесплатная &lt;a href=&quot;https://xakep.ru/2020/04/24/admin-howto/&quot; target=&quot;_blank&quot;&gt;статья в журнале Xakep&lt;/a&gt; от вашего покорного слуги.&lt;/p&gt;
  &lt;figure id=&quot;2nhh&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/3bc/fea/7d4/3bcfea7d4ae7084196b1ee6c7a2b8aef.jpeg&quot; width=&quot;600&quot; /&gt;
    &lt;figcaption&gt;Будни админа&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;j5eE&quot;&gt;Юрист&lt;/h2&gt;
  &lt;p id=&quot;eJO8&quot;&gt;IT-юрист, это как обычный юрист, но в сфере IT. Про него все очень часто забывают, но он пусть и не является ITшником, но ни одна крупная IT-компания не может обойтись без него. Вспомните сериал &amp;quot;&lt;a href=&quot;https://habr.com/ru/post/498766/&quot; target=&quot;_blank&quot;&gt;Кремниевая долина&lt;/a&gt;&amp;quot; и вам всё станет понятно.&lt;/p&gt;
  &lt;figure id=&quot;Et6J&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/7ff/6c5/a4e/7ff6c5a4eea1d19e664488778e5fc726.png&quot; width=&quot;515&quot; /&gt;
    &lt;figcaption&gt;IT-юрист&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;Qojg&quot;&gt;Аналитик&lt;/h2&gt;
  &lt;p id=&quot;BRzV&quot;&gt;Бизнес-аналитик в IT - очень &lt;s&gt;нудная&lt;/s&gt; нужная вещь, так как аналитики занимаются сбором требований от заказчика и передачей этих требований техническим специалистам. Звучит просто, но на деле человек должен понимать и сторону IT, и сторону бизнеса. К слову, есть очень крутой &lt;a href=&quot;https://music.yandex.ru/album/12998464?dir=desc&amp;activeTab=about&quot; target=&quot;_blank&quot;&gt;подкаст&lt;/a&gt; о том, кто такие аналитики в айти и как ими стать.&lt;/p&gt;
  &lt;figure id=&quot;5gVh&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/88c/f36/a42/88cf36a42135a5277cd936e28f1c878d.jpeg&quot; width=&quot;640&quot; /&gt;
    &lt;figcaption&gt;Аналитики&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;ysT9&quot;&gt;Программисты&lt;/h2&gt;
  &lt;p id=&quot;WXr5&quot;&gt;Если первый уровень карты я рассказал, то на втором появился мифический объект - &lt;em&gt;программист&lt;/em&gt;. Я ни в коем случае не хочу сказать, что программисты лучше остальных ITшников. Нет. Они просто другие. Большинство программистов получили статус &amp;quot;Не от мира сего&amp;quot; и не просто так.&lt;/p&gt;
  &lt;p id=&quot;uhxk&quot;&gt;Во-первых, они учат кучу языков программирования. Не один десяток лет.&lt;/p&gt;
  &lt;p id=&quot;gZZN&quot;&gt;Во-вторых, они чаще других имеют свой язык общения и не только относительно пользователей, но и относительно друг друга.&lt;/p&gt;
  &lt;p id=&quot;ga0T&quot;&gt;В-третьих, программисты работают ближе к информации и дальше от пользователей, а из это вытекает четвёртое и самое главное.&lt;/p&gt;
  &lt;p id=&quot;tR61&quot;&gt;&lt;strong&gt;Программисты способны создать что-то уникальное&lt;/strong&gt;. Это не значит, что условный сетевик не может. Каждый человек способен совершить открытие, однако кто-то работает в &lt;strong&gt;располагающей для этого среде&lt;/strong&gt;, а кто-то - нет.&lt;/p&gt;
  &lt;p id=&quot;5OQK&quot;&gt;Яркий пример такого расположение - программисты. Они все знают опыт предыдущих поколений, а также умеют создавать что-то новое и ключевой навык - создание. Их также называют разрабами (&lt;s&gt;Deus&lt;/s&gt; Devs). У них есть своя внутренняя &lt;a href=&quot;https://habr.com/ru/post/499176/&quot; target=&quot;_blank&quot;&gt;философия&lt;/a&gt; и взгляд на жизнь и себя в ней.&lt;/p&gt;
  &lt;figure id=&quot;Yq0t&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/9d3/db0/bef/9d3db0bef585b53e2e958b9bd8b78188.jpeg&quot; width=&quot;1920&quot; /&gt;
    &lt;figcaption&gt;Программист в работе&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;DU6E&quot;&gt;И это всё?!&lt;/h2&gt;
  &lt;p id=&quot;OiUc&quot;&gt;Нет. Далеко не всё. Каждый из перечисленных мной IT-спецов имеют свои собственные разделения и точки роста. Программисты могут знать много языков и разбираться в сетях или вообще уйти в лидов и админов, сетевики часть переходят в белый хакинг, а затем и в чёрный минуя серый, ИБшники могут стать крутыми разрабами нового защитного ПО.&lt;/p&gt;
  &lt;p id=&quot;6qPU&quot;&gt;Очень сложно (я бы сказал невозможно), описать каждого специалиста в одной статье, да и читать это будет очень не просто. Поэтому мы запустили свой подкаст. Лежачий подкаст.&lt;/p&gt;
  &lt;figure id=&quot;63a8b24c14d7249a467a2e13&quot; class=&quot;m_16x9&quot;&gt;
    &lt;iframe src=&quot;https://embedd.srv.habr.com/iframe/63a8b24c14d7249a467a2e13&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;sSrI&quot;&gt;В нём мы и будем рассказывать более детально про каждого разработчика и я, уважаемые читатели хабра, прошу вас об услуге. Если среди вас есть специалист, который готов поделиться с нами своим опытом в подкасте, пожалуйста, свяжитесь со мной через Хабр. Расскажите свою историю всему миру!&lt;/p&gt;
  &lt;figure id=&quot;hkv0&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/8b8/d18/148/8b8d18148376eec6be6cc0de6ef8e2be.jpeg&quot; width=&quot;704&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;I3bA&quot;&gt;Почему стоит слушать нас?&lt;/h2&gt;
  &lt;p id=&quot;SG1C&quot;&gt;К сожалению, простому человеку сложно понять, кто такой айтишник, однако мы сами, отвечая на вопрос &amp;quot;кем ты работаешь?&amp;quot; чаще всего отвечаем &amp;quot;айтишником&amp;quot;, потому что объяснить всё, что ты делаешь - довольно проблематично. Тут и возникает проблема - айтишник становится мифическим существом. Тем не менее, программист и сетевик - совершенно разные профессии (что было для моей жены открытием). Поэтому хотим простым языком объяснить тем, кто хочет разобраться, кто мы такие и почему не все айтишники умеют писать сайты, ставить винду и чинить принтер&lt;/p&gt;
  &lt;p id=&quot;IRBh&quot;&gt;Я знаю, что есть куча подкастов от разных площадок IT-обучалок. Я сам работаю в ряде из них, поэтому мы и хотели бы работать с вами &lt;strong&gt;без рекламы&lt;/strong&gt;, &lt;strong&gt;без &amp;quot;красивых&amp;quot; историй с хеппи-эндом&lt;/strong&gt;, &lt;strong&gt;без цензуры&lt;/strong&gt; и &lt;strong&gt;без проплаченного мнения&lt;/strong&gt;. Как думаете, получится?&lt;/p&gt;
  &lt;p id=&quot;HDNX&quot;&gt;У меня на этом всё! Поздравляю всех наступающим новым 2023 годом и надеюсь в новом году мы сможем плодотворно посотрудничать!&lt;/p&gt;
  &lt;p id=&quot;e8xf&quot;&gt;P.S. Статья была написана не с целью рекламы, а с целью привлечения внимания к проблеме недопонимания IT-профессионалов с рядовыми пользователями. Надеюсь, у меня получилось!&lt;/p&gt;

</content></entry><entry><id>valerylinkov:QqRbFXkvxrH</id><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov/QqRbFXkvxrH?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><title>ЗаPython'ил ЕГЭ на сотку или почему Python поможет на ЕГЭ</title><published>2024-10-30T15:22:35.228Z</published><updated>2024-10-30T17:05:35.076Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/b0/7f/b07fb242-cd3b-4e38-bd83-b3076b9c9045.png"></media:thumbnail><category term="ed-tech" label="EdTech 🎓"></category><summary type="html">&lt;img src=&quot;https://img3.teletype.in/files/6a/94/6a94d963-e957-4d6e-9154-822db8db2ca7.jpeg&quot;&gt;В сегодняшней статье поговорим о насущной для многих выпускников школ теме - ЕГЭ. Да-да-да! Ребят опять посадили на дистант. Пока не ясно на какой период, но уже сейчас можно сказать, что ЕГЭ по информатике будет на компьютерах и его можно зарешать при помощи языка Python.</summary><content type="html">
  &lt;nav&gt;
    &lt;ul&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#MuAN&quot;&gt;Быстрый перевод из системы в систему&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#OcMX&quot;&gt;Задача 2&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#c6vq&quot;&gt;Задача 5&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#MGxJ&quot;&gt;Задача 6&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#TW0n&quot;&gt;Задача 12&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#sClC&quot;&gt;Задача 14&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#WhBm&quot;&gt;Задача 16&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#XR9T&quot;&gt;Задача 17&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#lkcm&quot;&gt;Задача 19, 20 и 21&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#hAOH&quot;&gt;Задача 22&lt;/a&gt;&lt;/li&gt;
      &lt;li class=&quot;m_level_1&quot;&gt;&lt;a href=&quot;#SHB0&quot;&gt;&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/nav&gt;
  &lt;p id=&quot;4aaX&quot;&gt;В сегодняшней статье поговорим о насущной для многих выпускников школ теме - ЕГЭ. Да-да-да! Ребят опять посадили на дистант. Пока не ясно на какой период, но уже сейчас можно сказать, что ЕГЭ по информатике будет на компьютерах и его можно зарешать при помощи языка Python.&lt;/p&gt;
  &lt;p id=&quot;AxQw&quot;&gt;Вот я и подумал, чтобы не получилось как в песне, стоит этим заняться. Я расскажу про все задачи первой части и их решения на примере демо варианта ЕГЭ за октябрь.&lt;/p&gt;
  &lt;p id=&quot;bbsT&quot;&gt;Всех желающих - приглашаю ниже!&lt;/p&gt;
  &lt;figure id=&quot;VNQP&quot; class=&quot;m_column&quot;&gt;
    &lt;iframe src=&quot;https://music.yandex.ru/iframe/#track/104865829/22622868&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;MuAN&quot;&gt;Быстрый перевод из системы в систему&lt;/h3&gt;
  &lt;p id=&quot;dvVG&quot;&gt;В Python есть интересные функции &lt;code&gt;bin()&lt;/code&gt;, &lt;code&gt;oct()&lt;/code&gt; и &lt;code&gt;hex()&lt;/code&gt;. Работают данные функции очень просто:&lt;/p&gt;
  &lt;pre id=&quot;iHbd&quot; data-lang=&quot;python&quot;&gt;bin(156) #Выводит &amp;#x27;0b10011100&amp;#x27;
oct(156) #Выводит &amp;#x27;0o234&amp;#x27;
hex(156) #Выводит &amp;#x27;0x9c&amp;#x27;&lt;/pre&gt;
  &lt;figure id=&quot;s6ii&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/107/da0/461/107da0461adeb3a00378a8af32efb01b.png&quot; width=&quot;979&quot; /&gt;
    &lt;figcaption&gt;Вывод в интерпретационном режиме&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;F0Pt&quot;&gt;Как вы видите, выводится строка, где 0b - означает, что число далее в двоичной системе счисления, 0o - в восьмеричной, а 0x - в шестнадцатеричной. Но это стандартные системы, а есть и необычные...&lt;/p&gt;
  &lt;p id=&quot;96Fq&quot;&gt;Давайте посмотрим и на них:&lt;/p&gt;
  &lt;pre id=&quot;f4rI&quot; data-lang=&quot;python&quot;&gt;n = int(input()) #Вводим целое число
 
b = &amp;#x27;&amp;#x27; #Формируем пустую строку
 
while n &amp;gt; 0: #Пока число не ноль
    b = str(n % 2) + b #Остатот от деления нужной системы (в нашем сл записываем слева
    n = n // 2 #Целочисленное деление
 
print(b) #Вывод&lt;/pre&gt;
  &lt;p id=&quot;BHiN&quot;&gt;Данная программа будет работать при переводе из десятичной системы счисления в любую до 9, так как у нас нет букв. Давайте добавим буквы:&lt;/p&gt;
  &lt;pre id=&quot;g6VY&quot; data-lang=&quot;python&quot;&gt;n = int(input()) #Вводим целое число

b = &amp;#x27;&amp;#x27; #Формируем пустую строку

while n &amp;gt; 0: #Пока число не ноль
    if (n % 21) &amp;gt; 9: #Если остаток от деления больше 9...
        if n % 21 == 10: #... и равен 10...
            b = &amp;#x27;A&amp;#x27; + b #... запишем слева A
        elif n % 21 == 11:#... и равен 11...
            b = &amp;#x27;B&amp;#x27; + b#... запишем слева B

&amp;#x27;&amp;#x27;&amp;#x27;

И так далее, пока не дойдём до системы счисления -1 (я переводил в 21-ную систему и шёл до 20)

&amp;#x27;&amp;#x27;&amp;#x27;

        elif n % 21 == 11:
            b = &amp;#x27;B&amp;#x27; + b
        elif n % 21 == 12:
            b = &amp;#x27;C&amp;#x27; + b
        elif n % 21 == 13:
            b = &amp;#x27;D&amp;#x27; + b
        elif n % 21 == 14:
            b = &amp;#x27;E&amp;#x27; + b
        elif n % 21 == 15:
            b = &amp;#x27;F&amp;#x27; + b
        elif n % 21 == 16:
            b = &amp;#x27;G&amp;#x27; + b
        elif n % 21 == 17:
            b = &amp;#x27;H&amp;#x27; + b
        elif n % 21 == 18:
            b = &amp;#x27;I&amp;#x27; + b
        elif n % 21 == 19:
            b = &amp;#x27;J&amp;#x27; + b
        elif n % 21 == 20:
            b = &amp;#x27;K&amp;#x27; + b
    else: #Иначе (остаток меньше 10)
        b = str(n % 21) + b #Остатот от деления записываем слева
    n = n // 21 #Целочисленное деление

print(b) #Вывод&lt;/pre&gt;
  &lt;p id=&quot;jND7&quot;&gt;Способ объёмен, но понятен. Теперь давайте используем тот же функцию перевода из любой системы счисления в любую:&lt;/p&gt;
  &lt;pre id=&quot;PZVV&quot; data-lang=&quot;python&quot;&gt;def convert_base(num, to_base=10, from_base=10):
    # Перевод в десятичную систему
    if isinstance(num, str): # Если число - строка, то ...
        n = int(num, from_base) # ... переводим его в нужную систему счисления
    else: # Если же ввели число, то ...
        n = int(num) # ... просто воспринять его как число
    # Перевод десятичной в &amp;#x27;to_base&amp;#x27; систему
    alphabet = &amp;quot;0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;quot; # Берём алфавит
    if n &amp;lt; to_base: # Если число меньше системы счисления в которую переводить...
        return alphabet[n] # ... вернуть значения номера в алфавите (остаток от деления)
    else: # Иначе...
        return convert_base(n // to_base, to_base) + alphabet[n % to_base] # ... рекурсивно обратиться к функии нахождения остатка&lt;/pre&gt;
  &lt;p id=&quot;Xpyl&quot;&gt;Вызвав функцию вывода &lt;code&gt;print(convert_base(156, 16, 10))&lt;/code&gt; мы переведём 156 из 10 в 16 систему счисления, а введя &lt;code&gt;print(convert_base(&amp;#x27;23&amp;#x27;, 21, 4))&lt;/code&gt; переведёт 23 из 4-ичной в 21-ичную систему (ответ: B).&lt;/p&gt;
  &lt;h3 id=&quot;OcMX&quot;&gt;Задача 2&lt;/h3&gt;
  &lt;p id=&quot;ExtS&quot;&gt;Все задания беру из первого октябрьского варианта (он же вариант № 9325894) с сайта &lt;a href=&quot;https://inf-ege.sdamgia.ru/test?id=9325894&quot; target=&quot;_blank&quot;&gt;Решу.ЕГЭ&lt;/a&gt;.&lt;/p&gt;
  &lt;figure id=&quot;q5MP&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/f04/f14/09f/f04f1409f50aa91bac10feba607a2a94.png&quot; width=&quot;852&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;xStM&quot;&gt;Решение данной задачи совсем простое: банальный перебор.&lt;/p&gt;
  &lt;pre id=&quot;vElC&quot; data-lang=&quot;python&quot;&gt;print(&amp;#x27;y&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;z&amp;#x27;, &amp;#x27;F&amp;#x27;) #Напечатаем заголовки таблицы
for y in range(2): #Берём все переменные и меняем их в циклах &amp;#x27;0&amp;#x27; и &amp;#x27;1&amp;#x27;
    for x in range(2):
        for z in range(2):
            for w in range(2):
                F = ((not x or y) == (not z or w)) or (x and w) #Записываем функцию
                print(x, y, z, F) #Выводим результат&lt;/pre&gt;
  &lt;p id=&quot;iJwg&quot;&gt;Результат:&lt;/p&gt;
  &lt;figure id=&quot;F1Ed&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b44/ac0/029/b44ac002998bf0a69d46315be639eeac.png&quot; width=&quot;979&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;uteM&quot;&gt;Нам вывелась вся таблица истинности (1 = True, 0 = False). Но это не очень удобно. Обратите внимание, что в задании, функция равно 0, так и давайте подправим код:&lt;/p&gt;
  &lt;pre id=&quot;miRA&quot; data-lang=&quot;python&quot;&gt;print(&amp;#x27;y&amp;#x27;, &amp;#x27;x&amp;#x27;, &amp;#x27;z&amp;#x27;, &amp;#x27;F&amp;#x27;) #Напечатаем заголовки таблицы
for y in range(2): #Берём все переменные и меняем их в циклах &amp;#x27;0&amp;#x27; и &amp;#x27;1&amp;#x27;
    for x in range(2):
        for z in range(2):
            for w in range(2):
                F = ((not x or y) == (not z or w)) or (x and w) #Записываем функцию
                if not F:
                    print(x, y, z, F) #Выводим результат&lt;/pre&gt;
  &lt;p id=&quot;bsC7&quot;&gt;Результат:&lt;/p&gt;
  &lt;figure id=&quot;2KnJ&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/c4c/8b9/67c/c4c8b967c54340e337b17eb9732522e8.png&quot; width=&quot;979&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;JI6b&quot;&gt;Далее - простой анализ.&lt;/p&gt;
  &lt;h3 id=&quot;c6vq&quot;&gt;Задача 5&lt;/h3&gt;
  &lt;figure id=&quot;j2R7&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/61f/6e2/f0d/61f6e2f0dd2f7378ae4aec09e13e578a.png&quot; width=&quot;837&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;lIHn&quot;&gt;Данная задача легко решается простой последовательностью действий в интерпретационном режиме:&lt;/p&gt;
  &lt;figure id=&quot;7D6H&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/41c/21b/40b/41c21b40ba7779a8d468fc14997e928e.png&quot; width=&quot;979&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;MGxJ&quot;&gt;Задача 6&lt;/h3&gt;
  &lt;figure id=&quot;5CFO&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/4b2/234/efc/4b2234efc992a0cf1aa31496bdbe80d9.png&quot; width=&quot;832&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;C71S&quot;&gt;Перепечатали и получили ответ:&lt;/p&gt;
  &lt;pre id=&quot;p3cM&quot; data-lang=&quot;python&quot;&gt;s = 0
k = 1
while s &amp;lt; 66:
    k += 3
    s += k
print(k)&lt;/pre&gt;
  &lt;h3 id=&quot;TW0n&quot;&gt;Задача 12&lt;/h3&gt;
  &lt;figure id=&quot;M2R7&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/946/931/bca/946931bcacf5d4d827bd9ec29b31f412.png&quot; width=&quot;844&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;0UFe&quot;&gt;В очередной раз, просто заменим слова на код:&lt;/p&gt;
  &lt;pre id=&quot;Q12T&quot; data-lang=&quot;python&quot;&gt;a = &amp;#x27;9&amp;#x27; * 1000

while &amp;#x27;999&amp;#x27; in a or &amp;#x27;888&amp;#x27; in a:
    if &amp;#x27;888&amp;#x27; in a:
        a = a.replace(&amp;#x27;888&amp;#x27;, &amp;#x27;9&amp;#x27;, 1)
    else:
        a = a.replace(&amp;#x27;999&amp;#x27;, &amp;#x27;8&amp;#x27;, 1)
print(a)&lt;/pre&gt;
  &lt;h3 id=&quot;sClC&quot;&gt;Задача 14&lt;/h3&gt;
  &lt;figure id=&quot;QYyD&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b8e/262/971/b8e2629718bb8fd442199a86ccafe479.png&quot; width=&quot;827&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;8YAk&quot;&gt;Компьютер железный, он всё посчитает:&lt;/p&gt;
  &lt;pre id=&quot;zn02&quot; data-lang=&quot;python&quot;&gt;a = 4 ** 2020 + 2 ** 2017 - 15
k = 0

while a &amp;gt; 0:
    if a % 2 == 1:
      	k += 1
    a = a // 2
 
print(k)&lt;/pre&gt;
  &lt;h3 id=&quot;WhBm&quot;&gt;Задача 16&lt;/h3&gt;
  &lt;figure id=&quot;AAq5&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/330/ce4/14c/330ce414cdebc3dff111822d3d5b7a74.png&quot; width=&quot;818&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;G1hM&quot;&gt;Опять же, просто дублируем программу в python:&lt;/p&gt;
  &lt;pre id=&quot;ckYv&quot; data-lang=&quot;python&quot;&gt;def F(n):
    if n &amp;gt; 0:
        F(n // 4)
        print(n)
        F (n - 1)
print(F(5))&lt;/pre&gt;
  &lt;p id=&quot;3pAf&quot;&gt;Результат:&lt;/p&gt;
  &lt;figure id=&quot;THTZ&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/5b3/923/b6e/5b3923b6e0eaa7c20fce425235be4fff.png&quot; width=&quot;979&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;XR9T&quot;&gt;Задача 17&lt;/h3&gt;
  &lt;figure id=&quot;Yeaa&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/e54/fc3/46b/e54fc346bc4dc7261e117042af942488.png&quot; width=&quot;834&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;0r1X&quot;&gt;Задача с &lt;a href=&quot;https://inf-ege.sdamgia.ru/get_file?id=91146&quot; target=&quot;_blank&quot;&gt;файлом&lt;/a&gt;. Самое сложное - достать данные из файла. Но где наша не пропадала?!&lt;/p&gt;
  &lt;pre id=&quot;16EQ&quot; data-lang=&quot;python&quot;&gt;with open(&amp;quot;17.txt&amp;quot;, &amp;quot;r&amp;quot;) as f: #Открыли файл 17.txt для чтения
    text = f.read() #В переменную text запихнули строку целиком
a = text.split(&amp;quot;\n&amp;quot;) #Разбили строку энтерами (\n - знак перехода на новую строку)

k = 0 #Стандартно обнуляем количество
m = -20001 #Так как у нас сумма 2-ух чисел и минимальное равно -10000, то минимум по условию равен -20000, поэтому...

for i in range(len(a)): #Обходим все элементы массива
    if (int(a[i - 1]) % 3 == 0) or (int(a[i]) % 3 == 0): #Условное условие
        k += 1 #Счётчик
        if int(a[i - 1]) + int(a[i]) &amp;gt; m: #Нахождение минимума
            m = int(a[i - 1]) + int(a[i])

print(k, m) #Вывод&lt;/pre&gt;
  &lt;p id=&quot;PshT&quot;&gt;Немного пояснений. Функция with() открывает файл считывает данные при помощи функции read() и закрывает файл. В остальном - задача стандартна.&lt;/p&gt;
  &lt;h3 id=&quot;lkcm&quot;&gt;Задача 19, 20 и 21&lt;/h3&gt;
  &lt;p id=&quot;165v&quot;&gt;Все три задачи - задачи на рекурсию. Задачи идентичны, а вопросы разные. Итак, первая задача:&lt;/p&gt;
  &lt;figure id=&quot;kSpD&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/05a/add/e7b/05aadde7b07966acfdc62720d88e7288.png&quot; width=&quot;837&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;QPEA&quot;&gt;Пишем рекурсивную функцию и цикл перебора S:&lt;/p&gt;
  &lt;pre id=&quot;5CQV&quot; data-lang=&quot;python&quot;&gt;def f(x, y, p): #Рекурсивная функция
    if x + y &amp;gt;= 69 or p &amp;gt; 3: #Условия завершения игры
        return p == 3
    return f(x + 1, y, p + 1) or f(x, y + 1, p + 1) or\
           f(x * 2, y, p + 1) or f(x, y * 3, p + 1) #Варианты действий

for s in range (1, 58 + 1): #Перебор S
    if f(10, s, 1): #Начали с 10 камней
        print(s)
        break&lt;/pre&gt;
  &lt;p id=&quot;xkTR&quot;&gt;Немного пояснений. В рекурсивной функции существует 3 переменные &lt;code&gt;x&lt;/code&gt; - число камней в первой куче, &lt;code&gt;y&lt;/code&gt; - число камней во второй куче, &lt;code&gt;p&lt;/code&gt; - позиция. Позиция рассчитывается по таблице:&lt;/p&gt;
  &lt;figure id=&quot;e5Pt&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/aa/47/aa479817-afbc-45c1-9832-9ba1de51dece.png&quot; width=&quot;755&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;yUro&quot;&gt;Далее - всё по условию задачи.&lt;/p&gt;
  &lt;p id=&quot;aqUO&quot;&gt;Вторая задача на теорию игр:&lt;/p&gt;
  &lt;figure id=&quot;Erxp&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/1e4/8a7/b0d/1e48a7b0db3f2da08b6a10008b9c1df2.png&quot; width=&quot;839&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;tR5a&quot;&gt;Все отличия в рамке. Ну и код, соответственно, не сильно отличается:&lt;/p&gt;
  &lt;pre id=&quot;bzMt&quot; data-lang=&quot;python&quot;&gt;def f(x, y, p): #Рекурсивная функция
    if x + y &amp;gt;= 69 or p &amp;gt; 4: #Условия завершения игры
        return p == 4
    if p % 2 != 0:
        return f(x + 1, y, p + 1) or f(x, y + 1, p + 1) or\
               f(x * 2, y, p + 1) or f(x, y * 3, p + 1) #Варианты действий
    else:
        return f(x + 1, y, p + 1) and f(x, y + 1, p + 1) and\
               f(x * 2, y, p + 1) and f(x, y * 3, p + 1) #Варианты действий


for s in range (1, 58 + 1): #Перебор S
    if f(10, s, 1): #Начали с 10 камней
        print(s)&lt;/pre&gt;
  &lt;p id=&quot;rxQ0&quot;&gt;Отличия:&lt;/p&gt;
  &lt;ol id=&quot;Qpz2&quot;&gt;
    &lt;li id=&quot;uYap&quot;&gt;Выиграл Петя, соответственно, позиция 4&lt;/li&gt;
    &lt;li id=&quot;0UlB&quot;&gt;Так как Петя не может выиграть за один ход - он выигрывает за 2 хода (and, а не or на нечётных позициях (играх Пети))&lt;/li&gt;
    &lt;li id=&quot;LqNj&quot;&gt;Убрали break, так как нам нужны все S, а не единственный&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;F2MX&quot;&gt;Последняя вариация задачи:&lt;/p&gt;
  &lt;figure id=&quot;n9vy&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/76c/374/be7/76c374be7d9d0601f2a4eb77fc268e30.png&quot; width=&quot;836&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;XxqC&quot;&gt;Сразу код:&lt;/p&gt;
  &lt;pre id=&quot;UAuX&quot; data-lang=&quot;python&quot;&gt;def f(x, y, p): #Рекурсивная функция
    if x + y &amp;gt;= 69 or p &amp;gt; 5: #Условия завершения игры
        return p == 3 or p == 5
    if p % 2 == 0:
        return f(x + 1, y, p + 1) or f(x, y + 1, p + 1) or\
               f(x * 2, y, p + 1) or f(x, y * 3, p + 1) #Варианты действий
    else:
        return f(x + 1, y, p + 1) and f(x, y + 1, p + 1) and\
               f(x * 2, y, p + 1) and f(x, y * 3, p + 1) #Варианты действий


for s in range (1, 58 + 1): #Перебор S
    if f(10, s, 1): #Начали с 10 камней
        print(s)&lt;/pre&gt;
  &lt;p id=&quot;AHMw&quot;&gt;Ну и всего лишь 2 отличия:&lt;/p&gt;
  &lt;ol id=&quot;kfK7&quot;&gt;
    &lt;li id=&quot;OlCr&quot;&gt;Позиции 3 или 5, а не 4, так как выиграл Ваня&lt;/li&gt;
    &lt;li id=&quot;MVVw&quot;&gt;На второй ход выигрывает Ваня и нам нужно or и and поменять. Я заменил только кратность 2.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;hAOH&quot;&gt;Задача 22&lt;/h3&gt;
  &lt;figure id=&quot;Wi9R&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/403/423/618/40342361838fb0db70a6eb3c89e32121.png&quot; width=&quot;823&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;YfNr&quot;&gt;Ctrl+C, Ctrl+V - наше всё! :)&lt;/p&gt;
  &lt;pre id=&quot;m8OK&quot; data-lang=&quot;python&quot;&gt;for i in range(1, 100000):
    x = i
    L = 0
    M = 0
    while x &amp;gt; 0 :
        L = L+1
        if (x % 2) != 0:
            M = M + x % 8
        x = x // 8
    if L == 3 and M == 6:
        print(i)&lt;/pre&gt;
  &lt;h3 id=&quot;SHB0&quot;&gt;&lt;/h3&gt;
  &lt;figure id=&quot;CHaU&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b63/d6a/997/b63d6a9978f92d6ce40be18ce054076e.png&quot; width=&quot;836&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;kYeU&quot;&gt;Итак, код:&lt;/p&gt;
  &lt;pre id=&quot;vOyy&quot; data-lang=&quot;python&quot;&gt;def f(x, y):
    if x &amp;gt; y: #Перегнали цель
        return 0
    if x == y:  #Догнали цель
        return 1
    if x &amp;lt; y: #Догоняем цель тремя методами
        return f(x + 1, y) + f(x + 2, y) + f(x * 2, y)

print(f(3, 10) * f(10, 12)) #Прошло через 10, значит догнали 10 и от де догоняем 12&lt;/pre&gt;
  &lt;p id=&quot;RZSt&quot;&gt;Так как в условии задачи мы увеличиваем число, но будем числа &amp;quot;догонять&amp;quot;. Три метода описаны, ну а пройти через 10 - значит дойти до него и идти от него.&lt;/p&gt;
  &lt;p id=&quot;5rAH&quot;&gt;Собственно, это и есть вся первая часть ЕГЭ по информатике решённая на Python.&lt;/p&gt;
  &lt;p id=&quot;hXLK&quot;&gt;&lt;a href=&quot;https://github.com/Babaika25/EGE&quot; target=&quot;_blank&quot;&gt;Ссылка на репозиторий со всеми программами&lt;/a&gt;.&lt;/p&gt;
  &lt;p id=&quot;unhu&quot;&gt;Надеюсь, что смог помочь в своей статье выпускникам и готовящимся ;)&lt;/p&gt;
  &lt;p id=&quot;FMhJ&quot;&gt;Остался один вопрос - нужен ли разбор второй части ЕГЭ по информатике на Python? Оставлю этот вопрос на ваше голосование.&lt;/p&gt;
  &lt;p id=&quot;k08X&quot;&gt;Всем удачи!&lt;/p&gt;

</content></entry><entry><id>valerylinkov:cWbT0W_F3m7</id><link rel="alternate" type="text/html" href="https://teletype.in/@valerylinkov/cWbT0W_F3m7?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=valerylinkov"></link><title>Свойства блочной модели CSS. Объяснение с примерами</title><published>2024-10-30T15:16:40.871Z</published><updated>2024-10-30T17:12:12.034Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/89/de/89ded829-cf4b-4bae-8ae9-1b9f59ce4853.png"></media:thumbnail><category term="gajdy" label="Гайды 📖"></category><summary type="html">&lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/da6/fd4/0cc/da6fd40cc3b9707b7d88a30640001681.png&quot;&gt;Сегодня я подготовил для вас материал по основам по блочной модели CSS. Безусловно, многие из вас знают о чём идёт речь, но сегодня я постараюсь объяснить прописные истины более понятно и наглядно, что поможет вам создавать веб-сайты, с идеально подходящими друг другу элементами (с точностью до пикселя), и научит более точно использовать свойства размеров, полей, отступов и границ. Итак, всех приглашаю под кат и погнали!</summary><content type="html">
  &lt;p id=&quot;1tqZ&quot;&gt;Сегодня я подготовил для вас материал по основам по блочной модели CSS. Безусловно, многие из вас знают о чём идёт речь, но сегодня я постараюсь объяснить прописные истины более понятно и наглядно, что поможет вам создавать веб-сайты, с идеально подходящими друг другу элементами (с точностью до пикселя), и научит более точно использовать свойства размеров, полей, отступов и границ. Итак, всех приглашаю под кат и погнали!&lt;/p&gt;
  &lt;figure id=&quot;FcUq&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/da6/fd4/0cc/da6fd40cc3b9707b7d88a30640001681.png&quot; width=&quot;1910&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;bswk&quot;&gt;Оглавление&lt;/h2&gt;
  &lt;ul id=&quot;dPVn&quot;&gt;
    &lt;li id=&quot;EOyD&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/569530/#1&quot; target=&quot;_blank&quot;&gt;Зачем изучать блочную модель CSS?&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;gaZR&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/569530/#2&quot; target=&quot;_blank&quot;&gt;Структура блочной модели CSS&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;TUXY&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/569530/#3&quot; target=&quot;_blank&quot;&gt;Свойство Padding&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;U4DA&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/569530/#4&quot; target=&quot;_blank&quot;&gt;Свойство Border&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;3IAK&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/569530/#5&quot; target=&quot;_blank&quot;&gt;Свойство Margin&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;e8wL&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/569530/#6&quot; target=&quot;_blank&quot;&gt;Свойство box-sizing&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;ivmy&quot;&gt;&lt;a href=&quot;https://habr.com/ru/articles/569530/#7&quot; target=&quot;_blank&quot;&gt;Content-box VS Border-box&lt;/a&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h2 id=&quot;jzeC&quot;&gt;Зачем изучать блочную модель CSS?&lt;/h2&gt;
  &lt;figure id=&quot;D2pL&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/80a/2ab/007/80a2ab007f77399939a7f73c7fa11841.png&quot; width=&quot;861&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;4gwq&quot;&gt;Блочная модель CSS состоит из свойств: &lt;strong&gt;box-sizing&lt;/strong&gt;, &lt;strong&gt;padding &lt;/strong&gt;и &lt;strong&gt;margin&lt;/strong&gt;. Если их &lt;strong&gt;не&lt;/strong&gt; использовать, то получим что-то похожее ​&lt;/p&gt;
  &lt;figure id=&quot;ExJw&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/441/f22/b2b/441f22b2b680cafc1e673b08618f896a.png&quot; width=&quot;1440&quot; /&gt;
    &lt;figcaption&gt;Веб-сайт без полей и отступов&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;F0QO&quot;&gt;Но если вы будете правильно использовать свойства блочной модели, ваш сайт будет выглядеть так ​&lt;/p&gt;
  &lt;figure id=&quot;0Pxe&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/101/189/2bf/1011892bffd572f05ce5f5e7d3152ee7.png&quot; width=&quot;1440&quot; /&gt;
    &lt;figcaption&gt;Веб-сайт, использующий свойства блочной модели&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;bQgL&quot;&gt;Выглядит гораздо более привлекательно, не так ли? Если вы хотите создать свой сайт с точными расчетами, как тот, что указан выше​, то вы попали по адресу. Изучение блочной модели CSS - один из многих способов, которые помогут вам сделать &lt;strong&gt;веб-сайты, идеальные до пикселя.&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;fot8&quot;&gt;В этой статье мы поговорим о том, как использовать эти свойства:&lt;/p&gt;
  &lt;ul id=&quot;N3Ux&quot;&gt;
    &lt;li id=&quot;mQq0&quot;&gt;Padding&lt;/li&gt;
    &lt;li id=&quot;p1zI&quot;&gt;Margin&lt;/li&gt;
    &lt;li id=&quot;4onX&quot;&gt;Border&lt;/li&gt;
    &lt;li id=&quot;eh38&quot;&gt;box-sizing&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;3Hbl&quot;&gt;Как использовать свойства блочной модели CSS&lt;/h3&gt;
  &lt;p id=&quot;ITlf&quot;&gt;Давайте посмотрим на несколько примеров, где мы можем использовать свойства блочной модели CSS. Мы собираемся проанализировать &lt;strong&gt;сайт, показанный выше. ​&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;2KHG&quot;&gt;Давайте внимательнее посмотрим на навигационную панель (&lt;strong&gt;navbar&lt;/strong&gt;). Вы можете заметить разницу между примером, в котором используется свойство &lt;strong&gt;padding&lt;/strong&gt;, и примером, в котором его нет:&lt;/p&gt;
  &lt;figure id=&quot;d1qo&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/a8f/ca0/1cb/a8fca01cb333433307765a5e7c1aa93c.png&quot; width=&quot;990&quot; /&gt;
    &lt;figcaption&gt;Элементы навигационной панели, использующие свойство padding&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;8hZ1&quot;&gt;Теперь давайте подробнее рассмотрим &lt;strong&gt;раздел содержимого вместе с кнопками&lt;/strong&gt;. Опять же, вы заметите разницу - на правой картинке также используется свойство &lt;strong&gt;padding&lt;/strong&gt;.&lt;/p&gt;
  &lt;figure id=&quot;VrBj&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/f87/f44/4bc/f87f444bc25a0487cb3bd3f7589b80ef.png&quot; width=&quot;990&quot; /&gt;
    &lt;figcaption&gt;Раздел содержимого, использующий свойство padding&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;PaF9&quot;&gt;Структура блочной модели CSS&lt;/h3&gt;
  &lt;p id=&quot;YZ4m&quot;&gt;Говоря о блочной модели, стоит воспринимать её как &lt;strong&gt;луковицу&lt;/strong&gt;. И эта &amp;quot;луковица&amp;quot; имеет &lt;strong&gt;4 слоя&lt;/strong&gt;:&lt;/p&gt;
  &lt;ul id=&quot;6knM&quot;&gt;
    &lt;li id=&quot;aIdA&quot;&gt;&lt;strong&gt;1&lt;/strong&gt; слой: Content&lt;/li&gt;
    &lt;li id=&quot;zzmg&quot;&gt;&lt;strong&gt;2 &lt;/strong&gt;слой: Padding&lt;/li&gt;
    &lt;li id=&quot;SJI0&quot;&gt;&lt;strong&gt;3 &lt;/strong&gt;слой: Border&lt;/li&gt;
    &lt;li id=&quot;b6ji&quot;&gt;&lt;strong&gt;4 &lt;/strong&gt;слой: Margin&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h3 id=&quot;Pac8&quot;&gt;1 слой блочной модели: Content&lt;/h3&gt;
  &lt;p id=&quot;2Hz7&quot;&gt;В HTML &lt;strong&gt;все ведет себя как ящик с контентом&lt;/strong&gt;. Давайте вставим контент с изображением котенка. ​&lt;/p&gt;
  &lt;figure id=&quot;65NW&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/d7f/ad8/4a5/d7fad84a50937820fb0b8bd74630fa09.png&quot; width=&quot;857&quot; /&gt;
    &lt;figcaption&gt;Первый слой&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;rjP2&quot;&gt;2 слой блочной модели: Padding&lt;/h3&gt;
  &lt;p id=&quot;OGpu&quot;&gt;Следующий слой блочной модели CSS - это слой &lt;strong&gt;заполнения&lt;/strong&gt;. Он обертывает наш контент следующим образом ​&lt;/p&gt;
  &lt;figure id=&quot;AH5u&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/376/abe/18a/376abe18ada076ff3ffe2307366478e7.png&quot; width=&quot;857&quot; /&gt;
    &lt;figcaption&gt;Второй слой&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;24Hp&quot;&gt;3 слой блочной модели: Border&lt;/h3&gt;
  &lt;p id=&quot;zuP3&quot;&gt;Следующий слой блочной модели CSS - это &lt;strong&gt;пограничный&lt;/strong&gt; слой. Он обертывает наш контент + отступы следующим образом ​&lt;/p&gt;
  &lt;figure id=&quot;E6bB&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/96f/b54/e3b/96fb54e3b2ef16763c229889efcee4e9.png&quot; width=&quot;857&quot; /&gt;
    &lt;figcaption&gt;Черная пунктирная линия - граница&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h4 id=&quot;nvIe&quot;&gt;4 слой блочной модели: Margin&lt;/h4&gt;
  &lt;p id=&quot;pZuy&quot;&gt;Следующим и последним слоем блочной модели CSS является слой &lt;strong&gt;полей&lt;/strong&gt;. Он обертывает наш &lt;strong&gt;контент + отступ + границу &lt;/strong&gt;следующим образом&lt;strong&gt; ​&lt;/strong&gt;&lt;/p&gt;
  &lt;figure id=&quot;sunK&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/afe/975/404/afe975404bad4c07454385c21b1a6a65.png&quot; width=&quot;857&quot; /&gt;
    &lt;figcaption&gt;Четвёртый слой&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;YzlL&quot;&gt;Итак, давайте посмотрим, как эти свойства работают в проекте.&lt;/p&gt;
  &lt;h2 id=&quot;FPZ1&quot;&gt;Как настроить проект&lt;/h2&gt;
  &lt;figure id=&quot;OmuL&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/3d0/beb/888/3d0beb888b9f4d6ce66b493c8adcc5af.png&quot; width=&quot;748&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;gDm2&quot;&gt;Это руководство &lt;strong&gt;подходит для всех, в том числе для новичков. &lt;/strong&gt;Если вы хотите писать код, выполните следующие действия.&lt;/p&gt;
  &lt;h3 id=&quot;bPCS&quot;&gt;HTML&lt;/h3&gt;
  &lt;p id=&quot;9dZO&quot;&gt;Откройте VS Code или &lt;a href=&quot;http://codepen.io/&quot; target=&quot;_blank&quot;&gt;&lt;u&gt;Codepen.io&lt;/u&gt;&lt;/a&gt; и напишите этот код ​ внутри &lt;strong&gt;тега body:&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;wBO0&quot; data-lang=&quot;html&quot;&gt;&amp;lt;div class=&amp;quot;box-1&amp;quot;&amp;gt; Box-1 &amp;lt;/div&amp;gt;&lt;/pre&gt;
  &lt;h3 id=&quot;wY1D&quot;&gt;CSS&lt;/h3&gt;
  &lt;p id=&quot;Uoh7&quot;&gt;Очистите стили нашего браузера по умолчанию ​&lt;/p&gt;
  &lt;pre id=&quot;pgw4&quot; data-lang=&quot;css&quot;&gt;* {
  margin: 0px;
  padding: 0px;
  font-family: sans-serif;
}&lt;/pre&gt;
  &lt;p id=&quot;SDQ2&quot;&gt;Теперь давайте стилизуем наш блок ​&lt;/p&gt;
  &lt;pre id=&quot;9klQ&quot; data-lang=&quot;css&quot;&gt;.box-1 {
  width: 300px;
  background-color: skyblue;
  font-size: 50px;
}Все готово, приступим к программированию! ​&lt;/pre&gt;
  &lt;figure id=&quot;6zW0&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b08/993/2b6/b089932b693baad0ed0a7a4c339f2b21.png&quot; width=&quot;748&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;9Iep&quot;&gt;Свойство Padding&lt;/h2&gt;
  &lt;p id=&quot;9Tdv&quot;&gt;Но сначала давайте обсудим &lt;strong&gt;практическое использование&lt;/strong&gt; свойства padding. Затем мы увидим, как использовать это свойство.&lt;/p&gt;
  &lt;p id=&quot;IVHV&quot;&gt;Обычно я использую отступы, &lt;strong&gt;чтобы оставить пространство между содержимым. &lt;/strong&gt;Посмотрите на эту навигационную панель&lt;strong&gt; ​&lt;/strong&gt;&lt;/p&gt;
  &lt;figure id=&quot;yEk3&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/37f/a27/d34/37fa27d34c5ad75d1ad98dc60c186b48.png&quot; width=&quot;990&quot; /&gt;
    &lt;figcaption&gt;Элементы навигационной панели, использующие свойство padding&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;lU4p&quot;&gt;Вот вам еще один пример - посмотрите на содержимое ниже с двумя кнопками​&lt;/p&gt;
  &lt;figure id=&quot;HP5y&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/38d/881/75e/38d88175e0af4548934b11d8002d67fe.png&quot; width=&quot;990&quot; /&gt;
    &lt;figcaption&gt;раздел содержимого с использованием свойства заполнения&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;3ty6&quot;&gt;Как использовать свойство padding в CSS&lt;/h3&gt;
  &lt;p id=&quot;d1wO&quot;&gt;Ниже представлены названия четырех свойств заполнения:&lt;/p&gt;
  &lt;ul id=&quot;U3fi&quot;&gt;
    &lt;li id=&quot;Jpl8&quot;&gt;padding-top&lt;/li&gt;
    &lt;li id=&quot;dmyC&quot;&gt;padding-right&lt;/li&gt;
    &lt;li id=&quot;NRDr&quot;&gt;padding-bottom&lt;/li&gt;
    &lt;li id=&quot;y3am&quot;&gt;padding-left&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;uToE&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/ba2/497/aff/ba2497affc9e76e15595f55eceb69a76.png&quot; width=&quot;748&quot; /&gt;
    &lt;figcaption&gt;Свойства padding&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;kwAc&quot;&gt;И помните, что отступы - это пространство, которое вы добавляете&lt;strong&gt; поверх &lt;/strong&gt;основного контента&lt;strong&gt;:&lt;/strong&gt;&lt;/p&gt;
  &lt;figure id=&quot;fPhl&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/142/81f/d03/14281fd03d6f5cfe453e7d8e355aecd3.png&quot; width=&quot;857&quot; /&gt;
    &lt;figcaption&gt;Второй слой&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;4Zs8&quot;&gt;Давайте добавим отступы к нашему контенту. &lt;strong&gt;Область красного цвета - это отступ ​&lt;/strong&gt;&lt;/p&gt;
  &lt;figure id=&quot;b80k&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/getpro/habr/upload_files/87e/2ef/291/87e2ef291042ae47b535e05f6fd0341f.gif&quot; width=&quot;864&quot; /&gt;
    &lt;figcaption&gt;Область красного цвета - это отступ&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ccYf&quot;&gt;Чтобы воссоздать результаты, указанные выше, ​ напишите этот код в свой CSS: ​&lt;/p&gt;
  &lt;pre id=&quot;Mn1B&quot; data-lang=&quot;css&quot;&gt;// Padding added on top, right, left, bottom of .box-1

.box-1{
   padding : 100px;
}&lt;/pre&gt;
  &lt;p id=&quot;I3i5&quot;&gt;Откроем консоль разработчика и &lt;strong&gt;перейдем в вычисляемый раздел&lt;/strong&gt;:&lt;/p&gt;
  &lt;figure id=&quot;fi6O&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/279/046/1e5/2790461e5fb59e4e338ceb3d1e1f7075.png&quot; width=&quot;1013&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;8xnI&quot;&gt;В самом центре - &lt;strong&gt;контент&lt;/strong&gt;, который &lt;strong&gt;300px&lt;/strong&gt; в ширину. Посмотрите, вокруг контента мы добавили &lt;strong&gt;отступы по 100 пикселей&lt;/strong&gt;.&lt;/p&gt;
  &lt;p id=&quot;Y9xh&quot;&gt;Давайте попробуем добавить отступ &lt;strong&gt;только к одной стороне нашего контента (только с правой стороны):&lt;/strong&gt;&lt;/p&gt;
  &lt;figure id=&quot;anRQ&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/2f6/0b5/a4a/2f60b5a4a605ad5d293cdc3ab693575a.png&quot; width=&quot;664&quot; /&gt;
    &lt;figcaption&gt;свойство padding-right&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;xbqq&quot;&gt;Чтобы воссоздать результаты, указанные выше, ​ напишите этот код в свой CSS: ​&lt;/p&gt;
  &lt;pre id=&quot;ROoi&quot; data-lang=&quot;css&quot;&gt;.box-1{
   padding: 0 100px 0 0;
}

// Or you can use ​
.box-1{
   padding-right: 100px;
}&lt;/pre&gt;
  &lt;p id=&quot;Wsba&quot;&gt;Теперь откройте вычисляемый раздел в консоли разработчика ​&lt;/p&gt;
  &lt;figure id=&quot;KAt1&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/c05/46b/2ad/c0546b2ad017b507d18e461992f3a40e.png&quot; width=&quot;995&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;hF6X&quot;&gt;Посмотрите - отступ в 100 пикселей был добавлен &lt;strong&gt;только с правой стороны&lt;/strong&gt; нашего контента, как мы указали.&lt;/p&gt;
  &lt;h2 id=&quot;FSES&quot;&gt;Свойство Border&lt;/h2&gt;
  &lt;p id=&quot;Byov&quot;&gt;Обычно вы будете использовать свойство border при создании&lt;strong&gt; кнопок&lt;/strong&gt;. Вот демонстрация GIF ​&lt;/p&gt;
  &lt;figure id=&quot;0Po7&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/getpro/habr/upload_files/3d0/f8d/6be/3d0f8d6bea300820c57f894a97ffe902.gif&quot; width=&quot;480&quot; /&gt;
    &lt;figcaption&gt;Кнопки, использующие свойство Border&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;vv9e&quot;&gt;Обратите внимание, как появляется &lt;strong&gt;белая рамка&lt;/strong&gt; вокруг кнопки, когда наводится указатель мыши на кнопку.&lt;/p&gt;
  &lt;h3 id=&quot;1sti&quot;&gt;Как использовать свойство границы в CSS&lt;/h3&gt;
  &lt;p id=&quot;9nB9&quot;&gt;И помните, &lt;strong&gt;граница&lt;/strong&gt; - это пространство, добавленное поверх нашего &lt;strong&gt;контента + отступа&lt;/strong&gt;: &lt;strong&gt;​&lt;/strong&gt;&lt;/p&gt;
  &lt;figure id=&quot;fY2W&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/499/b6a/ed3/499b6aed3b1bcc5eae2f0dd82b3f134b.png&quot; width=&quot;857&quot; /&gt;
    &lt;figcaption&gt;Черная пунктирная линия - граница&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;QPCq&quot;&gt;Есть три важных &lt;strong&gt;параметра&lt;/strong&gt; свойства границы:&lt;/p&gt;
  &lt;ul id=&quot;FqqC&quot;&gt;
    &lt;li id=&quot;StlL&quot;&gt;border size&lt;/li&gt;
    &lt;li id=&quot;dhqv&quot;&gt;border style: &lt;strong&gt;solid &lt;/strong&gt;(сплошная линия)&lt;strong&gt; / dotted &lt;/strong&gt;(&amp;quot;точечная&amp;quot; линия)&lt;strong&gt; / dashed &lt;/strong&gt;(пунктир)&lt;/li&gt;
    &lt;li id=&quot;9BxI&quot;&gt;border color&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;zNKa&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/62c/bd4/9a8/62cbd49a8bae6a8a10609880789e3711.png&quot; width=&quot;748&quot; /&gt;
    &lt;figcaption&gt;Синтаксис свойства границы&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;qvk2&quot;&gt;Как я перечислил выше, существует три стиля свойства границы. В этом примере мы будем использовать &lt;strong&gt;пунктирный&lt;/strong&gt; стиль:&lt;/p&gt;
  &lt;figure id=&quot;NYa3&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/ce8/bb7/e10/ce8bb7e104305e0ec9fae8a675086071.png&quot; width=&quot;636&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;gO5e&quot;&gt;Чтобы воссоздать приведенные выше результаты, напишите этот код в своем CSS: ​&lt;/p&gt;
  &lt;pre id=&quot;vwhw&quot; data-lang=&quot;css&quot;&gt;.box-1 {
  width: 300px;
  font-size: 50px;
  padding: 50px;
  border: 10px dashed black;
}&lt;/pre&gt;
  &lt;p id=&quot;w250&quot;&gt;Откроем консоль и посмотрим расчеты блочной модели:&lt;/p&gt;
  &lt;figure id=&quot;ezkg&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/c4e/b1d/e02/c4eb1de02052699611e9b0beae789448.png&quot; width=&quot;967&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;BCR8&quot;&gt;Теперь посмотрите на изображение выше​ - вокруг нашего &lt;strong&gt;контента + отступа&lt;/strong&gt; добавлена ​​&lt;strong&gt;граница&lt;/strong&gt; 10 пикселей.&lt;/p&gt;
  &lt;h2 id=&quot;x2oN&quot;&gt;Свойство Margin&lt;/h2&gt;
  &lt;p id=&quot;EBJr&quot;&gt;Обычно я использую свойство &lt;strong&gt;margin,&lt;/strong&gt; чтобы добавить &lt;strong&gt;отступ&lt;/strong&gt; между моим контентом и экраном на макете рабочего стола. Посмотрите на эту гифку:&lt;/p&gt;
  &lt;figure id=&quot;djL2&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/getpro/habr/upload_files/2ca/496/051/2ca496051674a2495df26a24d322247a.gif&quot; width=&quot;680&quot; /&gt;
    &lt;figcaption&gt;Добавление отступов на сайт&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;g1vH&quot;&gt;Обратите внимание, что я добавил поля к левому и правому краям веб-сайта выше ​&lt;/p&gt;
  &lt;p id=&quot;iKUc&quot;&gt;Вот еще один пример &lt;strong&gt;использования&lt;/strong&gt; свойства margin: ​&lt;/p&gt;
  &lt;figure id=&quot;CcKH&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/getpro/habr/upload_files/218/c16/135/218c1613575c6c333ff577faf88d820b.gif&quot; width=&quot;680&quot; /&gt;
    &lt;figcaption&gt;Добавление отступов на сайт&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;0rcR&quot;&gt;Как использовать свойство margin в CSS&lt;/h3&gt;
  &lt;p id=&quot;egHp&quot;&gt;Margin имеет всего четыре &lt;strong&gt;свойства&lt;/strong&gt; поля:&lt;/p&gt;
  &lt;ul id=&quot;eilH&quot;&gt;
    &lt;li id=&quot;ZqUl&quot;&gt;margin-top&lt;/li&gt;
    &lt;li id=&quot;VNRo&quot;&gt;margin-right&lt;/li&gt;
    &lt;li id=&quot;vwwp&quot;&gt;margin-bottom&lt;/li&gt;
    &lt;li id=&quot;pb3B&quot;&gt;margin-left&lt;/li&gt;
  &lt;/ul&gt;
  &lt;figure id=&quot;ij3h&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/1a5/907/703/1a5907703aaff57d313eb8a1d176dbcb.png&quot; width=&quot;748&quot; /&gt;
    &lt;figcaption&gt;Свойства margin&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;USq6&quot;&gt;И помните, &lt;strong&gt;margin&lt;/strong&gt; - это пространство, добавленное поверх нашего &lt;strong&gt;контента + отступы &lt;/strong&gt;(по padding)&lt;strong&gt; + границы&lt;/strong&gt;:&lt;/p&gt;
  &lt;figure id=&quot;Jq1W&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/b71/23d/68f/b7123d68f7a9ed9a67c56968fe144b1f.png&quot; width=&quot;857&quot; /&gt;
    &lt;figcaption&gt;Серая область - margin&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;HfCj&quot;&gt;Давайте добавим отступ к нашему контенту. Весь наш набор &lt;strong&gt;смещается&lt;/strong&gt; из-за &lt;strong&gt;margin&lt;/strong&gt;,как в этом GIF: &lt;strong&gt;​&lt;/strong&gt;&lt;/p&gt;
  &lt;figure id=&quot;wCG0&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/getpro/habr/upload_files/444/d74/a99/444d74a9902e8a647ffe31b12acdc454.gif&quot; width=&quot;876&quot; /&gt;
    &lt;figcaption&gt;Смещение&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ZfVD&quot;&gt;Чтобы воссоздать приведенные выше результаты, напишите этот код в своем CSS: ​&lt;/p&gt;
  &lt;pre id=&quot;fWab&quot; data-lang=&quot;css&quot;&gt;.box-1 {
  padding: 50px;
  border: 10px dashed black;
  
  margin: 50px;
}&lt;/pre&gt;
  &lt;p id=&quot;pPnh&quot;&gt;Можем еще раз проверить расчеты: ​&lt;/p&gt;
  &lt;figure id=&quot;ml3s&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/e6b/dc9/e3a/e6bdc9e3a0d52372e809f269320ff88f.png&quot; width=&quot;947&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;GjhG&quot;&gt;Посмотрите, вокруг нашего &lt;strong&gt;контента + отступов + границы&lt;/strong&gt; было добавлено поле 50 пикселей .&lt;/p&gt;
  &lt;p id=&quot;t4VZ&quot;&gt;Давайте попробуем добавить &lt;strong&gt;поле&lt;/strong&gt; только к одной стороне нашего контента (только левой стороне):&lt;/p&gt;
  &lt;figure id=&quot;TAWW&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/ec8/a8e/7bf/ec8a8e7bfa6fff9d28db12285f588c07.png&quot; width=&quot;636&quot; /&gt;
    &lt;figcaption&gt;Свойство margin-left&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;m9f2&quot;&gt;Чтобы воссоздать результаты выше, напишите этот код в своем CSS ​&lt;/p&gt;
  &lt;pre id=&quot;zR4y&quot; data-lang=&quot;css&quot;&gt;.box-1 {
  padding: 50px;
  border: 10px dashed black;
  margin-left: 50px;
}&lt;/pre&gt;
  &lt;p id=&quot;wOH2&quot;&gt;На консоли мы видим, что &lt;strong&gt;поле&lt;/strong&gt; в &lt;strong&gt;50 пикселей&lt;/strong&gt; применено только к &lt;strong&gt;левой стороне&lt;/strong&gt; ​&lt;/p&gt;
  &lt;figure id=&quot;Cx9z&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/2c2/c4f/414/2c2c4f4144b5060d4e7add7793213203.png&quot; width=&quot;827&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;lYEJ&quot;&gt;Свойство box-sizing&lt;/h2&gt;
  &lt;p id=&quot;QSmM&quot;&gt;Это свойство определяет, как будут рассчитываться поля, отступы и границы. Есть &lt;strong&gt;три типа вычислений&lt;/strong&gt; (можно называть их &lt;strong&gt;свойствами&lt;/strong&gt;):&lt;/p&gt;
  &lt;ul id=&quot;jURe&quot;&gt;
    &lt;li id=&quot;5FV6&quot;&gt;border-box&lt;/li&gt;
    &lt;li id=&quot;yXmV&quot;&gt;padding-box&lt;/li&gt;
    &lt;li id=&quot;tjtY&quot;&gt;content-box&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h4 id=&quot;1gnU&quot;&gt;Примечание:&lt;/h4&gt;
  &lt;p id=&quot;jfDT&quot;&gt;Мы не будем обсуждать &lt;strong&gt;padding-box&lt;/strong&gt;, поскольку его поддерживает только Firefox, и он используется не очень часто.&lt;/p&gt;
  &lt;h2 id=&quot;kIAJ&quot;&gt;В чем разница между content-box и border-box в CSS?&lt;/h2&gt;
  &lt;p id=&quot;DxwQ&quot;&gt;И &lt;strong&gt;border-box&lt;/strong&gt;, и &lt;strong&gt;content-box&lt;/strong&gt; работают одинаково. Посмотрите на эти изображения: ​&lt;/p&gt;
  &lt;figure id=&quot;yJZ5&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/5a9/beb/e5c/5a9bebe5c3c39096f10d884886230774.png&quot; width=&quot;664&quot; /&gt;
    &lt;figcaption&gt;Блоки, использующие свойство border-box&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;figure id=&quot;0h4A&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/125/e0d/2a8/125e0d2a8e1942f1a5dfe91d9157a087.png&quot; width=&quot;664&quot; /&gt;
    &lt;figcaption&gt;Блоки, использующие свойство content-box&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;hUeT&quot;&gt;Итак, в чем здесь главное отличие? Разница заметна, когда мы добавляем поля, границу или отступы к нашим блокам.&lt;/p&gt;
  &lt;p id=&quot;rAl1&quot;&gt;Когда мы используем &lt;strong&gt;box-sizing: content-box&lt;/strong&gt;, который является значением по умолчанию, он &lt;strong&gt;добавит&lt;/strong&gt; поля, отступы и границы &lt;strong&gt;за пределами поля&lt;/strong&gt;, например: ​&lt;/p&gt;
  &lt;figure id=&quot;enf8&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/getpro/habr/upload_files/fac/420/31a/fac42031a3700a153631f6cd2d625c92.gif&quot; width=&quot;904&quot; /&gt;
    &lt;figcaption&gt;Заполнение применяется стандартно&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;1wiQ&quot;&gt;Вы также можете увидеть расчеты здесь: ​&lt;/p&gt;
  &lt;figure id=&quot;T9Ij&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/r/w1560/getpro/habr/upload_files/1a9/8c6/0ea/1a98c60ea741994d42cd0af6b7c70a00.png&quot; width=&quot;664&quot; /&gt;
    &lt;figcaption&gt;Расчеты с content-box&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Ubxh&quot;&gt;Это означает, что все может выйти из-под контроля, и вы можете получить неожиданный результат. Это означает, что при таком подходе, будет &lt;strong&gt;сложно создавать адаптивные веб-сайты. &lt;/strong&gt;Вместо этого всегда используйте свойство &lt;strong&gt;box-sizing: border-box&lt;/strong&gt;.&lt;/p&gt;
  &lt;p id=&quot;Ou3y&quot;&gt;Но когда мы используем свойство &lt;strong&gt;box-sizing: border-box&lt;/strong&gt;, оно &lt;strong&gt;добавит&lt;/strong&gt; поля, отступы и границы &lt;strong&gt;вовнутрь блока&lt;/strong&gt;, например: ​&lt;/p&gt;
  &lt;figure id=&quot;CJs5&quot; class=&quot;m_custom&quot;&gt;
    &lt;img src=&quot;https://habrastorage.org/getpro/habr/upload_files/5c5/97c/68c/5c597c68cbc63f51d8ec9e41aec1e56d.gif&quot; width=&quot;904&quot; /&gt;
    &lt;figcaption&gt;Применение вовнутрь блока&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;TAmr&quot;&gt;В &lt;strong&gt;box-sizing: border-box&lt;/strong&gt; абсолютно точные расчеты HTML - элементов, а это значит, что такой способ является идеальным для создания адаптивных веб-сайтов.&lt;/p&gt;
  &lt;p id=&quot;Sa2c&quot;&gt;Вы также можете поэкспериментировать со значениями - просто используйте этот код: ​&lt;/p&gt;
  &lt;pre id=&quot;PuxN&quot; data-lang=&quot;css&quot;&gt;* {
  box-sizing: border-box;
}

/* Or, Write ​ */
* {
  box-sizing: content-box;
}&lt;/pre&gt;
  &lt;h2 id=&quot;M8uq&quot;&gt;Заключение&lt;/h2&gt;
  &lt;p id=&quot;2DT5&quot;&gt;Вот собственно и всё. Для желающих оставлю ссылку на видео-инструкцию к данному уроку от автора (Джоя Шахеба):&lt;/p&gt;
  &lt;figure id=&quot;610550a7920526a288c7e194&quot; class=&quot;m_16x9&quot;&gt;
    &lt;iframe src=&quot;https://embedd.srv.habr.com/iframe/610550a7920526a288c7e194&quot;&gt;&lt;/iframe&gt;
  &lt;/figure&gt;

</content></entry></feed>