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

--- Цитата: rep-stosw от 01 Ноябрь 2021, 04:49:50 ---щё на счёт коллизий не совсем понятно.   Можно ли сделать коллизию с точностью до пиксела?
--- Конец цитаты ---

Эммм, градиус, ты логику от представления не можешь отделить?

Коллизии это привязанные к спрайтам и окружению  Box-Box и существуют в вообще отдельном программном слое от графики.

Сооотвественно, как ты эти самые хитбоксы сделаешь такая точность и будет.



ALKOSHA:

--- Цитата ---Сооотвественно, как ты эти самые хитбоксы сделаешь такая точность и будет.
--- Конец цитаты ---

На сеге есть игры и с per-pixel колижном.
Worms, sub-terrania, pugsy и прочее. Но эти игры с акцентом на физику.
Другой вопрос, зочем ему это нужно, если он делает кальку с контры, судя по всему. Там просто надо позу спрайта поменять при проверке краёв платформы. То есть по-тайловой проверки более чем достаточно.
lupus:
Вставлю свои 5 копеек: я при “переносе” Silent Hill: Play Novel с GBA на SMD активно использовал вышеупомянутый Retro Graphics Toolkit и его алгоритмы дизеринга, после чего ещё маленько в фотошопе поправлял. Оптимизировать от души пришлось, т.к. палитра ограничена и самой графики немало, а её надо было как-то в 4 метра уместить, вместе с непожатым звуком.
rep-stosw:

--- Цитата: nonamezerox от 01 Ноябрь 2021, 14:11:15 ---Коллизии это привязанные к спрайтам и окружению  Box-Box и существуют в вообще отдельном программном слое от графики.
Сооотвественно, как ты эти самые хитбоксы сделаешь такая точность и будет.
--- Конец цитаты ---

Чувачок, представленный на картинке с таким боксом упадёт вниз.  Не удержится.

Для платформера желалась пиксельная точность. На учёт гравитации.  Чтобы ноги в воздухе не висели и чтоб не падал, когда перекрытие хотя бы на 1 пиксел.

В случае с сегой надо определить какие тайлы пересекаются и потом ещё проверить на локальное пересечение внутри тайлов.  Насколько это будет ресурсоёмко?  Как вообще в нормальных сеговских платформерах  это делается?   Чем обыгрывается?






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

--- Цитата: lupus от 01 Ноябрь 2021, 16:40:14 ---Оптимизировать от души пришлось
--- Конец цитаты ---

Я уже наигрался от души! :lol: Понял, что лучше перерисовать под требования сеги.   Только вот беда - не художник я.

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

--- Цитата: ALKOSHA от 01 Ноябрь 2021, 05:31:24 ---проверка коллизий откуда-то из примеров взята, или же свой велосипед?
--- Конец цитаты ---

Пока взял отсюда: https://under-prog.ru/sgdk-%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d0%b5-%d0%bf%d0%bb%d0%b0%d1%82%d1%84%d0%be%d1%80%d0%bc%d0%b5%d1%80%d0%b0-%d0%b4%d0%bb%d1%8f-sega-genesis/

Автор этого сайта здесь недавно был.

ALKOSHA:

--- Цитата ---Как вообще в нормальных сеговских платформерах  это делается? 
--- Конец цитаты ---

Как правило - по-тайлово.
Даже в сонике на наклонных плоскостях в таблички загнаны интерполированные значения оффсета.
Шоба чувачок не падал - делаешь шире колижн-бокс. Шоба нога не свисала в воздухе - меняешь кадры анимации... Та блин, ты ни разу не становился на край в том же сонике, флинке, ультра-коре и тд?
Тут чисто вопрос арт-исполнения, а не каких-то заумных алгоритмов.
Werton:

--- Цитата: rep-stosw от 01 Ноябрь 2021, 04:49:50 ---Как это сделать средствами SGDK ?

Пока приходят в голову 2 идеи:

