Войти
ПроектыФорумКонкурсы

[320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции) (10 стр)

Страницы: 19 10 11 1214 Следующая »
#135
11:50, 5 ноя 2014

Почему после последней строки почти везде отсутствует перевод строки? Это же неполноценная строка получается!

Вот, в wiki нарыл

Даже в современных изданиях ОС UNIX и Linux отсутствие перевода строки в конце системных конфигурационных файлов приводит к тому, что последняя строка не учитывается[2], а казалось бы правильно составленный файл не работает, представляясь головоломкой для пользователя, не предупреждённого об этой самобытной особенности. См. раздел Конец строки.

#136
13:15, 5 ноя 2014

entryway
> после последней строки почти везде отсутствует перевод строки?
По стандарту С это вообще UB, компилятор может смело винт стирать. Но про С++ мне тут недавно говорили, что эта проблема в стандарте решена.

#137
13:19, 5 ноя 2014

гцц с -pedantic не ругается, значит норм )

#138
13:38, 5 ноя 2014

я не знаю про переводы
кому интересно, в icweapons.h лежат ТТХ оружия

#139
14:12, 5 ноя 2014

TarasB
> > Если вся память задана фиксированно прямо из кода, то это и есть говнокод в
> > чистом виде, так как такую игру нельзя ни модифицировать ни доработать
> лолшто, сто лет игры только так и писали, чёто с модификациями и доработками
> всё в порядке было

Посмотри на код UE и удивись ...

#140
14:20, 5 ноя 2014

innuendo
Почитай логику и роль единичного примера и удивись.

#141
14:27, 5 ноя 2014

TarasB
> Почитай логику и роль единичного примера и удивись.

Есть не только UE, есть иные. Хотя некоторые игры для конзолей так и делают до сих пор. С такими бюджетами и огромной командой можно переписывать код по многу раз )

#142
14:30, 5 ноя 2014

TarasB
> Почитай
TarasB
> и удивись.

Ты в курсе, что раньше игры писались только на asm ?

#143
17:21, 5 ноя 2014

Короче, я решил написать статейку про свою игру, про то, как сделать такие прикольные картинки.
Итак, часть первая.

1. Палитра.


Есть несколько приёмов скрыть недостатки картинки, сводятся они к огрублению картинки, к её урезанию. Причём чсх намеренно кастрированная картинка кажется выглядящей "стильно":
Изображение
Два цвета, заливающий большие области, всё блин, картинка века, молодёжь печатает её на футболках и ваще.

В старых играх часто картинка лучше выглядит в низком разрешении, потому что это скрывает угловатость геометрии, это тоже приём такой. Но я не про него.

Есть очень избитый приём, я не знаю как он называется, но я дохрена часто его замечаю. Посмотрите на эту картинку:
Изображение
тут только два цвета - тёмно-зелёный и розово-жёлтый. По сути цвета всех пикселей находятся примерно на одной плоскости, если изобразить их в кубе RGB, то есть пространство цветов получается не трёхмерное, а двухмерное.

Для особо криворуких удобна оранжево-голубая цветовая плоскость:
palette | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
то есть это все цвета, для которых

G=(R+B)/2;

ну можно немного от неё в стороны уходить, но недалеко.

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

Смотрите, вот вырвиглазный оригинал:
wc3before | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)

а теперь я беру и нахрен проецирую на эту оранжево-голубую плоскость:
wc3filter1 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
вааааау как стильно!!!!
Возьмите любой фотоконкурс, наверняка в призёрах будет такая оранжево-голубая фигня. Короче, отличный приёмчик для нубов. Я тоже не побрезговал)

можно другой фильтр применить, тоже стильно выходит:
wc3filter2 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)

Короче, одна из причин няшной картинки в игре - это кастрированная палитра. Вообще 8-битный фон был вынужденной мерой, потому что фон является огромной картинкой на 14 мегабайт, если б не 8 бит, он был бы намного больше. Ну и ограниченный набор пришлось как-то придумывать, как получше разметить. Ну и я как раз применил такую вот почти плоскую палитру:

  // первые 11 цветов служебные
  for (int i=11; i<256; ++i)
  {
    const int r = (i-11)%7;
    const int g = (i-11)/7%5;
    const int b = (i-11)/35;
    colorTable[i] = tbal::Color (r*28+g*8+b*3+37, r*14+g*18+b*13+21, r*6+g*10+b*29+5); 
  }

