Category: Баги

23
Авг
2024

Электрики атакуют

Второй лабиринт начинает понемногу запускаться. Обнаружились ошибки конвертации — почему-то я внес в словарь нулевой элемент в начале данных, хотя это неверно. Перепаковал лабиринт, нашел начало реальных данных обстановки. Но при обработке второго слоя возникла странность — в лабиринте обнаружилась целая толпа «Электриков» (монстров с кодом 6). Завтра буду разбираться, откуда там взялась эта бригада.

13
Май
2024

Ножи полетели

Сегодня ножи, которыми кидаются Бабки, полноценно полетели по лабиринту — они находят стены и разбиваются о них:

Не обошлось без неожиданных глюков:

Теперь можно начать обрабатывать попадания в монстров. Тут две задачи:

  1. Спрайт монстра, при попадании пули, нужно превратить в целиком белый спрайт. Средствами блиттера этого не сделать, там нет таких фич. Палитрой этого тоже не сделать. Придется попробовать генерить новый, белый спрайт из текущего спрайта монстра.
  2. Разлетание ошметков мяса — та еще задачка. Надо поизучать, как эти куски разлетаются на самом деле. Влияют ли на это стены, чтобу будет, если кусок мяса падает в яму и т.д.

 

12
Май
2024

Достать ножи!

Итак, Бабки научились кидаться ножами. Применил такую же стереофонию, как в «Prince of Persia»: звук броска слева — воспроизводится в левом канале, звук броска справа — в правом. Однако, возник интересный глюк — при левом броске звук воспроизводится с искажениями, хотя массив играется один и тот же. Похоже, что-то я сломал в звуковом стерео-движке, пока переделывал его под Goonies:

 

 

30
Апр
2024

Внезапные грабли

Графика в текущем проекте (Dave) выводится с помощью AZBK, а точнее с помощью одной из графических фич AZBK — блиттера. Суть «азбучного» блиттера состоит в том, что ему можно давать пакет команд, который он читает себе в буфер и потом выполняет уже самостоятельно, не отнимая процессорного времени.

Читать далее

16
Апр
2024

Призраки и Блиттер

Наконец-то я победил эти «хвосты» при скроллинге! Можно делать игру дальше!

При больших сдвигах рулона среднего экранного слоя (где бродят Зомби) промелькивали объекты, которые должны были уже быть стерты. И борьба с ними заняла у меня три дня…

Пока я использовал блиттер в атоматическом режиме (он при этом сам стартует при каждом прерывании по вектору 100) — все было почти хорошо. Точнее, в эмуляторе было вооще все хорошо, а вот на реальном железе при глобальном скроллинге экрана иногда наблюдалось какое-то дергание экрана.  Этим, конечно же, было поручено заняться Тэду из будущего. При этом возникал вопросы о скоростном построении экрана из множества тайлов — ведь количество команд, которые можно скормить блиттеру за раз, ограничено.  А это значит, что лабиринт будет заполняться порциями, каждыя из которых будет выводиться при очередном прерывании по вектору 100 («кадровое»). С появлением в AZBK режима ручного запуска блиттера, эта проблема ушла — выдаем блиттеру пакет за пакетом и запускаем все это сами, не ожидая милостей от вектора 100. Заодно появилась возможность сбрасывать блиттеру фоновые задачи, типа «удали старые спрайты со скрытого экрана, а мы в это время посчитаем куда какому монстру сделать шаг». И вывод на экран стало возможно делать тогда, когда хочется, а не ожидая очередного «кадрового» прерывания. Вот тут и был подвох.

Как только я добавил Зомби, шагающих туда-сюда, потребовалось их еще и скроллить вместе с фоном, когда Дейв инициирует движение окна. При этом, когда скроллинг (вертикальный или горизонтальный) докручивался до максимума и надо было уже переключать окно, вдруг могли промелькнуть какие-то дополнительные фигуры Зомби, там, где их никак быть не могло. Я предположил, что это спрайты, которые не успели стереться, а это место экранной страницы было вытащено скроллингом на видимую область экрана.  Стало ясно, что эти вещи надо тоже теперь синхронизировать вручную — сдвиг рулонов и переключение видимой области экрана. Но когда пакет команд блиттеру ушел, то о том, что блиттер его обработал, можно судить только по биту 15 в регистре 177270. Т.е. надо ждать, когда этот бит сбросится в 0 и потом можно переключать  рулоны.

А рулоны двигаются совсем в другом месте — в подпрограмме перемещения слоев в зависимости от деятельности Дейва. Блиттер работает сам по себе где-то в фоне, а вот регистры скроллинга изменяют изображение сразу. Значит, нам в этой подпрограмме нельзя изменять сами регистры, нужно просто вычислять новые значения, чтобы применить их потом, сразу кучей, после того, как блиттер закончит стирать/выводить спрайты и все будет готово к отображению нового кадра. Причем желательно  это сделать как раз в момент обратного хода луча, чтобы было незаметно.

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

Вот тогда призраки и были изгнаны и «дрожь земли» пропала!

Да, еще я напоролся на небольшие грабли: если пакет команд маленький, то блиттер так шустро его выполняет, что бит 15 (признак работы блиттера) и установиться не успевает. И это приводило к бесконечным ожиданиям «когда ты там начнешь команды обрабатывать??» и зависаниям.

