https://alexlogachev.itch.io/commodore-64-dungeon-crawler-prototype/devlog/684092/unnamed-commodore-64-dungeon-crawler-devlog-0
Наконец-то дописал devlog на itch.io. Стало интересно, насколько вообще реально продвинуть игру на зарубежной площадке.
Наконец-то дописал devlog на itch.io. Стало интересно, насколько вообще реально продвинуть игру на зарубежной площадке.
itch.io
Unnamed Commodore 64 Dungeon Crawler Devlog #0
Hello everyone! Half a year ago I decided to launch my new Commodore 64 game project. My previous project by the name of "The Last Effort" was published in the august of 2023. It was not fully complet...
❤🔥4❤2
Изучил я исходники Doom RPG и понял, что все не так, как мне бы хотелось.
Во-первых, вот эта формула высчитывает количество нанесенного урона:
Commodore такое потянет, но с натяжкой. По моим подсчетам, тут числа могут выйти даже в 32 бита. А хотелось бы остаться в 8-ми, максимум в 16-ти.
Во-вторых, в Doom RPG используются дополнительные параметры (например, при каждом выстреле высчитывается мощность оружия в 16 битах, которая потом используется при расчете). Да, можно перенести как есть, но я не хочу все усложнять.
В общем, после сотен вариантов я пришел к такой формуле:
В целом, получаются нормальные цифры, но они немного зависят от случайности. Минус в том, что придется писать функции деления и умножения, которые мне пока что ни разу не пригодились. И все это в 16-ти битах.
Но и это еще не все! Есть же еще два показателя: accuracy и dexterity. Они должны влиять на вероятность попадания (как и на вероятность уклониться от атаки и избежать боя).
А еще у врагов и игрока есть броня! То есть помимо базового урона придется еще высчитывать урон, который на себя принимает броня (скорее всего, это будут какие-нибудь фиксированные проценты).
Короче, ролевка для меня - пока что самая сложная часть игры. Как бы я ни любил RPG, писать систему - это та еще дичь=)
Во-первых, вот эта формула высчитывает количество нанесенного урона:
calDmg = (((((((wpn->strMin << 8) + ((randStr * ((wpn->strMax - wpn->strMin) << 8)) >> 8)) * (strength / defense)) >> 8) * i) >> 8) * calWpnDmg) >> 8;
Commodore такое потянет, но с натяжкой. По моим подсчетам, тут числа могут выйти даже в 32 бита. А хотелось бы остаться в 8-ми, максимум в 16-ти.
Во-вторых, в Doom RPG используются дополнительные параметры (например, при каждом выстреле высчитывается мощность оружия в 16 битах, которая потом используется при расчете). Да, можно перенести как есть, но я не хочу все усложнять.
В общем, после сотен вариантов я пришел к такой формуле:
полученный урон = мин. урон оружия + (((случайный урон оружия)*атака)*(атака/защита врага))
смещаем результат на 4 бита вправо (делим на 4) и прибавляем 1 (для того, чтобы даже при очень большом разрыве прилетал урон в 1 пункт)
если для врага оружие смертельно, то смещаем биты на 2 влево (умножаем на 2)
В целом, получаются нормальные цифры, но они немного зависят от случайности. Минус в том, что придется писать функции деления и умножения, которые мне пока что ни разу не пригодились. И все это в 16-ти битах.
Но и это еще не все! Есть же еще два показателя: accuracy и dexterity. Они должны влиять на вероятность попадания (как и на вероятность уклониться от атаки и избежать боя).
А еще у врагов и игрока есть броня! То есть помимо базового урона придется еще высчитывать урон, который на себя принимает броня (скорее всего, это будут какие-нибудь фиксированные проценты).
Короче, ролевка для меня - пока что самая сложная часть игры. Как бы я ни любил RPG, писать систему - это та еще дичь=)
❤🔥2
А еще я понял, как сохранять текущий прогресс на дискету (правда для этого потребуется 6 Кб памяти).
Карту вместе с активированными триггерами, спрайтами и так далее, сохранить не сложно. Благо в KERNAL есть функция, которая за это отвечает.
То есть надо банально скопировать текущее состояние карты (которая изначально подгружается с дискеты и изменяется в процессе прохождения) в нужный файл.
Вопрос возникает с показателями игрока.
Вариант 1 — создать второй файл, где будут храниться только параметры игрока.
Вариант 2 — выделить отдельный участок памяти, в котором параметры игрока будут расположены перед данными карты (сложно, т.к. потребует нарушения логики кода).
Вариант 3 — использовать пароли и забить на состояние карты. Вышел из игры — начинаешь с начала карты.
Вариант 4 — вместо паролей — показатели сохраняются в отдельный файл, но начинаешь с начала уровня.
Суть в том, что на дискете ограниченное пространство. Уже сейчас выходит не более 17 уровней. А что будет дальше, с музыкой, новыми спрайтами и ролевой системой? Десять штук максимум?
Есть вариант, сжать уровни на дискете. Это будет неплохой вариант, потому что там много повторяющихся байт, но я никогда не имел дело с архиваторами, поэтому придется еще повозиться=)
Карту вместе с активированными триггерами, спрайтами и так далее, сохранить не сложно. Благо в KERNAL есть функция, которая за это отвечает.
То есть надо банально скопировать текущее состояние карты (которая изначально подгружается с дискеты и изменяется в процессе прохождения) в нужный файл.
Вопрос возникает с показателями игрока.
Вариант 1 — создать второй файл, где будут храниться только параметры игрока.
Вариант 2 — выделить отдельный участок памяти, в котором параметры игрока будут расположены перед данными карты (сложно, т.к. потребует нарушения логики кода).
Вариант 3 — использовать пароли и забить на состояние карты. Вышел из игры — начинаешь с начала карты.
Вариант 4 — вместо паролей — показатели сохраняются в отдельный файл, но начинаешь с начала уровня.
Суть в том, что на дискете ограниченное пространство. Уже сейчас выходит не более 17 уровней. А что будет дальше, с музыкой, новыми спрайтами и ролевой системой? Десять штук максимум?
Есть вариант, сжать уровни на дискете. Это будет неплохой вариант, потому что там много повторяющихся байт, но я никогда не имел дело с архиваторами, поэтому придется еще повозиться=)
❤🔥1🔥1
И даже поучаствовал в турнире по Quake 3. Но так как никогда особо в эту игру не играл, то финал получился довольно предсказуемым...
❤🔥1
Forwarded from ЛУНОХОД [ Компьютерный ретро клуб, антикафе, музей]
Media is too big
VIEW IN TELEGRAM
Турнир в Q3 в разгаре
❤3❤🔥1
Подумал я еще над формулами для битвы и остановился на следующем:
Урон:
Если враг предрасположен к оружию, то сдвигаем еще на 1 влево. Даже, если защита врага больше, чем атака игрока, то все равно можно нанести фиксированный урон. Но я буду стараться добавлять врагов на уровни таким образом, чтобы подобных ситуаций не возникало.
Попадание:
Получается число, которое увеличивается (но не более 255 == 100%) при увеличении разрыва между этими двумя числами. Потом на основе случайного числа уже высчитывается фактическое попадание.
А еще написал функции для 16-ти битного деления и умножения. В целом, работают быстро, а так как эти операции потребуются 4 раза за ход, то вообще не страшно. Я даже хочу сделать небольшую случайную задержку перед ходом врага, как будто он думает.
Урон:
damage = (weapon min. strength + random weapon strength * int(player attack/enemy defence)) << 1
Если враг предрасположен к оружию, то сдвигаем еще на 1 влево. Даже, если защита врага больше, чем атака игрока, то все равно можно нанести фиксированный урон. Но я буду стараться добавлять врагов на уровни таким образом, чтобы подобных ситуаций не возникало.
Попадание:
chance = (int(((player accuracy << 2) / enemy dexterity) * 128) >> 4)
Получается число, которое увеличивается (но не более 255 == 100%) при увеличении разрыва между этими двумя числами. Потом на основе случайного числа уже высчитывается фактическое попадание.
А еще написал функции для 16-ти битного деления и умножения. В целом, работают быстро, а так как эти операции потребуются 4 раза за ход, то вообще не страшно. Я даже хочу сделать небольшую случайную задержку перед ходом врага, как будто он думает.
❤🔥1
Опять немного поправил функцию для расчета урона и перенес ее в ассемблер. Получилась конечно та еще дичь, но вроде работает.
; ---------------------- CALCULATE DAMAGE ------------------------------
; weapon_min + (rand(weapon_min; weapon_max) * ((((player_attack << 4)/enemy_defence)*32)>>6))
; ----------------------------------------------------------------------
; rotate left player attack 4 times
lda fight_player_attack
sta rotate_inout
lda #0
sta rotate_inout+1
ldy #3
jsr rol_16bit
; divide player_attack by enemy_defence
lda rotate_inout
sta div_dividend
lda rotate_inout+1
sta div_dividend+1
lda fight_enemy_defence
sta div_divisor
lda #0
sta div_divisor+1
jsr divide_16bit
; multiply the previous result by 32
lda div_dividend
sta mult_f_number
lda div_dividend+1
sta mult_f_number+1
lda #32
sta mult_s_number
lda #0
sta mult_s_number+1
jsr mult_16bit
; rotate right the previous result 6 times
lda mult_result
sta rotate_inout
lda mult_result+1
sta rotate_inout+1
ldy #5
jsr ror_16bit
; get random weapon strength
jsr get_random_number
lda rnd_1
ldy curr_weapon_mod
jsr mod
clc
adc curr_weapon_add
; multiply random number by the previous result
sta mult_f_number
lda #0
sta mult_f_number+1
lda rotate_inout
sta mult_s_number
lda rotate_inout+1
sta mult_s_number+1
jsr mult_16bit
; add minimum weapon strength
lda mult_result
clc
adc curr_weapon_add
sta mult_result
lda mult_result+1
adc #0
sta mult_result+1
❤🔥1
А вообще возникла такая идея.
У игрока будет всего 4 возможных варианта в бою (не считая аптечки и брони):
— Атака - обычная атака;
— Защита - defence * 2;
— Уклонение - dexterity * 2;
— Побег - dexterity / 2;
А вот с врагами интереснее!
Будет три типа атаки:
— Обычная атака;
— Усиленная атака - attack * 2
— Хитрая атака - accuracy * 2
И также будут уклонение и защита, как и у игрока.
И игроку надо будет выбирать, как поступить дальше. Например, если враг использует усиленную атаку, логичным вариантом будет встать в защиту.
На экран будут выводиться подсказки, но думаю, что для каждого врага нужно будет придумать свою собственную подсказку, как в старых jrpg.
Хочется уже показать что-то кроме сплошных формул, но пока на экране ничего не происходит=(
У игрока будет всего 4 возможных варианта в бою (не считая аптечки и брони):
— Атака - обычная атака;
— Защита - defence * 2;
— Уклонение - dexterity * 2;
— Побег - dexterity / 2;
А вот с врагами интереснее!
Будет три типа атаки:
— Обычная атака;
— Усиленная атака - attack * 2
— Хитрая атака - accuracy * 2
И также будут уклонение и защита, как и у игрока.
И игроку надо будет выбирать, как поступить дальше. Например, если враг использует усиленную атаку, логичным вариантом будет встать в защиту.
На экран будут выводиться подсказки, но думаю, что для каждого врага нужно будет придумать свою собственную подсказку, как в старых jrpg.
Хочется уже показать что-то кроме сплошных формул, но пока на экране ничего не происходит=(
❤🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Немного помучился вчера с боями и теперь есть, что показать=)
Пока работают только 3 кнопки: атака, защита и уклонение.
— При атаке урон высчитывается по уже известной формуле. При этом, 25% урона всегда идет на броню, а остаток на здоровье. Если урон броне перевалил за количество брони, то остаток урона прибавляется к урону здоровья. Возможно над этим надо еще подумать.
— При нажатии на "Защиту", показатель defence умножается на 2.
— Аналогично с "Уклонением". Но на 2 умножается dexterity.
— После хода игрока все показатели врага сбрасываются до дефолтных значений и vice versa.
А ну и еще немного перерисовал текстуры первого уровня, изменил сам уровень и начал добавлять сюжетный текст.
Когда-нибудь это закончится, а то 14 мая будет уже ровно полгода, как мне в голову пришла идея снова заняться игрой на коммодор...
Пока работают только 3 кнопки: атака, защита и уклонение.
— При атаке урон высчитывается по уже известной формуле. При этом, 25% урона всегда идет на броню, а остаток на здоровье. Если урон броне перевалил за количество брони, то остаток урона прибавляется к урону здоровья. Возможно над этим надо еще подумать.
— При нажатии на "Защиту", показатель defence умножается на 2.
— Аналогично с "Уклонением". Но на 2 умножается dexterity.
— После хода игрока все показатели врага сбрасываются до дефолтных значений и vice versa.
А ну и еще немного перерисовал текстуры первого уровня, изменил сам уровень и начал добавлять сюжетный текст.
Когда-нибудь это закончится, а то 14 мая будет уже ровно полгода, как мне в голову пришла идея снова заняться игрой на коммодор...
🔥5❤🔥2
https://youtu.be/LnzuMJLZRdU?si=S59nYuS6Pftfr8tw
Офигенная серия видео. Мужик на макетной плате собирает компьютер на базе процессора 6502 и тут же программирует его.
После этого видео захотелось тоже чем-то таким заняться, но с чего начать, не могу сообразить.
Погуглил, оказывается, есть куча современных микропроцессоров, да и 6502 все еще производят (точнее 65С02). Но как к этому подступиться, пока не понимаю)
Офигенная серия видео. Мужик на макетной плате собирает компьютер на базе процессора 6502 и тут же программирует его.
После этого видео захотелось тоже чем-то таким заняться, но с чего начать, не могу сообразить.
Погуглил, оказывается, есть куча современных микропроцессоров, да и 6502 все еще производят (точнее 65С02). Но как к этому подступиться, пока не понимаю)
YouTube
“Hello, world” from scratch on a 6502 — Part 1
Learn how computers work in this series where I build and program a basic computer with the classic 6502 microprocessor. More info: https://www.eater.net/6502
Part 2: https://www.youtube.com/watch?v=yl8vPW5hydQ
Part 3: https://www.youtube.com/watch?v=oO8_2JJV0B4…
Part 2: https://www.youtube.com/watch?v=yl8vPW5hydQ
Part 3: https://www.youtube.com/watch?v=oO8_2JJV0B4…
❤🔥1
This media is not supported in your browser
VIEW IN TELEGRAM
Не так давно я начал заниматься ролевой системой и уже добавил проверку на попадание и расчет урона.
И это все хорошо, но у меня даже изображений врагов нет, как и других изображений, потому что их было сложно рисовать.
Один игровой спрайт в моей игре состоит из 4 хардварных спрайтов. Я сперва рисовал игровые спрайты в Aseprite (двойные пиксели трудно рисовать), а потом переносил вручную изображение в редактор спрайтов для Commodore, где рисовал их уже по отдельности (и это очень неудобно).
Поэтому я не придумал ничего лучше, чем создать собственный редактор спрайтов исключительно для своей игры. Это очень сырая версия, которую потом я конечно же доработаю (нет). Осталось добавить только функции для сохранения изображений в json, png и asm.
А писал я кстати на Godot. Обожаю этот движок за то, что на нем можно спроектировать все что угодно за день-два.
Редактор поддерживает все возможности Commodore:
Во-первых, можно отдельно отключить сетку для каждого пикселя и сетку для каждого спрайта.
Во-вторых, можно выбрать цвет для каждого спрайта и два цвета, общих для всех спрайтов.
В-третьих, можно выбрать, каким из цветов рисовать конкретный пиксель (или стереть его)
В-четвертых, все это работает в 60 FPS.
Короче, как допишу сохранение и загрузку, станет намного проще.
А то, как я реализовал в итоге шанс попадания по врагу в игре потом покажу)
И это все хорошо, но у меня даже изображений врагов нет, как и других изображений, потому что их было сложно рисовать.
Один игровой спрайт в моей игре состоит из 4 хардварных спрайтов. Я сперва рисовал игровые спрайты в Aseprite (двойные пиксели трудно рисовать), а потом переносил вручную изображение в редактор спрайтов для Commodore, где рисовал их уже по отдельности (и это очень неудобно).
Поэтому я не придумал ничего лучше, чем создать собственный редактор спрайтов исключительно для своей игры. Это очень сырая версия, которую потом я конечно же доработаю (нет). Осталось добавить только функции для сохранения изображений в json, png и asm.
А писал я кстати на Godot. Обожаю этот движок за то, что на нем можно спроектировать все что угодно за день-два.
Редактор поддерживает все возможности Commodore:
Во-первых, можно отдельно отключить сетку для каждого пикселя и сетку для каждого спрайта.
Во-вторых, можно выбрать цвет для каждого спрайта и два цвета, общих для всех спрайтов.
В-третьих, можно выбрать, каким из цветов рисовать конкретный пиксель (или стереть его)
В-четвертых, все это работает в 60 FPS.
Короче, как допишу сохранение и загрузку, станет намного проще.
А то, как я реализовал в итоге шанс попадания по врагу в игре потом покажу)
🔥5❤🔥1
Короче повозился я с этой программой, а все потому что ассемблер приучил меня все усложнять ради производительности. В Godot импорт изображений в рантайме осуществляется одной строкой, а я написал аж 4. Из-за этого, после экспорта в .exe, она перестала работать нормально (уже починил).
Но рисовать спрайты реально стало удобнее. Теперь не приходится подгонять пиксели под сетку 2*1, а потом переносить каждый спрайт по отдельности в другой редактор.
Но проблема все равно есть. Для редактора я брал цвета с Commodore Wiki, и они должны быть правильными. Но вот в эмуляторе это все выглядит совершенно иначе (на реальном железе еще не проверял).
Вот, нарисовал кривую собаку) В редакторе выглядит ну... нормально, а в самой игре ИМХО хуже.
Хотя и в этом есть вайб 80-х. Там и не таких уродцев можно было встретить=)
Но рисовать спрайты реально стало удобнее. Теперь не приходится подгонять пиксели под сетку 2*1, а потом переносить каждый спрайт по отдельности в другой редактор.
Но проблема все равно есть. Для редактора я брал цвета с Commodore Wiki, и они должны быть правильными. Но вот в эмуляторе это все выглядит совершенно иначе (на реальном железе еще не проверял).
Вот, нарисовал кривую собаку) В редакторе выглядит ну... нормально, а в самой игре ИМХО хуже.
Хотя и в этом есть вайб 80-х. Там и не таких уродцев можно было встретить=)
👍4❤🔥1
А вообще жесть. Я тут посчитал, что раз у меня на каждый уровень уникальные текстуры стен и спрайты врагов и объектов, то получается, что мне надо нарисовать:
— 16 * 10 уровней = 160 текстур;
— 4 * 10 = 40 врагов;
— 4 * 10 = 40 объектов;
Итого 240 изображений.
Кажется, что я буду использовать уже имеющиеся текстуры на других уровнях, но менять окраску (как в Doom RPG), и это должно сработать.
Немного цветовой магии, и вот обычная собака превращается в посланника ада (нет)
В общем, это можно использовать)
— 16 * 10 уровней = 160 текстур;
— 4 * 10 = 40 врагов;
— 4 * 10 = 40 объектов;
Итого 240 изображений.
Кажется, что я буду использовать уже имеющиеся текстуры на других уровнях, но менять окраску (как в Doom RPG), и это должно сработать.
Немного цветовой магии, и вот обычная собака превращается в посланника ада (нет)
В общем, это можно использовать)
😁3❤🔥2👍2
This media is not supported in your browser
VIEW IN TELEGRAM
Почти дописал боевую систему!!!
Правда не очень понятно, насколько она вышла адекватной. Надо тестировать. А еще обязательно надо будет проверить пошагово на правильность кода. Визуально он вроде работает, но где-нибудь могла закрасться ошибка.
А еще надо бы как-то показывать на экране, чей ход. Сейчас, в принципе, это видно по тексту, но хотелось бы более понятный индикатор.
Когда враг планирует сильную или хитрую атаку, это отображается на экране. При этом игроку надо угадать, что делать дальше: защищаться или уклоняться. Ну и после каждого хода врага есть задержка в 2 секунды, чтобы игрок успевал прочитать текст. Да, вродекривого кода дофига с кучей деления и умножения, но отрабатывает моментально.
Ну и последнее. Я решил пойти по простому пути в части поведения врагов. У каждого врага будет тип (или характер). Будут тупые или аккуратные враги, которые только атакуют и/или защищаются. Будут враги-маньяки, которые будут чаще бить усиленными атаками и т.д. Все паттерны поведения будут храниться в таблице
Правда не очень понятно, насколько она вышла адекватной. Надо тестировать. А еще обязательно надо будет проверить пошагово на правильность кода. Визуально он вроде работает, но где-нибудь могла закрасться ошибка.
А еще надо бы как-то показывать на экране, чей ход. Сейчас, в принципе, это видно по тексту, но хотелось бы более понятный индикатор.
Когда враг планирует сильную или хитрую атаку, это отображается на экране. При этом игроку надо угадать, что делать дальше: защищаться или уклоняться. Ну и после каждого хода врага есть задержка в 2 секунды, чтобы игрок успевал прочитать текст. Да, вроде
Ну и последнее. Я решил пойти по простому пути в части поведения врагов. У каждого врага будет тип (или характер). Будут тупые или аккуратные враги, которые только атакуют и/или защищаются. Будут враги-маньяки, которые будут чаще бить усиленными атаками и т.д. Все паттерны поведения будут храниться в таблице
👍2🔥2❤🔥1
И тут я подумал, что неплохо было бы на экране как-нибудь визуально отображать попадания и промахи.
Например, при попадании в игрока можно быстро переключать цвета рамки экрана.
А при попадании во врага с помощью XOR переключать цвета спрайта.
И скорее всего это все нужно будет делать в прерываниях. Надеюсь, у меня там еще осталось время для такого.
И конечно, на все это надо наложить какие-нибудь звуки, а это вообще моя больная тема😢
Например, при попадании в игрока можно быстро переключать цвета рамки экрана.
А при попадании во врага с помощью XOR переключать цвета спрайта.
И скорее всего это все нужно будет делать в прерываниях. Надеюсь, у меня там еще осталось время для такого.
И конечно, на все это надо наложить какие-нибудь звуки, а это вообще моя больная тема
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5❤🔥2