Разработка и ромхакинг > Ромхакинг и программирование
SGDK
<< < (21/40) > >>
Sharpnull:

--- Цитата: ALKOSHA от 23 Январь 2019, 10:01:17 ---так ведь 64 тайла - это 512 пикселей. Зачем рисовать лишнее за пределами экранной области?

--- Конец цитаты ---
Это если делать один вызов VDP_setTileMapData(), размер слоя 64x32, там же память должна идти линейно. Можно вызывать 28 раз по 40 тайлов и смотреть на скорость.

В Red Zone заранее рассчитанные тайлы. Попиксельно меняется только мини-карта. Вода + часть объектов на слое A, земля на слое B, у обоих при повороте приходится переставлять все тайлы и по-моему это делается не каждый кадр, вода точно каждый второй кадр обновляется при макс. скорости поворота. При перемещении вверх/вниз было бы необязательно переставлять тайлы, но вертолёт шатает, поэтому как минимум вода обновляется. Арки, которые кажутся трёхмерными, и большинство других объектов - просто спрайты. Вывод фактически в 256x224.
ALKOSHA:

--- Цитата: Sharpnull от 23 Январь 2019, 11:48:15 ---Вывод фактически в 256x224.
--- Конец цитаты ---

А, ну да. Забыл, что справа ещё интерфейс.

 
--- Цитата: Sharpnull от 23 Январь 2019, 11:48:15 ---Арки, которые кажутся трёхмерными, и большинство других объектов - просто спрайты.
--- Конец цитаты ---
Ну эт я в курсе. Однако параллакс стен внутри зданий - полигоны, как  мне кажется. Ещё внутри зданий 3 слоя этажей бывает местами, тоже довольно интересная фишка.
Sharpnull:
ALKOSHA, я забыл, что MD поддерживает 3D полигоны. Возможно там и используются.
ALKOSHA:

--- Цитата: Sharpnull от 23 Январь 2019, 12:50:39 ---что MD поддерживает 3D полигоны
--- Конец цитаты ---

"поддерживает" эт сильно сказано. Ведь для переброски хотя бы одного пиксела в позицию XY, процу нужно выполнить кучу лишних операций. бенчмарк в SGDK - предел оптимизации в этом плане, позволяет залить экран с филл-рейтом 15-20 кадров в секунду. И это при шакальном разрешении 256*160.


--- Цитата: Sharpnull от 23 Январь 2019, 09:43:52 ---15 FPS  Даже если вызывать random() один раз на кадр.
--- Конец цитаты ---

я тут подумал, при такой дискретности даже 15-ти кадров должно хватить. Там, где для per-pixel вывода нужно 60 кадров, в потайловом выводе достаточно 60/8. Тем паче при трассировке стен зачастую одна треть экрана пустует (если не смотреть на стенку в упор). Так что, вполне неплохой результат, имхо.
Но оптимизация хотя бы до 30-ти кадров не будет лишней, конечно же.

Добавлено позже:

--- Цитата: Sharpnull от 22 Январь 2019, 15:06:31 --- например этот простой движок
--- Конец цитаты ---
По объёму строк он вроде бы и прост.
Но некоторые ф-ции высокоуровневые JS непонятно как перенести в сишку.
К примеру ray = map.cast(player, player.direction + angle, this.range);
или
? inspect(stepX, 1, 0, origin.distance, stepX.y)
    : inspect(stepY, 0, 1, origin.distance, stepY.x);

и с JS я практически не знаком.


Тут тоже кажется простым на первый взгляд.

Но тоже есть свои подводные камни.
Как например класс векторов надо в массив структур переделать
vector<pair<float, float>> p;

Или как быть с этим?
sort(p.begin(), p.end(), [](const pair<float, float> &left, const pair<float, float> &right) {return left.first < right.first; });

Уже готовая ф-ция сортировки.

 более доходчивые примеры пытаюсь найти.
Sharpnull:
ALKOSHA, там внизу статьи порты, например на Java.

--- Цитата: ALKOSHA от 23 Январь 2019, 13:19:57 ---К примеру ray = map.cast(player, player.direction + angle, this.range);
или
? inspect(stepX, 1, 0, origin.distance, stepX.y)
    : inspect(stepY, 0, 1, origin.distance, stepY.x);
--- Конец цитаты ---
map.cast - это метод у map, а inspect функция. Тернарный операция ?: работает как в C/C++. Да, в JS нужно привыкнуть к ООП через прототипы и функции и к замыканиям.
--- Цитата: ALKOSHA от 23 Январь 2019, 13:19:57 ---sort(p.begin(), p.end(), [](const pair<float, float> &left, const pair<float, float> &right) {return left.first < right.first; });
--- Конец цитаты ---
Обычная функция сортировки: начало, конец и функция сравнения. В SGDK есть сортировка qsort(), но возможно придётся свою реализовать.
ALKOSHA:

--- Цитата: Sharpnull от 23 Январь 2019, 15:40:01 ---ALKOSHA, там внизу статьи порты, например на Java.

--- Конец цитаты ---

О, это жы LibGDX.
На нём я нынче пишу Кровавого мяча под андроид/ПК. (сега-версия слишком утомила непредсказуемыми багами, поэтому решил, не пропадать же добру - перенесу на мобилки хотя бы)

https://vk.com/wall-145919754_381

https://vk.com/wall-145919754_229

https://vk.com/wall-145919754_278

Но делать рейкаст для современных платформ иррационально по сравнению с аппаратной растеризацией поликов, конечно же.
Sharpnull:
ALKOSHA, посмотрел код с консолью, в принципе проблем не должно быть. Вместо sqrt для расчёта длины можно использовать упрощённое вычисление, в SGDK уже есть: u32 getApproximatedDistance (s32 dx, s32 dy).
vector там не нужен, всегда 4 элемента :lol:, а pair заменить на структуру.

--- Код: ---pair<float, float> p[4];

// Test each corner of hit tile, storing the distance from
// the player, and the calculated dot product of the two rays
int i = 0;
for (int tx = 0; tx < 2; tx++)
    for (int ty = 0; ty < 2; ty++)
    {
        // Angle of corner to eye
        float vy = (float)nTestY + ty - fPlayerY;
        float vx = (float)nTestX + tx - fPlayerX;
        float d = sqrt(vx*vx + vy * vy);
        float dot = (fEyeX * vx / d) + (fEyeY * vy / d);
        p[i] = make_pair(d, dot); //.push_back(make_pair(d, dot));
        i++;
    }

// Sort Pairs from closest to farthest
sort(&p[0], &p[4], [](const pair<float, float> &left, const pair<float, float> &right) {return left.first < right.first; });

