Как сделать игру в блокноте windows

Обновлено: 05.07.2024

Не так давно мы разбирали, как искусственный интеллект учится играть в змейку. А теперь мы сами сделаем такую игру, чтобы ей могли насладиться обычные люди. Что нам понадобится:

  • HTML, чтобы можно было играть прямо в браузере;
  • CSS для украшений;
  • JavaScript для самой игры.

Логика игры

У классической змейки правила простые:

  • есть поле из клеточек, где случайным образом появляется еда;
  • есть змейка, которая всё время двигается и которой мы можем управлять;
  • если змейка на своём пути встречает еду — еда исчезает, появляется в новом месте, а сама змейка удлиняется на одну клеточку;
  • если змейка врежется в стену или в саму себя, игра заканчивается.

Чтобы играть было проще, мы сделаем так, чтобы змейка не врезалась в стенки, а проходила сквозь них. Если что — сможете это сами потом настроить в коде, когда захотите посложнее.

Последовательность наших действий будет такой:

  1. Делаем пустую HTML-страницу.
  2. Настраиваем внешний вид с помощью CSS.
  3. Рисуем игровое поле.
  4. Пишем скрипт, который и будет отвечать за всю игру.

Делаем HTML-страницу

С этим всё просто: берём стандартный код и сохраняем его как файл snake.html .

Это даст нам пустую страницу, которую мы сейчас немного настроим стилями.

Настраиваем внешний вид

За внешний вид на странице у нас отвечает раздел <style> , поэтому мы просто добавим в него CSS-код:

Теперь у нас на странице нет лишних отступов, зато всё по центру, есть чёрный фон и граница вокруг игрового поля. Самое время создать само игровое поле.

Рисуем игровое поле

Поле делается очень просто:

<canvas width="400" height="400"></canvas>

400 пикселей в ширину, столько же в высоту, название поля — game. Этого достаточно, чтобы браузер отобразил холст с такими размерами и позволил нам на нём рисовать.

Пишем скрипт

1. Зададим все переменные, которые нам понадобятся.

2. Сделаем генератор случайных чисел. Он нам понадобится, чтобы размещать еду на поле случайным образом.

// Делаем генератор случайных чисел в заданном диапазоне

3. Напишем основной игровой цикл, который будет работать бесконечно.

4. Сделаем управление стрелочками на клавиатуре.

5. Запускаем игру. Для этого достаточно запустить предыдущий бесконечный цикл, поэтому пишем:

6. Наслаждаемся результатом:

Чтобы у вас тоже получилось такое, просто скопируйте готовый код, сохраните его как HTML-файл и откройте в браузере.

Как улучшить

Этот код — самая простая реализация змейки, и игру можно сделать ещё лучше:

  • выводить количество набранных очков;
  • сделать так, чтобы нельзя было проходить сквозь стены;
  • добавить препятствия;
  • поставить таймер — кто больше соберёт еды за 5 минут;
  • добавить вторую змейку и играть вдвоём.

Проголосуйте за тот вариант, который вам больше всего нравится, в комментариях, или сделайте свою змейку, где всё это будет одновременно.

Пока читал про необычные решения от инди-разработчиков, наткнулся на золото. Вот вам статья про игру в текстовом редакторе. Арт, анимация, сюжет — все как положено.

Я создал игру And yet it hurt (возможно, автор хотел сказать it hurts, но мог использовать такой вариант намеренно, — прим.).

Все началось в 2017 году с вопроса: «Реально ли сделать игру в Блокноте?» Тогда я только усмехнулся. Прошло три года. Обдумав, как все будет работать, и убедившись, что это реально, я решил сделать эту игру.

Обычно вы жмете на кнопку, и в игре что-то происходит. Жмете А, и Марио прыгает. Все завязано на получении информации и отклике. Игра получает входные данные и выводит свои.

В игре для Блокнота на входе будут изменения, которые вносит пользователь в файл, а на выходе изменения, которые вносит в файл сама игра. Для этого приложение отслеживает время последнего сохранения файла. Если оно изменилось, игра считывает содержимое файла и вносит в него новые данные.

