Пошаговая RPG в Excel (Начало)

Вам бывает скучно на работе? Часто сидите два-три дня без единого намёка на трудовую деятельность и пытаетесь ее имитировать, а руководство так и ждет ошибки с вашей стороны?

В закладки
Слушать

Теперь этого можно будет избежать, ведь в разработке находится пошаговая RPG в стиле Dragon Quest на NES для офисного приложения Excel.

Конечно, идея не нова. В Excel и раньше делали разнообразные игры (даже полноценный шутер). Но если вы читали мои предыдущие статьи, то поймёте, что создавать троллейбусы из батонов белого (или чёрного) хлеба — мое небольшое хобби.

Перейдём же к делу

На данный момент готова альфа-версия графического движка и редактор карт. С вероятностью в 99% они будут дорабатываться в процессе разработки.

Сперва немного расскажу о некоторых технических характеристиках.

1. Скорее всего в игре будет использоваться событийная модель, а не циклическая, ведь для пошаговой стратегии цикл не так уж и важен. Это будет зависеть от того, как быстро Excel справится с рендером одного кадра. Минус такого подхода заключается в том, что написать какой-нибудь платформер на этой основе не получится. В любом случае я попробую оба варианта.

2. Все текстуры имеют размер 16*16 пикселей. Палитра состоит всего из 56 цветов (стандартный размер палитры Excel). В качестве основы я взял палитру NES.

3. Текстуры я рисую в программе Aseprite, а в Excel из. bmp перевожу с помощью небольшого, написанного на VBA софта, который нашел в интернете.

4. Бэкграунд состоит из тайлов, спрайты же привязаны к системе координат.

Графический движок

Карта уровня представляет собой двумерный массив с кодовым обозначением тайла в формате «XXXY», где XXX — номер текстуры по порядку, Y — значение, указывающее на то, можно ли пройти сквозь тайл. Вторая функция пока что не реализована.

Спрайты хранятся в отдельном массиве в формате: координата X, координата Y, порядковый номер спрайта, тип спрайта и тэг. Два последних значения пока не используются.

Для создания графического движка сперва необходимо инициализировать различные переменные. Часть из них хранится на отдельном листе, а в коде я сделал их публичными (знаю, что так нельзя):

- высота и ширина игрового экрана;

- диапазон игрового экрана;

- массив игрового экрана для рендеринга;

- размер одной текстуры;

- координаты камеры;

- координаты игрока;

- номер уровня;

- карта тайлов и координаты спрайтов;

- массив спрайтов, тайлов и спрайтов игрока.

Все текстуры хранятся на отдельном листе с отображением индексов цветов палитры.

Так как это только первая версия движка, нажатие на «Новую игру» тут же запускает метод fillWithTextures (процесс создания массива цифровых значений цвета).

'##########ЯДРО ГРАФИЧЕСКОГО ДВИЖКА########## Sub fillWithTextures() Dim cntRow As Integer, cntCol As Integer, pixOffsetX As Double, pixOffsetY As Double, _ mapBlockX As Integer, mapBlockY As Integer, texXOffset As Integer, texYOffset As Integer, _ texNumber As Integer, arrBlockTex() As Variant Dim cntSprites As Integer, spriteOffsetX As Integer, spriteOffsetY As Integer, _ spriteNumber As Integer ReDim arrRender(main.screenH, main.screenW) For cntRow = 1 To main.screenH For cntCol = 1 To main.screenW 'Считаем смещение пикселя экрана относительно координат камеры pixOffsetX = main.cameraX + cntCol pixOffsetY = main.cameraY + cntRow 'считаем спрайты For cntSprites = 1 To UBound(arrMapSprites(), 1) 'считаем смещение спрайта относительно пикселя spriteOffsetX = pixOffsetX - arrMapSprites(cntSprites, 1) spriteOffsetY = pixOffsetY - arrMapSprites(cntSprites, 2) 'если пиксель содержит спрайт If spriteOffsetX >= 0 And spriteOffsetY >= 0 And spriteOffsetX + pixOffsetX < pixOffsetX + main.blockSize _ And spriteOffsetY + pixOffsetY < pixOffsetY + main.blockSize Then 'если элемент спрайта не пуст If arrSprites((spriteOffsetY + blockSize * arrMapSprites(cntSprites, 3)) + 1, spriteOffsetX + 1) <> 0 Then arrRender(cntRow, cntCol) = arrSprites((spriteOffsetY + blockSize * arrMapSprites(cntSprites, 3)) + 1, spriteOffsetX + 1) End If End If Next 'рисуем тайлы If (pixOffsetX > 0 And pixOffsetX < main.mapWidth) And _ (pixOffsetY > 0 And pixOffsetY < main.mapHeight) Then 'расчет тайла, в который входит пиксель mapBlockX = WorksheetFunction.RoundUp(pixOffsetX / main.blockSize, 0) mapBlockY = WorksheetFunction.RoundUp(pixOffsetY / main.blockSize, 0) 'определяем номер текстуры texNumber = arrMapTiles(mapBlockY, mapBlockX) 'Определение цвета текстуры для пикселя texXOffset = getTexOffset(pixOffsetX) + 1 texYOffset = getTexOffset(pixOffsetY) + 1 If arrMapTiles(mapBlockY, mapBlockX) <> "" And arrTiles(texNumber * _ main.blockSize + texYOffset, texXOffset) <> "" And arrRender(cntRow, cntCol) = "" Then arrRender(cntRow, cntCol) = arrTiles(texNumber * main.blockSize + texYOffset, texXOffset) End If End If Next Next End Sub