13
Апр
2024

Призрачные Зомби

Переделал движок анимации монстров. В анимации Зомби каждая фаза движения стоит на экране 8 кадров, напрашивалось решение выводить на экран только один из этих спрайтов, первый. А потом 7 кадров пусть он себе стоит, не надо выводить его заново. Что и было реализовано. Получен, конечно, большой выигрыш в скорости обработки монстров. Но можно еще ускорить, если сдвинуть начальные фазы монстров так, чтобы они обновляли свои ключевые спрайты не одновременно.

Не обошлось без подводных камней: пакет команд в блиттер уходит сразу после получения «кадрового» прерывания, а вот изменения начального адреса отображения слоя видеопамяти — в процессе обработки скроллинга движком. В итоге иногда на экране мелькают призраки Зомби, которые не успели стереться. Идеи борьбы с этими «хвостами» у меня есть, завтра попробую реализовать.

Монстров на одном уровне в Дейве прямо толпы — количество их достигает 60 штук. Конечно, не все они видны и в реальной игре Дейва быстро сожрут при большом столпотворении, но все равно есть что оптимизировать…

23
Мар
2024

Если где-то закрывается дверь, значит это кому-нибудь не нужно!

Итак, чтобы было понятно в чем суть, объясню как устроен вывод лабиринта в Дейве (моем). Хранится он, конечно, в виде кодов объектов, но его ведь надо вывести на экран. Причем экран в Дейве скроллится во все стороны с произвольным смещением, значит надо или постоянно дорисовывать невидимые части и вдвигать их в видимое окно, или вывести сразу весь лабиринт тайлами и только двигать по нему окно отображения. Во втором случае рисовать больше ничего не надо, только смещай окно да и все. Как угодно можно смещать.

Тут начинаются (как обычно) ограничения.

  1. В контроллере AZBK можно вывести на экран любую область его памяти, просто указав «экран начинается с такой-то страницы».
  2. В контроллере AZBK максимальная длина строки для экранного отображения — 512 байт. Для используего в Дейве видеорежима (256х192,  256 цветов) это байт на точку. Значит, рисовать «полотно» можно только кусками 512х512, а не каким-то там гигантским холстом.
  3. Скроллинг окна есть аппаратный, как горизонтальный так и вертикальный. Это прекрасно. Но он сворачивает окно в кольцо. Т.е., если мы двигаем окно влево, то справа вылезает начало этого же самого окна. Хорошие новости — размер окна может быть 512х512, а видимая часть у нас 256х192. Значит, мы можем протянуть 256 «новых» точек рулоном из невидимой части. Но после этого все равно в окно вползет левый край этого же, пусть и большого, окна.

Каким же образом двигаться по большому холсту? Можно в невидимой части дорисовывать новую обстановку. Но Макс (MaxiolLtd) предложил идею покруче: «У нас же море памяти! Можно сделать кучу страниц и оперировать ими!».

Т.е. мы делаем две страницы 512х512 таким образом, что вторая страница ПОВТОРЯЕТ половину первой. И тогда, когда горизонтальным скроллом мы втянем влево эти правые 256 точек, мы может сбросить счетчик рулона на ноль, а начало экрана для отображения переключить уже на вторую страницу 512х512. Ведь у нас эти два куска по 256 точек полностью совпадают. И таким макаром двигать можно бесконечно — половину вкручиваем, перключаемся на следующую страницу. Расход памяти дикий, олды бьются в истерике «это не наш метод», ну да и пофиг, развлекаемся 🙂

Коряво нарисую как выглядит «мегаэкран» в моем ремейке Дейва:

Специально сдвинул квадратики, чтобы они не затерли границы друг друга. В целом, понятно, как это выглядит — по вертикали тоже надо продублировать половины (много половин, много, да).

Скролл заработал весело, но чуть позже стало понятно, что везде есть подводные камни — если на пересекающихся частях нужно что-то изменить (открыли дверь, к примеру), то ведь и скопировать теперь надо эти изменения на ВСЕ пересекающиеся части. Итого может быть от 1 до 4 копий одного места.

Вот тут и начались развлечения с дверями. Дело в том, что эти виртуальные видеостраницы 512х512 тоже состоят из страниц, которые имеют фиксированный размер 10000(8) байт. Блиттер, конечно, лихо рисует на них, ему только адреса подкидывай. 24-битные. Но надо еще и все «соседские отношения» помнить — кто на ком стоял. Причем, размеры у лабиринтов у всех разные, окошек 512х512 может быть разное количество и по вертикали и по горизонтали. Поэтому двери у меня два или три дня появлялись непонятно где (неверно считались смещения на соседних страницах), потом вроде открываешь дверь, идешь от нее, а она у тебя за спиной закрывается! Страница включилась с неоткрытым вариантом. Ну и все в таком духе.

Записал видеоролик, залил в ютуб и потом там заметил, что на 1:31 там мелькает снова закрытая дверь! Начал думать как это снова могло произойти и понял, что не учел того, что дверь имеет размеры 2х3 тайла и при этом может стоять на границе аж четырех страниц! Т.е. левая часть в одном окне, правая часть в другом, а нижняя половина еще черт знает где.

Но сегодня я их добил! Теперь можно в эти шкафы что-то и поставить. Ролик исправлять уже не стал, пусть останется для истории: