Тайлы и изометрияМатериал из Blitz Et Cetera(Перенаправлено с Тайлы и Изометрия (на примере BlitzMax))
Очередные потуги в направлении игростроя привели меня на поприще тайлов и изометрии. Если с тайловой графикой и обработкой все понятно (смотри тут и тут), то вот с изометрией дело обстоит сложнее. Результатом моих изысканий стали пара формул. Основной теорией и формулами, включая пояснение параметров, я и хочу поделиться. Если не хочется много читать, то вкратце так: Вывод массива на экран в изометрии:
где:
где:
Изометрия – это вид объемного объекта под углом. Обычно 45 градусов по оси Y и примерно в 30 градусов по X относительно камеры (взгляда или горизонта). К примеру кубик на чертеже выглядит квадратиком, т.к. видим только одну сторону. В изометрии мы видим три стороны и понимаем, что объект объемный. Вот и с двухмерной графикой на плоскости, если отобразить тайлы изометрически, то будет выглядеть вполне объемисто. Самым известным примером приведу игру Дьябло. Из выше сказанного делаем вывод, что если наше плоское поле повернуть на 45 градусов и немного наклонить, то получится вполне похожая на 3Д картинка. Так как мы говорим о плоскости, то все объемы сугубо теоретические и эффект сильно зависит от медиа контента, т.е. непосредственно от красоты тайлов. Визуально это выглядит так: Это скрин моего простенького тайлово-изометрического редактора. Слишком большое вступление получилось, переходим к работе. В первую очереди расскажу о тайлах. Понятно, что тайл – это маленькая картинка, сложив несколько картинок рядом, получается карта мира (игры). В процессе создания тайлов есть свои нюансы, а у изометрических тайлов их еще больше, но тема не моя. Я же взял минимальный набор изометрических тайлов из бесплатной библиотеки различной медиа для игр: На данной картинке тайлы размером 64х64 + несколько больших объектов для красоты. Так как я говорю о изометрии, то отличия от обычных тайлов бросаются в глаза – кусочки все повернуты на 45 и 30 градусов по осям, отсюда у объектов появляется иллюзия объемности. Иногда я встречал примеры, когда объем пытаются придать и без изометрии, т.е. рисуют обычную квадратную матрицу, но с объектами выглядящими как эти. Получается не очень. Заметьте, что картинка изометрического тайла имеет форму ромба, обычные тайлы квадратные. Если мы сложим два камня квадратами, то получим тоже, что и на картинке – пустоты в нижней части. Их можно зарисовать травкой, но стены не получается. Можно и стену нарисовать… Так и делают. К примеру, «Герои Меча и Магии 3» мир нарисован обычной матрицей (квадратными тайлами), но смотрится вполне прилично. Там только земля тайловая, все остальными объекты нарисованы поверх. Вот только человечки там всегда на плоскости, нельзя подняться на горку или спуститься в ямку – всегда бродишь по идеально плоской равнине, на которой местами нарисованы горы. Вот вам горка тайлами в изометрии: Я специально удалил тайлы вокруг для наглядности. С тайлами разобрались. Теперь разберем как же с ними работать? А работают с изометрическими тайлами точно также как и с обычными, т.е. движок изометрических тайлов работает точно также как и с обычными. Тут вся прелесть: работаем мы с обычными матрицами (массивами) по обычным принципам и методам, вот только отображаем на экран не квадратиками по квадратам, а ромбиками по ромбам. Немного раздвинул тайлы и подписал их позиции в матрице (массиве). Теперь наглядно показано, что работаем с обычной матрицей (столбцы и строки), но повернуты. Для еще большей наглядности привожу упрощенный кусок кода (немного забегая вперед), который рисует эти тайлы: For i=0 To 15
For j=0 To 15 Видим, что отличий от обычного тайлового движка практически нет, тот же массив mas(i,j), те же два цикла перебирающие строки и столбцы. Вот только координаты рассчитываются иначе. А рассчитываются они просто. Точнее не очень просто, есть формулы поворота точки вокруг осей, там поворотные матрицы и прочее, но все это фигня, т.к. градусы поворота всегда одинаковые, то все вычесления сокращаются до минимума и получаем:
где:
Изометрический тайл на плоскости имеет форму ромба, а не квадрата. Таким образом его высота в два раза меньше ширины. «В два раза» это в частном случае, зависит от угла поворота относительно горизонта. Проще: зависит от ваших тайликов. У меня картинка тайла 64 пикселя в ширину и 32 по высоте. Половинные соответственно 32 и 16. Попробуйте потом поиграть этими параметрами – увеличивая, появятся зазоры между тайлами, уменьшая – будут наложения. Теперь в бой! Смело и решительно начинаем писать движок для изометрических тайлов. И все прекрасно: и алгоритм *А прекрасно работает, и персонажи красиво перемещаются, причем изменяя только строку координат персонажа в массиве, на экране он будет красиво перемещаться по диагонали. И тут возникает трудность: как провести обратные расчеты? Т.е. узнать где рисовать тайл, зная его позицию в массиве легко, а как узнать какому элементу массива принадлежит точка экрана? Самый яркий пример – это мышка. Как узнать в какой тайлик ткнул мышкой пользователь? На моём примере (см. картинки выше) видно как за мышкой бегает ромбовидный курсор, который выделяет нужный тайл и показывает его координаты в массиве. На форумах зачастую предлагают проверять какой тайл под курсором мыши и затем сравнивать позицию мыши с альфа-каналом тайла. Но этот вариант сразу отметаем, т.к. положение мыши обычно проверяется в каждом расчете сцены и если в каждом расчете мы будем залазить в альфа-канал рисунков… производительность резко снизится, а с ней и ФПС. Так что будем разбираться математическими (стереометрическими если точнее) методами. Тут не обойтись обычным выражением через формулы рисования, можно, но сложно. У нас тут по две переменные в каждой формуле, а это система уравнений и всякое прочее. Люди это все уже просчитали и упростили:
где:
Тут совсем интересно: с – это маштабер – если можно так выразится. Половинная ширина наших изометрических тайлов. Математически это размер квадрата, который мы повернули в пространстве на 45 и 30 градусов по осям. a и b – это соотношение размеров нашего плоского изображения тайла, т. е. соотношение высоты и ширины ромба. В моем случае это 2 к 1. Ширина 64, высота 32 = 64 к 32, сокращаем и получаем 2 к 1. отсюда a=2; b=1. Тут интересный эффект. Если не сокращать, то увеличится масштаб проверяемой фигуры, если этот масштаб скомпенсировать «маcштабером» (переменной «с»), то грани проверяемого ромба будут как бы запикселенными: Это рисунок проверяемой области. В данном случае я закрасил белым область на которую ответом по формулам будет 0 как для строк, так и для столбцов. Вот код, на котором я отлаживал области проверки положения курсора мыши в изометрии для моего примера: Global GH=600
Global GW=800 Тут все просто. Перебираем точки на экране (как будто туда тыкает курсор мыши) и проверяем результат формул. Если результат будет указывать на нулевой квадрат массива, т.е. результат выдаст 0 по обоим формулам, то закрашиваем эту точку. Затем я накладывал на полученный рисунок свой тайл и, если размеры не совпадали, то подбирал другие параметры. Все. Мой рассказ закончен. Прикрепляю небольшой редактор изометрических тайловых карт, написанный мною. В управлении разберетесь по коду. Редактор лишь для примера использования вышеуказанных формул. Предупреждаю! код совершенно не оптимизирован. Местами даже слишком. Картинки для кода ниже. Global GH=600
Global GW=800 Автор: Grover (e-mail: mail_grover |