Первым делом происходит поиск спрайтов, которые нужно отрисовать. Для этого программа проверяет каждый «пиксель» игрового экрана, считает смещение этого пикселя относительно стартовых координат камеры, а также смещение относительно всех спрайтов на уровне. Если смещение «пикселя» относительно спрайта по каждой оси равно от 0 до 15 (так как размер текстуры 16*16), берётся индекс нужного цвета из массива спрайтов.

Вторым пунктом программа на основе смещения относительно координат камеры высчитывает позицию «пикселей» на карте тайлов. Когда нужный тайл найден, программа с помощью функции getTextOffset возвращает индекс цвета пикселя из массива тайлов.

'Возвращает координату текстуры Function getTexOffset(dCoordinate As Double) As Integer getTexOffset = (dCoordinate - 1) Mod main.blockSize End Function

Почему сперва происходит проверка спрайтов, а затем тайлов?

Все просто. Программа просто не трогает те «пиксели», которые уже закрашены спрайтами, что влияет на производительность в лучшую строну.

P.S. На следующий день я понял, что проверка условия «закрашенности» спрайтами должна производиться в начале. Тогда это повлияет на производительность. Привет, оптимизация.

Вторая проблема — это проверка спрайтов для каждого пикселя экрана. Предположим, что на уровне находится 40 спрайтов. При размере экрана 96*64 = 6144 пикселей количество итераций цикла достигает 6144 * 40 = 245760. Если пойти другим путём и проверять спрайты не для каждого пикселя, а по условию нахождения в поле зрения камеры, то количество итераций не превысит 40*16*16 = 10240. Эта проблема решается быстро.

Создание игрока и рендеринг изображения

Для того, чтобы поместить спрайт игрока в рендер-массив нужно посчитать смещение спрайта относительно координат камеры.

Sub renderPlayer(imagePose As Integer) Dim offsetX As Double, offsetY As Double, cntRow As Integer, _ cntCol As Integer 'Считаем смещение относительно координат камеры offsetX = main.playerX - main.cameraX offsetY = main.playerY - main.cameraY 'Если игрок не находится за пределами камеры If offsetX >= 0 And offsetY >= 0 And _ offsetX < main.cameraX + main.screenW And _ offsetY < main.cameraY + main.screenH Then For cntRow = 0 To main.blockSize - 1 For cntCol = 0 To main.blockSize - 1 'Если пиксель текстуры заполнен If main.arrPlayerSpr((cntRow + 1) + (imagePose * main.blockSize), cntCol + 1) <> 0 Then 'Если пиксель не заходит за пределы камеры If cntRow + main.playerY <= main.screenH + main.cameraY And cntCol + main.playerX <= main.screenW + main.cameraX Then arrRender(offsetY + cntRow, offsetX + cntCol) = main.arrPlayerSpr((cntRow + 1) + (imagePose * main.blockSize), cntCol + 1) End If End If Next Next End If End Sub

Аргумент imagePose будет использоваться для имитации поворота игрока при движении.

В конце-концов рендер-массив готов, поэтому вызываем последнюю процедуру, которая рисует сформированный кадр на игровом поле. Ее я показывать не буду, потому что она очень сырая и будет дорабатываться.

Будут дорабатываться и текущие процедуры, потому что на данный момент быстродействие немного хромает и реализовать упомянутую циклическую модель в данный момент проблематично.

Вот, что получается в итоге:

На этом можно пока закончить. Надеюсь, что из ваших глаз не пошла кровь от «лучшего в мире» языка программирования и попыток написать что-то осмысленное.

В любом случае жду критику и советы. Всегда интересно послушать, что скажут люди.

Немного саморекламы

Я создал паблик ВКонтакте, куда буду выкладывать свои мысли, алгоритмы, код, ссылки на эти статьи и конечно мемасики:) Если вам интересно наблюдать за разработкой игр и разных странных вещей, добро пожаловать.

