Game Maker - создание игр | HellRoom Games
Июль 12, 2025, 12:31:21 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Войти
Новости:
 
   Начало   Game Maker Помощь Правила форума Поиск Календарь Войти Регистрация  
Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Огромный цельный мир  (Прочитано 36184 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Sky Rider
Активный участник
*****

Репутация: 70
Offline Offline

Пол: Мужской
Награды:
За постоянность! [10 дней на форуме]
API: Love
Деятельность: Lua, Python
Сообщений: 323


« : Февраль 09, 2012, 18:26:53 »

Думаю, многие хотели бы сделать так, чтобы действие игры происходило в одном, цельном и бесшовном мире. Но деактивация объектов в огромной комнате не спасает от жутких тормозов, поэтому создавать просто большую комнату - не вариант.
Я предлагаю вам своё решение этой проблемы :)

Управление:
- WASD для движения (персонаж двигается в сторону курсора)
- E и Q для изменения скорости передвижения персонажа

Скриншоты:

СОДЕРЖАНИЕ:
Пример 1: Очень большой мир с занесением координат объектов в массив и генерацией карты заранее;
Пример 2 (добавлено 10.02.2012): Бесконечный мир с хранением координат и id объектов в файлах, карта генерируется по мере надобности (а-ля Minecraft).

ПРИМЕР 1

Вкратце, как работает пример:

Во-первых, надо сказать, что персонаж, которым мы управляем, не двигается. Вообще. Это мир крутится вокруг него :) Комната имеет фиксированный размер 4096x4096 пикселей, и персонаж всегда находится строго в центре. В принципе, можно было бы сделать на четверть меньше, но я слегка перестраховался. У каждого объекта есть две переменные абсолютных координат world_x и world_y (а обычные x и y - это относительные координаты, т. е. положение объекта в комнате). В зависимости от того, как в абсолютных координатах переместился персонаж, мы двигаем все объекты в относительных координатах. К фону это тоже относится.

Весь мир разбит на локации. Одна локация - квадрат 1024x1024 пикселей (в абсолютных координатах). В любой момент времени активны лишь 9 локаций - та, в которой находится персонаж, и 8 прилегающих. При переходе между локациями мы выгружаем три устаревшие и подгружаем три новые.

Загрузка и выгрузка происходит следующим образом. У нас есть два двухмерных массива (в комментариях к коду я иногда называю их матрицами) - location и locobj. Location содержит координаты всех расположенных в нём деревьев через запятую. Если несколько усложнить код и применить шифрование, можно записать в этот массив координаты любых объектов в достаточно больших количествах, но я пока что этим не занимался. При подгрузке новой локации мы берём координаты объектов из массива location с соответствующими индексами (например, если мы подгружаем локацию 100/100, то берём строку location[100,100]), и заносим id всех созданных объектов через запятую в массив locobj с соответствующими индексами (например, locobj[100,100]). При выгрузке локации мы просто удаляем все объекты с id, записанными в locobj.

Достоинства:
- Большой бесшовный мир с минимумом объектов в комнате.

Недостатки на текущий момент:
- При большом количестве локаций массив location жрёт много памяти (locobj в разы меньше, ибо зачищается). В перспективе лучше работать с файлом;
- Ограниченное количество объектов, которые можно поместить на локацию, хотя и достаточно большое. Опять же, если использовать файл вместо двухмерного массива, проблема решается;
- Сложность "осмысленного" добавления объектов при создании карты. В перспективе решается несложным скриптом;
- По непонятной пока что причине деревья дёргаются при перемещении. Вроде всё связанное с координатами записал в End Step. Разберусь попозже. Спасибо Krib за помощь :)

БОНУС:
В пример входят пять авторских скриптов:
- Три для перевода целых чисел из 10-ричной системы счисления в 128-ричную (!) и обратно. Может заметно сократить объём занимаемой цифрами памяти. Использовать осторожно, т. к. переход обратно из 128-ричной в 10-ричную систему ест ресурсы;
- Два для шифрования id объектов в более компактный вид. По сути, просто отнимаем 100 000 и остаток переводим в 128-ричную систему, но длина номера уже сокращается до 1-2 символов :)

Ни один из этих скриптов я в примере не использовал, чтобы не запутывать код. Но тем, кто возьмётся за это дело всерьёз, думаю, они помогут очень неплохо :)

ПРИМЕР 2:

Как несложно догадаться из содержания, отличие от предыдущего примера по большому счёту лишь в том, что вместо массивов location и localobj используются файлы world.map и locobj.map (обрабатываются они как ini-файлы). Однако это решение не только устранило часть существовавших ранее проблем с массивами, но и добавило новых. Некоторые моменты пришлось переделывать существенно, поэтому я счёл нужным вынести это в отдельный пример.