1) Распилить атлас на отдельныве анимации и задать им разное время.
2) Сделать самостоятельно процедуры анимации - с нужными задержками и переходами между фреймами в одном большом атласе.
--- Конец цитаты ---
Ну в целом да, для одной задержки на отдельную анимацию сойдет и первый, для покадровой задержки 2ой.
Ti_:

--- Цитата: rep-stosw от 01 Ноябрь 2021, 04:49:50 ---Исходный фрагмент атласа (RGB 8:8:8):
--- Конец цитаты ---
rep-stosw:

--- Цитата: Ti_ от 01 Ноябрь 2021, 20:34:08 ---
--- Конец цитаты ---

Глянул оба варианта на реальной сеге + ТВ.
Да, стало лучше:  более выделены груди, немного стали различимы детали лица.





Для сравнения:

Ti_:

--- Цитата: rep-stosw от 02 Ноябрь 2021, 05:30:58 ---Да, стало лучше:  более выделены груди, немного стали различимы детали лица.

--- Конец цитаты ---
scolor_gen.exe in.png 16 out.png 0.1 3 3
но есть нюанс -  там каждый раз разные результаты выдаёт, поэтому все спрайты надо разом конвертить.  несколько раз прогнать и выбрать лучший вариант. как-то так.
Ссылки тут:
http://gendev.spritesmind.net/forum/viewtopic.php?p=20105#p2010
rep-stosw:

--- Цитата: Ti_ от 02 Ноябрь 2021, 19:34:49 ---scolor_gen.exe in.png 16 out.png 0.1 3 3
но есть нюанс -  там каждый раз разные результаты выдаёт, поэтому все спрайты надо разом конвертить.  несколько раз прогнать и выбрать лучший вариант. как-то так.
Ссылки тут:
http://gendev.spritesmind.net/forum/viewtopic.php?p=20105#p2010
--- Конец цитаты ---

Интересная программа, спасибо!  :) Да и вся ветка того форума интересная.

Несколько раз прогнать - это как?  Результат загонять в качестве исходного?

Было бы неплохо понять смысл параметров:  уровень дизеринга, размер фильтра и режим GEN.

Почему-то  генерит пустой белый прямоугольник, когда размер фильтра =1.
Ti_:

--- Цитата: rep-stosw от 03 Ноябрь 2021, 04:50:03 ---Несколько раз прогнать - это как?  Результат загонять в качестве исходного?

Было бы неплохо понять смысл параметров:  уровень дизеринга, размер фильтра и режим GEN.

--- Конец цитаты ---
нет, исходный один:
scolor_gen.exe in.png 16 out1.png 0.1 3 3
scolor_gen.exe in.png 16 out2.png 0.1 3 3
scolor_gen.exe in.png 16 out3.png 0.1 3 3gen - от названия sega genesis. то есть адаптация под её палитру. 
дизеринг это просто его величина, чем больше, тем сильнее. 0 не ставится.
по фильтру не знаю.

rep-stosw:

--- Цитата: Ti_ от 03 Ноябрь 2021, 08:40:54 ---нет, исходный один:
--- Конец цитаты ---

Глянул сорец этой программы. Да, там действительно random() используется. Поэтому результат каждый раз разный. Интересно, зачем так сделано?

---

Начал изобретать свой велосипед с коллизиями, так как примеры из интернета меня не впечатлили: либо всё в общем и ни о чём, либо неприменимо к СЕГе.

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

Мало определить индексы i,j   массива клеток, ещё нужно пиксельные смещения взаимно учесть : движение спрайта и скролы плоскости.

Ну и конечно, ограничение приращения координат спрайта, если шаг приращения больше дистанции до стены (когда спрайт близко к стене) чтобы не впечатывался в стену.

Скажу, что был мощный брэйн-фак, но мне удалось родить рабочий код: сделал 4 коллизии спрайта с тайлами плоскости.

Код:


--- Код: ---#define STEP 3 /* шаг приращения координат спрайта */

//Координаты спрайта
s16 RegionX=0;
s16 RegionY=0;

//Скроллы:
s16 ScrollX=0;
s16 ScrollY=0;