{ "author_name": "Александр Милашев", "author_type": "self", "tags": ["\u044f\u0434\u0440\u043e"], "comments": 31, "likes": 91, "favorites": 97, "is_advertisement": false, "subsite_label": "gamedev", "id": 139334, "is_wide": false, "is_ugc": true, "date": "Tue, 26 May 2020 14:19:04 +0300", "is_special": false }
0
31 комментарий
Популярные
По порядку
Написать комментарий...

Комментарий удален

Комментарий удален

Комментарий удален

Комментарий удален

Комментарий удален

24

«ТОП-10 игровых движков для новичков»
1) Microsoft Excel

Ответить
2

На нем даже онлайн игру написали! Что то там про космос... ))

Ответить
15

И трассировку лучей.

Ответить
5

Японский художник уже 17 лет рисует в Excel.

Ответить
8

ну это японец, так что не интересно 

Ответить

Статистический браслет

Егор
2

Охренеть.

Ответить
1

Я сперва подумал, что он будет ячейки закрашивать, типа пиксельарта. Но так даже прикольнее)

Ответить
4

А кто-то ради рофлов даже пытается дизайнить сайты в электронных таблицах.

Ответить
4

Да поговаривают, что в нем даже и таблицы рисуют.

Ответить
1

Да не, брешут наверное

Ответить
0

Ебануться

Ответить

Комментарий удален

Комментарий удален

5

И это заслуживает большего уважения, чем Playrix!

Ответить

Комментарий удален

2

Прям копия Aldons Crossing для PalmOS

Ответить
0

Заинтересовала. Надо бы поискать способ поиграть в нее)

Ответить
0

О, прикольная тема. Надо бы поискать способ поиграть в это)

Ответить
0

Интернет лаганул))

Ответить
2

 Вам бывает скучно на работе? Часто сидите два-три дня без единого намёка на трудовую деятельность и пытаетесь ее имитировать, а руководство так и ждет ошибки с вашей стороны?

Пиздец, ребята, подскажите, где такую работу найти!

Ответить
1

"Пошаговая RPG в Excel"
- Круто. Но зачем?
- Чёрт его знает. Но блин, круто же!!!
- Да вообще офигенно! Но зачем?
______________________________________
Человек, твори. Ради всего святого, не останавливайся =)

Ответить
3

У меня примерное такое и было в голове в первое время)) Но потом я понял, что это очень полезно и для саморазвития, и интересно качестве развлечения/хобби. Так что почему бы и нет)

Ответить
1

Это действительно здорово. С нетерпением жду новых публикаций =)

Ответить
1

Имхо, но графин у версий геймбой колор лучше

Ответить
1

Знаю) но пока что я тестирую именно алгоритмы, поэтому графика стоит на втором месте. Не факт, что эти текстуры будут использоваться в будущем.

Ответить
1

Цвета из кода назначаешь или через условное форматирование?
Когда свой клон цивилизации, на скрытом листе с отключенным пересчётом записывал цветовую кодировку, потом делал встроенный recalculate()
На видимом листе условное форматирование ссылалось на ту же ячейку скрытого листа и через впр подтягивало цвет из палитры. Так работало гораздо быстрее, чем через прямое заполнение цветом.

Ответить
0

Я сначала через ActiveWorkbook.Colors() добавил в палитру книги 56 цветов по их константам. В процессе у меня получается массив 64*96 элементов, которые содержат индекс цвета из палитры. А отрисовка происходит через цикл с помощью Cells.Interior.ColorIndex().

Было бы интересно посмотреть на реализацию цивилизации:)

Ответить
1

Поискал. Последняя версия не сохранилась. В том варианте который есть, цвет ещё из кода заполнялся. Работает только на Excel 2007.
Я тогда только учился программировать, так что код там, мягко говоря, так себе.
Если играл в первую цивилизацию, то проблем с управлением возникнуть не должно.

Ответить
0

Отлично, завтра заценю)

Ответить
0

Ты конечно заморочился) Крутая реализация цивы получилась.

Ответить
0

По концовке до играбельной версии оставалось только прикрутить ИИ для противников, но оказалось, что в VBA есть очень серьёзный баг - он иногда теряет глобальные переменные. Узнав о нём, решил изучить нормальный язык))

Ответить
1

Ни фига не понял в технической части, но если смогу на рабочем компе запустить что-то кроме браузерной версии King's Bounty, это будет кайф! :D

Ответить

Комментарий удален

Комментарий удален

0

(Начало)

... сага?

Ответить

Комментарии

{ "jsPath": "/static/build/dtf.ru/specials/DeliveryCheats/js/all.min.js?v=05.02.2020", "cssPath": "/static/build/dtf.ru/specials/DeliveryCheats/styles/all.min.css?v=05.02.2020", "fontsPath": "https://fonts.googleapis.com/css?family=Roboto+Mono:400,700,700i&subset=cyrillic" }