Розробка гри Frogger для комп'ютера Vectrex

Якийсь час назад я перекладав оповідання Chris Salomon про його розробці гри Frogger для комп'ютера Vectrex. Розповідь, написаний ним у 1998 році, є, на мій погляд, дуже цікавим документом, що дозволяє перейнятися як духом цієї незвичайної платформи, так і специфікою розробки на асемблері взагалі.

Chris не закинув Vectrex і, порівняно недавно, довів до релізу власний емулятор Vectrex для Windows (кращий на даний момент) під назвою «Vide». Мені, до речі, приємно, що мої исходники Electric Force допомогли йому реалізувати пристойну підтримку відображення векторних кривих у цьому емуляторі.

І ось, отримавши в руки такий потужний інструмент, Chris не зміг відмовити собі в задоволенні повернутися до свого старого Frogger', щоб доробити і поліпшити його. Про це він розповів у своєму блог.

Таким чином, тут я публікую дві частини мого перекладу — першу, про оригінальній розробці 1998 року (з файлу progger.txt, бродившего разом з вихідними кодами гри) і другу — про її продовження (з блогу автора).


Рік 1998. Початок



Цей файл містить примітки, які можуть бути цікаві іншим розробникам під Vectrex.
Також він включає «коротку» історію розробки Vectrex Frogger.

Оновлення зображення в Vectrex Frogger завжди відбувається з частотою 50Гц. Все малюється не більше, ніж за 30000 тактів. Нижче наводяться деякі замітки про техніки оптимізації, що дозволяють цього досягти.
Насправді, я дуже місто досягнутої швидкістю! Цілком можливо, що мої функції для роботи зі спрайтами — найшвидші з усіх існуючих в іграх під Vectrex (як мінімум, мені подобається так думати...)

Спрайт виглядають трохи дивно на цьому Vectrex — злегка «плямистими», однак, до цього можна звикнути. Пятнисты вони тому, що я використовував для кожного з них фіксований масштаб (scale) 6. Довгі лінії доводилося складати з більш коротких. Vectrex, за своєю природою, не завжди вимикає промінь коли потрібно (двома-трьома тактами пізніше, ніж потрібно). І він завжди включає промінь за декілька тактів перед початком малювання…
Це призводить до яскравої точці (можна було б написати нові функції для малювання векторів, які не використовують таймер і обчислюють час інакше, більш точно, проте кому захочеться цим займатися?).

Vectrex Frogger, серед іншого, повинен був служити добре документованої програмою для навчання програмуванню на цьому комп'ютері. Мені здається, цього зробити не вдалося.
З-за велетенського кількість векторів, які повинні були отрисовываться в крихітні проміжки часу, необхідно було оптимізувати кожен такт. З-за цих оптимізацій, як мені здається, програма перестала бути добре видно. В основному циклі залишився виклик єдиної функції BIOS (опитування стану цифрового джойстика).
Всі інші виклики були послідовно видалені і замінені оптимізованими (для конкретних ситуацій) макросами або подпрограммами.
У все це надзвичайно важко зрозуміти, якщо тільки не ви самі це писали.

Одна із застосованих технік оптимізації:

Пояснення, як намалювати вектор.

Так чи інакше, щоб перемістити промінь до потрібної позиції, ви ставите його швидкість, напрямок і час, протягом якого ця швидкість застосовується. Потім чекаєте, коли цей час мине.
Час — це масштаб, який ви задали. Якщо встановлюєте масштаб $90, значення повинно бути записано в таймер 1 (VIA_t1_cnt_lo. Прим. пер.) і потім, «марне» циклі, очікується, коли воно закінчиться.
Що я зробив, так це зробив цей цикл корисним. Істотна частина обчислення робиться в Vectrex Frogger якраз в це, зазвичай непотрібне, час.
Я використав цей підхід, переважно, при переміщенні луча. Великий плюс тут у тому, що як би багато я не робив у цей час, це ні на що не впливає! Єдине, за чим ви повинні стежити, це не займати МЕНШЕ часу, ніж значення таймера. Втім, це легко вирішується тим же циклом опитування таймера (VIA_int_flags — прим. пер.) в кінці ваших обчислень.

Той же підхід можна використовувати і під час малювання вектора. Малювання та переміщення вектора — одне і те ж. Єдина різниця — «патерн», записаний в сдвиговый регістр. Для переміщення туди записується 0, для малювання — $FF (якщо, звичайно, хочете намалювати суцільну лінію).
Однак, при малюванні потрібно впевнитися, що ви вимкнули промінь (записом 0 в сдвиговый регістр) вчасно. В іншому випадку отримаєте в кінці вектора яскраву крапку!

