Давненько я тут не появлялся.
Пора мне отвлечься от твёрдотельных лазеров и снова заняться разработкой игр. Собственно, о чём бишь я?
Я тут планирую воплотить свою давнюю мечту и сделать очередную игрушку про Диззи. Сначала для Windows, а потом уже и для QNX. А там и до PSP должно дело бы дойти (основная проблема портирования - я использую кое-то из С++ 11 и выше, которого на момент моего devkit ещё не изобрели). Не знаю, когда я завершу этот проект, но для тех, кому интересны приключения Диззи, показываю, что на текущий момент уже сделано (и будет обновляться).
Как с ним работать - это отдельная больная тема. На текущий момент редактор далёк от совершенства, и часть функций висит на клавишах (insert и delete) и иными способами не доступна. Логика работы с ним тоже специфическая.
В игру можно сыграть. Правда, там почти ничего не надо делать. Всего-то, напоить котёнка. На этом всё. Это ж прототип. Даже погибнуть пока нельзя.
Вот как всё это выглядит:
Сейчас на очереди разработка языка для описания взаимодействия с окружающим миром.
А вот сюжета пока нет. Но хочется сделать нелинейную игру. Чтобы получалось по-разному в зависимости от того, как и что сделает игрок. Такая возможность есть. Так что, будем надеяться, я игру доделаю. Когда-нибудь.
А сейчас всё это выглядит уже так. И это уже практически полноценная игра (точнее, движок).
Диззи уже может погибнуть.
Принцип работы движка следующий. Весь мир разбит на тайлы 16x16. Тайлы могут иметь имена. Всё взаимодействие описывается через эти самые имена тайлов. Сценарии игры лежат в папке ScreenPlay в обычном текстовом виде. При запуске игра сканирует этот каталог и все сценарии (они могут называться как угодно) добавляет в условия игры.
Возможны сейчас следующие условия:
1) Пересечение тайла с Диззи: IfDizzyIntersection("CAT") - данное условие сработает при столкновении с тайлом с именем "CAT".
2) Пересечение тайлов между собой. IfIntersection("FIRE_LEFT","FIRE_LEFT_BORDER") - данное условие сработает при столкновении тайла "FIRE_LEFT" с тайлом с именем "FIRE_LEFT_BORDER" (это движущийся влево огонь и граница его перемещения).
3) Взятие тайлов в инвентарь (да, Диззи нужно отдельно разрешать что-то брать - могут быть неберущиеся предметы, как это было с мечом в камне из Диззи-4 - взять его можно только используя "липкие руки"): IfPickUp("RING") данное условие сработает при попытке взять тайл "RING".
4) Срабатывание таймера: IfTimer("WAIT CAT") - данное условие сработает для тайла "WAIT CAT "при срабатывании таймера.
5) Использование тайлов между собой: IfUse("BOTTLE WATER","CAT") - данное условие сработает при взаимодействии тайла с именем "BOTTLE WATER" на тайле "CAT".
На данный момент это все возможные условия. Потом, может быть, появятся новые.
Когда условие сработало, выполняются какие-то действия (Action). Для некоторых условий действия только для одного тайла, а для других нужно описывать действие для двух тайлов ( скажем, при столкновении нужно задать каждому столкнувшемуся, что произойдёт с ним)
Этих действий много. Сейчас они такие:
1) ActionMessage(20,100,"СООБЩЕНИЕ") - будет выведено сообщение в заданнх координатах. Да, экран в Диззи 320x240, растянутый до 640x480 для PC.
2) ActionChangeName("BOTTLE OF WATER") - поменять тайлу имя на заданное. Зачем нужно? Бежал у вас огонь до границы влево и теперь должен бежать в право. Как это сделать? Поменять ему имя. И для другого имени сделать уже условие контроля правой границы и условие таймера с событием изменения координаты в другую сторону.
3) ActionChangeDescription("БУТЫЛКА ВОДЫ") - заменяет описание предмета, которое выводится в инвентаре. Была у вас бутылка пустая, а стала с водой. Имя вы поменяли. А теперь надо описание для инвентаря поменять.
4) ActionChangeGlobalName("BOTTLE OF WATER") - поменять имя для ВСЕХ тайлов с таким же именем на карте. Зачем нужно? Если картинка состоит из ряда тайлов (скажем, фигура Волшебника), то изменяет его состояние все его тайлы, а не только та часть, с которой вы взаимодействовали.
5) ActionChangeGlobalDescription("БУТЫЛКА ВОДЫ") - так же меняет глобально все описания.
6) ActionChangePosition(100,100) - задать тайлу позицию в числах. Неудобно для использования. Не гибко.
7) ActionCopyPosition("RING","RING_POS") - перенести позицию первого тайла на место второго. Например, когда кот вам даёт кольцо, он переносит кольцо из некой области карты (вам не видимой - вы там не будете гулять) в заданную позицию.
8) ActionPickUp() - добавляет тайл в список возможных для взятия в инвентарь.
9) ActionSingle() - однократное действие. Зачем нужно? Диззи коснулся тайла воды. Должен терять энергию. Но вот беда, коснулся он нескольких тайлов воды. Совершенно незачем для каждого тайла отнимать у Диззи энергию. Вот это действие и выполнит для данного события действия стоящие следом ровно один раз.
10) ActionSetAnimationStep(1) - устанавливает шаг анимации (анимация обычно в этом случае есть, но остановлена в редакторе). Позволяет менять картинку одного тайла на другой. Была бутылка без воды, стала с водой.
11) ActionMove(1,0) - изменяет координату тайла на заданные приращения по X и по Y. Именно с помощью этого действия и движется, например, тайл огня.
12) ActionSetEnabled(true) - задаёт разрешён тайл или нет. Если нет, он удаляется с игрового поля. Так можно избавляться от ненужных предметов и персонажей.
13) ActionEnergyUpdate(-1) - изменяет энергию Диззи.
14) ActionAddScore(100) - изменяет очки Диззи. Кстати, можно и уменьшать.
15) ActionAddLife() - добавляет Диззи жизнь.
16) ActionAddItem() - увеличивает счётчик найденных предметов на 1 (в Диззи-6 Диззи собирал вишенки, например).
Начало и конец блоков действий описывают:
ActionBegin
ActionEnd
Есть ещё команды, выполняемые до начала игры и к действиям и условиям не относящиеся:
1) SetDescription("BOTTLE WATER","БУТЫЛКА ВОДЫ")- задать описание.
2) CopyPosition("FIRE","FIRE_POS") - перенести тайл в позицию другого тайла.
3) SetDizzyPosition("DIZZY_START_POSITION") - перенести Диззи в позицию тайла. Позволяет задать место старта.
Особый тайл имеет имя "RESPAWN" - его нужно ставить там, где Диззи может погибнуть. Тогда Диззи возродится у ближайшего такого тайла.
Пример сценария:
IfUse("BOTTLE WATER","WAIT CAT")
ActionFirstBegin
ActionChangeGlobalDescription("ПУСТАЯ БУТЫЛКА")
ActionChangeGlobalName("BOTTLE")
ActionSetAnimationStep(0)
ActionFirstEnd
ActionSecondBegin
ActionSingle()
ActionChangeGlobalName("LUCKY CAT")
ActionCopyPosition("RING","RING_POS")
ActionMessage(30,100,"ДИЗЗИ ДАЛ БУТЫЛКУ ВОДЫ КОТЁНКУ...")
ActionMessage(40,80,"БУЛЬК-БУЛЬК!\СПАСИБО! ЗА ЭТО Я ДАМ ТЕБЕ\КОЛЬЦО. Я ЕГО ГДЕ-ТО СПЁР.")
ActionAddScore(100)
ActionSecondEnd
Спасибо. Вроде бы внутри всё есть. Осталось подключить. Пока не удалось. Задаю компилятору в CodeBlocks параметр std=c++11. Не видит shared_ptr.
Makefile у меня вот такой:
Ну, быть может, тут ещё кто-нибудь, писавший/пишущий для PSP остался.
Всё же странно, что компилятор не желает понимать ключи. Я ему и std=C++45 писал. Даже сообщений об ошибке нет. Хм.
Всё заработало и всё собралось. Это я скопировал настройки, и там ссылка на другой каталог с SDK (а я его так и не стёр). Поменял на правильный путь и всё заработало.
Впечатляет EBOOT в мегабайт. Поддержка Си++ 11, видно, дорого далась.
Ну вот, прибил гвоздями к PSP. Правда, пришлось цвет перевести на 565 вместо 8888. Иначе FPS около 20-35 (у меня же ручная отрисовка в видеопамяти без ускорителя). А нужно 30. С 565 где-то около 45 FPS без синхронизации, а это уже хорошо.
Кстати, не знает ли кто хорошую программу для записи видео с экрана компьютера? Понятно, что поисковиком кучу ссылок выскакивает, вот только вирус поймать мне совсем не хочется. Гораздо надёжнее скачать с какого-нибудь известного и проверенного торрента, но для этого нужно хоть примерно знать, что качать.
В картинке не то? Не стыкуются? Вся беда с графикой у меня как раз вот в этом. Есть набор тайлов. Он лежит в папке Tiles. И вся проблема в том, что, а хрен его знает, как их правильно стыковать. Они лежат почти в произвольном порядке. Те же монолиты раскиданы так, что без оригинальной картинки я их собрать вообще не смог. Я сейчас пытаюсь отыскать, что с чем правильно стыкуется и положить рядом в новом файле тайлов, для получения правильного изображения. Пока получается плохо - меня очень раздражают тонкие операции мышкой на уровне "выделить ровно квадрат 16x16 и перенести к другому квадрату" (естественно, в увеличении).
Программа для PSP полностью работает (за исключением мерцания в момент открытия меню использования предметов - пока лень исправлять (это связано с переключением активной страницы и её блокированием в момент работы меню)). Но игры как не было, так и нет. Это просто движок. Так получилось потому, что я не то что сюжет так и не придумал, так ещё и задолбался графику из кусочков собирать (в файле тайлов они просто разбросаны как попало. Я хотел прямо как картинки поставить, чтобы видно было, где и что. Но там такое количество элементов и их сочетаний, что я в них запутался). А ведь ещё каждому тайлу надо указать границы проницаемости, ибо автоматически построенные далеко не всегда корректны.
Программа для PSP полностью работает (за исключением мерцания в момент открытия меню использования предметов - пока лень исправлять (это связано с переключением активной страницы и её блокированием в момент работы меню)). Но игры как не было, так и нет. Это просто движок. Так получилось потому, что я не то что сюжет так и не придумал, так ещё и задолбался графику из кусочков собирать (в файле тайлов они просто разбросаны как попало. Я хотел прямо как картинки поставить, чтобы видно было, где и что. Но там такое количество элементов и их сочетаний, что я в них запутался). А ведь ещё каждому тайлу надо указать границы проницаемости, ибо автоматически построенные далеко не всегда корректны.
Приветствую! Будет ли продолжение данного проекта?
Добрый вечер. Там по сути проект сделан. Движок полностью работает. Но я так и не придумал саму игру и графику тоже не нашёл. Так что пока это проект для энтузиастов (там, кстати, ничего программировать не надо - достаточно написать скрипты и вставить два тайловых наброра - один графика, а второй проницаемость объектов первого - здесь описано подробнее https://habr.com/ru/articles/568332/ ).