<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
  <channel>
    <language>ru</language>
    <title>Создание простых игр на Java</title>
    <description>Подробные руководства, как создать простые игры на Java меньше, чем за час</description>
    <link>https://tproger.ru/tag/simple-java-games</link>
    <atom:link href="https://tproger.ru/tag/simple-java-games/feed" rel="self" type="application/rss+xml"/>
    <lastBuildDate>Thu, 24 Sep 2026 02:40:18 GMT</lastBuildDate>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>12</sy:updateFrequency>
    <image>
      <title>Создание простых игр на Java</title>
      <link>https://tproger.ru</link>
      <url>https://tproger.ru/apple-touch-icon.png</url>
    </image>
    <item>
      <title>Недельный геймдев: #242 — 7 сентября, 2025</title>
      <link>https://tproger.ru/articles/nedelnyj-gejmdev---242---7-sentyabrya--2025</link>
      <comments>https://tproger.ru/articles/nedelnyj-gejmdev---242---7-sentyabrya--2025?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Андрей Апанасик]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/nedelnyj-gejmdev---242---7-sentyabrya--2025</guid>
      <description><![CDATA[<p>Продажи The King is Watching достигли 300к копий, онлайн Silksong в Steam превысил 500к человек, No Man’s Sky достигла лучшего онлайна в Steam за 7 лет, отменённую Perfect Dark почти воскресили, но сделка сорвалась.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/nedelnyj-gejmdev---242---7-sentyabrya--2025">Недельный геймдев: #242 — 7 сентября, 2025</a>»</p>]]></description>
      <category><![CDATA[Разработка игр]]></category>
      <category><![CDATA[Игры для программистов]]></category>
      <category><![CDATA[Создание простых игр на Java]]></category>
      <category><![CDATA[Разработка]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Mon, 08 Sep 2025 07:22:39 GMT</pubDate>
      <content:encoded><![CDATA[<p>Из новостей: продажи The King is Watching достигли 300к копий, онлайн  Silksong в Steam превысил 500к человек, No Man’s Sky достигла лучшего  онлайна в Steam за 7 лет, отменённую Perfect Dark почти воскресили, но  сделка сорвалась.</p><p>Из интересностей: ужасные игровые миссии, орбитальная механика,  опубликовал свой первый пиксельный Asset Pack для itchio и попал на 1  место в Популярном, как не потерять свою игру.</p><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/4f93b4ce-8547-4570-8b37-1b1193723e04.jpg" alt="" /></figure><h2>Обновления/релизы/новости</h2><h2>Продажи The King is Watching достигли 300к копий</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/0dea82df-fbbc-415a-8cc3-eeaf5d7ed8cc.jpg" alt="" /></figure><p>На взятие этой отметки игре <a href="https://x.com/TKIWGame/status/1963226844141891767">понадобилось</a> полтора месяца.</p><h2>Независимые разработчики опасаются, что низкая цена Hollow Knight: Silksong навредит инди-индустрии</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/b857a5b1-a3de-49c7-bd13-5601ea77991f.png" alt="" /></figure><p>Совсем недавно наблюдали переносы игр индюков на фоне релиза Силксонга, но теперь совсем кекные крики пошли — инди-разработчики <a href="https://www.eurogamer.net/is-hollow-knight-silksongs-cheap-price-a-problem-for-other-indie-games-devs-and-publishers-weigh-up-its-impact">жалуются</a> на то, что «низкая цена Hollow Knight: Silksong навредит инди-индустрии»😂</p><p>Отметились:</p><ul><li>Геймдиректор Unbeatable, который <a href="https://bsky.app/profile/rj.dcellgames.com/post/3lxlbk2ldkc2s">думает</a>, что такая политика формирует у игроков установку, будто игры подобного уровня должны стоить всего 20 долларов.</li><li>Разрабы Dorfromantik считают, что назначить справедливую цену на<br />новую игру будет сложно, «ведь игроки будут сравнивать её с $20 за<br />Silksong».</li></ul><p>В целом жалобы на то, что у Team Cherry куча денег, поэтому «они  могут себе это позволить». Звучит максимально тупо, как по мне.  Последний раз подобный кринж мы наблюдали, когда были жалобы на то, что  «BG3 завысит планку ожиданий игроков».</p><h2>Онлайн Hollow Knight: Silksong в Steam превысил 500к человек</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/1063deab-2f9b-4590-a5e2-410186291559.png" alt="" /></figure><p>Игра <a href="https://steamdb.info/app/1030300/charts/">вошла в топ-20</a> в истории платформы по одновременному количеству игроков.</p><h2>No Man’s Sky достигла лучшего онлайна в Steam за 7 лет — более 93к одновременных игроков</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/c100b92a-c4cc-4a01-bd76-98c313358f32.jpg" alt="" /></figure><p>Космическая «песочница» также <a href="https://steamdb.info/app/275850/charts/#max">вошла</a> в топ-10 самых популярных игр августа для Steam Deck.</p><h2>Subnautica 2 стала самой желаемой игрой в Steam после выхода Hollow Knight: Silksong</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/725269a9-97f0-40a5-a76e-68f4142fff8e.png" alt="" /></figure><p>Судебные драмы <a href="https://www.gamesradar.com/games/survival/subnautica-2-takes-the-crown-on-steams-top-wishlists-chart-after-hollow-knight-silksong-finally-releases-despite-its-usd250-million-lawsuit/">не уменьшили интереса</a> аудитории к игре.</p><h2>Heroes of Might and Magic: Olden Era добавили в вишлисты более 750к пользователей Steam</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/050d958c-c417-4250-ae82-1636357c8038.jpg" alt="" /></figure><p>Игра по-прежнему <a href="https://app2top.ru/news/heroes-of-might-and-magic-olden-era-dobavili-v-vishlisty-bolee-750-ty-syach-pol-zovatelej-steam-233758.html">остаётся</a> самой желаемой пошаговой стратегией в Steam — такое звание игра носит как минимум с апреля.</p><h2>Отменённую Perfect Dark почти воскресили, но сделка сорвалась</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/67ee180e-4e54-4bda-8ba7-3ad21219f63a.jpg" alt="" /></figure><p>Проект <a href="https://www.bloomberg.com/news/articles/2025-09-02/-perfect-dark-developer-lays-off-staff-after-funding-deal-falls-through?accessToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJTdWJzY3JpYmVyR2lmdGVkQXJ0aWNsZSIsImlhdCI6MTc1NjgzNDY3OSwiZXhwIjoxNzU3NDM5NDc5LCJhcnRpY2xlSWQiOiJUMVoyQTRHUTdMRlEwMCIsImJjb25uZWN0SWQiOiJCMUVBQkI5NjQ2QUM0REZFQTJBRkI4MjI1MzgyQTJFQSJ9.iGoAomXADlAaCsr4KgsTEy8oHTbv4k9XTSl7NVtRZXo">хотела выкупить</a> Take-Two Interactive, но теперь его окончательно закрыли.</p><h2>Поставки и цифровые продажи ремейка Metal Gear Solid 3 превысили миллион копий в день релиза</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/536b65ea-684b-4ea6-9f97-76fad0df0025.png" alt="" /></figure><p>Ремейк Metal Gear Solid 3 <a href="https://dtf.ru/gameindustry/4007696-remeik-metal-gear-solid-3-prodazhi-million-kopiy">получил</a>  неплохие оценки и от СМИ, и от аудитории — 86 баллов из 100 на  Metacritic и 81% положительных отзывов в Steam соответственно.  Максимальный онлайн игры на площадке Valve превысил 19 тысяч человек.</p><h2>2K провела сокращения в Firaxis Games — студии разработчиков Civilization</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/5e751c09-d467-4467-ab35-581bdf2ce890.jpg" alt="" /></figure><p>Уволили десятки специалистов. Сокращения <a href="https://www.gamedeveloper.com/business/2k-confirms-layoffs-at-civilization-developer-firaxis">связаны</a> с реструктуризацией и оптимизацией, призванными улучшить «гибкость, совместную работу и креативность» команды.</p><h2>The Alters помогла 11 bit studios увеличить выручку на 86%</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/e78caad5-893a-4eb6-a37e-0ca9f91f69dc.jpg" alt="" /></figure><p>Вышедшая под конец полугодия The Alters <a href="https://ir.11bitstudios.com/wp-content/uploads/2025/08/Raport-polroczny-11-bit-studios-S.A.-za-I-polrocze-2025-roku.pdf">оказалась в ответе</a> за 35,6% выручки компании.</p><h2>На разработку Cronos: The New Dawn потратили менее 27,4 млн долларов</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/c15f064f-01c5-4634-b9f2-10c6d1794443.jpg" alt="" /></figure><p>Президент Bloober Team Петр Бабено в интервью PAP Biznes <a href="https://www.bankier.pl/wiadomosc/Bloober-nie-widzi-zagrozenia-dla-Cronos-The-New-Dawn-w-zwiazku-z-debiutem-Hollow-Knight-Silksong-wywiad-9003011.html">сообщил</a>, что производственный бюджет Cronos: The New Dawn был не таким большим, как предполагают некоторые аналитики.</p><h2>Халява/раздачи/бандлы/курсы</h2><h2>Бесплатный набор инструментов для создания персонажей в Maya mGear 5.1</h2><p>Обновлён RBF Manager для <a href="https://mgear4.readthedocs.io/en/latest/releaseLog.html">улучшения совместимости</a> с Shapes, популярным редактором Blendshape от Brave Rabbit.</p><h2>Интересные статьи/видео</h2><h2>[EN] Ужасные игровые миссии</h2><p>Не каждая миссия должна сводить вас с ума, но ужасный квест может  поставить под угрозу всю игру. Многие плохие миссии следуют общим  шаблонам, и для современных игр они представляют собой серьёзную  проблему.</p><h2>[RU] Кубистая планета — делаем шарообразный мир в стиле Minecraft</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/30922d1f-73d6-4fe4-a5a9-58bdc8464517.png" alt="" /></figure><p>Во многом эта реализация базируется на обычных приёмах, которые могут  быть знакомы из типичного кустарного клона Minecraft, но благодаря  сферической структуре игрового мира <a href="https://habr.com/ru/articles/944378/">возникает ряд уникальных аспектов</a>, которые учитываются в строительстве.</p><h2>[EN]  Multiple Frames In Flight // Vulkan For Beginners #24</h2><p>В видео показано, как реализовать несколько кадров в Vulkan, чтобы повысить производительность механизма передачи сообщений.</p><h2>[RU] Как пройти Stardew Valley за 4 минуты через code injection</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/633d10da-ed2e-42df-8b25-8e8913ea0d59.gif" alt="" /></figure><p>В статье посмотрены баги, глитчи и недоработки, которые сообщество  Stardew Valley нашло и собрало в кучу, чтобы спустя 9 лет после релиза  игры <a href="https://habr.com/ru/companies/swordfish_security/articles/940644/">реализовать</a> сбор Community Center за 4 минуты от старта игры с нового сохранения.</p><h2>[EN] Как выглядит игра, заработавшая 1млн долларов, в Unity</h2><p>Том Фрэнсис, создатель завирусившейся Tactical Breach Wizards, показывает закулисье своей игры.</p><h2>[RU] Обзор DI-фреймворков для Unity</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/caa6a1e6-7e93-488a-8dcf-f552ab0132d5.jpg" alt="" /></figure><p>Что лучше выбрать, <a href="https://habr.com/ru/articles/943354/">какие есть альтернативы</a>.</p><h2>[EN] Создание персонажа по мотивам Dark Souls с помощью ZBrush</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/c50d73c5-5a36-4258-8def-3eb676cfd1c8.jpg" alt="" /></figure><p>Франк Безансон <a href="https://80.lv/articles/sculpting-a-dark-souls-inspired-body-horror-style-character-with-zbrush">рассказал</a> о проекте Spillage, обсудив создание ужасающего персонажа с мясистым мечом с помощью ZBrush, KeyShot и Photoshop.</p><h2>[RU] КДИ 427. Что делать разработчикам игр на Gamescom</h2><p>tinyBuild обсуждает недавнюю конфу.</p><h2>[EN] Орбитальная механика</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/c1f556cb-eebe-442d-a032-971d7debe29d.jpg" alt="" /></figure><p>Глубокий <a href="https://www.alanzucconi.com/2025/09/04/orbital-mechanics/">разбор орбитальной механики</a>: от реализации симуляции гравитации до математики, управляющей кеплеровскими орбитами в задаче двух тел.</p><h2>[RU] Опубликовал свой первый пиксельный Asset Pack для itchio и попал на 1 место в Популярном</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/da876407-0bca-4f02-bd12-9a2082c8d915.gif" alt="" /></figure><p>Владимир Иванов <a href="https://dtf.ru/gamedev/4000854-kak-ya-opublikoval-svoy-pervyy-pikselnyy-asset-pack-na-itch-io">делится своим опытом</a>.</p><h2>[EN]  UI Toolkit for Industry</h2><p>Техническое руководство того, как можно начать работу с новыми возможностями World Space для UI Toolkit в Unity 6.2.</p><h2>[RU] Уволились с работы, потратили год на разработку игры — и заработали…</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/4d95e8f0-e64a-4cae-9943-d05084e30dae.jpg" alt="" /></figure><p>Возможно, кто-то узнает себя, а для тех, кто только планирует выпуск первой игры, эта статья будет полезна: автор <a href="https://dtf.ru/gamedev/3997877-istoriya-razrabotki-igry-oshibki-i-sovety">собрал</a> основные ошибки и способы их решения.</p><h2>[EN] Moonligher 2: The Endless Vault | Behind the Counter Ep.2 — The Duality of Moonlighter</h2><p>Во 2-м эпизоде ​​Digital Sun Games рассказывает об улучшениях магазина, скрытых пасхалках и новом приключении Уилла.</p><h2>[RU] Как не потерять свою игру: реальный кейс. Уроки, за которые автор заплатил целым проектом</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/0b06716d-0e93-4308-937e-9a048a7264eb.png" alt="" /></figure><p>В мае 2024 разработчик присоединился к команде, чтобы сделать игру  мечты. А в июле 2025 официально похоронил этот проект. Между этими двумя  датами — история о горящих глазах, невыполненных обещаниях,  предательстве и <a href="https://dtf.ru/gamedev/3997462-kak-sokhranit-svoyu-igru-uroki-iz-realnogo-keysa-gamevdeva">самом важном уроке в жизни</a>: в геймдеве, как и в любом бизнесе, доверять можно только документам.</p><h2>[EN] Помните о первоисточниках (Звёздные войны, Андор и Mass Effect)</h2><p>Когда мы создаём что-то, используя существующий IP, может возникнуть  соблазн вернуться только к последней работе, созданной в рамках этого  IP. Возвращаясь к первоисточнику, мы можем добиться большего, оставаясь  верными IP.</p><h2>[RU] Vulkan с использованием Rust. Часть 1</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/a1713fab-0775-4c9e-8ba0-3a86a6e6d3f3.jpg" alt="" /></figure><p>Данный <a href="https://habr.com/ru/articles/942880/">цикл статей</a> посвящён выводу цветного треугольника в Vulkan c использованием библиотеки ash.</p><h2>[EN] Video Game Blurs (and how the best one works)</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/bb100256-180e-4949-8583-166ffd0a4c85.png" alt="" /></figure><p>Размытие — <a href="https://blog.frost.kiwi/dual-kawase/">базовый элемент</a> многих эффектов постобработки в видеоиграх и неотъемлемая часть элегантного и современного графического интерфейса.</p><h2>[RU] Ещё один честный взгляд на инди-геймдев</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/5b91c7d6-f6fd-4b6a-b9a3-1afa7e66a9cc.jpg" alt="" /></figure><p>Разработчик <a href="https://habr.com/ru/articles/943640/">делится своим опытом</a>.</p><h2>[EN] Physically based rendering from first principles</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/9a04354b-216d-499e-90aa-6bb96409eeb8.png" alt="" /></figure><p>В своей интерактивной статье автор <a href="https://imadr.me/pbr/">рассматривает</a> физические явления, порождающие свет, и фундаментальные законы его взаимодействия с веществом.</p><h2>[EN] Создание игры, в которой вы создаёте жизнь</h2><p>Клеточные автоматы — популярная тема не без оснований: они способны  создавать невероятно сложные продукты на основе простых принципов.</p><h2>[EN] Реализация эффекта фольгированного стикера</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/c8e39cbe-5dca-4c3a-b340-a36645c7fe1f.gif" alt="" /></figure><p>В статье <a href="https://www.4rknova.com/blog/2025/08/30/foil-sticker">рассказывается</a>,  как создать собственный шейдер в Threejs, имитирующий фольгированный  стикер, с переливами, зависящими от угла обзора, и сверкающими  металлическими хлопьями.</p><h2>[EN] Cronos: The New Dawn готовится представить захватывающий хоррор на UE5</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/db096852-aad5-4b1d-9aba-b3acf159cde0.png" alt="" /></figure><p>Чтобы узнать больше о проекте, команда Epic Games <a href="https://www.unrealengine.com/en-US/developer-interviews/cronos-the-new-dawn-is-set-to-deliver-pulse-pounding-survival-horror-using-ue5">встретилась</a>  с геймдиректорами Bloober Team Яцеком Зембой и Войцехом Пейко, а также с  техническим директором Мариушем Шафликом, чтобы узнать больше об  уникальной механике выживастика в Cronos: The New Dawn, сотрудничестве  между командами с использованием Unreal Engine и многом другом.</p><h2>[EN] Создание симбиота с щупальцами и повреждённой кожей в ZBrush</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/bc4b0bff-cde0-4749-993b-d45c4a0482b8.jpg" alt="" /></figure><p>Теему Хартикайнен <a href="https://80.lv/articles/creating-a-symbiote-character-with-tentacles-damaged-skin-in-zbrush">рассказал</a>  о проекте Parasite Symbiote, обсудив моделирование и текстурирование  персонажа с щупальцами, выступами и слизистой, несовершенной кожей с  помощью ZBrush, Blender, Substance 3D Painter и Marmoset Toolbag 5.</p><h2>[EN] Как Abiotic Factor подняла продажи до 1,4 млн проданных копий</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/b47c2bb3-4487-4b7e-b9ba-5824f82cf30a.png" alt="" /></figure><p>Чего же <a href="https://newsletter.gamediscover.co/p/how-abiotic-factor-rode-a-hot-steam">такого особенно</a> в релизе 1.0 версии?</p><h2>[EN] Создание красочного 2D-кролика-воина в 3D с помощью Maya и Substance 3D</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/b5519acf-b691-45c6-8038-613e0c0cb758.jpg" alt="" /></figure><p>Морин Понселе <a href="https://80.lv/articles/how-to-make-colorful-2d-like-rabbit-warrior-in-3d-using-maya-substance-3d">поделилась</a> подробностями проекта Rabbit Warrior, показав, как создавались текстуры, и обсудив созданные позы.</p><h2>[EN] Венчурный капиталист Йоаким Ахрен: «20 причин, по которым я сказал НЕТ основателям стартапов»</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/3db3797c-caf1-41bf-a49b-393a278592f8.jpg" alt="" /></figure><p>Полезные <a href="https://premortem.games/2025/09/01/vc-joakim-achren-twenty-reasons-why-i-said-no-to-startup-founders/">советы</a>, которые могут пригодиться инди-разработчикам.</p><h2>[EN] Художник делится опытом создания арта ежедневно в течение года</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/dc6a85c5-816e-4b2b-8cab-e58e9f9e2004.jpeg" alt="" /></figure><p>Кларенс Картер III <a href="https://80.lv/articles/blender-artist-shares-experience-of-creating-daily-art-for-a-year">рассказал</a>  о том, как создание проектов в Blender стало частью его повседневной  жизни, а также о трудностях, источниках вдохновения и рабочем процессе,  стоящих за этим процессом.</p><h2>[EN] Grass Rendering Series Part 4: Level-Of-Detail Tricks for Infinite Plains of Grass in Godot</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/4a056ff6-1c8a-4709-97dc-056128fda083.png" alt="" /></figure><p>Представлены <a href="https://hexaquo.at/pages/grass-rendering-series-part-4-level-of-detail-tricks-for-infinite-plains-of-grass-in-godot/">методы реализации</a> систем детализации для рендеринга травы.</p><h2>Разное</h2><h2>Голых механик не хватает, нужно ещё и аккуратно работать с эмоциями игрока, чтоб он игру хейтить не начал</h2><p>Ты работаешь не с механиками, а с эмоцией игрока. Если игрок фрустрируется, то его легко потерять.</p><h2>Анимешная тян с катаной, созданная с помощью Blender Grease Pencil</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/dc820695-779e-488d-857d-9dee734c1020.gif" alt="" /></figure><p>Из <a href="https://x.com/yumae531/status/1962513256456855742">Твиттера</a>.</p><h2>Атмосферная дождливая киберпанковская сцена</h2><figure><img src="https://media.tproger.ru/user-uploads/111192/2025-09-08/a51607b6-127c-41c4-9e62-e5bd9753edc9.png" alt="" /></figure><p>Из <a href="https://x.com/AffinityPlay/status/1962326105873928252">Твиттера</a>.</p><p>Если хотите поддержать выход дайджеста и других материалов, сделать это можно одним из способов.</p><ul><li><a href="https://www.patreon.com/suvitruf">На Патреоне</a></li><li><a href="https://boosty.to/apanasik">На Boosty</a></li><li><a href="https://www.paypal.com/paypalme/andreiapanasik">Через Paypal</a></li><li><a href="https://yoomoney.ru/to/41001674710054">Через Яндекс.Деньги</a></li></ul><p>Также вы можете подписаться на <a href="https://gamedevsuffering.substack.com/p/weekly-gamedev-242-07-september-2025">рассылку дайджеста</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Общаемся с инди и соло разработчиками игр про развитие карьеры</title>
      <link>https://tproger.ru/articles/obshhaemsya-s-indi-i-solo-razrabotchikami-igr-po-teme-razvitiya-karery-v-gejmdeve</link>
      <comments>https://tproger.ru/articles/obshhaemsya-s-indi-i-solo-razrabotchikami-igr-po-teme-razvitiya-karery-v-gejmdeve?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Roman]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/obshhaemsya-s-indi-i-solo-razrabotchikami-igr-po-teme-razvitiya-karery-v-gejmdeve</guid>
      <description><![CDATA[<p>Ищем респондентов для общения среди разработчиков игр — инди и соло. Пообщаемся про тенденции в индустрии геймдева.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/obshhaemsya-s-indi-i-solo-razrabotchikami-igr-po-teme-razvitiya-karery-v-gejmdeve">Общаемся с инди и соло разработчиками игр про развитие карьеры</a>»</p>]]></description>
      <category><![CDATA[Разработка игр]]></category>
      <category><![CDATA[Создание простых игр на Java]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Tue, 16 Jan 2024 11:42:01 GMT</pubDate>
      <content:encoded><![CDATA[<p>Всем привет! Ищем людей (респондентов) для общения. Буду признателен за помощь и участие.</p><p>Сейчас проводим большое исследование в геймдеве и общаемся с ее различными представителями, особенно с теми, кто уже работает в индустрии, с теми, кто уже делает инди-игры и хочет заниматься этим профессионально (как основным видом деятельности и источником дохода).</p><p>Мы периодически работаем с различными медиа и брендами такими как «Gamedeveloper com», «GamesIndustry biz», «Venturebeat», «Gamedev JS», и некоторыми Ру-язычными брендами и медиа из индустрии, проводя совместные и независимые исследования.</p><p>И сейчас мы общаемся с ГЕЙМДЕВЕЛОПЕРАМИ о том, как в этот период работается на геймдев-рынке, какие есть потребности и вызовы, а также в целом какие у участников рынка задачи, желания и настрой, как они себе представляют решения своих задач.</p><p>И если вы:</p><ol><li>Инди-разработчик или участник небольшой инди-команды (студии), который уже делал несколько игр (проекты любого масштаба);</li><li>Издавал их и зарабатывал на этом (зарабатывал на продажах в Steam, Itch io, возможно на мобильных или веб-платформах, уже зарабатывали на рекламе или внутриигровых покупках), т.е. уже есть опыт создания и монетизации игр;</li><li>У кого в целом есть интерес к разработке и дистрибуции игр для веб-платформ и браузеров;</li><li>Либо dы — веб-разработчик с опытом работы в несколько лет (работавший со спектром языков и фреймворков/технологий – Javascript, Typescript, Python, Html5, PHP, Websocket, React, Web-Based движками для разработки игр, и т.д.), с интересом к геймдеву и возможно уже делавший несколько своих инди-игр для браузеров и других платформ;</li><li>Проживаете как в РФ/СНГ, так и за рубежом…</li></ol><p>То приглашаю провести неформальный диалог (в формате видеоинтервью, который продлится +-30-40 минут), на котором обсудим, какие сейчас есть потребности и задачи в рамках твоей сферы деятельности, чтобы ты хотел решить, каким образом, и как ты представляешь решение. Также обсудим некоторые другие интересные вопросы, в том числе происходящие изменения и тренды в геймдеве!</p><p>Зачем идти?</p><ol><li>Как это обычно бывает, в процессе диалога вы сможете посмотреть на свою деятельность и проекты под другим углом, сможете узнать что-то новое, и даже найти в процессе диалога какие-то ответы и решения для себя.</li><li>Так как у нас есть хороший объем полезных контактов в индустрии (медиа, паблишеры, сервисы и платформы, и т.д.), то, в благодарность за диалог, возможно, сможем быть полезными, сможем что-то подсказать или порекомендовать контакты.</li><li>По завершению исследования мы обязательно поделимся выжимкой и инсайтами со всеми участниками.</li><li>Ну и вы сможете приятно провести время, поговорив о любимом деле, играх и геймдеве!</li></ol><p>И да, важный момент. Мы ничего не продаем и продавать не будем… Это исключительно общение/диалог про индустрию с её участниками!</p><p>Поэтому, если кто-то готов поучаствовать, то оставьте отклик по этой ссылке:</p>]]></content:encoded>
    </item>
    <item>
      <title>Как написать свой Тетрис на Java за полчаса</title>
      <link>https://tproger.ru/articles/java-30-mins-tetris</link>
      <comments>https://tproger.ru/articles/java-30-mins-tetris?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Пётр Соковых]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/java-30-mins-tetris</guid>
      <description><![CDATA[<p>Продолжение серии после сапёра, змейки и клона 2048: работа над Тетрисом начинается с главного управляющего класса, исходники лежат на GitHub.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/java-30-mins-tetris">Как написать свой Тетрис на Java за полчаса</a>»</p>]]></description>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Обучение программированию]]></category>
      <category><![CDATA[Разработка игр]]></category>
      <category><![CDATA[DIY]]></category>
      <category><![CDATA[Создание простых игр на Java]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Sat, 16 Jul 2016 13:09:48 GMT</pubDate>
      <content:encoded><![CDATA[<p>В предыдущих статьях этой серии мы уже успели написать <a href="https://tproger.ru/articles/15-mins-for-minesweeper">сапёра</a>, <a href="https://tproger.ru/articles/15-mins-for-snake">змейку</a> и десктопный <a href="https://tproger.ru/articles/15-mins-for-2048">клон игры 2048</a>. Попробуем теперь написать свой Тетрис.</p><h3>Нам, как обычно, понадобятся:</h3><ul><li>30 минут свободного времени;</li><li>Настроенная рабочая среда, т.е. <a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html">JDK</a> и IDE (например, <a href="http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/mars2">Eclipse</a>);</li><li>Библиотека <a href="https://github.com/DoKel/tprogersTetris/tree/master/lib">LWJGL</a> (версии 2.x.x) для работы с графикой (опционально). Обратите внимание, что для LWJGL версий выше 3 потребуется написать код, отличающийся от того, что приведён в статье;</li><li>Спрайты, т.е. картинки плиток всех возможных состояний (пустая, и со степенями двойки до 2048). Можно нарисовать самому, или скачать <a href="https://github.com/DoKel/tprogersTetris/tree/master/src/ru/tproger/graphics/lwjglmodule">использовавшиеся при написании статьи</a>.</li></ul><p>Прежде чем задавать вопрос в комментариях, не забудьте заглянуть в <a href="https://tproger.ru/articles/15-mins-for-2048/">предыдущие статьи</a>, возможно там на него уже давался ответ. Исходный код готового проекта традиционно можно найти <a href="https://github.com/DoKel/tprogersTetris/">на GitHub</a>.</p><h3>С чего начать?</h3><p>Начать стоит с главного управляющего класса, который в нашем проекте находится выше остальных по уровню абстракции. Вообще отличный совет — в начале работы всегда пишите код вида if (getKeyPressed()) doSomething(), так вы быстро определите фронт работ.</p><p>Это наш main(). Он ничем принципиально не отличается от тех, что мы писали в предыдущих статьях — мы всё так же инициализируем поля и, пока игра не закончится, осуществляем по очереди: ввод пользовательских данных (input()), основные игровые действия (logic()) и вызов метода отрисовки у графического модуля (graphicsModule.draw()), в который передаём текущее игровое поле (gameField). Из нового разве что метод sync — метод, который должен будет гарантировать нам определённую частоту выполнения итераций. С его помощью мы сможем задать скорость падения фигуры в клетках-в-секунду.</p><p>Вы могли заметить, что в коде использована константа FPS. Все константы удобно определять в классе с public static final полями. Полный список констант, который нам потребуется в ходе разработки, можно посмотреть в классе <a href="https://github.com/DoKel/tprogersTetris/blob/master/src/ru/tproger/main/Constants.java">Constants</a> на GitHub.</p><p>Оставим пока инициализацию полей на потом (мы же ещё не знаем, какие нам вообще понадобятся поля). Разберёмся сначала с input() и logic().</p><h3>Получение данных от пользователя</h3><p>Код, честно говоря, достаточно капитанский:</p><p>Все данные от ввода мы просто сохраняем в соответствующие поля, действия на основе них будет выполнять метод logic().</p><p>Теперь уже потихоньку становится понятно, что нам необходимо. Во-первых, нам нужны клавиатурный и графический модули. Во-вторых, нужно как-то хранить направление, которое игрок выбрал для сдвига. Вторая задача решается просто — создадим enum с тремя состояниями: AWAITING, LEFT, RIGHT. Зачем нужен AWAITING? Чтобы хранить информацию о том, что сдвиг не требуется (использования в программе null <a href="http://www.yegor256.com/2014/05/13/why-null-is-bad.html">следует</a> всеми силами избегать). Перейдём к интерфейсам.</p><h3>Интерфейсы для клавиатурного и графического модулей</h3><p>Так как многим не нравится, что я пишу эти модули на LWJGL, я решил в статье уделить время только интерфейсам этих классов. Каждый может написать их с помощью той GUI-библиотеки, которая ему нравится (или вообще сделать консольный вариант). Я же по старинке реализовал их на LWJGL, код можно посмотреть <a href="https://github.com/DoKel/tprogersTetris/tree/master/src/ru/tproger/graphics/lwjglmodule">здесь</a> в папках graphics/lwjglmodule и keyboard/lwjglmodule.</p><p>Интерфейсы же, после добавления в них всех упомянутых выше методов, будут выглядеть следующим образом:</p><h3>Отлично, мы получили от пользователя данные. Что дальше?</h3><p>А дальше мы должны эти данные обработать и что-то сделать с игровым полем. Если пользователь сказал сдвинуть фигуру куда-то, то передаём полю, что нужно сдвинуть фигуру в таком-то направлении. Если пользователь сказал, что нужно фигуру повернуть, поворачиваем, и так далее. Кроме этого нельзя забывать, что 1 раз в FRAMES_PER_MOVE (вы же открывали файл с константами?) итераций нам необходимо сдвигать падающую фигурку вниз.</p><p>Сюда же добавим проверку на переполнение поля (в Тетрисе игра завершается, когда фигурам некуда падать):</p><h3>Так, а теперь мы напишем класс для того магического gameField, в который мы всё это передаём, да?</h3><p>Не совсем. Сначала мы пропишем поля класса Main и метод initFields(), чтобы совсем с ним закончить. Вот все поля, которые мы использовали:</p><p>А инициализировать мы их будем так:</p><p>Если вы решили не использовать LWJGL и написали свои классы, реализующие GraphicsModule и KeyboardHandleModule, то здесь нужно указать их конструкторы вместо, соответственно new LwjglGraphicsModule() и new LwjglKeyboardHandleModule().</p><p>А вот теперь мы переходим к классу, который отвечает за хранение информации об игровом поле и её обновление.</p><h3>Класс GameField</h3><p>Этот класс должен, во-первых, хранить информацию о поле и о падающей фигуре, а во-вторых, содержать методы для их обновления, и получения о них информации — кроме тех, которые мы уже использовали, необходимо написать метод, возвращающий цвет ячейки по координатам, чтобы графический модуль мог отрисовать поле.</p><p>Начнём по порядку.</p><h4>Хранить информацию о поле…</h4><h4>…и о падающей фигуре</h4><p>TpReadableColor — простой enum, содержащий элементы с говорящими названиями (RED, ORANGE и т.п.) и метод, позволяющий получить случайным образом один из этих элементов. Ничего особенного в нём нет, код можно посмотреть <a href="https://github.com/DoKel/tprogersTetris/blob/master/src/ru/tproger/graphics/TpReadableColor.java">тут</a>.</p><p>Это все поля, которые нам понадобятся. Как известно, поля любят быть инициализированными.<br />Сделать это следует в конструкторе.</p><h4>Конструктор и инициализация полей</h4><p>“Что это за OFFSET_TOP?” — спросите вы. OFFSET_TOP это количество неотображаемых ячеек сверху, в которых создаются падающие фигуры. Если фигуре не сможет “выпасть” из этого пространства, и хоть одна ячеек theField выше уровня COUNT_CELLS_Y будет заполнена, это будет обозначать, что поле переполнено и пользователь проиграл, поэтому OFFSET_TOP должен быть строго больше нуля.</p><p>Далее в конструкторе стоит заполнить массив theField значениями константы EMPTINESS_COLOR , а countFilledCellsInLine — нулями (второе в Java не требуется, при инициализации массива все int‘ы равны 0). Или можно создать несколько слоёв уже заполненных ячейкам — на GitHub вы можете увидеть реализацию именно второго варианта.</p><h4>А что это там за spawnNewFigure()? Почему инициализация фигуры вынесена в отдельный метод?</h4><p>Вы правильно догадались, spawnNewFigure() действительно инициализирует поле figure. А в отдельный метод это вынесено, потому что нам придётся делать инициализацию каждый раз, когда будет создаваться новая фигура.</p><p>На этом с хранением данных мы закончили. Переходим к методам, которые отдают информацию о поле другим классам.</p><h4>Методы, передающие информацию об игровом поле</h4><p>Таких метода всего два. Первый возвращает цвет ячейки (для графического модуля):</p><p>А второй сообщает, переполнено ли поле (как это происходит, мы разобрали выше):</p><h4>Методы, обновляющие фигуру и игровое поле</h4><p>Начнём реализовывать методы, которые мы вызывали из Main.logic().</p><h4>Сдвиг фигуры</h4><p>За это отвечает метод tryShiftFigure(). В комментариях к его вызову из Main было сказано, что он “<i>пробует</i> сдвинуть фигуру”. Почему пробует? Потому что если фигура находится вплотную к стене, а пользователь пытается её сдвинуть в направлении этой стены, никакого сдвига в реальности происходить не должно. Так же нельзя сдвинуть фигуру в статические ячейки на поле.</p><p>Что мы сделали в этом методе? Мы запросили у фигуры ячейки, которые бы она заняла в случае сдвига. А затем для каждой из этих ячеек мы проверяем, не выходит ли она за пределы поля, и не находится ли по её координатам в сетке статичный блок. Если хоть одна ячейка фигуры выходит за пределы или пытается встать на место блока — сдвига не происходит. Coord здесь — класс-оболочка с двумя публичными числовыми полями (x и y координаты).</p><h4>Поворот фигуры</h4><p>Логика аналогична сдвигу:</p><h4>Падение фигуры</h4><p>Сначала код в точности повторяет предыдущие два метода:</p><p>Однако теперь, в случае, если фигура дальше падать не может, нам необходимо перенести её ячейки («кубики») в theField, т.е. в разряд статичных блоков, после чего создать новую фигуру:</p><p>Так как в результате переноса ячеек какая-то линия может заполниться полностью, после каждого добавления ячейки мы проверяем линию, в которую мы её добавили, на полноту:</p><p>Этот метод возвращает истину, если линию удалось уничтожить. После добавления всех кирпичиков фигуры в сетку (и удаления всех заполненных линий), мы, при необходимости, запускаем метод, который сдвигает на место пустых линий непустые:</p><p>Теперь GameField реализован почти полностью — за исключением геттера для фигуры. Её ведь графическому модулю тоже придётся отрисовывать:</p><p>Теперь нам нужно написать алгоритмы, по которым фигура определяет свои координаты в разных состояниях. Да и вообще весь класс фигуры.</p><h3>Класс фигуры</h3><p>Реализовать это всё я предлагаю следующим образом — хранить для фигуры (1) «мнимую» координату, такую, что все реальные блоки находятся ниже и правее неё, (2) состояние поворота (их всего 4, после 4-х поворотов фигура всегда возвращается в начальное положение) и (3) маску, которая по первым двум параметрам будет определять положение реальных блоков:</p><p>Rotation мод здесь будет выглядеть таким образом:</p><p>Соответственно, от самого класса Figure нам нужен только конструктор, инициализирующий поля:</p><p>И методы, которыми мы пользовались в GameField следующего вида:</p><p>Вдобавок, у фигуры должен быть цвет, чтобы графический модуль мог её отобразить. В тетрисе каждой фигуре соответствует свой цвет, поэтому цвет мы будем запрашивать у формы:</p><h3>Форма фигуры и маски координат</h3><p>Чтобы не занимать лишнее место, здесь я приведу реализацию только для двух форм: I-образной и J-образной. Код для остальных фигур принципиально не отличается и выложен на GitHub.</p><p>Храним для каждой фигуры маску координат (которая определяет, насколько каждый реальный блок должен отстоять от “мнимой” координаты фигуры) и цвет:</p><p>Реализуем методы, которые использовали выше:</p><p>Ну а сами маски координат я предлагаю просто захардкодить следующим образом:</p><p>Т.е. для каждого объекта enum‘а мы передаём с помощью импровизированных (других в Java нет) делегатов метод, в котором в зависимости от переданного состояния поворота возвращаем разные реальные координаты блоков. В общем-то, можно обойтись и без делегатов, если хранить в каждом элементе отсупы для каждого из режимов поворота.</p><h3>Наслаждаемся результатом</h3><figure><img src="https://media.tproger.ru/uploads/2016/07/Screenshot-from-2016-07-12-23-31-59.png" alt="" /><figcaption>Работающая программа</figcaption></figure><p><b>P.S.</b> Ещё раз напомню, что исходники готового проекта <a href="https://github.com/DoKel/tprogersTetris/">доступны на GitHub</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Как написать свою 2048 на Java за 15 минут</title>
      <link>https://tproger.ru/articles/java-15-mins-2048</link>
      <comments>https://tproger.ru/articles/java-15-mins-2048?scrollTo=tproger-comments</comments>
      <dc:creator><![CDATA[Пётр Соковых]]></dc:creator>
      <guid isPermaLink="true">https://tproger.ru/articles/java-15-mins-2048</guid>
      <description><![CDATA[<p>Десктопный клон 2048 продолжает серию после сапёра и змейки: готовый код можно скопировать и запустить за 15 минут, понимая происходящее.</p><p>— Читать дальше «<a rel="follow" href="https://tproger.ru/articles/java-15-mins-2048">Как написать свою 2048 на Java за 15 минут</a>»</p>]]></description>
      <category><![CDATA[Java]]></category>
      <category><![CDATA[Обучение программированию]]></category>
      <category><![CDATA[Разработка игр]]></category>
      <category><![CDATA[DIY]]></category>
      <category><![CDATA[Создание простых игр на Java]]></category>
      <category><![CDATA[Статьи]]></category>
      <slash:comments>0</slash:comments>
      <pubDate>Wed, 06 Jul 2016 14:05:23 GMT</pubDate>
      <content:encoded><![CDATA[<p>В предыдущих статьях этой серии мы уже писали <a href="https://tproger.ru/articles/15-mins-for-minesweeper">сапёра</a> и <a href="https://tproger.ru/articles/15-mins-for-snake/">змейку</a>, а теперь попробуем написать десктопный клон игры <a href="https://gabrielecirulli.github.io/2048/">2048</a>.</p><h3>Нам, как обычно, понадобятся:</h3><ul><li>15 минут свободного времени;</li><li>Настроенная рабочая среда, т.е. <a href="http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html">JDK</a> и IDE (например, <a href="http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/mars2">Eclipse</a>);</li><li>Библиотека LWJGL (версии 2.x.x) для работы с графикой (опционально). Обратите внимание, что для LWJGL версий выше 3 потребуется написать код, отличающийся от того, что приведён в статье;</li><li>Спрайты, т.е. картинки плиток всех возможных состояний (пустая, и со степенями двойки до 2048). Можно нарисовать самому, или скачать <a href="https://github.com/DoKel/tprogersTetris/tree/master/src/ru/tproger/graphics/lwjglmodule">использовавшиеся при написании статьи</a>.</li></ul><h3>FAQ по опыту предыдущих статей</h3><h4>В: Вы что! Это большой проект, за 15 минут такое нельзя накодить!</h4><p>О: Разумеется, чтобы придумать всё это и написать, у меня ушёл целый вечер и даже немножко ночи. Но прочитать статью и, скопировав из неё код, запустить работающую игру (при этом понимая, что происходит) вполне реально и за 15 минут.</p><h4>В: Зачем тянуть ради такого простого проекта LWJGL? Гвозди микроскопом!</h4><p>О: Вся работа с отображением вынесена в два с половиной метода  в 2 интерфейса. Вы можете реализовать их на чём хотите, мне же удобнее на LWJGL.</p><h4>В: А почему код выкладываете архивом? На гитхаб нужно!</h4><p>О: Да, теперь весь проект <a href="https://github.com/DoKel/tprogers2048game/">выложен на GitHub</a>.</p><h4>В: У меня не получается подключить твою эту LWJGL! Что делать?</h4><p>О: В прошлые разы у многих возникли с этим вопросом проблемы, поэтому мне показалось уместным посвятить этому немного времени.</p><p>Во-первых, выше я дал ссылку на папку с библиотеками на GitHub, которые использую я, чтобы не было путаницы с версиями и вопросов, где найти что-то. Папку из архива требуется поместить в папку проекта и подключить через вашу IDE.</p><p>Во-вторых, у многих пользователей InteliJ IDEA возникли проблемы как раз с их подключением. Я нашёл в сети следующий видеогайд:</p><p>После того, как я сделал всё в точности по нему, у меня библиотеки подключились корректно и всё заработало.</p><h4>В: А почему на Java?</h4><p>О: На чём бы я не написал, можно было бы спросить “Почему именно на X?”. Если в комментариях будет реально много желающих увидеть код на каком-то другом языке, я перепишу игру на нём и выложу (только не Brainfuck, пожалуйста).</p><h3>С чего начать?</h3><p>Начать стоит с главного управляющего класса, который в нашем проекте находится выше остальных по уровню абстракции. Вообще отличный совет — в начале работы всегда пишите код вида if(getKeyPressed()) doSomething(), так вы быстро определите фронт работ.</p><p>Это наш main(). Что тут происходит, понять несложно — мы инициализируем поля, потом создаём первые две ячейки и, пока игра не закончится, осуществляем по очереди: ввод пользовательских данных (input()), основные игровые действия (logic()) и вызов метода отрисовки у графического модуля (graphicsModule.draw()), в который передаём текущее игровое поле (gameField).</p><p>Так как пока мы не знаем, какие поля инициировать, постараемся написать createInitialCells(). Но так как создавать клетки нам пока просто-напросто не в чем, то создадим класс игрового поля.</p><h3>Создаём игровое поле</h3><p>Всё наше поле — матрица чисел и методы, позволяющие их изменять (геттеры и сеттеры). Договоримся только, что пустую ячейку мы будем обозначать числом 0. Выглядеть этот класс будет так:</p><p>Возможно, пока не совсем очевидно, почему нужны именно такие геттеры и сеттеры, это станет ясно в процессе дальнейшей работы (при разработке с нуля следовало бы создать только getState() и setState(), а остальное дописывать потом).</p><h3>Создаём в поле первые две ячейки</h3><p>Совсем очевидно, что нам нужно просто вызвать два раза метод создания одной ячейки.</p><p>Заметьте, я не пишу вызов одного метода два раза. Для программистов существует одна максима: “Существует только два числа: один и много”. Чаще всего, если что-то нужно сделать 2 раза, то со временем может возникнуть задача сделать это и 3, и 4 и куда больше раз. Например, если вы решите сделать поле не 4х4, а 10х10, то разумно будет создавать не 2, а 10 ячеек.</p><p>Вы могли заметить, что в коде использована константа COUNT_INITIAL_CELLS. Все константы удобно определять в классе с public static final полями. Полный список констант, который нам потребуется в ходе разработки, можно посмотреть в классе <a href="https://github.com/DoKel/tprogers2048game/">Constants</a> на GitHub.</p><p>Теперь постараемся решить вопрос — как в матрице создать ячейку вместо одного из нулей? Я решил пойти по такому пути: мы выбираем случайные координаты, и если там находится пустая ячейка, то создаём новую плитку там. Если там уже есть плитка с числом, то пытаемся создать в следующей клетке (двигаемся вправо и вниз). Обратите внимание, что после хода не может не быть пустых клеток, т.к. ход считается сделанным, когда клетки либо переместились (т.е. освободили какое-то место), либо соединились (т.е. клеток стало меньше, и место снова высвободилось).</p><p>Немного более затратен по времени и памяти другой метод, который тоже имеет право на жизнь. Мы складываем в какую-либо коллекцию (например, ArrayList) координаты всех ячеек с нулевым значением (простым перебором). Затем делаем new Random().nextInt(X), где X — размер это коллекции, и создаём ячейку по координатам, указанным в члене коллекции с номером, соответствующем результату.</p><h3>Реализуем пользовательский ввод</h3><p>Следующим по очереди у нас идёт метод input(). Займёмся им.</p><p>Отсюда нам нужно запомнить только, какие интерфейсы (графический и клавиатурный модули) нам нужно создать и какие методы в них определить. Если не запомнили — не волнуйтесь, ворнинги вашей IDE особо забыть не дадут.</p><h3>Интерфейсы для клавиатурного и графического модулей</h3><p>Так как многим не нравится, что я пишу эти модули на LWJGL, я решил в статье уделить время только интерфейсам этих классов. Каждый может написать их с помощью той GUI-библиотеки, которая ему нравится (или вообще сделать консольный вариант). Я же по старинке реализовал их на LWJGL, код можно посмотреть <a href="https://github.com/DoKel/tprogersTetris/tree/master/src/ru/tproger/graphics/lwjglmodule">здесь</a> в папках graphics/lwjglmodule и keyboard/lwjglmodule.</p><p>Интерфейсы же, после добавления в них всех упомянутых выше методов, будут выглядеть следующим образом:</p><h4>Графический модуль</h4><h4>Клавиатурный модуль</h4><h3>Метод логики</h3><p>Вполне понятно, что если было определено направление сдвига, то нужно произвести в этом направлении сдвиг — в этом вся суть игры. Также, если сдвиг произвести удалось, необходимо создать новую ячейку. Направление для нового сдвига должно снова стать неопределённым — до следующего пользовательского ввода.</p><p>Вы могли заметить, что мы часто используем enum Direction для определения направления. Т.к. его используют различные классы, он вынесен в отдельный файл и выглядит так:</p><h3>Давай уже серьёзно. Как нам сдвинуть это чёртово поле?</h3><p>Самое ядро нашего кода! Вот самое-самое. К слову, спорный вопрос, куда поместить этот метод — в Main.java или в GameField.java? Я выбрал первое, но это решение нельзя назвать слишком обдуманным. Жду ваше мнение в комментариях.</p><p>Очевидно, что должен быть какой-то алгоритм сдвига линии, который должен применяться к каждому столбцу (или строке, зависит от направления) по очереди и менять значения необходимым нам образом. К этому алгоритму мы и будем обращаться из Main.shift(). Так же такой алгоритм (вынесенный в метод) должен определять, изменил он что-то или не изменил, чтобы метод shift() это значение мог вернуть.</p><p>Так как этот магический метод с алгоритмом должен будет по сути вернуть два объекта (новую линию и boolean, который будет говорить о наличии изменений в ней), создадим в начале класса Main для такого результата обёртку:</p><p>Можно, конечно. просто возвращать линию, а затем сравнивать её (не забываем, что это нужно делать через метод equals(), а не через ==), но на это будет уходит больше времени (из-за сравнение каждого элемента массива), но меньше памяти (на один boolean).</p><h3>Самое сердце программы. Метод shiftRow()</h3><p>Если подумать, то вам предстоит решить задачку — как за наименьшее (линейно зависящее от количества поступающих данных) время произвести с рядом чисел следующие последовательные операции: (1) если в ряде есть нули, их необходимо удалить, (2) если любые два соседних числа равны, то вместо них должно остаться одно число, равное сумме двух равных чисел. И (3) — если число получено через пункт (2), оно не может совмещаться с другими числами.</p><p>Если представить себе алгоритм таким образом, то придумать линейное решение будет гораздо легче. Вот какой алгоритм должен получиться:</p><ul><li>Выкидываем все нули — проходимся по всему массиву и копируем элемент в новый массив, только если он не равен нулю. Если вы попробуете удалять эти нули из середины того же массива, алгоритм будет работать за O(n^2).</li><li>Рассмотрим (поставим указатель на) первое число получившегося массива без нулей.Если с ним можно совместить следующее за ним число (наш указатель +1), то переписываем в новый массив лишь их сумму, затем ставим указатель на третье число (второго уже нет).Иначе переписываем только первое, и ставим указатель на второе число.</li></ul><p>При этом нам необходимо хранить место в возвращаемом массиве, на которое необходимо произвести запись.</p><p>А вот как он выглядит в виде кода:</p><h3>Наслаждаемся результатом</h3><figure><img src="https://media.tproger.ru/uploads/2016/07/Screenshot-from-2016-07-05-05-53-57.png" alt="" /><figcaption>Работающая программа</figcaption></figure><p>P.S Ещё раз напомню, что исходники готового проекта <a href="https://github.com/DoKel/tprogers2048game/">доступны на GitHub</a>.</p>]]></content:encoded>
    </item>
  </channel>
</rss>