Начнём с проблем, которые использование файлов решило. В первую очередь, конечно, процесс игры больше не занимает такого бешеного количества памяти :) Во-вторых, ранее неприятным моментом являлось то, что массивы не могут иметь отрицательных индексов и содержать больше 1 000 000 значений. Таким образом, в нашем мире нижней границей была локация 0/0, а верхней - 999/999. Поскольку файлы не имеют подобных ограничений, мир стал практически бесконечным. А раз так, я посчитал нужным несколько изменить формулу расчёта локаций. Старая формула (world_координата div 1024, где 1024 - ширина/высота комнаты) не работает диапазоне от (-1024,-1024) до (1024,1024) - четыре локации слипаются в одну. Новая формула такова:

location_x = round(world_x/1024)
Где location_x - номер локации по оси Х, world_x - положение объекта в абсолютных координатах по оси Х.
Такая же формула справедлива и для У-координат, надо только заменить Х на У.
Таким образом, персонаж, появляясь в точке (0,0) оказывается в самом центре локации 0/0

Ну а теперь о тех проблемах, которые использование файлов добавило. Первая и самая главная - они работают медленнее. Я отказался от генерации карты заранее не только потому, что мне так захотелось, но и из-за того, что скорость генерации упала просто невыносимо. Если 10х10 локаций генерируются за ~5 секунд, то 50х50 я так и не дождался (хотя и ждал не слишком долго, около минуты). И, поскольку загрузка локаций тоже происходит из файла, FPS игры несколько упал. Хотя я бы не сказал, что значительно. Во-первых, частично это из-за того, что карта теперь генерируется на лету (на уже сгенерированных локациях FPS больше). А во-вторых, при скорости передвижения 100% (а мы ведь в нормальной игре не будем летать со скоростью 200 пикселов за шаг? ;) ) даже этого не замечается. FPS стабильно держится 58-60.

Но всё-таки я размышлял над тем, как оптимизировать всю эту ерунду. Подумал: "может, если всё-таки переводить координаты в 128-ричную систему, а id объектов шифровать, запись файлов будет идти быстрее - т. к. записывать надо меньше?" Проверил. Не быстрее. Но я знал, что в этом варианте слабое звено - скрипт перевода из 128-ричной системы обратно в 10-ричную, поскольку он жрёт до неприличия много ресурсов - а всё из-за перебора массива с 128 значениями. И я подумал: может, со switch будет работать быстрее? Проверил. И удивился :)

В спринтерском забеге на 250 локаций по диагонали со скоростью 64 пиксела за шаг (примерно полторы минуты по времени) программы показали следующие результаты:
1. Без 128-ричной системы и шифрования средний FPS составил 51.75
2. Со 128-ричной системой и шифрованием средний FPS составил 53.3
Естественно, чистота эксперимента была сохранена, то есть кроме игры ничего не функционировало. Кто там спрашивал, нафига эта система нужна? :)

В обоих примерах скрипты 128-ричной системы обновил на более оптимизированные.

Ну и конечно, это ещё не предел. В планах:
- Оптимизация использования файлов:
     а) Запись в world.map координат объекта на локации, а не в мире (сделано)
     б) Выкидывание из записей в файле world.map запятых (сделано)
     в) Запись в world.map только положительных чисел (по локации и так понятно, в какой координатной четверти объект) (сделано)
     г) Возврат обратно к массиву locobj вместо файла locobj.map (сделано)
- Введение других объектов и сохранение их на локации. А то всё деревья да деревья... :)
- Offline-alive. Рассчитываем поведение активных объектов за пределами комнаты;
- Удобный редактор карты (сейчас создать её самому можно только путём прямого редактирования world.map)

Надеюсь, кому-то это интересно :)

* Огромный мир.gmk (161.55 Кб - загружено 1000 раз.)
* Бесконечный мир.gmk (193.71 Кб - загружено 1010 раз.)
« Последнее редактирование: Февраль 20, 2012, 13:23:44 от Sky Rider » Записан
VladTheCat
Немного
GM Pro user
*

Репутация: 145
Offline Offline

Пол: Мужской
Награды:
1000 сообщений!За постоянность! [100 дней на форуме]Настоящий игродел!
API: Love
Деятельность: Целая игростудия, состоящая из одного кота.
Сообщений: 1435



« Ответ #1 : Февраль 09, 2012, 18:36:30 »