Наглядно вот так:
palette | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
цветов хоть завались, выбирай любой
Ну да, она не совсем плоская, но рядом
Ещё видно, что у меня нет чёрного, есть коричневый, это необходимо, чтобы провалы не были невидимыми, а ещё это добавляет ламповости, это увеличивает долю жёлтого цвета ламп накаливания.

Тот же вырвиглазный скрин, но в этой палитре, будет таким:
wc3filter3 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
мутновато, но тут контрастность надо как-то поправить, это да, и нифига не заметно, что 8 бит

#144
17:50, 5 ноя 2014

TarasB
> вааааау как стильно!!!!
Если честно, то стало выглядеть как говно.

#145
17:53, 5 ноя 2014

2. Топология


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

Для зерна-по-умолчанию (15071987) генерируется такая топология:
topology | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
треугольнички - это однонаправленные стрелочки, то есть можно пройти только в одну сторону. При этом горизонтальные односторонние переходы на самом деле становятся двусторонними после первого же прохода с нужной стороны (дверь открылась и так и осталась), но генератор это не учитывает. Односторонние проходы наверх в генераторе запрещены.

Цветные линии - это двери, требующие ключ соответствующего цвета (буква "К"). Цветные клетки - это до которых можно добраться только зайдя за соответствующую линию.

Итак, как такую картинку сгенерировать?

Ну, для начала надо построить один кольцевой маршрут что ли.
Итак, план такой.
Мы выходит из клетки (0,0) и идём тупо куда глаза глядят. Приоритетное направление - на новые пустые клетки.

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

Условие конца - дойти до клетки (0,0), либо до другой клетки, где мы были до первого необратимого хода (это клетка (0,0) и ещё две следующие). В алгоритме стоит ограничение на число попыток, и через эн шагов мы попали хрен знает куда, а вовсе не в начало:
top1 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)

Ну, в таком случае алгоритм берёт и просто прокладывает кратчайший путь к началу, при этом двигаясь по клеткам, где мы уже были.
В итоге получается так:
top2 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
некоторые проходы стали обратимыми, плюс добавились два новых прохода, за счёт рандома один из них стал односторонним, один стал двусторонним.

Итак, петля замкнулась. Получился уже неплохой лабиринт, при этом полностью проходимый из любой точки в любую.

Но нам этого мало. Давайте к этой петле новую присвинячим. Берём произвольную посещённую точку и идём из неё в случайную сторону, приоритетно выбирая путь в сторону пустой клетки. Через эн шагов, если мы не вернулись на старый маршрут, идём назад кратчайшим путём к клетке, начинающей новый маршрут, избегая предыдущих маршрутов.
Итак, добавили вторую петлю:
top3 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
я покрасил в цвет клетки второй петли.

Уже сейчас можно ставить дверь-на-ключе перед жёлтыми клетками, как видите. При этом жёлтый ключ ставится на любую чёрную клетку.

Повторять, пока не надоест:
top4 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
я ещё один новый маршрут покрасил цветом.

Всего число маршрутов может превышать число ключей, но можно объединять несколько соседних маршрутов в один:

клетки каждого маршрута покрашены одним цветом. Ещё сделаны кой-какие ограничения, чтобы переходы на новый маршрут не были вертикальными, но это нюансы уже.
top5 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)

Осталось повесить двери-на-ключах (угадайте куда) и расставить сами ключи.
Алгоритм расстановки ключей простой: жёлтый ключ можно ставить на любую чёрную клетку, красный - на любую жёлтую, зелёный - на любую красную итд. Но я ставлю не на любую. Я выбираю самую дальнюю клетку от предыдущего ключа, МУАХАХАХАХАХА.
В итоге получается та картинка, что вы видели изначально.

Дальше мы каждой клетке назначаем номер, в каком порядке её проходить. В зависимости от номера выбирается, какие ништяки в эту клетку размещать и каких монстров. Для клеток, расположенных в стороне от кратчайшего пути, слегка понижается вероятность напороться на кучу монстров и повышается до 100% вероятность найти ништяк. То есть боковые отростки и тупички, как правило, хранят хорошие вещи. Так делаются "секретики".

Алгоритм подходит и для 3Д, как вы видите.

#146
17:54, 5 ноя 2014

3. Форма пещер


Настало время генерировать тот самый огромный битмап.

Прежде чем нагенерить пещены, надо порезать уровень на сегменты. Сегмент - это горизонтальная часть уровня от стены до стены. Итак, режем уровень на сегменты, вот я все сегменты нарисовал:
seg | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)

