Портирование Mobile Basic игры на MIDlet Pascal. Начало
от Витаминыч
ПредисловиеВсем привет!
В общем, решил начать писать небольшой цикл статей, посвященных портированию приложений. Точнее, начать хотел аж в 2014, когда обмазался MIDlet Pascal, но..
Но я, как обычно, залипал в дотку, либо копал бесконечные шахты в минекруфте Сами понимаете, как это иногда может затянуть.
Так вот, о чем это я.. А, недавно мне приснилось, что я с @Death зарегистрировал студию, которая занималась разработкой игр под мобильные плаформы. "И что здесь "такого"? - спросите вы. А я отвечу: все писалось на MIDlet Pascal'e.
Проснулся я в холодном поту, живот корчило от боли.. и слегка ощущались рвотные позывы. Умывшись, я сел в кресло, колени прижал к груди, обхватил их руками (не грудь) и призадумался... Какого чёрта!
Была ли это тоска по стримам с @Helltar'ом или же это из-за нескончаемых володиных дневников? Как бы там ни было, чуть позже я открыл папку со старыми проектами и пустил слезу И, между делом, вспомнил о незавершенном порте Legends of Warriors.
На данный момент он не завершен, допиливать буду в процессе написания статей. А пока что начнем!
Необходимый инструментарий
1. Mobile Basic IDE by HoldFast (online)
2. AMPASIDE by Helltar
3. Notepad.exe
(*) 4. Листы бумаги/тетрадь/блокнот и ручка
Порядок работ следующий:
а) берем исходный код вашей игры, либо достаем bas из чужой Загружаем bas в MB IDE Online, выделяем текст кода и копируем в буфер обмена. Ваш же код просто пересохраняем в текстовый файл.
б) открываем обычный блокнот, и делаем вставку. Сохраняем
в) для удобства рекомендую полученный листинг распечатать, либо переписать руками
г) приступить к анализу кода
д) разбив все на логические блоки (на распечатке удобно делать пометки), рисуем схему взаимодействия
е) программируем полученную схему
В моем примере:
а-в) бас-файл был изъят из архива, распарсен, сохранен и распечатан
г, д) разделять пришлось, в основном, разные меню (формы), даны адекватные имена переменных, поправлены расчеты и убрана лишняя логика. Блок-схемы не рисовал, просто на полях подписал названия блоков и стрелочками объединил их, на отдельном листе нарисовал существующие меню, так же соединил стрелками и дописал над ними условия перехода. В дальнейшем такой подход очень поможет (меньше отвлекаться на сам код и искать нужный блок). Но это не обязательно)
е) самое интересное
Анализ кода. Меню (формы), переменные
Полный листинг приводить не буду, лишь фрагменты кода.
Начинается все с загрузки логотипа и его отрисовки:
Далее, GOTO 10 отправляет нас в главное меню игры:
Здесь нас пока что интересуют строки с номерами 300, 5000, 50. BYE - завершение работы мидлета, потому идем к строке 300.
Обычно, я в бейсике (QBasic) заранее определял переменные, в этом же диалекте иногда лучше только перед использованием их объявлять (а вдруг на мобилке не хватит хипа? ). Что касается оформления, то это просто вырвиглаз
Попробуем таки разобраться, что там понаписал уважаемый @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 на горизонте не маячит, а это значит, что интерпретатор продолжит свою работу в обычном порядке. И следом у нас новый блок:
Это меню выбора расы. Думаю, расписывать каждую переменную нет смысла, все и так очевидно. Однако, стоит отметить, что здесь переинициализируется переменная ОВ% - помните, ровно перед созданием этой формы мы ее объявляли и присваивали её значение. Смею предположить, что Vapigor хотел в дальнейшем усложнить математику и прибавлять к дефолтной броне тела бонусную броню расы.
Я бы тоже так мог сделать, но, мы пока что просто анализируем код и переписываем его на МР. Конечно, в планах есть что-то подобное, но об этом чуть позже. Вернемся к коду. После создания необходимых переменных, программа отправляет нас на строку 500. Появляется сообщение о прибытии игрока во Вридорг и, затем, если была нажата кнопка "5" (либо ОК/центр джойстика), появляется меню выбора класса. И так далее, следим за GOTO. Собственно, там и располагается вся основная логика игры.
Теперь давайте вернемся в главное меню. У нас осталась строка с номером 5000. Ибо на строке 50 такой простенький код, который не нуждается в комментариях:А вот то, что на 5000:
Код загрузки данных. Похоже, что из ФС, не из RMS. Если честно, не помню, что там МВ открывает с помощью OPEN. В порте я пытался сохранять в RMS и с этим были трудности. О том, как я решил проблемы (пока что нет, гг), напишу в статье, посвященной написанию кода на МР.
ГОТО 600 - меню выбора локаций. Ищем очередной GOTO, затем номер строки - почти всегда это будут меню SELECT. Об остальном напишу в следующей статье, это пока что затравочка)
Послесловие
Можно сказать, что треть кода мы уже разобрали. То, что очевидно, я описывать не буду, лишь некоторые моменты в основной логике и механике поясню. Это будет во второй статье. А в третьей, собственно, начнем переписывать сие великолепие на MIDlet Pascal.
Может, к моменту написания, я успею пофиксить баги и скомпоновать важную информацию. Иначе будет еще пара статей, но не более) О том, что будет после полного переноса - в следующем цикле.
А пока что всё, спасибо за прочтение и до скорых встреч
да, все это потом будет переписано на рфо ява4андроид)
* Необязательное условие
В общем, решил начать писать небольшой цикл статей, посвященных портированию приложений. Точнее, начать хотел аж в 2014, когда обмазался MIDlet Pascal, но..
Но я, как обычно, залипал в дотку, либо копал бесконечные шахты в минекруфте Сами понимаете, как это иногда может затянуть.
Так вот, о чем это я.. А, недавно мне приснилось, что я с @Death зарегистрировал студию, которая занималась разработкой игр под мобильные плаформы. "И что здесь "такого"? - спросите вы. А я отвечу: все писалось на MIDlet Pascal'e.
Проснулся я в холодном поту, живот корчило от боли.. и слегка ощущались рвотные позывы. Умывшись, я сел в кресло, колени прижал к груди, обхватил их руками (не грудь) и призадумался... Какого чёрта!
Была ли это тоска по стримам с @Helltar'ом или же это из-за нескончаемых володиных дневников? Как бы там ни было, чуть позже я открыл папку со старыми проектами и пустил слезу И, между делом, вспомнил о незавершенном порте Legends of Warriors.
На данный момент он не завершен, допиливать буду в процессе написания статей. А пока что начнем!
Необходимый инструментарий
1. Mobile Basic IDE by HoldFast (online)
2. AMPASIDE by Helltar
3. Notepad.exe
(*) 4. Листы бумаги/тетрадь/блокнот и ручка
Порядок работ следующий:
а) берем исходный код вашей игры, либо достаем bas из чужой Загружаем bas в MB IDE Online, выделяем текст кода и копируем в буфер обмена. Ваш же код просто пересохраняем в текстовый файл.
б) открываем обычный блокнот, и делаем вставку. Сохраняем
в) для удобства рекомендую полученный листинг распечатать, либо переписать руками
г) приступить к анализу кода
д) разбив все на логические блоки (на распечатке удобно делать пометки), рисуем схему взаимодействия
е) программируем полученную схему
В моем примере:
а-в) бас-файл был изъят из архива, распарсен, сохранен и распечатан
г, д) разделять пришлось, в основном, разные меню (формы), даны адекватные имена переменных, поправлены расчеты и убрана лишняя логика. Блок-схемы не рисовал, просто на полях подписал названия блоков и стрелочками объединил их, на отдельном листе нарисовал существующие меню, так же соединил стрелками и дописал над ними условия перехода. В дальнейшем такой подход очень поможет (меньше отвлекаться на сам код и искать нужный блок). Но это не обязательно)
е) самое интересное
Анализ кода. Меню (формы), переменные
Полный листинг приводить не буду, лишь фрагменты кода.
Начинается все с загрузки логотипа и его отрисовки:
- 1 GELLOAD "logo","logo2.png"
- 2 DRAWGEL "logo",0,0: SLEEP 3500: CLS : GOTO 10
- 10 A%=SELECT("Legends of warriors","новая игра","продолжить","об игре","выход")
- 15 IF A%=0 THEN GOTO 300
- 20 IF A%=1 THEN GOTO 5000
- 30 IF A%=2 THEN GOTO 50
- 35 IF A%=3 THEN BYE
- 40 GOTO 10
- 300 SCOINS%=0:COINS%=10:OD%=0:OR%=0:SP%=0:SL%=0:OB%=5
- 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%
- 302 OR$="ничего":OD$="ничего":SP$="ничего":SL$="ничего":Q4%=0
Попробуем таки разобраться, что там понаписал уважаемый @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 на горизонте не маячит, а это значит, что интерпретатор продолжит свою работу в обычном порядке. И следом у нас новый блок:
- 310 RASSA%=SELECT("расса","человек","эльф","орк","мертвец","гном","мутант","северный человек","пещерный орк","назад")
- 315 IF RASSA%=0 THEN PLIFE%=100:LIFE%=PLIFE%:PMANA%=20:SILA%=10:OB%=2:MANA%=PMANA%:OD%=1:SLVL%=100:RASSA$="человек": GOTO 500
- 320 IF RASSA%=1 THEN PLIFE%=100:LIFE%=PLIFE%:PMANA%=30:MANA%=PMANA%:SILA%=10:OB%=0:SLVL%=100:RASSA$="эльф": GOTO 500
- 325 IF RASSA%=2 THEN PLIFE%=110:LIFE%=PLIFE%:SILA%=9:OB%=0:PMANA%=15:MANA%=PMANA%:SLVL%=120:SP%=1:RASSA$="орк": GOTO 500
- 330 IF RASSA%=3 THEN PLIFE%=130:LIFE%=PLIFE%:SILA%=12:OB%=1:PMANA%=10:MANA%=PMANA%:SLVL%=100:OD%=1:RASSA$="мертвец": GOTO 500
- 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
- 340 IF RASSA%=5 THEN PLIFE%=85:LIFE%=PLIFE%:SILA%=14:OB%=3:PMANA%=25:MANA%=PMANA%:SLVL%=125:RASSA$="мутант": GOTO 500
- 345 IF RASSA%=6 THEN PLIFE%=120:LIFE%=PLIFE%:SILA%=12:OB%=3:PMANA%=10:MANA%=PMANA%:SLVL%=115:RASSA$="северный человек": GOTO 500
- 350 IF RASSA%=7 THEN PLIFE%=115:LIFE%=PLIFE%:SILA%=11:OB%=2:PMANA%=0:MANA%=PMANA%:SLVL%=120:RASSA$="пещерный орк": GOTO 500
- 355 IF RASSA%=8 THEN GOTO 10
- 360 GOTO 310
Я бы тоже так мог сделать, но, мы пока что просто анализируем код и переписываем его на МР. Конечно, в планах есть что-то подобное, но об этом чуть позже. Вернемся к коду. После создания необходимых переменных, программа отправляет нас на строку 500. Появляется сообщение о прибытии игрока во Вридорг и, затем, если была нажата кнопка "5" (либо ОК/центр джойстика), появляется меню выбора класса. И так далее, следим за GOTO. Собственно, там и располагается вся основная логика игры.
Теперь давайте вернемся в главное меню. У нас осталась строка с номером 5000. Ибо на строке 50 такой простенький код, который не нуждается в комментариях:
- 50 PRINT "автор vapigor. Сохраняемся в городе у магистра магии"
- 60 IF FIRE (0) THEN SLEEP 300: CLS : GOTO 10
- 70 GOTO 60
- 5000 OPEN #2,"s.dat","input"
- 5010 INPUT #2,SCOINS%
- 5020 INPUT #2,COINS%
- 5030 INPUT #2,OD%
- 5040 INPUT #2,OR%
- 5050 INPUT #2,SP%
- 5060 INPUT #2,SL%
- 5070 INPUT #2,RES1%
- 5080 INPUT #2,RES2%
- 5090 INPUT #2,RES3%
- 5100 INPUT #2,LVL%
- 5110 INPUT #2,OP%
- 5120 INPUT #2,SLVL%
- 5130 INPUT #2,MAG1%
- 5140 INPUT #2,MAG2%
- 5150 INPUT #2,MAG3%
- 5160 INPUT #2,Q1%
- 5170 INPUT #2,Q2%
- 5180 INPUT #2,Q3%
- 5190 INPUT #2,OR$
- 5200 INPUT #2,OD$
- 5210 INPUT #2,SP$
- 5220 INPUT #2,SL$
- 5230 INPUT #2,LIFE%
- 5240 INPUT #2,PLIFE%
- 5250 INPUT #2,PMANA%
- 5260 INPUT #2,MANA%
- 5270 INPUT #2,SILA%
- 5280 INPUT #2,RASSA%
- 5290 INPUT #2,RASSA$
- 5300 INPUT #2,CLAS%
- 5310 INPUT #2,CLAS$
- 5320 INPUT #2,OB%
- 5325 INPUT #2,Q4%
- 5350 CLOSE #2
- 5360 GOTO 600
ГОТО 600 - меню выбора локаций. Ищем очередной GOTO, затем номер строки - почти всегда это будут меню SELECT. Об остальном напишу в следующей статье, это пока что затравочка)
Послесловие
Можно сказать, что треть кода мы уже разобрали. То, что очевидно, я описывать не буду, лишь некоторые моменты в основной логике и механике поясню. Это будет во второй статье. А в третьей, собственно, начнем переписывать сие великолепие на MIDlet Pascal.
Может, к моменту написания, я успею пофиксить баги и скомпоновать важную информацию. Иначе будет еще пара статей, но не более) О том, что будет после полного переноса - в следующем цикле.
А пока что всё, спасибо за прочтение и до скорых встреч
да, все это потом будет переписано на рфо ява4андроид)
* Необязательное условие