Возникает проблема: Блокнот от Microsoft не проверяет, был ли файл изменен. Пришлось бы сохранять файл, закрывать и открывать его заново. Создать такую игру возможно, но звучит не очень весело. Пришлось искать альтернативу.

Могу понять ваше разочарование из-за того, что игра в итоге сделана не в самом обычном Блокноте. Мой тайтл можно запустить в нем — просто процесс немного замороченный. Я решил пожертвовать крутостью проекта, чтобы сделать игру более приятной.

Альтернатива

Пришлось искать другой текстовый редактор. Единственным требованием было — автоматическое обновление файла. Хотя чуть позже вы увидите, что я использовал еще одну фичу.

Сначала на ум пришли Notepad++ и Sublime Text. Но они совсем не похожи на Блокнот внешне, очарование проекта развеялось бы окончательно. Плюс, они спрашивают игрока, хотел бы он обновить файл. Это куда лучше, чем закрывать и открывать файл, но все равно отвлекает от геймплея. Я хотел, чтобы файл обновлялся автоматически. Тогда мне на глаза попался Notepad2. Он был почти идеален.

Редактор можно настроить, чтобы он был похож на MS Блокнот, а главное — он проверяет изменения, внесенные в файл. Но также как Notepad++ и Sublime Text, Notepad2 спрашивает игрока, нужно ли изменить файл. К счастью, у редактора открытый код, и я мог отполировать его до совершенства.


Notepad2 написан на C. Я немного знаком с этим языком, пусть меня и нельзя назвать экспертом. Опытный программист Javascript сможет прочитать и уловить общую суть кода, но понять исходный код Notepad2, чтобы внести необходимые изменения, оказалось не так просто.

Для начала я решил поискать текст из диалогового окна: «Файл был изменен внешней программой. Перезагрузить файл?». Это значение переменной, которая используется в качестве аргумента в функции диалогового окна. И я ее нашел.


Этот код проверяет, не изменилось ли содержимое файла. Если оно изменилось, открывается окно, и программа проверяет, выбрал ли пользователь ответ «Да». Мне нужно было лишь заменить кусок


на TRUE, и программа начала автоматически обновлять файл. Таким образом, я создал рендер на базе ASCII. Осталось создать подходящий движок.

Отрисовка

Игра создана с любовью: LÖVE — фреймворк с открытым исходным кодом для 2D-игр, написанных на Lua. Я много лет пользовался этой платформой и даже собрал туториал. Для этого проекта в основном использовался LÖVE-модуль файловой системы, потому что он предоставляет все необходимые возможности. Обычно с помощью LÖVE создают изображение, которое затем выводится на экран.

Мне нужно было почти то же самое: вывод ASCII-арта в текстовом файле. Я начал с домика и птички, причем птичка должна была лететь через файл. Взял арт, который нашел на ASCII Art, но в игре используются только оригинальные работы (за исключением шрифтов).



Загрузка арта — это просто чтение файла.


Дом используется в качестве фона, поэтому я начал с прорисовки этого изображения на «экране». Экран в данном случае — это home.txt.


Я хотел, чтобы с птичкой можно было работать в таком ключе:


х — номер столбца, y — номер строки. Поэтому разбил экран и птицу на списки строк.


С птицей сделал то же самое. Теперь код, описывающий птицу, должен был перекрывать код про дом. Вот, что мне было нужно:

  1. Найти строку, в которой должна быть отрисована птица.
  2. Вывести всю строку до x.
  3. Вывести оставшуюся часть строки, начиная с x + длина арта с птицей.
  4. Создать новую строку с первой частью, птицей и оставшейся частью.
  5. Повторить то же самое для всех остальных строк.


Стало намного лучше:

Анимация

Я начал добавлять больше фишек, например, анимацию:

Все кадры расположены в одном файле и разделены тегом >. Тег определяется при чтении и позволяет задать последовательность кадров. Благодаря этому мы получаем классическую анимацию. Создаем таймер и отрисовываем кадры в соответствии с ним.


Также я реализовал вывод печатаемого текста и отобразил отдельно экран, инвентарь и окно для ввода решения. Оставалась одна проблема. Как игра узнает, что был открыт файл? Это и есть вторая фича, о которой я говорил ранее.