// First two/three are closest (we will never see all four)
float fBound = 0.01f;
if (acos(p[0].second) < fBound) bBoundary = true;
if (acos(p[1].second) < fBound) bBoundary = true;
if (acos(p[2].second) < fBound) bBoundary = true;
--- Конец кода ---
--------
Ошибся с sort(&p[0], &p[4], здесь второй аргумент это элемент после последнего.
Sharpnull:
Попробовал реализовать этот код из видео, оказалось что там вместо нормального вычисления шага для проверки стены, делается шаг постоянный 0.1, что медленно, а если его увеличить до 1.0, будет 30 FPS на 256x224, но тогда будут неточные высоты. В общем, лучше код из моего примера реализовывать.
ALKOSHA:

--- Цитата: Sharpnull от 23 Январь 2019, 09:43:52 ---Если вместо DMA_QUEUE использовать DMA или CPU, видны разрывы экрана.
Я думал, что всё-таки будет 60 FPS для такого простого кода. Может знающие ASM и архитектуру сделают лучше.
--- Конец цитаты ---

А если перед циклом рендеринга отрубить прерывания? Может побыстрее будет?

Я проверить смогу только вечером.
Sharpnull:
ALKOSHA, я не понял о каком коде речь, в том примере, если изменить на CPU разрывы не уйдут и будет даже меньше FPS - 56.2:

--- Код: ---VDP_showFPS(TRUE);
SYS_disableInts();
u16 rand = random() % 16;
for (int i = 0; i < 32 * 28; i++) {
    u16 tileIndex = (rand + i) % 16;
    tileAttrs[i] = TILE_ATTR_FULL(PAL1, FALSE, FALSE, FALSE, tileIndex);
}
VDP_setTileMapData(VDP_PLAN_B, tileAttrs, 0, 32 * 28, CPU);
SYS_enableInts();
VDP_waitVSync();
--- Конец кода ---
Я так и не узнал, что будет, если не отключать прерывания во время доступа к VDP. Может только на реальном железе заметно.
ALKOSHA:
Если чё, там ф-ция рандома неоптимизированная.
http://gendev.spritesmind.net/forum/viewtopic.php?f=19&t=2968

Добавлено позже:
Вот только как бы это линейное заполнение преобразовать в X Y ?
  *dst++ = TILE_ATTR_FULL(PAL1, FALSE, FALSE, FALSE, rand() & 0xF);
ALKOSHA:
u16 x,y;

x=10;
y=10;

dst = x*y;

эмм.. .пытаюсь сообразить.. ээ.. там же  24 неиспользующихся тайла за экраном.
поэтому...  :shifty: щас...
dst = x*y*24 ? Не... чёт многовато, мне кажется.
Думай, галава, думай.  :wall:
если
Y
равен 1
то
dst = x+y+24;
 да?
или...
dst= x+y+24*y;
SeregaZ:
в моем случае экран это 64х28 тайлов. для чтения их нумеров тайлов используется массив в массиве и соответственно два цикла. не знаю есть ли в твоей среде разработки сложные массивы...


--- Код: ---Structure constr
  Y.l[28]
EndStructure
Global Dim CoordX.constr(64)

; в итоге это выглядит примерно так

CoordX(5)\Y[5] = 123 ; типа в координатах 5:5 рисовать номер 123

; чтение
If ReadFile(#File, PathFile$)
 
 
  For y = 1 To 28   ; y выше так как построчно х1, х2, х3... y+1, x1, x2...
    For x = 1 To 64
      CoordX(5)\Y[5] = ReadUnicodeCharacter(#File)
    Next
  Next
 
  CloseFile(#File)
EndIf

; но это случай, когда весь экран на 64 по х забитый.
; там просто начиная с 41 нули

; в твоем случае должно быть что-то типа:
dst = y * 64 + x
--- Конец кода ---
ALKOSHA:
Моё видение тайлового рейкастинга на СМД.
Sharpnull:
ALKOSHA, вот код того парня с ютюба. Он там к тому же перепутал синусы и косинусы, но всё работало правильно, так как и карта, и углы были в другую сторону. Теперь карта записанная в коде отображается на обычную координатную плоскость: ноль слева внизу, x - вправо, y - вверх. Исправления от "рыбьего глаза" добавил. Всё ещё нужно определять stepX, stepY, так как из-за шага в 0.1 и дальности 16 происходит 160 проверок на одну колонку и FPS может падать до 8. Если шаг увеличить - fStepSize, то расстояния будут с большой погрешностью. В книге Game Engine Black Book: Wolfenstein 3D есть про рейкастинг, но не очень подробно, автор реализовал вульфа под винду (код рейкастинга), но там код сложнее чем у A first-person engine in 265 lines (нужный код в Map.prototype.cast = function(point, angle, range)).
Напомню, что в SGDK у sin/cos входные значения от 0 до 1023 (0 - 2PI). У Fusion скорость эмуляции выше, чем в других эмуляторах, так что нужно ориентироваться на другие.
Skay:

--- Цитата: Sharpnull от 30 Январь 2019, 12:11:09 ---В книге Game Engine Black Book: Wolfenstein 3D есть про рейкастинг, но не очень подробно
--- Конец цитаты ---
про рейкастинг вроде бы неплохо рассказывается у Е.В. Шишкин, А.В. Боресков - Компьютерная графика - 2001 (по матчасти лучше и более полного руководства, с таким уровнем вхождения не встречал), там и теория и тоже на примере волфстейна, дума
Werton:

--- Цитата: Sharpnull от 30 Январь 2019, 12:11:09 ---вот код того парня с ютюба
--- Конец цитаты ---
Работает прыкольна :) но фпс маловато, наверное не обойтись без уменьшения области рендера, да и без текстур все как то грустно.
worm:

--- Цитата: Werton от 30 Январь 2019, 14:24:06 ---Работает прыкольна :) но фпс маловато, наверное не обойтись без уменьшения области рендера, да и без текстур все как то грустно.

--- Конец цитаты ---
Ну тут уж ничего не поделаешь - не тянет сежка псевдо 3д на адекватном уровне. Лучше играть в качественные 2д игры, чем в пиксельное слайд-шоу.
SPOT:
Помню KRIKzz делал рейкастинг и вроде бы даже были какие-то исходники.
ALKOSHA:

--- Цитата: Werton от 30 Январь 2019, 14:24:06 --- да и без текстур все как то грустно.

--- Конец цитаты ---

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

Добавлено позже:

--- Цитата: worm от 30 Январь 2019, 15:23:32 ---Ну тут уж ничего не поделаешь - не тянет сежка псевдо 3д на адекватном уровне. Лучше играть в качественные 2д игры, чем в пиксельное слайд-шоу.

--- Конец цитаты ---


А как жы недоделанный порт вульфва ? Вполне адекватный уровень.
Так там вообще по горизонтали более ста лучей. Ещё и per-pixel вывод, что само по себе тормознее, чем аппаратные тайлы.

Добавлено позже:
Для тайлов нужно заготовить табличные значения. 40 лучей - не так уж и много.

Добавлено позже:

--- Цитата: Skay от 30 Январь 2019, 12:38:05 ---там и теория и тоже на примере волфстейна, дума
--- Конец цитаты ---

В думе не рейкаст, а полигончики. Так, для справки. Там оптимизация за счёт BSP-отсечения плоскостей (как и в кваке, только в отличие от кваки, BSP-дерево работает в одной плоскости, поэтому нет этажей)
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

Перейти к полной версии