Ще одним способом оптимізації було написання спеціальної функції (макросів), для відображення списку векторів. Кожен виграний там такт був на вагу золота.
Припустимо, виводжу 30 спрайтів і кожен спрайт складається з, скажімо, 20 векторів. Це становить близько 600 векторів. Якщо я напишу оптимізовану функцію, яка заощадить близько 10 тактів на вектор, ми одним ударом виграємо близько 6000 тактів!!!

І ще — розгортання циклів!
Насправді, я використав цей підхід постійно з моїми програмами на Watcom C, проте ніколи не думав, що буду реалізовувати таке сам. Сьогодні я спробував щастя, розгортаючи функцію відтворення списку векторів. Удача! Я виграв більше 10 тактів на КОЖЕН вектор. Це дало мені ще одне прискорення в майже 3000 тактів! Я розкрутив лише один цикл — головний цикл малювання спрайту.
Інший важливий цикл малювання спрайтів (для спрайтів будинків) залишався недоторканим, хоча, якщо б я оптимізував таким чином всі цикли, я б ймовірно виграв від 500 до 1000 тактів. Але тут є і негативна сторона — це робить програму значно довше. Ну, ми не можемо отримати все, чи не так?

Ще одна техніка не використана, оскільки в ній, здається, більше немає потреби:
Реалізація нового типу векторного списку, який включав би інформацію про масштабі, може дати виграш у кілька циклів, так як багато довгі лінії тепер малювалися б короткими. Це може знизити втрати, якщо список буде включати другу змінну для довжини.

до Речі:
Асемблер який я використовував — ДУЖЕ хороший. Для оптимізації обов'язково дивіться у створюваний ним *.lst файл. У ньому не тільки код, але і кількість тактів для кожної інструкції і їх довжина… Правда, дуже класно :-)

Трохи про визначення об'єктів (специфічно для підпрограм, використаних у Vectrex Frogger):

Всі зображувані у грі «предмети» тепер називаються об'єктами. Ці об'єкти складаються з двох різних сутностей — списку векторів і визначення структури об'єкта. Список векторів — звичайний для Vectrex. Спочатку йде кількість векторів (мінус 1), потім відносні координати векторів (зміщення).

Для полегшення фіксації зіткнень, всі ці списки векторів повинні починатися з крайньої лівої точки. У ранній версії підпрограми вони повинні були бути обов'язково замкнутими, однак більше цього не потрібно.
Нижче наведено приклад структури об'єкта (взято з Vectrex Frogger):

otter1a_object:
 
DB 0 ; швидкість + напрямок
 
DW otter1a_sprite ; визначення графіки
 
DB 0 ; довжина SCALE_FACTOR_GAME
 
DB 5 ; затримка для анімації
 
DW otter1b_object ; покажчик на наступний анімований об'єкт
 
DB -4 ; зміщення y 'SCALE_IN_HOME', оскільки це об'єкт "дім"
 
DB 0 ; зміщення x 'SCALE_IN_HOME', оскільки це об'єкт "дім"
 
DB $60 ; яскравість
 
DB 0 ; спеціальний прапор


Спрайт відмальовує з фіксованим масштабом 6 (це може змінитися в майбутніх версіях — я розмірковую щодо нового списку векторів, який буде включати інформацію про масштабі).

Через надзвичайно оптимізованих підпрограм малювання це не може (і не повинна) бути змінено. Фактично, підпрограми оптимізовані настільки, що вони більше не малюють в точності те, що потрібно.

Існують дві проблеми:

  • Останній вектор у списку обрізається на 2-4 такти раніше необхідного.
  • Між об'єктами в списку об'єктів (поки ще не згадуваному) ми завжди обнуляем промінь (мова про обнулення інтеграторів та встановлення променя в центр викликом Reset0Ref — прим. пер.)
    Це обнулення робиться не на 100% коректно (тільки на 98% або типу того :-))
    Насправді, підпрограма злегка быстровата. Променю не вистачає часу, щоб досягти нуля (це з урахуванням того факту, що я вже забарився підпрограму на 4 або 5 циклів, однак цього недостатньо...), що призводить до ледь помітної неточності в позиціонуванні об'єктів.


Зауваження емулятора:

Vectrex Frogger нормально працює на емуляторі (тут мова про DVE — прим. пер.), однак:

Оптимізація робилася з використанням цього Vectrex, емулятор поки не може впоратися з деякими дрібницями, які необхідні для перевірки коду. Вони працюють нормально такими, які вони зараз. Але якщо ви будете самі щось оптимізувати, потрібен Vectrex — ви турбуватиметеся, якщо на реальному залозі все запрацює зовсім інакше. Особливо це стосується точного дотримання часових інтервалів.
Емулятор робить багато речей негайно, в той час як справжньому Vectrex-потрібно на це час. Наприклад, це вірно для обнулення променя і доступу до будь-якого регістру VIA…
Існує багато цікавих експоненціальних функцій для перегляду на екрані вашого Vectrex-a :-)
(такі як зарядження та розрядження конденсаторів інтеграторів).

Історія