bool CollisionU(s16 rx,s16 ry)
{
 rx+=ScrollX;
 ry+=ScrollY;

 s16 i=rx>>3;
 s16 j=ry>>3;

         if(LevelMask[j][i  ])return TRUE;
 if(rx&7)if(LevelMask[j][i+1])return TRUE;

 return FALSE;
}

bool CollisionD(s16 rx,s16 ry)
{
 rx+=ScrollX;
 ry+=ScrollY -1;

 s16 i= rx>>3;
 s16 j=(ry>>3)+1;

         if(LevelMask[j][i  ])return TRUE;
 if(rx&7)if(LevelMask[j][i+1])return TRUE;

 return FALSE;
}

bool CollisionL(s16 rx,s16 ry)
{
 rx+=ScrollX;
 ry+=ScrollY;

 s16 i=rx>>3;
 s16 j=ry>>3;

         if(LevelMask[j  ][i])return TRUE;
 if(ry&7)if(LevelMask[j+1][i])return TRUE;

 return FALSE;
}

bool CollisionR(s16 rx,s16 ry)
{
 rx+=ScrollX  -1;
 ry+=ScrollY;

 s16 i=(rx>>3)+1;
 s16 j= ry>>3;

         if(LevelMask[j  ][i])return TRUE;
 if(ry&7)if(LevelMask[j+1][i])return TRUE;

 return FALSE;
}

void Joystick(void)
{
 u16 J=JOY_readJoypad(JOY_1);

 if(J&BUTTON_UP   )
 {
  for(s16 s=STEP;s>0;s--)if(!CollisionU(RegionX,RegionY-s))
  {
   RegionY-=s;
   break;
  }
 }
 else
 if(J&BUTTON_DOWN )
 {
  for(s16 s=STEP;s>0;s--)if(!CollisionD(RegionX,RegionY+s))
  {
   RegionY+=s;
   break;
  }
 }

 if(J&BUTTON_LEFT )
 {
  for(s16 s=STEP;s>0;s--)if(!CollisionL(RegionX-s,RegionY))
  {
   RegionX-=s;
   break;
  }
 }
 else
 if(J&BUTTON_RIGHT)
 {
  for(s16 s=STEP;s>0;s--)if(!CollisionR(RegionX+s,RegionY))
  {
   RegionX+=s;
   break;
  }
 }

 static u8 t=0;

 if(!t)
 {
  if(J&BUTTON_A)ScrollX--;
  if(J&BUTTON_B)ScrollX++;
  if(J&BUTTON_X)ScrollY--;
  if(J&BUTTON_Y)ScrollY++;
 }

 t++;
 if(t==8)t=0;
}

#define LEVEL_W 40
#define LEVEL_H 28

const u8 LevelMask[LEVEL_H][LEVEL_W] = {   //маска тайлов: 0 - свободно,  1 - cтена
{ 0, 0, 1,1,1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
....

--- Конец кода ---

Скроллы двигаются кнопками: A,B,X,Y.
Спрайт двигается: Up,Down,Left,Right

Протестировал - всё чётко.  Спрайт при тесном контакте со стенами не осциллирует.


rep-stosw:
Прикрутил прыжок и гравитацию.  Пока без ускорения.

Кстати, какая механика более правильная? :

1) В прыжке отжатие влево-вправо приводит к остановке перемещения игрока по горизонтали

2) В прыжке отжатие влево-вправо НЕ приводит к остановке перемещения игрока по горизонтали

На видео, сделан способ (1).


 
 
И как побороть этот треш?  При этом все ресурсы вроде как собираются...

rep-stosw:

--- Цитата: rep-stosw от 05 Ноябрь 2021, 05:16:53 ---И как побороть этот треш?  При этом все ресурсы вроде как собираются...
--- Конец цитаты ---

Пофиксил этот придурошный баг: https://allthe.codes/mirror/sgdk/commit/13b13e37d98e5e876befbc55120cee2cb418cff2

Прикрепил пофикшенный Jar (класть в bin).

 sizebnd(fixed).zip (2.5 КБ - загружено 26 раз.)