Для каждого сегменты выбирается его внешний вид. Для верхних сегментов всегда выбирается лес, для нижних всегда выбирается ад.

Для остальных - случайным образом либо туннель с кирпичными стенами, либо пещера просто, либо туннель с бетонными стенами, либо туннель в клеточку, либо лавовая пещера. Ну, не совсем случайно, выбор зависит от того, в начале или в конце игры мы доходим до этого сегмента.

Для туннелей выбор формы пещеры простой - тупо прямоугольник, высота случайная в небольших пределах.
Для пещер хитрее. Форма пещеры задаётся двумя линиями y(x), одна линия для пола, другая для потолка.
Линии можно генерировать перлином наверное, но я сделал иначе.
Я генерирую координаты последовательно.

Сначала генерируется пол. Потом аналогично потолок, только он прибавляется к полу и у краёв сегмента делается наклонный потолок.

Самый простой способ - это

y[x+1] = y[x] + random(-1..1)

но это приведёт к отсутствию длинных наклонных участков, это не очень красиво

я сделал так, чтобы рандом как бы запоминал профиль последнего участка
я запоминаю профиль в отдельной переменной
этот профиль случайно меняется на random(-1..1) при переходе к следующей координате, при этом он ограничено диапазоном -3..3

приращение берётся как

(профиль + random(-2..2)).clamp(-1..1)

то есть к профилю прибавляем этот рандом, результат урезаем между -1 и 1, и это и есть то, на сколько надо изменить координату при переходе к следующему пикселю.

Так я генерирую кривую линию, идущую из точки x1 вправо. Аналогично генерирую линию из x2 влево. А потом миксую их, причём с разным весом. Вблизи точки x1 вес первой линии единичен, вблизи точки x2 вес второй линии единичен.

Сгенерировался такой сегмент короче (хранится как два массива y[x]):
seg2 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)

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

Раскидав сегменты, получаем такую картинку:
seg3 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)

То есть просто берём и сегменты кидаем друг на друга, это просто.

Теперь ещё надо заполнить вертикальные проходы. Форма прохода зависит от того, какие сегменты он связывает. Если нижний проход - туннель (либо снизу ад, а сверху туннель), то проход прямой, иначе кривой. Кривой проход тоже генерируется тем же алгоритмом генерации кривой линии, только немного не так: сначала генерируется форма осевой линии, а форма левой и правой границы отсчитается от осевой линии.

Не буду показывать, как выглядит карта с вертикальными проходами, это вы и так знаете.
Вопрос, где именно рисовать проход, простой, потому что мы знаем, на какой высоте находится какая точка какого сегмента. Скажу ещё, что вертикальные проходы через один сдвигаются либо влево от середины клетки, либо вправо. Чтобы при падении из дыры не провалиться дальше.

Ну и ещё надо в проходах нарисовать лестницы, тут не вижу сложностей.

#147
17:54, 5 ноя 2014

4. Текстуры


В игре используется:
1. Шум Перлина.
2. Клеточная текстура, это когда заранее выбирается эн случайных точек, а потом текстура заполняется так: для каждой точки (i,j) берётся разница расстояний до двух ближайших точек.
3. Волновая текстура - тоже берётся эн случайных точек, а потом для каждой точки суммируются синусы расстояний до них.
4. Тупо шум, рандом в каждой точке.

Все текстуры имеют размер 64х64.

Итак, вот так выглядит типичный Перлин:
texture1 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
мы видим зацикленное говно.

Я применил несколько приёмов расцикливания.

Приём1: смиксовать несколько текстур, растянутых в разное число раз, в идеале - чтобы коэффициенты растяжения имели иррациональное соотношение.

Чтобы его расциклить, надо сгенерировать два перлина, потом один из них растянуть в 7/16 раз, другой в 17/16 раз (чтобы числа плохо делились друг на друга и в итоге период был побольше) и взять полусумму:

int k = int(level.bunker1[sy*17/16][sx*17/16]<<7)+int(level.bunker2[sy*7/16][sx*7/16]<<7);
pixel = ColorToByte(tbal::Color(k,k,k));
//примечание - для текстур оператор [] сам берёт остаток по модулю

Получается совсем иная картинка, где цикл найти довольно трудно:
texture2 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
Вот такой вот фокус-покус! Основное условия, чтобы это проканало - это возможность заранее нарисовать огромный битмап.
Впрочем, для тридэ игор тоже можно, особенно если движок поддерживает кеширование текстур.