Моя історія програмування під Vectrex і, в особливості, Vectrex Frogger.

Вперше я зацікавився Vectrex в 1983 році, але грошей, щоб його купити у мене не було. У 1996 я подумав, що можу перевірити свої здібності програміста і написати емулятор Vectrex. Однак, в тому ж напрямку думав і Кейт Уілкінс. Він виклав свої вихідні в той момент, коли у мене були лише перші начерки мого емулятора, так що я закинув їх і став дивитися у вихідні Кейта.
За наступні 2 роки я поліпшив його емулятор в деяких аспектах і думаю, що я тепер, типу, несу за нього відповідальність.
Кілька місяців тому я подумав, що було б прикольно перетворити DVE (згаданий емулятор — прим.пер.) у середу розробки для Vectrex, оскільки мені здавалося, що емуляція тепер досить хороша для цього (хоча тепер я знаю, що це не так і, можливо, ніколи не буде так, якщо незабаром не випустять Pentium III 500МГц, причому за помірною ціною).
Я ще раз оглянув Internet на предмет все, що стосується програмування Vectrex щоб розібратися, що знадобилося б програмісту.
Знайдено було досить мало. Трохи дизассемблированных образів ігор, втім, добре документованих. Дещо від Клея і Джона, хоча не сказав би, що добре документоване (особливо твоє, Джон). «Справжньою» інформації з програмування не було. Так що я вирішив, що повинен розбиратися сам.
Якось, в один із днів, я сів і спробував написати мою першу гру для Vectrex — VPONG. Вона була написана приблизно за 4-5 годин і для новачка працювала напрочуд добре, хоча тут не мається на увазі досягнення в плані іграбельності (там один гравець і грати досить складно). Однак все, що потрібно, там було — звук, вектора, текст, джойстик, кнопки, масштабування, фейдинг і т. д.
Наступного тижня мені в голову прийшла ідея Vectrex Frogger, звідки і народився перший прототип спрайтового движка. Тоді я зробив «відкриття», що масштабування великими значеннями — погана ідея.

Я розмірковував над швидкістю моєї програми і метою було одне оновлення (тут і далі мова йде про повну візуалізації одного умовного «кадру» — до чергового виклику Wait_Recal. Прим.пер.) як мінімум за 70000 тактів, інакше б я кинув це діло. Я вважав, що якщо це буде відбуватися за 70000 тактів, частота оновлення буде більше 20 Гц — тобто з прийнятними мерехтінням.
На той момент у мене вже був Vectrex, однак він ще не був підключений до паралельного порту комп'ютера (і добре, так як якщо б я тоді розібрався із з'єднанням, то закинув би всю затію досить швидко).

Експериментуючи зі значенням масштабу, я дізнався, що великі значення призводять до того, що оновлення тривають більше 100000 тактів. Подальші перевірки виявили, що малі значення працюють відмінно і я прийшов до, приблизно, 50000 тактів (до речі те, що я відповідав за емулятор, іноді дуже допомагало. Я написав функцію емулятора для вимірювання числа тактів — мені достатньо було набрати 'rc' і вона видавала такти необхідні оновлення :-))
(тепер абсолютно ясно, що масштаб насправді впливає, оскільки це таймер… однак тоді, теж знаючи це, я насправді не уявляв, що це означає).

У будь-якому випадку у мене в руках був працюючий спрайтовый движок і всякі дивні векторні малюнки, що рухаються по екрану на манер жаби. Мої підпрограми роботи зі спрайтами тоді вже підтримували анімацію, однак, зробивши два або три спрайту, я зовсім запарився. Малював спрайт олівцем на папері і перекладав координати координати для Vectrex. Робити таке для купи спрайтів — повний !$"$"&!"$&=(!!!
На щастя, я знайшов приятеля, шукає, чим би зайнятися і переконав його зробити маленьку програму для малювання векторів, що був зберігала координати таким способом, з яким я би легко міг працювати у своїй програмі. Джеймс (мій приятель) зробив таку програму, а я займався основний.
Досить швидко були скомпоновані підпрограми роботи з джойстиком і визначення зіткнень.
В першу версію Frogger (початкові рівні) можна було грати через три дні програмування, хоча ви не могли увійти в будинок і не було реалізовано жодних інших спеціальних можливостей.

Повторюся, я кілька запарився робити спрайти. Над деякими подпрограммами я думав навіть в автобусі по дорозі з роботи додому. Подпрограммами, які я щедро охрестив «подпрограммами морфінга».
У мене була ідея, що один список векторів може бути повільно змінено в іншій, і що в результаті вийде класний ефект. Я трохи поміркував над цим і виявив, що в 6809 не було інструкції DIV, а MUL була беззнаковой.
Я написав дві таких функції і дві (досі існуючі) підпрограми морфінгу (setup і do_one_step). Ох, вони були дуже повільні через ділення і множення багато разів за кадр через самописні підпрограми довелося дорого заплатити, скажу я вам. Незабаром я замінив функцію розподілу оптимізованою версією, яка працювала як треба.
Досі у мене була функція морфінга, яка могла морфить за будь-яке (8 біт) число кроків. Але вона все ще була надто повільна для практичного застосування. Після численних оптимізацій я прийшов до функції морфінга з фіксованим числом кроків — 16. Це та функція, яка використовується під час запуску гри і в деяких проміжних епізодах.