P.S. Чё-то я не понял... Релиз 1.65 у Стефа без фикса: https://allthe.codes/mirror/sgdk/src/tag/v1.65/tools/sizebnd/src/sgdk/sizebnd/Launcher.java
Werton:

--- Цитата: rep-stosw от 05 Ноябрь 2021, 09:12:53 ---P.S. Чё-то я не понял... Релиз 1.65 у Стефа без фикса:
--- Конец цитаты ---
Потому что фикс закомичен после релиза 1.65, ваш КО.
rep-stosw:
Приделал ускорение при прыжке и падении.

Скорость линейно убывает при прыжке: V-=A
И линейно возрастает при падении: V+=A
Максимальная скорость S
Максимальная высота прыжка H

Необходимо было один раз просчитать ускорение (насколько увеличивать/уменьшать скорость).

Реккурентная формула:   S + S-A + S-2A + ... +S-nA = H

Граничное условие сверху:   S-nA = V = 1  (минимальная скорость)

Граничное условие снизу:  V= S (максимальная скорость)

Решая, получил:  A = (S-1)(S+1)/(2H-S-1)

Загоняем в код, получим:


--- Код: ---#define JUMP_H 32    /* максимальная высота прыжка                          */
#define JUMP_S 5.0F  /* начальная скорость прыжка/конечная скорость падения */

//#define JUMP_A FIX16((JUMP_S*JUMP_S)/((2.0F*JUMP_H)-JUMP_S))                  /* ускорение прыжка/падения (скорость уменьшается до 0) */
#define JUMP_A FIX16(((JUMP_S-1.0F)*(JUMP_S+1.0F))/((2.0F*JUMP_H)-JUMP_S-1.0F)) /* ускорение прыжка/падения (скорость уменьшается до 1) */

f32 js=FIX16(JUMP_S); //скорость прыжка/падения с учётом ускорения

u8 BF=1;    //разрешено нажатие кнопки "B"
u8 JF=0;    //прыжок запрещён
s16 Ground; //уровень земли

