Портирование Mobile Basic игры на MIDlet Pascal. Начало

от
Прочие языки    just for fun, lulz, портирование, mobile basic, midlet pascal, gamedev

ПредисловиеВсем привет! :preved:

В общем, решил начать писать небольшой цикл статей, посвященных портированию приложений. Точнее, начать хотел аж в 2014, когда обмазался MIDlet Pascal, но..
Но я, как обычно, залипал в дотку, либо копал бесконечные шахты в минекруфте :gg: Сами понимаете, как это иногда может затянуть.

Так вот, о чем это я.. А, недавно мне приснилось, что я с @Death зарегистрировал студию, которая занималась разработкой игр под мобильные плаформы. "И что здесь "такого"? - спросите вы. А я отвечу: все писалось на MIDlet Pascal'e.
Проснулся я в холодном поту, живот корчило от боли.. и слегка ощущались рвотные позывы. Умывшись, я сел в кресло, колени прижал к груди, обхватил их руками (не грудь) и призадумался... Какого чёрта!
Была ли это тоска по стримам с @Helltar'ом или же это из-за нескончаемых володиных дневников? Как бы там ни было, чуть позже я открыл папку со старыми проектами и пустил слезу :plak: И, между делом, вспомнил о незавершенном порте Legends of Warriors.

На данный момент он не завершен, допиливать буду в процессе написания статей. А пока что начнем!

Необходимый инструментарий
1. Mobile Basic IDE by HoldFast (online)
2. AMPASIDE by Helltar
3. Notepad.exe
(*) 4. Листы бумаги/тетрадь/блокнот и ручка

Порядок работ следующий:
а) берем исходный код вашей игры, либо достаем bas из чужой :кек2: Загружаем bas в MB IDE Online, выделяем текст кода и копируем в буфер обмена. Ваш же код просто пересохраняем в текстовый файл.
б) открываем обычный блокнот, и делаем вставку. Сохраняем
в) для удобства рекомендую полученный листинг распечатать, либо переписать руками
г) приступить к анализу кода
д) разбив все на логические блоки (на распечатке удобно делать пометки), рисуем схему взаимодействия
е) программируем полученную схему

В моем примере:
а-в) бас-файл был изъят из архива, распарсен, сохранен и распечатан
г, д) разделять пришлось, в основном, разные меню (формы), даны адекватные имена переменных, поправлены расчеты и убрана лишняя логика. Блок-схемы не рисовал, просто на полях подписал названия блоков и стрелочками объединил их, на отдельном листе нарисовал существующие меню, так же соединил стрелками и дописал над ними условия перехода. В дальнейшем такой подход очень поможет (меньше отвлекаться на сам код и искать нужный блок). Но это не обязательно)
е) самое интересное

Анализ кода. Меню (формы), переменные
Полный листинг приводить не буду, лишь фрагменты кода.
Начинается все с загрузки логотипа и его отрисовки:
  1. 1 GELLOAD "logo","logo2.png"
  2. 2 DRAWGEL "logo",0,0: SLEEP 3500: CLS : GOTO 10
Далее, GOTO 10 отправляет нас в главное меню игры:
  1. 10 A%=SELECT("Legends of warriors","новая игра","продолжить","об игре","выход")
  2. 15 IF A%=0 THEN  GOTO 300
  3. 20 IF A%=1 THEN  GOTO 5000
  4. 30 IF A%=2 THEN  GOTO 50
  5. 35 IF A%=3 THEN  BYE
  6. 40 GOTO 10
Здесь нас пока что интересуют строки с номерами 300, 5000, 50. BYE - завершение работы мидлета, потому идем к строке 300.
  1. 300 SCOINS%=0:COINS%=10:OD%=0:OR%=0:SP%=0:SL%=0:OB%=5
  2. 301 RES1%=0:RES2%=0:RES3%=0:LVL%=0:OP%=0:SLVL%=100:MAG1%=0:MAG2%=0:MAG3%=0:Q1%=0:Q2%=0:Q3%=0:DEF%=OB%+DSP%+DOD%+DSL%
  3. 302 OR$="ничего":OD$="ничего":SP$="ничего":SL$="ничего":Q4%=0
