| Разработка и ромхакинг > Ромхакинг и программирование |
| SGDK |
| << < (19/40) > >> |
| Sharpnull:
ALKOSHA, по умолчанию 64 на 32 тайла (512х256 пикселей). Меняется через void VDP_setPlanSize для обоих слоёв: --- Код: ---// vdp.h void VDP_setPlanSize(u16 w, u16 h) Set background plan size (in tile). Parameters: w width in tile. Possible values are 32, 64 or 128. h height in tile. Possible values are 32, 64 or 128. --- Конец кода --- Получить значения можно через переменные u16 planHeight и u16 planWidth. ------ В доках не сказано, но в спецификации не доступны варианты 64x128, 128x64, 128x128: SCROLL PLAYFIELDS Two scrolling play fields. whose size in cells is selectable from; 32*32, 32*64, 32*128, 64*32, 64*64, 128*32 |
| ALKOSHA:
Да, всё. Спс. Выставил 64*64 - полегчало... На время. Потому как при старте игры такая жесть, что в порядок всё никак не могу привести. Там же я эффекты выжимал всякими трюками с палитрой, анимацией кешированных тайлов и построчными скроллами, А щас вся эта дичь вообще неадекватная. :-\ :-\ :-\ :-\ |
| ALKOSHA:
Не знаете почему происходит затирание спрайта, когда тот оказывается за пределами экрана ? То есть по возвращению его оттуда - он остаётся пустым. |
| Sharpnull:
ALKOSHA, без кода не обойтись, потому что при обычных условиях такого не должно быть. Неплохо было бы минимальный проект с одним спрайтом, на котором это видно. Пока будете разгребать и убирать лишний код, может сами поймёте. Если использовали код завязанный на расположении VRAM, попробуйте код из этого комментария (он должен вернуть адреса как раньше до версии 1.30): --- Код: ---// these lines can be used in your code to change VRAM layout as olders SGDK (<= 1.30) VDP_setPlanSize(64, 64); VDP_setWindowAddress(0xB000); VDP_setSpriteListAddress(0xBC00); VDP_setHScrollTableAddress(0xB800); VDP_setBPlanAddress(0xC000); VDP_setAPlanAddress(0xE000); --- Конец кода --- |
| ALKOSHA:
--- Цитата: Sharpnull от 25 Февраль 2018, 05:42:09 ---Пока будете разгребать и убирать лишний код, может сами поймёте. --- Конец цитаты --- Эх, да. Видимо проще будет всё опять с нуля писать. :'( Добавлено позже: И ещё один момент. Каким образом вы синхронизируете игровой процесс? Всё лень на зарубежном форуме сформулировать данный вопрос. Дело в том, что конкретно в моём случае на экране бывает то единицы спрайтов, то резко обрабатывается траектория десятков спрайтов. Вследствие чего образуются лаги. Я из данной статьи взял предпоследний пример https://habrahabr.ru/post/136878/ разделив игровой цикл на две функции update() и display() Конечно же при инициализации запустил таймер startTimer(0); А после проверяю его значение u32 current = getTimer(0, FALSE); В эмуляторе всё ок получается. Но на железе почему-то возникали непредвиденные глюки (то палитра не присвоится, то тайлы посыпятся. Хз из-за чего, может скорости ОЗУ не хватает). По крайней мере в старых версиях. Интересно, как синхронизируете вы. Конечно ещё как вариант можно умножать каждое перемещение на дельта-тайм, но это как-то геморно. |
| Sharpnull:
ALKOSHA, учитывая, что железо одно и желательно постоянное FPS, лучше добиться отсутствия просадок и простой цикл подходит. Впрочем, всё зависит от ситуации, игры не приставках тоже тормозят иногда. --- Цитата: ALKOSHA от 25 Февраль 2018, 10:24:13 ---Но на железе почему-то возникали непредвиденные глюки --- Конец цитаты --- SYS_disableInts и SYS_enableInts использовали? Проблема возможна в прерываниях, но это моё дилетантское мнение. --- Цитата: ALKOSHA от 25 Февраль 2018, 10:24:13 ---можно умножать каждое перемещение на дельта-тайм --- Конец цитаты --- Умножение и деление, особенно для 32-разрядных чисел - дорогое удовольствие для такого железа, тут лучше не увлекаться. |
| worm:
--- Цитата: ALKOSHA от 25 Февраль 2018, 02:38:09 ---Не знаете почему происходит затирание спрайта, когда тот оказывается за пределами экрана ? То есть по возвращению его оттуда - он остаётся пустым. --- Конец цитаты --- У меня он наоборот вылазит из другого конца экрана. Поставил спрайт горящего факела на задний план - при скролле картинки, он появляется где не надо. Думаю, что дело в железе и нужно допиливать это на программном уровне что в моем, что в твоем случае. |
| Sharpnull:
--- Цитата: worm от 28 Февраль 2018, 05:41:46 ---У меня он наоборот вылазит из другого конца экрана. --- Конец цитаты --- Говоря о спрайте (на sprite plan), он должен возвращаться с другой стороны при выходе за пределы слоя. Проблемы из вашего описания не видно. К тому же, затирание в эмуляторе, а вы, полагаю, говорите о проблеме только на реальном железе. |
| ALKOSHA:
--- Цитата: worm от 28 Февраль 2018, 05:41:46 ---Думаю, что дело в железе --- Конец цитаты --- С новой версией до железа я ещё не добрался. Пока что только в Кега-Фьюжн тестирую. |
| worm:
--- Цитата: Sharpnull от 28 Февраль 2018, 06:07:42 ---затирание в эмуляторе --- Конец цитаты --- Тоже возможно, однако алкаш использует тот же поганый эмулятор для проверки ромов что и я, а у меня не затирает. Скорее всего, дело в версиях сгдк. К слову о затираниях и точности эмуляции - было бы здорово, если бы под genesis plus gx кто-нибудь гуёвину написал, т.к. бластем слишком багованный, а точности такого уровня, как у этих 2х эмулей, больше нигде нет. --- Цитата: ALKOSHA от 28 Февраль 2018, 08:42:20 ---Пока что только в Кега-Фьюжн тестирую. --- Конец цитаты --- попробуй ретроарч с GX модулем, вдруг результат будет другой. Фьюжен - та еще дрянь. |
| Sharpnull:
ALKOSHA, я тут понял, что не учёл с функцией VDP_setPlanSize(): если ставить размеры 32*128, 64*64, 128*32, то изменение расположения VRAM обязательно, иначе будет пересечение памяти и соответственно вылезающие не к месту тайлы. Этот код показывал выше: --- Код: ---// these lines can be used in your code to change VRAM layout as olders SGDK (<= 1.30) VDP_setPlanSize(64, 64); VDP_setWindowAddress(0xB000); VDP_setSpriteListAddress(0xBC00); VDP_setHScrollTableAddress(0xB800); VDP_setBPlanAddress(0xC000); VDP_setAPlanAddress(0xE000); --- Конец кода --- Надо быть со всем этим осторожно, потому что вероятно влияние на другой функционал. |
| ALKOSHA:
Начал проект с чистого листа. Один спрайт, один слой. Скроллится / перемещается в полном здравии без багов. Но хотелось бы более понятное для меня толкование данной ф-ции. void SPR_init (u16 maxSprite, u16 vramSize, u16 unpackBufferSize ) maxSprite - максимальное количество массива указателей Sprite *sprites[..]; ? Так ведь? То есть, если у меня на игровом экране будет, скажем, 100 спрайтов, то мне надо сперва Sprite *sprites[100]; А затем первый параметр maxSprite тоже указывать 100? vramSize - методом тыка подгонять, чтоб не перекрыло тайлы фона ненароком? unpackBufferSize - Я так полагаю, что буфер распаковки всё в той же VRAM, где и спрайты, и фоны. Т.е. его лучше оставлять дефолтным. |
| Sharpnull:
--- Цитата: ALKOSHA от 12 Март 2018, 18:00:24 ---maxSprite - максимальное количество массива указателей Sprite *sprites[..]; ? --- Конец цитаты --- Да, там заранее выделяется оперативная память и если вызвать лишний раз SPR_addSprite(Ex), то он не сработает и вернёт NULL. --- Цитата: ALKOSHA от 12 Март 2018, 18:00:24 ---vramSize - методом тыка подгонять, чтоб не перекрыло тайлы фона ненароком? --- Конец цитаты --- Посмотрел код, там такая история: Тайлы лежат в памяти с 0-го адреса, до maps_addr (из vdp.c). После установки адресов VRAM (VDP_setBPlanAddress() и т. п.) этот адрес обновляется. По умолчанию (когда размер слоёв только 64x32, 32x64, 32x32) там памяти до начала слоя B. Максимальное количество тайлов, которые можно использовать - TILE_MAXNUM (в vdp.h есть другие полезные константы). При это немного взято вначале и в конце на системный шрифт. Спрайтовый движок (sprite_eng) выделяет тайлы заранее как раз перед шрифтом. Поэтому возможно использование низкоуровневых операций со спрайтами (функции из vdp_spr и vdp_tile), в этом случае обычно используют тайлы с начала TILE_USERINDEX. Следовательно, если под тайлами фона имеются в виду тайлы, которые расположены вначале, то придётся расчитывать как-то самому (движок проверяет границы и сам лишнего не запишет в пределах vramSize). Либо больше места для спрайтов выделять заранее, либо для всего остального. При правильной установки адресов VRAM, на сами слои (т. е. фон, plan) ничего не залезет. В случае размеров слоёв 64х64, 128х32, 32х128 будет просто меньше места на 128 тайлов. unpackBufferSize - это выделенная в ОЗУ память, которая используется только в SPR_update(), когда необходимо подгрузить тайлы (если только включена автоподгрузка SPR_FLAG_AUTO_TILE_UPLOAD), такое случается при смене фрейма SPR_setFrame() или анимации SPR_setAnim(), а значит можно примерно представить сколько одновременно спрайтов можно сменить одновременно за один кадр. Например, у Соника размер 25 тайлов, если одновременно 11 соников сменят анимацию, то памяти не хватит (по умолчанию 256). Ещё важное: при SPR_FLAG_AUTO_TILE_UPLOAD (по умолчанию), каждый Sprite будет использовать тайлы VRAM, это значит, что вызов 5 раз SPR_addSprite() с одним и тем же спрайтом (даже если фрейм один, т. е. нет анимации) будет занимать при отображении памяти как 5 спрайтов, а не один. В примерах есть летающие пончики sgdk\sample\astrofra\starfield_donut, там не используется автоматическая загрузка, поэтому удаётся отобразить 32 пончика одновременно. Пример нужно брать из репозитория, а не архива 1.34 (sgdk134.7z), была исправлена ошибка, но всё равно остался косяк: MAX_DONUT должен быть 32, а не 65, иначе рисуются лишние спрайты и происходит отброс спрайтов, если включён лимит в эмуляторе. В GensKMod или других эмуляторах есть возможность отладки, например вот VRAM из примера с Cоником. |
| ALKOSHA:
Как в новой версии захайдить спрайты? В старой было так Выкл: sprites->visibility = 0x00000000; Включить видимость: sprites->visibility = 0x3FFFFFFF; |
| Sharpnull:
ALKOSHA, void SPR_setVisibility(Sprite * sprite, SpriteVisibility value) Set the visibility state for this sprite. Parameters: sprite Sprite to set the visibility information value Visibility value to set. SpriteVisibility.VISIBLE = sprite is visible SpriteVisibility.HIDDEN = sprite is not visible SpriteVisibility.AUTO_FAST = visibility is automatically computed from sprite position (global visibility) SpriteVisibility.AUTO_SLOW = visibility is automatically computed from sprite position (per hardware sprite visibility) То есть SPR_setVisibility(sprite, HIDDEN);. По умолчанию SPR_addSprite() ставит VISIBLE. |
| ALKOSHA:
Спасибо. Кровавыш после довольно продолжительного анабиоза оживает. Но предстоит ещё море работы по его восстановлению. У меня там было всё выверено, каждый тайлик, каждая ячейка палитры, каждый порядковый номер спрайта.... Эххх.. пичаль. Сизифов труд. |
| ALKOSHA:
Тестирую цикл Меню->игра->геймовер->меню. И столкнулся с очередной проблемой. После геймовера не отображается титульная картинка. Разумеется все режимы ресетил, скроллы устанавливал в 0, выполнял очистку спрайтов/плейнов. Как выяснилось позже, картинка отказывается рисоваться именно после выполнения функции SPR_Init Сам титульный экран состоит лишь из двух плейнов, поэтому инициализацию спрайтов не делал, и картинка отображалась. Но SPR_Init используется при инициализации игры. Решил его поставить до инициализации меню, и действительно, в нём проблема. Шаманил с параметрами этой функци, выставлял дэфолтные, как указаны в мануале. Безрезультатно. Но что странно, игровые фоны отображаются без проблем. Хмм. |
| Sharpnull:
ALKOSHA, пробовали вызывать SPR_end()? Должны освободиться все ресурсы: End the sprite engine and release attached resources. This releases the allocated VRAM region, memory for unpacking and hardware sprite. Правда спрайтовый движок занимает VRAM перед шрифтом, то есть задевать тайлы от фона не должен. Если SPR_end() не поможет и надоест мучиться, я бы мог посмотреть код. |
| ALKOSHA:
Хууух. Спасибо огромное. вызов SPR_end() решил проблему. Добавлено позже: ....однако после второго проигрыша в цикле почему-то всё равно чёрный бэкграунд. |
| ALKOSHA:
Попробовал добавить модуль jaws.c из прошлого проекта. Получилась такая краснота. Попробовал удалить этот модуль из проекта. Но при компиляции он будто бы остался в проекте. Все темп-файлы подчистил, нажал ребилд - и всё равно. Даже сами файлы .с и .h с каталога удалил. И всё равно такая муть... Ничего не понимаю. |
| Навигация |
| Главная страница сообщений |
| Следующая страница |
| Предыдущая страница |