void MoveControl(void)
{
 u16 J=JOY_readJoypad(JOY_1);

 if(BF==1)if(J&BUTTON_B) //если разрешено нажатие кноки "B" и нажата кнопка "B"
 {
  BF=0;             //запретить следующие нажатия кнопки "B"
  JF=1;             //разрешаем прыжок (движение вверх)
  Ground=RegionY;   //запоминаем уровень земли
//  js=FIX16(JUMP_S); //начальная скорость прыжка/падения
 }

// if(BF==0)if(!(J&BUTTON_B))BF=1; //если запрещено нажатие кнопки "B" и если кнопка "B" отжата, то разрешаем следующее нажатие кнопки "B" (запрет TURBO-нажатия)

 if(JF==0) //если прыжок запрещён, то движение вниз (гравитация)
 {
  for(s16 s=fix16ToInt(js);s>0;s--)if(!CollisionD(RegionX,RegionY+s)) //если нет коллизии вниз...
  {
   RegionY+=s; //...то движемся вниз
   break;
  }
  else BF=1; //...в противном случае разрешаем нажатие кнопки "B" (убрать, если используется запрет TURBO-нажатия)

  js+=JUMP_A;                           //увеличиваем скорость
  if(js>FIX16(JUMP_S))js=FIX16(JUMP_S); //ограничение
 }
 else //если прыжок разрешён, то движение вверх
 {
  for(s16 s=fix16ToInt(js);s>0;s--)if(!CollisionU(RegionX,RegionY-s)) //если нет коллизии вверх...
  {
   RegionY-=s; //...то движемся вверх

   if(RegionY<=Ground-JUMP_H)JF=0; //если высота превысила длину прыжка, то запрещаем прыжок

   break;
  }
  else JF=0; //...в противном случае запрещаем прыжок

  js-=JUMP_A;                       //уменьшаем скорость
  if(js<FIX16(1.0F))js=FIX16(1.0F); //ограничение
 }

--- Конец кода ---

Все скорости - [пиксели/c],  расстояния - [пиксели]

Вот весь автомат прыжка  без движка! :lol:

rep-stosw:
Есть ли способ в SGDK  обращаться к отдельным спрайтам из спрайтового атласа?

К примеру, у меня есть один большой спрайтовый атлас со сгруппированными спрайтами (выровнены на фрейм) каждый спрайт M x N  тайлов.

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

Стандартную функцию анимации использовать не хочу по причинам, изложенным ранее здесь в форуме.

Как в этом случае описать ресурс в res-файле и какими функциями выводить спрайты-устанавливать параметры?

Хочу создать свою анимацию - со своими последовательностями цепочек спрайтов  и со  своими атрибутами.

 Через железо сеги я и сам могу это сделать.   Интересует как это сделать ИМЕННО средствами SGDK через отрисов спрайта и установку атласа спрайтов.
Werton:
Все что можно описано в справке и в rescomp.txt, никаких секретных техник там нет.

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

--- Цитата: rep-stosw от 06 Ноябрь 2021, 15:53:50 ---Есть ли способ в SGDK  обращаться к отдельным спрайтам из спрайтового атласа?
--- Конец цитаты ---
стандартные
SPR_setAnim (Sprite *sprite, s16 anim)
SPR_setFrame (Sprite *sprite, s16 frame)

--- Цитата: rep-stosw от 06 Ноябрь 2021, 15:53:50 ---Необходимо выборочно дёргать произвольный спрайт и отображать его со своими: палитрой, координатами, атрибутами отзеркаливания.
--- Конец цитаты ---
SPR_addSprite (const SpriteDefinition *spriteDef, s16 x, s16 y, u16 attribut)
используй макрос TILE_ATTR(pal, prio, flipV, flipH) как параметр attribut

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

--- Цитата: rep-stosw от 06 Ноябрь 2021, 15:53:50 ---Стандартную функцию анимации использовать не хочу по причинам, изложенным ранее здесь в форуме.
--- Конец цитаты ---
Не используй, отключи автопроигрывание анимации и переключай фреймы вручную

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

--- Цитата: rep-stosw от 06 Ноябрь 2021, 15:53:50 ---Как в этом случае описать ресурс в res-файле
--- Конец цитаты ---
SPRITE name img_file width heigth [compression [time [collision [opt [iteration]]]]]
установи параметр time в 0, чтобы отключить автопроигрывание анимации

--- Цитата: rep-stosw от 06 Ноябрь 2021, 15:53:50 ---и какими функциями выводить спрайты-устанавливать параметры?
--- Конец цитаты ---
стандартными
rep-stosw:
Werton,  спасибо! 

Забыл отключить авто-анимацию, из-за этого мои анимации артефачили.

Можно ли заставить rescompiler выкидывать повторяющиеся тайлы в атласах спрайтов?

Спрайты-то он выкидывает.  Ещё хотелось бы оптимизации на уровне тайлов.

Ещё на счёт палитры вопрос.  Я сохраняю PNG как 16-цветный.  Но иногда цвет прозрачности в СЕГЕ не совпадает с прозрачностью в PNG.  Из-за этого изображение выводится с одним потеряным цветом и без прозрачности.   Что я делаю не так и как следует конвертить?

Использую IrfanView или GIMP.
Werton:

--- Цитата: rep-stosw от 06 Ноябрь 2021, 17:12:11 ---Ещё на счёт палитры вопрос.  Я сохраняю PNG как 16-цветный.  Но иногда цвет прозрачности в СЕГЕ не совпадает с прозрачностью в PNG.  Из-за этого изображение выводится с одним потеряным цветом и без прозрачности.   Что я делаю не так и как следует конвертить?
--- Конец цитаты ---
Альфа канал png тут не применим, нужно конвертить в png с индексированной палитрой. Первый цвет палитры и будет считаться прозрачным (либо же можно задать индекс прозрачного цвета вручную через VDP_setBackgroundColor (u8 value), но нужно знать индекс цвета). Для работы с индексированной палитрой я юзаю Graphics Gale, Aseprite, Pro Motion NG.
Навигация
Главная страница сообщений
Следующая страница
Предыдущая страница

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