Обычно, я в бейсике (QBasic) заранее определял переменные, в этом же диалекте иногда лучше только перед использованием их объявлять (а вдруг на мобилке не хватит хипа? :nokia: ). Что касается оформления, то это просто вырвиглаз :gg:
Попробуем таки разобраться, что там понаписал уважаемый @Vapigor)
SCOINS%=0 - серебряные монетки
COINS%=10 - видимо, медные монетки
OD%=0 - доспехи
OR%=0 - урон оружия
SP%=0 - ботинки
SL%=0 - шлем
OB%=5 - базовая броня игрока
RES1%=0 - квестовый предмет 1
RES2%=0 - квестовый предмет 2
RES3%=0 - квестовый предмет 3
LVL%=0 - уровень игрока
OP%=0 - очки опыта
SLVL%=100 - количество очков опыта до следующего уровня
MAG1%=0 - наличие заклинания_1
MAG2%=0 - наличие заклинания_2
MAG3%=0 - наличие заклинания_3
Q1%=0 - флаг выполнения квеста_1
Q2%=0 - флаг выполнения квеста_2
Q3%=0 - флаг выполнения квеста_3
Q4%=0 - флаг выполнения квеста_4
DEF%=OB%+DSP%+DOD%+DSL% - формула расчета брони:
ИТОГОВАЯ_ЗАЩИТА = БАЗОВАЯ_ЗАЩИТА + ЗАЩИТА_НОГ + ЗАЩИТА_ТЕЛА + ЗАЩИТА_ГОЛОВЫ
Три новых переменных рассчитываются только после создания персонажа, зачем заранее это делать - непонятно
OR$="ничего" - название оружия
OD$="ничего" - название шмотки
SP$="ничего" - название шмотки
SL$="ничего" - название шмотки

Конечно же, я не с первого раза понял, что это инициализируется, гг. Разве что, кроме совсем очевидных. Воспользовался поиском по файлу, затем отмечал эту переменную на листе и, следя за тем, в каком блоке она меняется, сделал выводы о её предназначении. Так же и с остальными. Затупы были с ор, од и т.п., но разобрался.
Итак, GOTO на горизонте не маячит, а это значит, что интерпретатор продолжит свою работу в обычном порядке. И следом у нас новый блок:
  1. 310 RASSA%=SELECT("расса","человек","эльф","орк","мертвец","гном","мутант","северный человек","пещерный орк","назад")
  2. 315 IF RASSA%=0 THEN PLIFE%=100:LIFE%=PLIFE%:PMANA%=20:SILA%=10:OB%=2:MANA%=PMANA%:OD%=1:SLVL%=100:RASSA$="человек": GOTO 500
  3. 320 IF RASSA%=1 THEN PLIFE%=100:LIFE%=PLIFE%:PMANA%=30:MANA%=PMANA%:SILA%=10:OB%=0:SLVL%=100:RASSA$="эльф": GOTO 500
  4. 325 IF RASSA%=2 THEN PLIFE%=110:LIFE%=PLIFE%:SILA%=9:OB%=0:PMANA%=15:MANA%=PMANA%:SLVL%=120:SP%=1:RASSA$="орк": GOTO 500
  5. 330 IF RASSA%=3 THEN PLIFE%=130:LIFE%=PLIFE%:SILA%=12:OB%=1:PMANA%=10:MANA%=PMANA%:SLVL%=100:OD%=1:RASSA$="мертвец": GOTO 500
  6. 335 IF RASSA%=4 THEN PLIFE%=125:LIFE%=PLIFE%:SILA%=12:OB%=4:PMANA%=5:MANA%=PMANA%:SLVL%=150:OD%=1:SL%=1:RASSA$="гном": GOTO 500
  7. 340 IF RASSA%=5 THEN PLIFE%=85:LIFE%=PLIFE%:SILA%=14:OB%=3:PMANA%=25:MANA%=PMANA%:SLVL%=125:RASSA$="мутант": GOTO 500
  8. 345 IF RASSA%=6 THEN PLIFE%=120:LIFE%=PLIFE%:SILA%=12:OB%=3:PMANA%=10:MANA%=PMANA%:SLVL%=115:RASSA$="северный человек": GOTO 500
  9. 350 IF RASSA%=7 THEN PLIFE%=115:LIFE%=PLIFE%:SILA%=11:OB%=2:PMANA%=0:MANA%=PMANA%:SLVL%=120:RASSA$="пещерный орк": GOTO 500
  10. 355 IF RASSA%=8 THEN  GOTO 10
  11. 360 GOTO 310