Цитировать
Три для перевода цифр из 10-ричной системы счисления в 128-ричную (!) и обратно.
Это нафига? И разве есть такая система?
Записан


Будьте вежливы: Вам помогли? Не забудьте поставить плюс. А то банда злобных апельсинов придет за вами. И даже тех. поддержка вам не поможет. :3

Когда я что-то пишу в "<>", то это значит, что содержимое надо заменить на свое значение.
Krib
«Старожил форума»
******

Репутация: 114
Offline Offline

Пол: Мужской
Награды:
500 сообщений!За постоянность! [10 дней на форуме]Знаток Game MakerЗа помощь новичкам!
API: Game Maker 8.0 Pro
Сообщений: 951


« Ответ #2 : Февраль 09, 2012, 18:37:14 »

При движении деревья смещаются относительно травы, вообще фон некрасиво себя ведет, лучше рисовать траву draw-ом.
Записан

Fuge, late, tace
Sky Rider
Активный участник
*****

Репутация: 70
Offline Offline

Пол: Мужской
Награды:
За постоянность! [10 дней на форуме]
API: Love
Деятельность: Lua, Python
Сообщений: 323


« Ответ #3 : Февраль 09, 2012, 18:44:27 »

Цитировать
Три для перевода цифр из 10-ричной системы счисления в 128-ричную (!) и обратно.
Это нафига? И разве есть такая система?
Если под "есть" вы подразумеваете, используется ли она где-то - скорее всего, нет. А вообще систему можно создать абсолютно любую, хоть стопицотричную.
Использовать её можно для сокращения объёма памяти, занимаемого цифрами. Для сравнения, число "15000" в 128-ричной занимает всего два символа.

При движении деревья смещаются относительно травы, вообще фон некрасиво себя ведет, лучше рисовать траву draw-ом.
Спасибо, попробую.
Записан
Krib
«Старожил форума»
******

Репутация: 114
Offline Offline

Пол: Мужской
Награды:
500 сообщений!За постоянность! [10 дней на форуме]Знаток Game MakerЗа помощь новичкам!
API: Game Maker 8.0 Pro
Сообщений: 951


« Ответ #4 : Февраль 09, 2012, 18:51:29 »

 ;D
Цифры.
10 цифр => 24 => на одну цифру 4 бита
Символы.
ANSI.
256 символов => 28 => на один символ 8 бит
Еще не факт, что в GM используется ANSI, некоторые символьные кодировки достигают 2 байт.
Записан

Fuge, late, tace
Sky Rider
Активный участник
*****

Репутация: 70
Offline Offline

Пол: Мужской
Награды:
За постоянность! [10 дней на форуме]
API: Love
Деятельность: Lua, Python
Сообщений: 323


« Ответ #5 : Февраль 09, 2012, 18:55:27 »

Тьфу, понятно Мда....
Ну ладно, будет просто экзотичный скрипт ;D
Записан
Krib
«Старожил форума»
******

Репутация: 114
Offline Offline

Пол: Мужской
Награды:
500 сообщений!За постоянность! [10 дней на форуме]Знаток Game MakerЗа помощь новичкам!
API: Game Maker 8.0 Pro
Сообщений: 951


« Ответ #6 : Февраль 09, 2012, 18:56:09 »

Хотя если представлять числа в виде строки, то тогда твоя теория верна.
Записан

Fuge, late, tace
Sky Rider
Активный участник
*****

Репутация: 70
Offline Offline

Пол: Мужской
Награды:
За постоянность! [10 дней на форуме]
API: Love
Деятельность: Lua, Python
Сообщений: 323


« Ответ #7 : Февраль 09, 2012, 18:58:17 »

Да, в массиве же вся эта ерунда в строковом виде :)
Хотя лучше слегка заморочиться и зашифровать только цифрами, тогда, по идее, количество занимаемой памяти ощутимо уменьшится.
Записан
Krib
«Старожил форума»
******

Репутация: 114
Offline Offline

Пол: Мужской
Награды:
500 сообщений!За постоянность! [10 дней на форуме]Знаток Game MakerЗа помощь новичкам!
API: Game Maker 8.0 Pro
Сообщений: 951


« Ответ #8 : Февраль 09, 2012, 19:03:54 »

В принципе можно сделать в виде файла для каждого блока карты.
Код:
id объекта|x|y|доп параметр|доп параметр|
1 128 256
1 129 276
2 150 200 250 1
Допустим id = 1 это дерево, а id = 2 враг (жизни = 250, тип = 1)
Записан

Fuge, late, tace
Sky Rider
Активный участник
*****

Репутация: 70
Offline Offline

Пол: Мужской
Награды:
За постоянность! [10 дней на форуме]
API: Love
Деятельность: Lua, Python
Сообщений: 323


« Ответ #9 : Февраль 09, 2012, 19:05:24 »

В файле же данные хранятся как строки? Тогда мой скрипт пригодится :)

Добавлено: Февраль 09, 2012, 19:06:11
Вообще да, я не знаю, какого чёрта я связался с массивами. Это ж ужос, стока памяти в унитаз ;D

Добавлено: Февраль 09, 2012, 19:10:24
Допустим id = 1 это дерево, а id = 2 враг (жизни = 250, тип = 1)
Не, хранить координаты в файле можно только для статичных объектов. Активные придётся всё равно держать в памяти (если нам нужно подобие offline-alive). Не переписывать же в файле постоянно координаты объекта? Хотя можно, конечно, но я бы лучше сделал файл карты неизменным.
Записан
Krib
«Старожил форума»
******

Репутация: 114
Offline Offline

Пол: Мужской
Награды:
500 сообщений!За постоянность! [10 дней на форуме]Знаток Game MakerЗа помощь новичкам!
API: Game Maker 8.0 Pro
Сообщений: 951


« Ответ #10 : Февраль 09, 2012, 19:20:28 »

После выхода из локации всё-равно будет цикл, пробегающийся по всем объектам, следовательно сделать перезапись файла не так уж и сложно, думаю от этого игра тормозить не станет.
Записан

Fuge, late, tace
Sky Rider
Активный участник
*****

Репутация: 70
Offline Offline

Пол: Мужской
Награды:
За постоянность! [10 дней на форуме]
API: Love
Деятельность: Lua, Python
Сообщений: 323


« Ответ #11 : Февраль 09, 2012, 19:40:31 »

Да тормозить-то вряд ли будет... Но мне почему-то больше нравится чтобы карта была как в сталкере, неизменной :)
Записан
Hamster099
«Старожил форума»
******

Репутация: 164
Offline Offline

Награды:
1000 сообщений!За постоянность! [100 дней на форуме]За лояльность! [+150 репутации]
API: GameMaker Studio Master
Сообщений: 1264



« Ответ #12 : Февраль 09, 2012, 19:46:28 »

- По непонятной пока что причине деревья дёргаются при перемещении. Вроде всё связанное с координатами записал в End Step. Разберусь попозже.
Попробуй поставить перемещение прямо в драв. Помогает. Необъяснимо но факт 

Добавлено: Февраль 09, 2012, 19:51:01
Нажал 6, загрузило процессор на 25% (полностью одно ядро), память уже 300мб и медленно растёт, пока ничего не происходит (загрузка)

Добавлено: Февраль 09, 2012, 19:55:42
загрузилась игра, тормозов нет вообще. занимает 412мб в памяти. грузилась минут 5
Записан
Sky Rider
Активный участник
*****

Репутация: 70
Offline Offline

Пол: Мужской
Награды:
За постоянность! [10 дней на форуме]
API: Love
Деятельность: Lua, Python
Сообщений: 323


« Ответ #13 : Февраль 09, 2012, 20:19:24 »

Попробуй поставить перемещение прямо в драв. Помогает. Необъяснимо но факт 

загрузилась игра, тормозов нет вообще. занимает 412мб в памяти. грузилась минут 5
Да вот пробую, пока безрезультатно :(
Про проц я на самом деле ошибся. Это дело просто накачивает память огроменным массивом, а вот сам проц не грузит, т. к. в самой комнате объектов минимум единовременно находится и рассчитывать особо ничего не надо. 5 минут, скорее всего, заняла сама генерация карты и закачка массива в память. Если бы у нас была уже готовая карта в каком-нибудь файле, это дело бы вообще грузилось за секунду.
Записан
Hamster099
«Старожил форума»
******

Репутация: 164
Offline Offline

Награды:
1000 сообщений!За постоянность! [100 дней на форуме]За лояльность! [+150 репутации]
API: GameMaker Studio Master
Сообщений: 1264



« Ответ #14 : Февраль 09, 2012, 20:23:58 »

Если бы у меня было одно ядро то я бы курил бамбук все эти 5 минут, нагрузка на проц в момент загрузки максимальная.
По поводу файла - нет нужды грузить его весь, нужен только маленький кусок территории вокруг игрока.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  

HellRoom Games © 2006-2012 All Rights Reserved
Powered by SMF 1.1.21 | SMF © 2013, Simple Machines
Страница сгенерирована за 0.108 секунд. Запросов: 29.