Приём2: сделать криво.

Вот так выглядит клеточная текстура без примесей:
texture3 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
ну вы понели
и видно, где даже центры клеток находятся

А теперь делаем так: заводим текстуру-невидимку, ну заполняеем по Перлину. Или две текстуры-невидимки. Растягиваем в кривое число раз. Делаем выборки. Но выбираем из них не цвет... а смещение! Из первой невидмки выбираем dx, из второй dy, а потом на карту уже выводим из клеточной текстуры пиксел с координатами не (x,y), а (x+dx, y+dy). Тем самым прямые линии становятся кривыми. А за счёт растяжения невидимок в кривое число раз кривизна становятся неповторяющейся:

        int dx = int(level.caves2[sy*17/16][sx*17/16]<<5);
        int dy = int(level.caves2[sy*5/4][sx*5/4]<<5);
        int r = std::min(255, int (level.caves1[sy+dy][sx+dx]<<8));
        int g = 0;

        pixel = ColorToByte(tbal::Color(r,g, std::min(r,g)));

ой, ну у меня тут вообще одна и та же невидимка, только растяжение разное. Ну и похххх
Короче, результат такой:
texture4 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
зацикленность всё равно видна, но она теперь стала немного неявной.

Кривая кирпичная кладка сделана аналогично, ну и ещё пару перлинов намиксовано сверху.

Для комнат-в-клеточку использовался тупо шум. Только он растягивался в 16 раз и между текселей рисовались клеточки.
Никаких миксов и прочих хитростей, растяжения в 16 раз достаточно.
texture5 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)

Для лавовых пещер бралась волновая текстура, причём она тоже искажается аналогично пещерной текстуре. Хотя можно и две волновые смиксовать, растянув одну из них.

#148
17:54, 5 ноя 2014

5. Предметы и освещение


Освещение сделано тупо, для каждого пикселя перебираются ближайшие источники света (не совсем все благодаря хешу), потом цвет умножается. Вернее, не для каждого, а только для пикселей, у которых обе координаты делятся на 8, для остальных интерполируется, но это не сильно ускоряет. В аду равномерное освещение максимальным значение, в лесу тоже равномерное освещение на 1/4 уровня, в остальных местах света изначально нет. Ещё к освещению прибавляется рандом, чтобы резкие переходы между уровнями заменялись на дизеринг.

Тут короч не о чем разговаривать, кроме одного нюанса.
В пещерах встречаются и синие, и жёлтые источники света. Цветное освещение в 8 битах это уже необычно и проблемно.
Смотрите, какая эта текстура на самом деле мерзско-белёсая:
light1 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)
Но кто про это узнает, если рядом с жёлтым источником света оно и незаметно нифига?
Зато без этой белёсости не будут работать синие источники света. Поэтому пришлось вот так вот текстуру испоганить.

Предметы - деревья и кустики это тупо фракталы. Провода тоже тупо фракталы. Фонарики - дуга с кружочком. Лампочки - линия с кружочками на концах, или кружочек на палочке. Ящики - квадратики в полосочку. Для расстановки ящиков берётся хитрый рандом, который избегает мест под лестницей или над проёмами. Короче, про предметы нечего говорить тоже.
В лесу фоновая картинка - тупо небо со случайными точками, снизу рисуются бугры (тот же алгоритм рисования кривой линии), над ними деревья.
light2 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)

Из-за того, что отсчёт цветов делается от коричневого, а не от чёрного, картинка сильно зажелтена. Кстати, небо тут не синее, а красное, проверьте пипеткой, будет (40,34,34).

В аду сверху - две случайные линии, снизу - сжатый по вертикали перлин, между ними случайные отрезочки:
light3 | [320*200*8] Тарас Бульба и платформы Хулиона (на 10й странице простыня про генереции)

Вот и всё.

Про двери и монстров говорить не буду, нарисовано всё в пеинте. Количество контента достигнуто за счёт мэдскиллзности, в ассетах картинки все есть, можете оценить, называется "программисты рисуют, пытаясь поскорее".

#149
17:55, 5 ноя 2014

Spartan
Надо ещё, чтоб игра изначально под такую палитру делалась, пока что при проекции просирается контраст. Но миникарта стала выглядеть намного интереснее, например.

Страницы: 19 10 11 1214 Следующая »
ПроектыФорумКонкурсы