Это меню выбора расы. Думаю, расписывать каждую переменную нет смысла, все и так очевидно. Однако, стоит отметить, что здесь переинициализируется переменная ОВ% - помните, ровно перед созданием этой формы мы ее объявляли и присваивали её значение. Смею предположить, что Vapigor хотел в дальнейшем усложнить математику и прибавлять к дефолтной броне тела бонусную броню расы.
Я бы тоже так мог сделать, но, мы пока что просто анализируем код и переписываем его на МР. Конечно, в планах есть что-то подобное, но об этом чуть позже. Вернемся к коду. После создания необходимых переменных, программа отправляет нас на строку 500. Появляется сообщение о прибытии игрока во Вридорг и, затем, если была нажата кнопка "5" (либо ОК/центр джойстика), появляется меню выбора класса. И так далее, следим за GOTO. Собственно, там и располагается вся основная логика игры.
Теперь давайте вернемся в главное меню. У нас осталась строка с номером 5000. Ибо на строке 50 такой простенький код, который не нуждается в комментариях:
  1. 50 PRINT "автор vapigor. Сохраняемся в городе у магистра магии"
  2. 60 IF  FIRE (0) THEN  SLEEP 300: CLS : GOTO 10
  3. 70 GOTO 60
А вот то, что на 5000:
  1. 5000 OPEN #2,"s.dat","input"
  2. 5010 INPUT #2,SCOINS%
  3. 5020 INPUT #2,COINS%
  4. 5030 INPUT #2,OD%
  5. 5040 INPUT #2,OR%
  6. 5050 INPUT #2,SP%
  7. 5060 INPUT #2,SL%
  8. 5070 INPUT #2,RES1%
  9. 5080 INPUT #2,RES2%
  10. 5090 INPUT #2,RES3%
  11. 5100 INPUT #2,LVL%
  12. 5110 INPUT #2,OP%
  13. 5120 INPUT #2,SLVL%
  14. 5130 INPUT #2,MAG1%
  15. 5140 INPUT #2,MAG2%
  16. 5150 INPUT #2,MAG3%
  17. 5160 INPUT #2,Q1%
  18. 5170 INPUT #2,Q2%
  19. 5180 INPUT #2,Q3%
  20. 5190 INPUT #2,OR$
  21. 5200 INPUT #2,OD$
  22. 5210 INPUT #2,SP$
  23. 5220 INPUT #2,SL$
  24. 5230 INPUT #2,LIFE%
  25. 5240 INPUT #2,PLIFE%
  26. 5250 INPUT #2,PMANA%
  27. 5260 INPUT #2,MANA%
  28. 5270 INPUT #2,SILA%
  29. 5280 INPUT #2,RASSA%
  30. 5290 INPUT #2,RASSA$
  31. 5300 INPUT #2,CLAS%
  32. 5310 INPUT #2,CLAS$
  33. 5320 INPUT #2,OB%
  34. 5325 INPUT #2,Q4%
  35. 5350 CLOSE #2
  36. 5360 GOTO 600
Код загрузки данных. Похоже, что из ФС, не из RMS. Если честно, не помню, что там МВ открывает с помощью OPEN. В порте я пытался сохранять в RMS и с этим были трудности. О том, как я решил проблемы (пока что нет, гг), напишу в статье, посвященной написанию кода на МР.
ГОТО 600 - меню выбора локаций. Ищем очередной GOTO, затем номер строки - почти всегда это будут меню SELECT. Об остальном напишу в следующей статье, это пока что затравочка)

Послесловие
Можно сказать, что треть кода мы уже разобрали. То, что очевидно, я описывать не буду, лишь некоторые моменты в основной логике и механике поясню. Это будет во второй статье. А в третьей, собственно, начнем переписывать сие великолепие на MIDlet Pascal.
Может, к моменту написания, я успею пофиксить баги и скомпоновать важную информацию. Иначе будет еще пара статей, но не более) О том, что будет после полного переноса - в следующем цикле.

А пока что всё, спасибо за прочтение и до скорых встреч ;-)

:ps: да, все это потом будет переписано на рфо ява4андроид)


* Необязательное условие