TamMgnovennoHappy
Новичок
Репутация: 5
Offline
API: GameMaker Studio 2
Деятельность: Пытаюсь понять насколько мне подходит GMS2
Сообщений: 10
Слева - тема которую нужно изучить, справа - я
|
 |
« : Июль 25, 2020, 16:34:21 » |
|

|
| Чему может научить этот урок/руководство:
- Отрисовке куба тремя спрайтами ( будет учитываться угол поворота камеры )
- Сортировке кубов по глубине
- Отрисовке 2d спрайтов в фейковой 3d проекции
|
Добрый день . Хочу поделиться своим опытом в создании fake3d вида. С game maker'ом я познакомился не так давно, так что не сочтите этот урок/руководство за грубость в Ваш адрес. 1. Немного теории:
Начну с того какие вводные параметры будут использоваться. В общем-то их два) global.z - глобальная переменная которая хранит угол поворота камеры (Нужно объявить в каком-нибудь объекте). cube_height - высота куба (объявляем в объекте куба).
Чтобы отрисовать куб, будем использовать функцию draw_sprite_ext для крышки куба, draw_sprite_pos для стен.
Как формируется куб:
Давайте представим куб ширина которого = 100px, высота по y = 100px, высота по "z" = 45px. Он у нас расположен где-нибудь на карте. Угол поворота камеры представим 45 градусов. Внимание! Формулы, которые приведены ниже могут быть не адаптированы к game maker'у, в связи с этим прошу не использовать для расчета в GM. Весь расчет для game maker'а будет расположен в главе 2. Практика. Спасибо за пониманиеТакже нам нужно определить axis_x, axis_y, это так называемая (мною) "z ось". axis_x = cos( 45) = 0,71( приблизительно ), 45 - это наш угол поворота ( на этот угол потом будем поворачивать наш view )axis_y = sin( 45 ) = 0.71( приблизительно ) Если мы в какой-нибудь точке( x,y), от у отнимем axis_y * cube_height, а также к x добавим axis_x * cube_height, то наша точка визуально сместиться вверх, несмотря на, то какой будет угол. (если не поняли, то потом поймете).Внимание! схемы, что приведены ниже не имитируют отрисовку куба в самом game maker'е. Это просто схемы для лучшего (надеюсь) понимания.- сначала рисуем спрайт в центре координат куба, с помощью draw_sprite_ext. c - x,y нашего куба, квадрат - наш условный спрайт - затем нужно нарисовать стены, выберем сначала правую. Для этого представим, что нам нужно нарисовать прямоугольник на правой грани спрайта (просто представьте, ненадолго) d1 - левый верхний угол, d1_1 - правый верхний, d2_2 - правый нижний, d2 - левый нижний. здесь я визуально отделил углы прямоугольника d1 и d1_1, но на самом деле они находятся друг на друге. Также как и d2 и d2_2. - дальше мы смещаем крышку нашего куба( только спрайт ): x + ( axis_x * cube_height ), т.е x + ( 0.71 * 45 ) = x + 32 (приблизительно) y - ( axis_y * cube_height ), т.е y - ( 0.71 * 45 ) = y - 32 (приблизительно) c - координаты куба, nc - точка отрисовки спрайта - помните я говорил что точки прямоугольника d1 и d1_1 стоят "друг на друге"?. Так вот, теперь точки d1_1 и d2_2 нужно сместить также как и крышку: x + ( axis_x * cube_height ), т.е x + ( 0.71 * 45 ) = x + 32 (приблизительно) y - ( axis_y * cube_height ), т.е y - ( 0.71 * 45 ) = y - 32 (приблизительно) получается:  В game maker'е, мы бы увидели что-то вроде:  Когда, будут отрисованы все четыре стороны куба, нужно будет сделать проверку поворота камеры так, чтобы у одного куба в текущий момент рисовались только две стены. ( две оставшиеся мы все равно не видим, так зачем их рисовать? ) В конечном счете выходит:  Сортировка кубов по глубине:Мы поняли как можно отрисовать куб, его крышу и каждую из его сторон. Теперь плавно подошли к вопросу сортировки кубов. Если мы не будем их сортировать, то при попытке расположить кубы вплотную, мы получим нечто следующее:  Я думаю, вы прекрасно знаете что чем ниже значение depth у объектов, тем выше на экране они рисуются. Формула для корректного изменения depth принимая во внимание угол поворота камеры, выглядит так: var axis_x = lengthdir_x( 1, global.z -90 ) или = dcos(global.z -90) * 1, -90 градусов нужно для того, чтобы стенки куба рисовались строго вертикально вверх, а не горизонтально вправо var axis_y = lengthdir_y( 1, global.z -90 ) или = -dsin(global.z -90) * 1depth = -(y * axis_y) + (x * axis_x);Так выглядят кубы после расчета depth  этот расчет потом поместим в step куба. Как эта формула работает, можете посмотреть более наглядно Здесь приведено три примера расчета сортировки при углах: 0, 116, 200 ( рандомно выбрал ) [ Пример 1 ]global.z = 0; axis_x = cos( global.z - 90 ) = 0; axis_y = -sin( global.z - 90 ) = 1; depth = -( y * axis_y ) + ( x * axis_x ); [block1] depth = -( 350 * 1 ) + ( 350 * 0 ) = -350 + 0 = -350 [block2] depth = -( 350 * 1 ) + ( 450 * 0 ) = -350 + 0 = -350 [block3] depth = -( 250 * 1 ) + ( 450 * 0 ) = -250 + 0 = -250 Результат на схеме. [ Пример 2 ]global.z = 116 axis_x = cos( global.z - 90 ) = 0.898 axis_y = -sin( global.z - 90 ) = -0.438 depth = -( y * axis_y ) + ( x * axis_x ) [block1] depth = -( 350 * -0.438 ) + ( 350 * 0.898 ) = 153.3 + 314.3 = 467.6 [block2] depth = -( 350 * -0.438 ) + ( 450 * 0.898 ) = 153.3 + 404.1 = 557.4 [block3] depth = -( 250 * -0.438 ) + ( 450 * 0.898 ) = 109.5 + 404.1 = 513.6 Результат на схеме. [ Пример 3 ]global.z = 200 axis_x = cos( global.z - 90 ) = -0.342 axis_y = -sin( global.z - 90 ) = -0.939 depth = -( y * axis_y ) + ( x * axis_x ) [block1] depth = -( 350 * -0.939 ) + ( 350 * -0.342 ) = 328.65 - 119.7 = 208.95 [block2] depth = -( 350 * -0.939 ) + ( 450 * -0.342 ) = 328.65 - 153.9 = 174.75 [block3] depth = -( 250 * -0.939 ) + ( 450 * -0.342 ) = 234.75 - 153.9 = 80.85 Результат на схеме.  Как отрисовать 2д спрайт вертикально:Самая легкая часть статьи. Для того чтобы отрисовать спрайт объекта вертикально при повороте камеры, нужно при рисовании спрайта указать отрицательный угол камеры. т.е. image_angle = -global.z; Как это работает? Если представим, что сначала рисуем спрайт при угле поворота 0 градусов, затем поворачиваем камеру на +45 ( влево ), то чтобы "выпрямить" объект, мы его повернем при отображении на отрицательный угол -global.z, т.е. вправо  2. Практика:Собираем воедино всю полученную информацию и создаем проект. Добавляем 3 спрайта: 1 - спрайт куба, 2 - спрайт поверхности ( земли, пола ), 3 - какой нибудь "стоячий" 2d спрайт Устанавливаем origin: middle center для спрайта куба, bottom center для "стоячих" спрайтов Создаем 3 объекта: o_main, o_cube, o_stone ( тот самый "стоячий" ). Также у нас в проекте должны быть 4 скрипта: прошу прощения за пробелы в круглых скобках, привык так писать(Рисуем куб, основываясь на имеющихся знаниях. var axis_x = lengthdir_x( 1, global.z-90 ); var axis_y = lengthdir_y( 1, global.z-90 );
//рисуем крышку куба draw_sprite_ext( sprite_index, 0, x+axis_x*cube_height, y-axis_y*cube_height, image_xscale, image_yscale, direction, image_blend, image_alpha );
if( global.z < 360 && global.z > 180 ) { //рисуем правую стенку draw_sprite_pos( sprite_index, 1, x -32 + 64 , y - 32, x -32 + ( axis_x * cube_height ) + 64 , y - 32 - ( axis_y * cube_height ) , x -32 + ( axis_x * cube_height ) + 64 , y - 32 - ( axis_y * cube_height ) + 64, x -32 + 64, y - 32 + 64, image_alpha ); }
if( global.z < 270 && global.z > 90 ) { //рисуем левую стенку draw_sprite_pos( sprite_index, 1, x -32 , y - 32, x -32 + 64, y - 32, x -32 + ( axis_x * cube_height ) + 64, y - 32 - ( axis_y * cube_height ), x -32 + ( axis_x * cube_height ), y - 32 - ( axis_y * cube_height ), image_alpha ); }
if( global.z > 0 && global.z < 180 ) { //рисуем верхнюю стенку draw_sprite_pos( sprite_index, 1, x -32 , y - 32, x -32 + ( axis_x * cube_height ), y - 32 - ( axis_y * cube_height ), x -32 + ( axis_x * cube_height ) , y - 32 - ( axis_y * cube_height ) + 64, x -32 , y - 32 + 64 , image_alpha ); } if( global.z >= 0 && global.z < 90 || global.z >270 ) { //рисуем нижнюю стенку draw_sprite_pos( sprite_index, 1, x -32 , y - 32 + 64, x -32 + 64, y - 32 + 64, x -32 + ( axis_x * cube_height ) + 64, y - 32 - ( axis_y * cube_height ) + 64, x -32 + ( axis_x * cube_height ), y - 32 - ( axis_y * cube_height ) + 64, image_alpha ); }
Все что тут написано в общем, так или иначе объяснялось выше. Мы сначала рисуем крышку нашего куба, далее делаем проверку поворота камеры, чтобы рисовать только те стены, которые мы можем увидеть. Рисуем стены. Хочу повторить что global.z -90 в lengthdir'e необходимо для правильной отрисовки стен. Наш маленький супер-полезный скрипт "сортировки по глубине". var axis_x = lengthdir_x( 1, global.z -90 ); var axis_y = lengthdir_y( 1, global.z -90 );
depth = -(y * axis_y) + (x * axis_x);
Эти расчеты тоже разбирались, так что говорить про них не буду. Поворачиваем спрайт вертикально. Для объектов с 2d спрайтами. draw_sprite_ext(sprite_index, image_index, x, y, image_xscale, image_yscale, -global.z, image_blend, image_alpha);
Тут мы ограничиваем угол камеры чтобы он не выходил за пределы 360-ти градусов. //ограничиваем global.z 0-359 if (global.z < 0) { global.z = 359; } if (global.z > 359) { global.z = 0; }
//поворачиваем камеру camera_set_view_angle(view_camera[0],global.z);
Присваиваем объектам свои спрайты, размещаем объекты на карте. Также в комнате нужно создать view. Убираем стандартный фон в комнате, либо нужно установить для него большой depth 1000000000 например И создаем тайлсет с спрайтом поверхности. Назовем его t_groundВ объекте o_cubeВ create объявляем переменную cube_height = 45;
В step запускаем скрипт "сортировки" scr_depth_3d();
В draw отрисовываем куб scr_draw_cube_3d();
В объекте o_stoneВ step запускаем скрипт "сортировки" scr_depth_3d();
В draw отрисовываем вертикально спрайт scr_draw_sprite_3d();
В объекте o_mainВ create пишем x = -5*64; y = -5*64;
display_reset(8, false);
global.z = 0; global.ground_layer = layer_create(100000000); global.ground_tilemap_layer = layer_tilemap_create( global.ground_layer, x-32, y-32, t_ground, room_width, room_height );
for( var i = 0; i < 35; i++ ) { for( var j = 0; j < 35; j++ ) { tilemap_set_at_pixel( global.ground_tilemap_layer, 1, x+i*64, y+j*64 ); } }
Тут я заполняю комнату тайлами. Включаю anti aliasing на 8. Объявляю global.z = 0 В step пишем логику вращения камеры + вызываем скрипт обновления камеры if( keyboard_check( ord("E") ) ) { global.z-=1; scr_update_camera(); }
if( keyboard_check( ord("Q") ) ) { global.z+=1; scr_update_camera(); }
Также прилагаю к уроку архив с проектом gms2 На этом все. Теперь можно запустить проект. Надеюсь у Вас все получилось. шо-то я устал.
|