Закінчивши з цим, я переключився на звук. Мене завжди цікавило, які ноти якими були, поки нарешті я в цьому не розібрався (мається на увазі, що відносяться до BIOS Vectrex-a). Я не можу читати ноти і я хто завгодно, але не музикант.
Пошукавши в Інтернеті ноти «The yankee doodle», я не зміг нічого знайти. Все скінчилося midi файлом. Потім я став шукати midi-плеєр/редактор. У результаті знайшовся один, який виводив ноти мелодії читається формі. Зрештою, я написав» музику yankee doodle для Frogger.
Для мене це було великим подвигом, правда!!!
На початку, я хотів щоб тему ставив барабан, однак це звучало досить погано. В способі, яким мелодія грається зараз використовуються три голоси, зі зрушенням октави в кожному. Звучить по мені так нормально — в будь-якому випадку, помилок я розпізнати не можу :-(

Тепер настав час додати кілька деталей. Це було те, чого я побоювався, оскільки це означало розвага з вже готовим кодом і впровадженням нових речей (звичайно, наповнених багами). Новими деталями були мухи, крокодили, змії, дівчата, таймер, годинник, видра, плаваючі черепашки…
Я запрограмував їх всіх з закритими очима, проте мені не сподобалося ні хвилини цього заняття. Сказати по правді, я це ненавидів. Проте, це були речі, які я повинен був зробити, щоб Frogger був Frogger'ом. Ці чортові гри з ідіотськими змінними часу, коли з'являються мухи, перевірками координат знову і знову, якщо жаба близько до голови змії і т. п… Терпіти це не міг.
Але, як ви можете бачити, я це зробив. Однак, все має свою ціну. Frogger став повільним — він знову став близький до тих 70000 тактів.
В той час я якраз отримав картридж з ППЗУ для мого Vectrex-a і запустивши декілька різних ігор, виявив, що повільні гри сильно мерехтять :-(. Мені це дуже не сподобалося. Я поки ще не міг перенести мій Frogger у Vectrex, оскільки замовлений емулятор ППЗУ ще не приїхав, але у мене було кілька ППЗП і я на них поглядав…
В той момент мене дуже турбувало, як буде виглядати Frogger на цьому Vectrex, але я не міг знайти нікого з програматором.
Тим не менш, я усвідомив, що Frogger у тому вигляді, як він є, був занадто повільним, так що я почав подумувати про оптимізацію та компромісах. Перше, що я зробив — видалив з головного екрана підрахунок очок, життів і індикатор рівня. Чи Можете ви повірити, що один виклик цієї ідіотської функції «print string' займає понад 10000 тактів!?
Далі, я відредагував всі спрайт, урізав їх так, щоб використовувалося не більше 20, а лише 10-15 векторів, що в результаті дало виграш близько 10000 тактів (терпіти не міг редагувати всі ці спрайт знову!)
(до речі, черепашка яку ви бачите в скроллящемся тексті — предок тих черепашок, які повзають у самій грі).

Після цього я був впевнений, що зможу досягти моєї мети за таймінгів. Цією метою тепер стала побудова кожного кадру в межах 50000 тактів, оскільки усі виміри зроблені над доступними мені комерційними іграми означали, що це значення достовірно, а деякі ігри навіть виходять за його межі.

(Все ще чекаю емулятор ППЗУ...)

Так як поки що було трохи вільного часу, я вирішив, що добре було б реалізувати скроллящийся текст. Маючи практично готовий Frogger з десятьма смугами рухомих спрайтів, я думав, що зробити одну смугу рухомих літер не буде надто складним. І дійсно, після малювання всіх букв по 3 або 4 рази (програма малювання векторів мала серйозний баг) і витративши на це деякий кількість нервів, я з цим розправився.
Однак, тепер виникла нова проблема. У Vectrex так „багато“ ОЗУ! (Один кілобайт. Прим. пер.). Мати інформацію про рівень і спрайтах, необхідність зберігати багато інших змінних в ОЗП, робити морфінг і ще мати скроллящийся текст — це був ще один виклик. Я змінив розподіл осередків ОЗУ і став використовувати деякі з них двічі і тричі. Це також було зроблено, хоча пізніше мені спало на думку, що в той час програмування під Vectrex було ще легким.

(Все ще чекаю емулятор ППЗУ...)

Таким чином, я просто чекав і час йшло без будь-яких змін в коді.
За пару тижнів я не зробив нічого, оскільки остаточна перевірка повинна була бути зроблена на цьому Vectrex…

Нарешті він приїхав, підключений і… не працює :-(
Перевірив дещо… Так, працювати-той працює, проте єдиний ППЗУ картридж, який у мене був, мав адреси тільки до 8Кб, а Привів до того часу вже перевищив цей розмір, так що я не зміг пограти в мою гру :-(
(хоча, пограв майже в усі інші ігри, вперше).
Оскільки я сам не розбираюся в електроніці і не знаю, як переробити картридж щоб він працював з 16Кб (або 32Кб) ППЗУ, я голосно заволав про допомогу. Джон почув мої крики і прислав мені пару ППЗУ картриджів, які працювали відмінно (на це пішли ще два тижні).
Можливість мати доступ до 8Кб для початку теж не так вже і погана, так що я зміг розбити Frogger на кілька частин і перевірити їх одна за одною. Хоча це не дозволяло оцінити всі можливості гри, для часткової перевірки цілком достатньо.

Тут я виявив сильний ефект „хитання“ (wobble), який емулятор відтворити не міг. Після вивчення питання я зрозумів, що це було пов'язано з таймінгами. Хитання було, здебільшого, помітно при запуску. І тільки коли малювалися „нерухомі“ вектори, або анімовані рухомі якимось чином купували щось типу імунітету до цього (дивно?)
Так чи інакше, поимев кілька сивого волосся, я розібрався, що якщо оновлення кадру займає більше 30000 тактів, нерухомі вектори починають хитатися (як мінімум, на моєму Vectrex-e). Це стосувалося не тільки моєї гри, а майже всіх ігор, які мали нерухомі вектори де-небудь і вимагали більше 30000 тактів на оновлення кадру.
Це було вірно навіть для Minestorm — вбудованої в Vectrex гри. Коли гра запускалася, через кілька секунд, коли перші міни з'являлися на екрані, точки хиталися (природно на моєму Vectrex, т. к. я міг перевірити тільки на ньому).

Як тільки ви дізналися, як виглядає цей ефект, то починаєте виявляти його досить часто.
Годі й казати, що мені, як перфекціоністу, це зовсім не подобалося.
Інші ігри можуть хитатися скільки їм завгодно, але не моя гра. І вже точно не на стартовому екрані, який ви бачите, коли її запускаєте.
Я досі не знаю, що викликає цей ефект — будь-яка технічна інформація по цій темі вітається. Я думав, що єдине, що трапиться, якщо оновлення буде займати занадто багато часу, це мерехтіння. Але навіть якщо я встановлюю таймер „очікування рекалибровки“ у більшу, ніж стандартні 30000 тактів, значення, нерухомі вектори ХИТАЮТЬСЯ! (зазвичай значення цього таймера ініціалізується при включенні Vectrex і перевіряється в Wait_Recal, щоб всі „кадри“ займали за часом не менше 30000 тактів. Прим. пер). Я думаю, існує друге „фіксує“ значення, де-то в районі 50000, однак мерехтіння при цьому виходить неприемлимое.

Я змінив код так, щоб напис 'VECTREX FROGGER' і все інше не з'являлися на екрані одночасно (цей безглуздий текст також вимагає близько 5000-6000 тактів для відтворення). Хитання (при старті) пішло в минуле.
Але тепер я знайшов ще один ефект :-( (який все ще можна бачити на цьому Vectrex, оскільки я не зміг виправити це ніяким розумним способом).
Координати завжди повільно дрейфують до +,+ (вгору вправо).
Якщо ви залишите промінь в спокої на досить тривалий час, він піде вгору вправо. Малювання великий жаби на початку гри проходженням за великим списком векторів, з використанням великого масштабу — досить тривалий. Щоб повністю намалювати гігантську жабу, потрібно близько 2000-3000 тактів. За цей час промінь спливає приблизно на півсантиметра. Потрібно рекалібрувати промінь між отрисовками, що вирішило б проблему. Але на це немає достатньо часу :-( (жаба складається з 63 векторів, а позиціонування 63 векторів при даному масштабі неможливо ніяким чином, який не був би критичний по часу!

(63 * $90 = 9000 чисте час руху променя, без накладних витрат
63 * $70 = 7000 чисте час малювання векторів, без накладних витрат
накладні витрати = 1000 тактів. Це вже близько 17000 тактів тільки на жабу. А я ще хотів скроллящийся текст, плюс має бути обрахований морфінг жаби!)).

Крім того, фіксоване зміщення не може бути задано, оскільки згаданий дрейф не постійний. Він залежить від мого настрою Vectrex (зрештою, це стара аналогова машина). Так що, жаба добре виглядає на емуляторі (якщо в ньому не вказаний дрейф), але на цьому Vectrex у неї втрачається кінчик. Це мене трохи турбує, але не може бути легко виправлено!

Не рахуючи цього, здається, все працює просто чудово. Я провів пару тижнів не займаючись Vectrex Frogger'ом (і не особливо сумував за нього — попрацювавши деякий час, я був радий залишити його, зрештою, в спокої).

В один прекрасний день картриджі Джона нарешті прибули.
Спробував Frogger… І він запрацював!!! (огидно :-()

Якимось чином я уникав цього раніше, але в самій грі також були нерухомі „хитаються“ вектори. І вони ХИТАЛИСЯ :-( В той момент я був готовий все кинути. Я був радий, що досяг мети в 50000 тактів враховуючи, що спочатку хотів 70000. Однак, цього виявилося недостатньо. Щоб позбутися від хитання, не було іншого способу, ніж досягти 30000 тактів (насправді, це можна зрозуміти з исходника Wait_Recal в BIOS. Прим. пер.)

Деякий час я експериментував, щоб позбутися від нерухомих векторів, винаходив „рухомі“ будинку, пунктирні лінії і т. п. Але це практично не допомогло. Я ЗОВСІМ засмутився. Моя подруга намагалася втішити мене говорячи „це не так уже й погано“, однак з моєї точки зору це було погано. Я хотів зробити повноцінну повну гру Vectrex Frogger БЕЗ компромісів з „хитанням“.

Я роздумував поміняти всі спрайт знову з метою знизити використання векторів, проте це призвело б до спрайтам як в Atari 2600 — швидше угадываемым, ніж помітним. Так що, від цієї ідеї я відмовився.
Тут я вперше спробував використовувати регістр DP (який раніше був завжди встановлений у D0). Більш або менш розумне його використання, укупі з іншими оптимизациями, заощадило мені від 1000 до 2000 байт коду. Це дозволило мені знову перенести деякі функції BIOS в свій код і оптимізувати їх. Я виграв ще 10000 тактів і досяг 40000, однак губився в здогадах, що ще можна соптімізіровать.
Крок за кроком проходячи по коду і переглядаючи *.lst файл створюваний ассемблером, я вишукував вузькі місця в критичних ділянках… займався цим півтора дня… рухаючись маленькими кроками і економлячи по 10-20, іноді навіть по 100 тактів, я досяг приблизно 37000. Такий довгий шлях, і кожен наступний крок був все складніше. Потрібен перерву…

Відмінно пограв у Diddy Kong на моїй N64 (так, у мене крім Vectrex є й інші консолі) і у мене визріла ідея…
Чому б не використовувати цикли очікування у функціях позиціонування променя і малювання векторів для чогось більш корисного, ніж просто очікування коли закінчиться час на таймері?
Сказано-зроблено — після двох днів нервування, реалізації занадто швидких функцій, появи експонент на екрані Vectrex, дивних ефектів і… і… і… я заощадив ще 5000 тактів! (це було легко сказати, але нерви попортило неабияк — подробиці див. в исходниках).
Так чи інакше, я був на 32000 (це в гіршому випадку — з чотирма зайнятими будинками, дівчиною, крокодилом, видрою і зміями на екрані...)
Після цього я не міг і думати більше про всіх цих оптимізацію. Я редагував всі рівні, міняв їх, видаляв спрайт, переставляв спрайт, вимикав всякі фішки,… і т. д., хоча рівні все ще мали той характер, який я поставив на початку, незважаючи на те, що велика їх частина злегка змінилася. Зрештою, я це зробив!!!

КОЖЕН РІВЕНЬ ОНОВЛЮВАВСЯ МЕНШ НІЖ ЗА 30000 ТАКТІВ!!!

Я і правда дуже пишається своїм досягненням. І тепер вважаю Vectrex Frogger видатної програмою для Vectrex.

Можливо, це лише марнославство з мого боку, але я вклав багато зусиль у Vectrex Frogger і сподіваюся, що люди отримають задоволення від гри, а деякі, можливо, знайдуть джерело корисними і/або повчальними.

СТОП СТОП СТОП СТОП СТОП СТОП СТОП СТОП СТОП СТОП СТОП СТОП СТОП СТОП СТОП

Ще один успіх в оптимізації! Сьогодні я розкрутив пару циклів, що дало виграш у швидкості близько 3000 тактів! Гіп-гіп ура! Я відкотив зміни всіх рівнів і вони все одно не вимагають більше 30000 тактів…
Тепер у мене навіть є приблизно 1500 тактів в запасі :-)

КІНЕЦЬ ФАЙЛУ (Нарешті)



Рік 2016-й. Свіжий погляд на Frogger



… на цьому тижні я впритул приступив до програмування Frogger'a. В моїх планах:

  • Музика та звукові ефекти
  • Більш гладка графіка
  • Вписатися при цьому в 30000 тактів
  • Анімація
  • Вигляд „зверху вниз“ (багатьом не подобається вигляд збоку)
  • Режим двох гравців (по-черзі)
  • Ймовірно, збереження рекордів
  • Заставку погарніше


В останні тижні я, час від часу, редагував у Vide окремі списки векторів, але тільки на цьому тижні зібрав їх разом і переніс у Frogger (див. діфку).

Міняти оригінальні исходники довелося сильніше, ніж я очікував, оскільки „спрайт“ гравця не мав анімації. І въезжание в старі исходники, яким вже виповнилося 18 років — теж не полегшувало справу.

Так або інакше, як ви можете бачити, анімована жаба в ракурсі „зверху вниз“ — реалізована.

Як я писав раніше (нагадаю — майже 20 років тому), однією з головних моїх завдань було вкластися у 30 тисяч тактів, щоб уникнути коливань зображення.





Оскільки тепер я хотів додати додаткових фіч, довелося вдивлятися в код.

Я міняв і підкручував частина, яка генерувала списки векторів, до тих пір, поки вона не стала мегаэффективной. Правда, перший рівень гри (найбільш завантажений) став отрисовываться всього за 22 тисячі тактів!

Одна проблема — графіка була того ж типу, що і раніше — »типовою" векторною графікою Vectrex'a, коли частенько на одному з кінців лінії можна бачити «точку», оскільки промінь запалюється занадто рано.

Вуаля!

Посмотрита на нового жабеня: хіба він не прекрасний?

Хоча я і зробив це сам, але все одно надзвичайно схвильований тим, як виглядають вектора без крапок :-)

Для тих, хто в темі:

  • Спочатку я намагався йти звичайним шляхом, використовуючи таймер T1 для scale і ramp, а shift для гасіння.
  • Як не старався, все одно залишався деякий «нахлест».
  • Тоді я спробував використовувати вручну PB7 (ramp) і CB2 (blank) — і це справді допомогло. Приблизно настільки, наскільки можна бачити на фото, проте я не зміг придумати, як прискорити цей код так, щоб він був корисний для Frogger'a.
  • Ліве [так у тексті, прим. пер.] зображення отримано за допомогою коду змішаного типу — я використовував таймер T1 щоб перемикати ramp, але сигнал blank (CB2) встановлював вручну (тобто сдвиговый регістр не використовувався взагалі).
  • Ретельно погоджуючи затримки, можна зробити гладкі вектора і соптімізіровать все так, щоб отримати від цього практичну користь для ситуації з великою кількістю даних.
  • Перший рівень Frogger'a перемальовується з цим кодом (і грає музика) менш ніж за 25 тисяч циклів.


Зайве говорити, що, незважаючи на те, що Vide дуже хороший емулятор, такого роду експерименти з точним дотриманням часових інтервалів вимагають цього Vectrex.

Ще одна чудова новина в тому, що, схоже, цей код безглючно працює на всіх трьох моїх Vectrex'ах.

І нарешті, трохи відео — перші кроки в якості рівня як в ігрових автоматах (проте, як ви можете помітити, переходи ще не дороблені).



Продовження...

Я додав в код Frogger'a «диспетчер». З диспетчера викликається старий код для «MoveTo-InBetween». Диспетчер використовує підпрограми так що, теоретично, такти витрачаються на JSR і RTS, однак код виглядає настільки пристойніше, що я залишив це як є (оскільки мені не були особливо потрібні додаткові такти).



Декодування YM [музика, прим пер.] зроблено через диспетчер — я розбив декодування на 9 частин, кожна з яких незалежна від інших і вони викликаються в різних частинах MoveTo. Таким чином, декодування YM майже не використовує додаткових тактів.

Майже закінчив редагування спрайтів для виду зверху (див. картинку) — спрайт двох різних машин, фургона, гоночної машини і трактори більш-менш схожі на оригінали.

В цілому, списки векторів приблизно на третину довше ніж ті, що були раніше. Хоча, я думаю що зараз намальовано приблизно на 40 векторів більше, ніж в оригінальному Frogger'e для Vectrex. Я вважав тільки намальовані об'єкти, проте в деяких сценах кількість векторів має значення. Один тільки трактор складається з 26 окремих векторів. Для Vectrex це гігантське число.

Також я дещо покращив играбельность, трохи розтягнувши ігрову область. Frogger тепер не так легко виходить за кордону. До крайнього правого будинку добратися було дуже нелегко. Тепер стрибки трохи повільніше (за анімації) і це навіть ще складніше. Тим не менш, додати анімацію було хорошою ідеєю. Стрибки відчуваються більш схожими на Frogger, ніж це було раніше.

Необхідно ще багато тестувати геймплей, зробити звукові ефекти і інші речі, проте справи з новою версією йдуть відмінно.

Продовження триває...

Знову позаймався Frogger'ом. Двічі перевірив перші 7 рівнів і змінив їх структуру, щоб відобразити зроблені в спрайтах зміни.



Вимірювання в Vide показали, що Frogger знову став трішки повільніше — 7-й рівень з 4-ма зайнятими будинками вимагає близько 32 тисяч тактів. Чорт — я повинен буду знову боротися за такти — думав, з цим уже покінчено.

Якщо подивитися на доступні ресурси, у мене за плечима тепер набагато більше, ніж в той час, коли я пішов в університет (подивіться на картинку справа — це саморобний ігровий автомат на базі MAME — здогадайтеся, що за Frogger :) [тут інтрига, див. далі прим. пер.]

Вийшовши за ліміт в 30 тисяч тактів я вже не розглядаю можливість додати відображення інформації про рекорди під час гри і це мене турбує!

Нижче ще один приклад поточного геймплея Frogger'a. Думаю, я додам відсутні звукові ефекти останніми — коли двічі перевірю і виправлю рівні.



Таке відчуття, що я переміщаюся в часі.

Тільки що закінчив оптимізацію коду, вигравши ще близько тисячі тактів. Однак не можу придумати, що тут ще можна зробити. Повинен зберегти ще близько тисячі тактів (у найважчих рівнях).

Оптимізацією коду я цього досягти вже не можу, так що буду редагувати нові спрайт — злегка їх міняти. 26 векторів на трактор (до прикладу) — не прокотить.
Вважав, що кожен намальований вектор використовує близько 50 тактів.

У найбільш заповнених рівнях мені потрібно заощадити 50 векторів.
Оскільки відображаються близько 20-25 об'єктів, що я повинен відшматувати від кожного приблизно за два вектори — це має бути здійснимо :-)

Після того, як кожен рівень буде знову вкладатися у менш ніж 30 тисяч, займуся іншими ефектами, тоді це все дійсно буде виглядати і відчуватися як Frogger. Ще потрібно вилизати «антракт» і зробити краще заставку… і, вуаля, де-небудь в 2017-му закінчу…

Десять хвилин продовження....



Невеликий звіт про просуванні в роботі над новою версією Frogger.

Майже готово!

Ймовірно я ще дещо пофиксю, соптимизирую і покращу, однак додавання фіч завершено.
Порівняно з вихідним Vectrex Frogger'му були змінені наступні речі:

  • вигляд зверху машин і жабеняти
  • більш гладкі вектора
  • під час геймплея відображаються очки, урови і життя
  • ігрова область трохи розширена
  • більше звуків і музики
  • опції одного і двох гравців
  • в режимі одного гравця додана опція «тренування»
  • опція для включення/вимикання музики
  • 5 кращих рекордів збережені в ППЗУ DS2431
  • новий головний екран
  • демо режим
Крім того видалені:

  • «антракт»
  • режим паузи


Я поки що в роздумах, чи потрібно змінювати рівні з тим, щоб вони більше схожі на «оригінал». В оригінальному Frogger'е (ігрових автоматів) дві сусідніх смужки води рухалися в одному напрямку — це я поки не взяв до уваги. Так що, смужки вище відчуваються по-іншому.

Так чи інакше, вистачить розмов… Ось десятихвилинне відео поточній версії:



Більше ніякого Frogger'a!



Я зупинив роботу над першоджерелом і вирішив, що нової версії Vectrex Frogger не буде.

Зважаючи на певні обставини, про які я скажу нижче, Vectrex Frogger мертвий і єдиною доступною версією буде та, яку я зробив 18 років тому.

Чому я більше не буду над цим працювати?

— Все завершено!
Якщо не вважати можливих багфіксів.

Чому не буде нової версії Привів?

— Тому що я вирішив перейменувати її.
Я знаю, Frogger — популярна назва. Однак, будемо чесними, ні одна Vectrex гра не досягне слави оригіналу.
І, хоча на гру над якою я працював мене надихнув Frogger, безумовно це вже інша гра!
Тому я вирішив змінити робочу назву на остаточне:



Вам, напевне, ця назва ні про що не говорить, однак на початку 1990-х я написав гру під DOS, яка називалася саме так.

(див.: Karl Quappe – DOS, або, на старій сторінці: Karl Quappe – AOL

Для читачів, які не читають по-німецьки, ось та ж сама інформація про назву, що і на сторінці AOL:

«KAULQUAPPE» перекладається як «пуголовок», «QUAPPE» — скорочення від пуголовка, а KARL — просто ім'я схоже на «KAUL» (омофон). Так що, якщо ви хочете перевести це, наприклад, на англійську, ви отримаєте щось типу «CHARLES POLE» (Charles — англійська версія Karl) або Tedpole ('Ted' — ім'я, яке звучить схоже на 'tad')'

Далі йде ще одне коротке відео. Великих змін немає, просто дещо відшліфовано. Я дозволив грі запуститися самої — не стосувався кнопок, так що геймплей який ви бачите — це демо режим.

Насолоджуйтесь!


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.