В исходном коде Notepad2 я прописал, что файл должен сохраняться сразу после открытия. Затем игра проверяет, не изменилось ли время последнего сохранения. Так она узнает, что файл был открыт, и может его менять.


В итоге я получил фреймворк, в котором можно работать. Самое время создавать игру.

За девять дней разработки (судя по дате создания gif-файлов) я сделал это:

Если вы запускали игру, то знаете, что в ней нет печатаемого текста и анимации. На то было несколько причин:

  • Я опасался, что порчу свой HDD/SSD постоянной перезаписью файла. Тестирование игры с этими функциями сделало из меня параноика. Не хочу, чтобы игроки испытывали это чувство.
  • Вы не можете ничего делать во время анимации. Если вы попытаетесь выбрать ответ и напечатаете символ в окошке, вы не успеете сохраниться до того, как следующий кадр загрузится и удалит ваш символ. Так что поначалу анимации кажутся классными, но в итоге только мешают.
  • Анимация — это здорово, но она не вписывается в стиль Блокнота. В текстовых файлах не должно быть анимации. По той же причине в игре нет музыки. Конечно, я мог сделать так, чтобы игра создавала аудио-файл, который вы открыли бы в медиаплеере. Но такие действия отвлекали бы от Блокнота. Я оставил несколько анимаций, чтобы показать, как круто они выглядят. Плюс, во время сражения врага лучше бить, когда он моргает, — хороший сигнал к действию.

Программа по умолчанию

Меня бесило, что пользователю приходилось перетаскивать файл в окно Notepad2 для запуска игры. При двойном щелчке по файлу, открывался Блокнот или другая программа по умолчанию для чтения .txt. Можно было прописать команду, которая меняла приложение для таких файлов на Notepad2, но лично мне не понравится, если какая-то игра проделает такой финт на моем компьютере.

Может, возвращать исходные настройки при закрытии игры? Это возможно, но возникнет проблема, если игра вылетит или неожиданно закроется.

Все решения казались недостаточно обоснованными, пока я не догадался, что вместо обычных .txt можно использовать файлы с другим «x». Если быть точным — Unicode-символ U+0445 (Cyrillic Small Letter Ha). Чтобы не запутаться, я назвал файл *.tXt. В итоге, все файлы игры были с разрешением *.tXt, и по дефолту открывались в Notepad2.


Программу по умолчанию можно назначить только от имени администратора. Если вы открываете игру под другой учетной записью, будут использоваться txt-файлы. Если вы открываете файл в обычном Блокноте, игра сообщит, что нужно перетащить файл в открытое окно Блокнота. Либо запустить ее от имени администратора, чтобы она открылась по дабл-клику.

Мотивация

На самом деле всё было сделано три года назад. Что я делал все остальное время? Классический пример отсутствия мотивации.

Изначально сюжет был немного длиннее, чем сейчас. Твоих родителей убил дракон, ты должен пойти к кузнецу Фердану, чтобы он выковал меч. Задумывалось, что меч делается из трех материалов, которые нужно собрать. Это сильно увеличивало объем игры и отодвигало конец разработки. Игра получалась не очень-то развлекательной, и я забросил проект через два месяца.

Но я все время держал его в голове. Я отладил целый фреймворк, который позволял создать игру в Блокноте, а проект не двигался с мертвой точки. Нужно было доделать его. В 2019 году я не завершил почти ни одного проекта. Разочарование подтолкнуло меня к решению: закончить незаконченное в 2020-м.

И вот она. Я сократил сюжет, дал себе месяц на все (получилось на неделю дольше) и бросился в бой. Еще подал заявку на A MAZE. Awards, соответственно, дедлайн был назначен на 2 февраля. Так появилась мотивация.

Заключение

Я рад, что доделал игру. Удивительно, сколько времени проект просто собирал цифровую пыль, а в итоге хватило месяца. Игру не стоило делать настолько объемной, как я хотел сначала — такой нестандартный проект должен лишь показывать особенности, которые можно в нем реализовать.

Что дальше? Игра в Paint? Игра в Калькуляторе? Вряд ли я их сделаю. Но мне нравится думать об играх, которые используют нетрадиционные платформы.

Читайте также: