Руководства по game maker

Если вы любите игры, несомненно задавались вопросом о том, как их делают. Если у вас есть (или будет) желание делать игры, но нет опыта, в этой статье я расскажу о том, как это лучше начать.

Я хотел бы рассказать об игровом движке Game Maker и разместить несколько публикаций, в которых мы напишем клон не сложной игры, например, Plants vs Zombies. Возможно, добавим поддержку геймпада и сделаем, например, Android-версию.

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

Вступление

Game Maker — это невероятно простой игровой движок, позволяющий создать игры для большого числа платформ — Windows, Mac OS X, Ubuntu, Android, iOS, Tizen, Windows Phone, Windows 8, PlayStation 3, PS 4, PS Vita, Xbox One и HTML 5. Есть поддержка SteamWorks. В случае успеха вашей игры, портирование на другую платформу сложной задачей не будет.

Скорость разработки даже при скромных знаниях и минимальной мотивации субъективно быстрее, чем на других движках. Установка и настройка для начинающих максимально проста и не требует особых знаний. Компиляция под другие платформы не требует смены кода игры и осуществляется одним кликом (ну почти).

YoYoGames — компания, создавшая Game Maker, недавно была приобретена Playtech, что дает уверенность в том, что Game Maker продолжит развиваться. Анонсированный Game Maker 2.0 вероятно будет еще более дружественным и простом, а также логично предположить, что будет обладать еще большими возможностями. Как пишут в пресс-релизе, GM 2.0 — одна из причин покупки компании.

В этой статье я кратко расскажу о Game Maker и мы сделаем простой набросок будущего проекта.

Для кого этот движок и с какой целью его еще можно использовать?
Для всех. Цель — любая 2D игра. Однако для тех, для кого программирование не родная стихия, а так же для быстрого прототипирования и создания игры с минимальными усилиями для любого желающего делать игры и/или заработать на них, Game Maker подойдет идеально.

Плюсы Game Maker

— простое вхождение;
— знакомый всем по Java/C/C#… синтаксис;
— возможность легкой компиляции на разные платформы;
— активное сообщество, которое за многие годы уже решило много проблем и написало код за вас;
— стандартный функционал, благодаря которому не нужно самому писать большое количество кода;
— расширяемость через extension’ы;
— справка (F1) очень простая и удобная с отличными объяснениями и примерами.

Минусы Game Maker

— платность (когда вы дорастете до публикации игры, придется купить лицензию);
— нет автоподстановки пользовательских переменных, только для стандартных и скриптов;
— высокая стоимость максимальной лицензии (впрочем, не всем нужны прямо все модули);
— техподдержка (дважды обращался в техподдержку, быстрее чем через 2 недели мне не отвечали);
— нет возможности авторефекторинга.

Теперь к созданию игры. Я думаю, установить Game Maker и создать пустой проект проблемой не является. Вообще для начала хорошо было бы продумать весь функционал, нарисовать схемки, продумать монетизацию и т.д., но это не является целью статьи, так что я покажу вам способ создания проекта для начинающего разработчика игр.

Кратко пробежимся по структуре проекта:

  • Sprites — папка с спрайтами(изображения, анимации);
  • Objects — объекты со своими заготовленными событиями (например, создание, отрисовка, клик и т.д.);
  • Rooms — игровые комнаты (экраны). Для каждого экрана нужно делать свою комнату. Очень удобно;
  • Background — фоны, которыми можно залить комнату. Так же используется как tile set’ы

Остальное нас пока не интересует.

Что такое спрайт в Game Maker?

Это изображение/анимация, которые используются в игре. Они обладают своей маской, формы и размеры которой можно менять. Маска — это область изображения, которая реагирует на события столкновения объектов (если этот спрайт присвоен какому-то объекту), кликов по нему. Можно задать точку отрисовки (Origin) — например, от центра, угла или любой другой точки.

Так же для спрайта можно можно задать Texture Group. Нужно для оптимизации отрисовки (например, незачем держать в памяти texture pages с изображениями, которые используются на экране меню, когда у нас сейчас игровой экран). Для каждой Texture Group можно задать платформу, на которой они будут действовать. Например, для Android можно иметь менее детальные изображения, чем для Windows 8 планшетов.

Что такое объект (object) в Game Maker?

Это описание некоторой сущности, обладающая своими методами (функциями). Каждый объект рисует себя сам (если не задано иное), реагирует на стандартные события — нажатия клавиши, клика по спрайту и т.д… По аналогии с ООП — это класс (class).

Что такое инстанс (instance) в Game Maker?

Если объект — это просто описание сущности, то инстанс — это экземпляр объекта, его реализация в самой игре. Создав инстанс вы даете ему жизнь и теперь все события, описание которых есть в объекте начнут реагировать.
По аналогии с ООП — это объект (object).

Первое, что необходимо сделать — создать новую комнату (на левой панели правый клик на Rooms — Create Room). Назовем её rm_game. Зададим размеры окна во вкладке Settings — Width — 800, Height — 480, Speed — 60. Т.е. игра у нас будет происходить в окне 800х480, fps будет не превышать и стремиться к 60 кадрам. Сохраняем, закрываем.

Добавим несколько спрайтов. Правой кнопкой по папке Sprites -> Create Sprite. Назовем его spr_unit_shooter, загрузим картинку (есть на гитхабе в конце статьи), например, размера 54х54 и отцентрируем (кнопка Center). Кнопка «OK» и данные сохранились.

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

По принципу, аналогичному со спрайтами и комнатами, создаем пустой объект. Назовем его o_unit_parent и больше пока с ним ничего не делаем. Теперь создадим o_unit_shooter и в графе Parent выберем o_unit_parent. Зададим ему спрайт — spr_unit_shooter. Для этого воспользуемся кнопкой, которая находится под именем.

Называть спрайты, объекты, комнаты и т.д. можно как вам удобно, но для того, чтобы потом не путаться, лучше сразу называть вещи своими именами, например, спрайты с приставкой spr_, объекты obj_ или o_, скрипты — scr_ и т.д.

Теперь, каждый раз, когда вы будете создавать объект o_unit_shooter в комнате, он будет сам рисовать выбранный вами спрайт (конечно, если вы не переопределите это кодом).

Спрайт можно задавать и программно, но в таком случае он не будет отображаться в превью Project Structure слева. Теперь добавим событие, которое будет срабатывать при создании инстанса объекта. В этом событии нужно задать начальную инициализацию переменных, если они имеются. Нажмем Add Event. Как видите Game Maker позволяет каждому объекту отлавливать большое число событий. Нас интересует — Create.

Как видите справа в контейнере Actions в нескольких вкладках есть огромное количество drag’n’drop элементов, с помощью которых в теории можно создать совершенно полноценную игру не написав ни строчки кода. Но это для извращенцев и вероятно в Game Maker 2.0 этот ненужный функционал наконец уберут.

Перейдем по вкладку Control перетащим или сделаем правый клик по иконке Execute code. Откроется текстовый редактор, в котором и можно размещать игровую логику.

Как вы помните, юниты должны с определенным периодом стрелять. Сделать это можно очень легко. В событии Create напишем этот код: alarm[0] = room_speed * 2;
Это означает, что мы запускаем alarm под номером 0, который сработает через room_speed*2 шагов(кадров). room_speed у нас равно 60, что примерно равно секунде. Так что alarm[0] сработает через 120 кадров(2 секунды). alarm — это функция, а точнее событие объекта, она срабатывает как только счетчик шагов дойдет до 0. Как и все другие событие оно добавляется через Add event. Теперь нужно прописать логику, которую мы добавим в alarm[0], но прежде давайте создадим то, чем будет стрелять наше растение.

Создаем новый спрайт spr_bullet, размером 16х16 и центрируем. Теперь создаем новый объект o_bullet и задаем ему только что созданный спрайт. В событии Create добавляем код hspeed = 7; точно так же как и с предыдущим объектом. Этой строчкой мы задаем, что объект будет двигаться со скоростью 7 по горизонтали (hspeed = horizontal speed, если кто не понял). Это встроенное свойство каждого объекта. Присвоив ему ненулевое значение, этот объект начнет двигаться на заданное количество пикселей(в нашем случае по 7 вправо) каждый шаг(Step). Если мы зададим hspeed = -7; — объект будет двигаться по -7 пикселей каждый шаг, т.е. будет двигаться справа налево.

Все, возвращаемся к объекту o_unit_shooter и создаем новое событие — Alarm 0. Код, который мы напишем в этом событии как раз и будет срабатывать когда запущенный счетчик, который мы создали в событии Create. В событии Alarm 0 мы и будем создавать «пули» (в оригинале — горох), которыми стреляет растение. Добавим такой код:

/// shoot
var b = instance_create(x + sprite_width/2, y, o_bullet);
b.depth = depth + 1;
alarm[0] = room_speed * 2;

Разберем этот код.

/// shoot — это просто комментарий, который будет отображаться при переходе на событие. По-умолчанию показывается — «Execute piece of code», что не очень-то информативно. Так что рекомендуется писать такие комментарии, чтобы не тратить время на переход в редактор кода.
var b = instance_create(x + sprite_width/2, y, o_bullet);
var b — мы объявляем локальную переменную, которая будет доступна исключительно в этом событии. После завершения события память освободится и обратиться к этом переменной вы не сможете.
instance_create(x + sprite_width/2, y, o_bullet); — так мы создаем новый экземпляр объекта и помещаем его в координаты по x: x + sprite_width/2, по y — y. В данном случае x и y — это координаты материнского объекта — o_unit_shooter. o_bullet — это тот объект, который мы создаем.
b.depth = depth + 1; — эта строка означает, что только что созданный экземпляр o_bullet будет находится на 1 слой ниже чем o_unit_shooter.
Последняя строка означает, что мы снова запускаем alarm[0] — растение же должно постоянно стрелять.

Как вы помните, в оригинале можно расставлять растительность только в определенных ячейках. Чтобы визуально было понятно в каких пределах можно поставить растение, создадим фон и зальем им нашу комнату. Правой кнопкой по Backgrounds — Create Background — Load Background, выбираем нужную картинку, скажем, 64х64 пикселя, обзываем bg_grass. Переходим в нашу комнату (rm_game), вкладка Backgrounds, выбираем созданный секунду назад фон. Ставим галочки, если не стоят как на изображении.

Теперь нам нужен какой-то стартовый объект, который будет делать начальную инициализацию. Создаем новый объект и называем его, например, o_game. Пусть этот объект и реагирует на клик по полю. Для этого добавим событие — Mouse -> Global mouse -> Global left released. Обычное mouse-событие означает непосредственный клик по объекту, но так как o_game не имеет своего спрайта+маски и т.к. нам нужно чтобы игрок мог кликнуть по любой точке игрового поля нужно отлавливать все события клика. Именно это и делает Global Mouse. Global left released означает, что где-то внутри игрового окна был сделан клик мышью или тач на сенсорном экране(событие срабатывает когда отпустили палец).

Добавим этому событию такой код:

var tBgWidth = background_get_width(bg_grass);
var tBgHeight = background_get_height(bg_grass);
var iX = mouse_x - mouse_x % tBgWidth + tBgWidth;
var iX = mouse_x - mouse_x % tBgWidth + tBgWidth/2;
var iY = mouse_y - mouse_y % tBgHeight + tBgHeight/2;

if (instance_position(iX, iY, o_unit_parent) != noone){
   exit;
}

instance_create(iX, iY, o_unit_shooter);    

Точку с запятой после операции можно и не ставить, логика кода от этого не меняется и ошибок не вызовет. Но если можно ставить, почему бы и не сделать это. Да и привычнее.

В первых четырех строках мы объявляем локальные переменные. background_get_width, background_get_height — встроенные функции, возвращающие width и height нашего фона. Как видите эти данные нам понадобятся для того, что бы просчитать iX и iY. iX и iY — это будут координаты, в которых мы создадим экземпляр объекта o_unit_shooter. mouse_x, mouse_y — встроенные в Game Maker глобальные переменные (т.е. те, к которым мы может обратиться из любого места), хранящие текущие координаты курсора мыши (пальца). Т.к. мы работаем в событии Global left released, в них хранятся последние координаты где пользователь отпустил левую кнопку мыши (отпустил палец). Математические операции, результат которых присваиваются переменным iX, iY нужны для просчета координат, в которых экземпляр объекта o_unit_shooter будет находится ровно по средине ячейки фона bg_grass. Т.е. помните, что в Plants Vs Zombies растение нельзя поставить где угодно, только в определенной точке, но при этом кликнуть-то можно где угодно и растение поставится как раз в нужном месте. Этим и занимается весь код выше.

Проверка instance_position (iX, iY, o_unit_parent) != noone означает, что мы смотрим находится ли по координатам iX, iY любой инстанс (экземпляр объекта), родительским объектом которого является o_unit_parent. По скольку у нас сейчас только один наследуемый юнит — o_unit_shooter, то мы проверяем, нет ли экземпляров o_unit_shooter на игровом поле, но пишем o_unit_parent в проверке для того, чтобы код срабатывал и тогда, когда мы добавим новые пользовательские юниты. noone (от «no one») — некий аналог null в других языках.

exit — код, который обрывает выполнение события. Т.е. если в координатах iX, iY какой-то юнит уже есть, срабатывает exit и инстанс o_unit_shooter не создается, т.к. мы прерываем выполнение всего последующего кода. Это нам нужно, чтобы в одной ячейке не могло стоять 2 пользовательских юнита.

Что ж, пришло время добавить первого врага. Создаем новый объект и опять же создадим базовый родительский объект. Назовем o_enemy_zombie и o_enemy_parent, который будет ему родительским. Создадим спрайт spr_enemy_zombie, отцентрируем и присвоим его o_enemy_zombie.

По сколько свойством всех врагов является движение в сторону растений, то создадим в o_enemy_parent в событии Create этот код:

cHspeed = -4;
hspeed = cHspeed;
HP = 10;
canAttack = true;

cHspeed — это пользовательская переменная, значение которой мы присваиваем hspeed, с которой мы уже встречались. Почему просто не написать hspeed = -4; — увидите потом.

Ранее мы объявили пользовательские переменные через конструкцию var, но здесь мы этого не делаем. В чем же разница между cHspeed = -4; и var cHspeed = -4;?
Все просто — в первом случае переменная будет доступна из любой точки кода этого объекта и к ней можно будет обратиться из любого другого объекта, но только не забыв упомянуть, к какому именно объекту мы обращаемся. Сейчас вникать в это необязательно. Помним то, что эта переменная существует все время существования инстанса объекта с тех пор, как она объявлена. В случае же с var cHspeed = -4; она будет доступна только на время действия события, в котором она создана.

На самом деле к ней тоже можно обратиться из другого объекта, но в случае если вы обратитесь к ней из другого объекта в момент, когда событие, в котором она создана уже закончилось, это вызовет ошибку — знакомый всем null pointer, ибо из памяти она уже выгружена.

Если сам не нравятся функции hspeed, wspeed вы можете сами их реализовать изменяя значение x или y в событии Step. Эти функции просто делают это за вас.

HP — это еще одна переменная, в которой мы будем хранить количество очков жизни врагов. Этой переменной будет «владеть» каждый инстанс, но ведь максимальное количество очков жизни у разных типов врагов разные, т.е. нужно как-то переопределить/перезадать это значение. Либо можно задать всем врагам одинаковое количество жизней, скажем, 100 и ввести понятие defence от которой будет зависеть получаемый врагом урон, но сейчас нету смысла усложнять, верно? Так что обойдемся только одной переменной — HP.

Запомните, gml — язык, используемый в Game Maker регистрозависимый, HP, hP, Hp и hp — будут разными переменными.

canAttack — просто переменная, которой мы присваиваем значение true(истина). Пока просто напишем и забудем о ней.

Раз у нас значение HP у каждого врага будет разное, нужно как-то переопределить это значение. Это очень-очень просто. Переходим к объекту o_enemy_zombie, создаем реакцию на событие Create и пишем код:

event_inherited();
HP = 20;

Функция event_inherited(); и занимается наследованием. Т.е. теперь o_enemy_zombie выполнит код:

cHspeed = -4;
hspeed = cHspeed;
HP = 10;

Который «импортирует» эта функция, а затем значение выполнится строка — HP = 20;
Т.е. по факту на конец события Create объект o_enemy_zombie будет иметь такие свойства:

cHspeed = -4;
hspeed = cHspeed;
HP = 20;

Если же мы забудем о функции event_inherited(); или забудем объекту o_enemy_zombie указать родительский объект, враг двигаться не будет, при попытке обратиться к переменной cHspeed этого объекта появится ошибка.

Великолепно, если мы захотим создать еще один тип врага, в событии Create мы напишем тоже самое, изменив на нужно количество HP:

event_inherited();
HP = 100;

Раз у зомби есть очки жизни, они должны быть и у растения. Добавьте самостоятельно в событие Create объекта o_unit_parent код HP = 20; и строку event_inherited(); в событие Create объекта o_unit_shooter.

А вы знаете?

Если вам не нужно ничего переопределять и дописывать в событии Create, добавлять код event_inherited(); без другой логики в событие не нужно — за вас это сделаем сам Game Maker. Тоже касается любых других событий, не только Create.

Отлично, наш зомби теперь идет, однако его не берут пули и растения его не тормозят. Решим сначала первую задачу. Перейдем в o_bullet и создадим новую реакцию на событие — Add Event -> Collision -> o_enemy_zombie. Это событие будет вызываться когда o_bullet и o_enemy_zombie врежутся друг в друга. Коллизия проверяется по маске, о которой вы читали в начале статьи. Добавим код:

with(other){
  HP -= 5;
  if (HP <= 0){
     instance_destroy();
  }
}

instance_destroy();

Это очень интересный момент. other — это инстанс объекта, с которым в этот момент события происходит коллизия. Естественно, т.к. этот код находится в событии столкновения с экземпляром объекта o_enemy_zombie, то в other и будет только инстанс o_enemy_zombie.

С помощью конструкции with(){} мы обращаемся к этому элементу other. Все, что происходит внутри {} касается исключительно этого экземпляра объекта. Таким образом, HP -= 5; — это вычитание 5 очков жизни из врага. В if (HP <= 0){} мы сравниваем количество очков жизни тоже именно у этого объекта. Помните я немного выше говорил про разницу между обычным объявлением переменной и с переменной через var. Вот этот пример должен вам окончательно прояснить ситуацию. Т.к. переменная HP у нас объявлена не через var, то она доступна в любой момент времени. Так что с помощью конструкции with мы можем к ней получить доступ. Альтернативный способ обращения к переменной другого объекта выглядел бы так:

other.HP -= 5;
if(other.HP <= 0){
    with(other){
		instance_destroy();
	}
  }
}
instance_destroy();

Но так обращаться к переменным менее удобно, особенно, если логики будет больше, но тем не менее в некоторых случая применимо.

Не забывайте, если вы объявили переменную не в событии Create, а в коде вы обращаетесь к ней до того, как она объявлена, это вызовет ошибку, если вы попытаетесь считать какие-то данные из нее.

Не нужно обладать большими знаниями английского, что бы понять, что функция instance_destroy(); удаляет этот экземпляр объекта(инстанс).

Таким образом весь этот код означает, что при коллизии мы отнимаем 5 очков жизни у зомби и если у него их становится 0 или меньше, то мы его уничтожаем. Независимо от результата в конце мы удаляем нашу пулю. Проще некуда. Вообще, наверное, лучше было бы заставить зомби самостоятельно следить за своим здоровьем, но пока нас это не интересует. Но это уже

другая история

вопрос оптимизации.

Было бы неправильно, если бы наши зомби могли только получать урон. Нужно же добавить возможность наносить урон. Прежде всего добавим новую переменную в событие Create объекта o_enemy_parent

isActive = true;

Пришло время ознакомится с событием Step, о котором я ранее рассказывал. Данное событие срабатывает каждый кадр. Все просто. Если room_speed равно 60, то данное событие будет срабатывать примерно 60 раз в секунду. Добавим этот код в событие Step -> Step объекта o_enemy_zombie.

if (!isActive) exit;

var tBgWidth = background_get_width(bg_grass);
var leftCellCenterX = x - x % tBgWidth - tBgWidth/2;

var frontEnemy = instance_position(leftCellCenterX, y, o_unit_parent);
if (frontEnemy != noone){
    var frontEnemySprtWidth;
    with(frontEnemy){
        frontEnemySprtWidth = sprite_width;
    }
    if (x - sprite_width/2 - frontEnemy.x - frontEnemySprtWidth/2 <= 12){
        hspeed = 0;
        if (!canAttack){ 
           exit;       
        }    
        canAttack = false;
        alarm[0] = room_speed * 1.2; // cantAttack -> true;
        with(frontEnemy){
           HP -= 5;
           if (HP <= 0){
              instance_destroy();
           }
        }
    }
   
}else{
   hspeed = cHspeed;
}

Ничего страшного в нем нет почти все конструкции вам уже знакомы.
if (!isActive) exit; — если объект не активен, т.е., скажем, отдыхает/перезаряжается/делает замах, данное событие выполнятся не будет. В следующих двух строках мы получаем координаты центра ячейки, находящейся слева от той, на которой сейчас находится центр нашего instance(помним, что x — возвращает координаты Origin-точки, а она у нас выставлена как раз по центру спрайта). Дальше мы смотрим, находится ли по координатам (leftCellCenterX, y) пользовательский юнит. Если там что-то есть происходит последующая логика, но о ней через секунду, если же там ничего нет, мы присваиваем hspeed значение переменной cHspeed, которую мы, помните, создаем в событии Create. Вот тут она и пригодилась. Смысл за этим скрывается такой — если наш зомби остановился для того, чтобы атаковать и уничтожил растение, нужно чтобы он продолжил свой путь. Можно, конечно, не вводить переменную cHspeed, но тогда нужно будет вспомнить где вы задаете скорость движения, а это забывается.

Это в случае если на пути зомби ничего нет, теперь же возвращаемся к моменту, когда нам предстоит бой. Первые же строки оказываются очень интересными, с подвохом. Дело в том, что объявив локальную переменную frontEnemySprtWidth мы в инстансе frontEnemy присваиваем ей значение. Знакомые с программированием, скажут, но ведь в таком случае мы обращаемся к переменной frontEnemySprtWidth не нашего зомби, а к переменной с таким же именем, но инстанса frontEnemy. Так да не так, дело в том, что локальные переменные(объявленные через var) становятся видимыми внутри этого события везде, даже изнутри инстанса frontEnemy. Таким образом в коде ошибки нет, мы действительно обращаемся именно к той переменной, которая была объявлена локальной внутри зомби. Если вы не поняли этого момента поэкспериментируйте или прочтите справку, там все прекрасно объяснено, а мы идем дальше.
Мы присвоили frontEnemySprtWidth значение длины(width) спрайта юнита пользователя(растения), который находится на ячейку левее нашего зомби. Вы скажете, а зачем нам городить такую сложную для первого понимания конструкцию, если можно обойтись var frontEnemySprtWidth = sprite_get_width(spr_unit_shooter);. Ответ прост — это сейчас у нас одно растение и мы знаем к какому спрайту обратиться, но при добавлении новых типов юнитов(подсолнухи и т.д.), придется городить громоздкую конструкцию switch, чтобы узнать что же за объект впереди нас, а так довольно просто решается эта проблемка.

Дальше мы проверяем, если расстояние между крайней правой точкой пользовательского юнита и крайней левой точкой нашего зомби меньше 12 пикселей, то мы останавливаем нашего зомби, проверяем может ли наш зомби атаковать(проверяем значение ранее созданной в событии Create объекта o_enemy_parent переменной canAttack), продолжается выполняться код, в котором мы говорим, что атаковать теперь уже нельзя и что следующий раз это можно будет сделать через room_speed * 1.2 кадров(через 60*1.2) — это мы делаем в alarm[0](сами добавьте его в соответствующее событие(Alarm 0) объекта o_enemy_parent, где напишите код canAttack = true;). Если атаковать можно, отнимаем у инстанса растения 5 очков жизни и проверяем, живо ли оно еще, если нет — уничтожаем.

Ну вот и отлично враг готов — он двигается, атакует и продолжает движение, если уничтожил растение, но у него есть один недостаток — его не существует. Мы создали только описание нашего врага, теперь нужно же помещать зомби на игровое поле. Возвращаемся в событие Create объекта o_game. Добавим код
alarm[0] = room_speed; // generate enemies

Т.е. через 60 кадров сработает Alarm 0 и будет создан зомби, правильно? Нет. Мы же не создали логики для этого Alarm. А код тут тоже простой:

var tBgHeight = background_get_height(bg_grass);
var eY = irandom(room_height - room_height % tBgHeight);

eY = eY - eY % tBgHeight + tBgHeight/2;
instance_create(room_width + sprite_get_width(spr_enemy_zombie)/2 + 1, eY, o_enemy_zombie);

alarm[0] = room_speed * 3;

Все просто — мы не будем усложнять и просто каждые 3 секунды(60 кадра * 3) создаем инстанс o_enemy_zombie по координатам X: room_width + sprite_get_width(spr_enemy_zombie)/2 + 1 т.е. за ровно на один пиксель правее, чем граница экрана, т.е. зомби изначально видно не будет и Y — случайная ячейка. room_width и room_height, как вы уже поняли, это width и height нашей комнаты. Т.е. 800 и 480 соответственно.

Это все отлично, но инстанс объекта o_game тоже кто-то должен создать иначе весь эпизод смысла не имеет. Но наш завершающий шаг очень прост — переходим в комнату rm_game -> Objects -> выбираем в менюшке o_game и помещаем его где попало в комнате. Альтернативный вариант выглядит так — вкладка Settings -> Creation Code( — это код, который будет срабатывать когда мы переходим в эту комнату). Добавляем строку instance_create(0,0, o_game);

Координаты можно любые. Теперь мы можете задать вопрос, а как Game Maker определит, что нужно запускать комнату rm_game или «а что если у нас будет много комнат, с какой Game Maker начнет?». Все как всегда просто — самая верхняя комната запускается первой(их порядок можно менять перетягивая мышкой). Сейчас она у нас одна потому сразу она же и запустится.

Теперь у нас должно получиться что-то такое:

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

В этом эпизоде мы ознакомились с базовыми понятиями Game Maker, использовав как можно больше возможностей. Некоторые моменты сделаны не очень рационально, их можно и нужно переделать, но не все сразу. Для начального понимания происходящего, я считаю, лучше все же писать по аматорски.

Как видите по уроку, в некоторых планах текущая версия Game Maker не идеальна, многое приходится держать в голове, зато в Game Maker проще делать все остальное. Небольшое неудобство стоит того.

Исходный код

В следующем эпизоде:

— /теория/ скрипты
— /теория/ отладка
— /практика/ юнит подсолнухи
— /практика/ мана(солнышки)
— /практика/ генерация врагов волнами
— /практика/ газонокосилки
— /практика/ новые юниты зомби и растений
— /теория + практика/ примитивный интерфейс

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

Designing Games
with
GameMaker

Version 8.1
by

YoYo Games Ltd.

The documentation for GameMaker is divided into four parts:

Using GameMaker

This section describes the basic use of GameMaker.
It explains the global idea behind the program and describes
how to add sprites, background and sounds and how to define
objects with events and actions and how to add them to
rooms.

The following topics exist in this section:

Introduction
Installation
Upgrading from the Lite Edition
Getting Started
The Global User Interface
Defining Sprites
Sounds and Music
Backgrounds
Defining Objects
Events
Actions
Creating Rooms
Distributing your Game

Advanced use

This section describes the more advanced aspects of GameMaker.
It deals with paths, fonts, time lines, scripts, and techniques for
creating tiled rooms and using views in rooms.

The following topics exist in this section:

Advanced User Interface
More about Sprites
More about Sounds and Music
More about Backgrounds
More about Objects
More Actions
Constants
Trigger Events
Including Files
More about Rooms
Fonts
Paths
Time Lines
Scripts
Extension Packages
Exporting and Importing Resources

Polishing your game

This section deals with how to turn your project into a finished
game. It describes how to add help information to your game, how
to set the various options for your game and how to create stand-alone
games that you can distribute to others and can be run without the
need for GameMaker.

The following topics exist in this section:

Game Information
Global Game Settings
Speed Considerations

The GameMaker Language

GameMaker contains a built-in programming language.
This programming language gives you much more flexibility
and control than the standard actions. This language we
will refer to as GML (the GameMaker Language).
In this section we describe the language GML and we give
an overview of all the (close to 1000) functions and
variables available to control all aspects of your game.

The following topics exist in this section:

Language overview
Computing things
Game play
User interaction
Game graphics
Sound and music
Splash screens, highscores and other pop-ups
Resources
Changing resources
Files, registry, and executing programs
Data structures
Creating particles
Multiplayer games
Using DLL’s
3D Graphics

() translation by (you can also view the original English article)

GameMaker: Studio is a full game development tool, featuring a level editor, asset manager, code editor, and its own scripting language known as GameMaker Language (GML). Earlier versions of GameMaker were were very basic, and many people will remember them as being mostly for total beginners — to make a game commercially with them would have seemed like a joke. Things are different now, with several commercial successes, including some very high profile games.


Who is GameMaker: Studio For?

The master collection of GM:S features cross platform compatibility for desktop, HTML5, and mobile devices (both Android and iOS). It also has source control integration and monetization options (such as ads and in-app purchases). The total cost of the master collection is around $800 as of the time of this writing. This makes it perfect for:

  • Anyone looking to do cross platform development
  • Indie development teams with a small budget

The barrier to entry for GM:S is low due to the inclusion of a drag-and-drop interface. As such, it’s a fantastic tool for people with very little programming experience to get their feet wet; this interface is a great way to learn program flow and some basic logic.

Due to its management features, GM:S allows developers to get a very basic game up and running quickly, which is great for game jams and making playable prototypes.


What It’s Good At

GM:S is very good at asset management, incorporating assets into code, providing an easy way to modify game object logic, and event-based programming.

Asset Management

Once the developer has a sprite created, adding it to GM:S can be done in a few clicks. After the sprite is imported, modifications can be made from inside GM:S.

Creating a sprite

Creating a sprite.
Modifying a spriteModifying a spriteModifying a sprite
Modifying a sprite.

Incorporating Assets Into Code

Once an asset is imported, its properties (the dimensions of an image, the volume of a sound effect, and so on) can be accessed from code, and it can be assigned to a game object. This makes creating game objects very simple, and is great for getting things up and running very quickly.

Modifying Game Object Logic and Event Based Programming

The game object editor is a great learning tool for those new to game development, and provides an easy way to modify game object logic. As you can see from this screenshot, GM:S allows you to write code for specific events:

Modifiying game object eventsModifiying game object eventsModifiying game object events

Modifiying game object events.

Who Is It Not For?

  • People looking to create a fully featured game with the press of a few buttons. Great games will take time.
  • Someone who wants to develop the next great MMO. Networking is still relatively new to GM:S, and there are better tools for MMOs.
  • Programming elitists who demand their language not manage its own memory. GM:S is not C/C++, and isn’t the ultimate performance-centric language. (That’s not to say performance is bad here, just that C/C++ is still the king of that category.)

What It’s Bad At

GML is not an object-oriented language in the strict sense. There are game objects, they have properties, and you can even create parent-child relationships. However, objects have no methods. In order to do an operation on an object, you will need to use its instance ID within a script. This can be confusing at first to those coming from an object-oriented background.

GM:S is capable of 3D, but it isn’t the main focus. There is no 3D editor, there’s no 3D model importer, and the code for getting 3D to work is fairly convoluted. If you are interested in 3D games, I would advise you to use a different tool for now. In the future, 3D may become a higher priority for YoYo Games (the company that owns GM:S), but at the moment, it’s clearly low on the list.


Where Can I Get GameMaker: Studio?

The main site for GM:S is http://www.yoyogames.com/. You can either download the free version or buy one of the licensed versions.

Here’s a comparison of the different versions of GameMaker, taken from the YoYo Games website:

feature comparefeature comparefeature compare

As you can see, the free (Studio) version is fairly limited, but it’s a great way to see the workflow and layout of the tool, and spend some time learning the language. 

Update: The free version of GameMaker: Studio is now the same as the Standard version! For more information, see GameMaker: Studio Goes Free.

The Standard edition is great for solo developers who only plan to develop desktop games; the Professional version is perfect for a small team of developers who are planning to go cross-platform eventually, as they can add the various modules over time after generating some revenue; and the Master Collection is great for small teams who are part of established studios and would like to go cross-platform right from the start of development.

GM:S is also available on Steam, however I would recommend against purchasing it there, as YoYo Games has no way of knowing that you’ve purchased it, and thus the customer service aspect of owning their product is a bit more of a hassle. Also, they will occasionally offer cheap upgrades for those who already own a certain version of GM:S, and they can’t give that same upgrade to Steam owners. Plus, if you buy from Steam then you must be logged into Steam in order to run GM:S, which can be annoying.


Learning GameMaker: Studio

GM:S offers two different ways to make games. The first is called the Drag and Drop interface (DnD for short). It’s quite powerful, and allows for some complex logic to be created. However, it’s not as powerful as the second option: using GameMaker Language (GML for short). GML is a great scripting language that can do everything DND can, and more.

Getting Started

After you’ve downloaded the version of GM:S you feel best fits your needs, you should start by checking out the tutorials that come with GM:S. These can be found under the Tutorials tab after you open GM:S.

The beginning tutorials will mostly show you how to use the drag and drop interface, while the later tutorials begin to cover GML. The nicest part about the included tutorials is that they actually add a window to the interface that walks you through how to create each game, so you don’t need to refer to a web page — it’s all laid out within GM:S for you!

I recommend working through as many of these as you need to, until you feel like you’ve got a solid grasp of the general workflow and tools that GM:S has to offer. You can find additional tutorials on the YoYo games wiki at http://wiki.yoyogames.com/index.php/GameMaker:Studio_Tutorials including some more advanced tutorials.

For the most advanced learning, you can look at the demos under the Demos tab after you start up GM:S. These won’t give you a tutorial window, but they give you access to all the source code used, so you can look through it, run the debugger, and watch what’s happening, so you get a good idea how to use their methods in your own games.

The Manual

The manual for GM:S can be found in the Help menu under Contents…. This should be the first place you look for answers to your problems — if you go straight to the forums, people are likely to give you grief for not just checking the manual. There is also an online manual that can be found at docs.yoyogames.com

The manual from within GMSThe manual from within GMSThe manual from within GMS

The manual, from within GM:S

If you search through both the included manual and the online manual and are still unable to find answers, fear not! There is a great community on reddit’s /r/gamemaker and the official forums. There is also an excellent site full of indie developers, some of whom use GM:S frequently, over at TIG Forums. These communities are full of helpful people, so don’t be afraid to ask your questions!


Extensions

If the built-in functionality of GameMaker isn’t enough for you, don’t worry; it’s extensible! The free version doesn’t allow you to use extensions, but any paid version will allow you to.

What Can Extensions Do?

Extensions add new functionality not originally envisioned by YoYo games. Some examples include:

GiiMote — Allows the developer to integrate WiiMote controls into their game by adding functions that poll the WiiMote’s state (position and button presses).

FX Creator Extension — Makes it easy to create effects such as weather, rays, and water splashes.

Database Interaction via SQL — Lets your game connect to a SQL database, get data back as a string, and then use it in your game. The extension adds functions such as TestDatabaseConnection and ExecuteSQL so you can get the data back in as few as two lines of code.

The one big limitation is that some extensions are incompatible with mobile platforms.

Where to Find Extensions

The best places I’ve found are the official resources site and an unofficial site called GMToolbox.

How to Install Them

  1. You’ll need to download the extension, which should be a .gex file.
  2. Right-click the Extensions folder inside GM:S, and select Add Existing Extension.
  3. This should bring up a dialog box, and in the lower right corner you should see a button that says Install. Click it.
  4. This brings up another dialog box with a list of installed packages (probably empty). To the right of that is a button that says, again, Install. Click it.
  5. This brings up yet another dialog box; navigate to the folder where you saved the .gex file, click that, and click Open.

Learning Resources

Indie Tutorials

Chevy Ray’s Tutorial List — Chevy Ray is the developer behind the Flash game engine FlashPunk, a frequent Ludum Dare competitor, and the developer of several cool games. He’s written several tutorials for GameMaker, and this is his compilation of those that he feels are the best. The tutorials cover topics such as View Scaling, Speed Optimizations, and Parallax Scrolling.

Derek Yu’s Tutorial Series — Derek Yu is a member of TIGSource and the developer of Spelunky. This tutorial series is for an older version of GameMaker, but you can still follow along very easily. It’s a full walkthrough for creating a side scrolling space shooter; as you build it, you’ll learn how game objects work, how to create scrolling backgrounds, how to create sprite fonts, and a host of other great subjects. Easily a must-read.

Other Tutorials and Manuals

Official Tutorials — The official tutorials go over creating several different styles of games (several of them are in 3D, so these tutorials may be especially insightful if that’s what you’re using GM:S for). There is also a tutorial for creating multiplayer games that I’ve found to be one of the best on the web for learning how to do multiplayer in GM:S.

I recommend these for people looking for to develop a specific type of game, and wanting to learn the workflow for developing that type of game, but if you’re looking for a tutorial for a total beginner, I recommend Derek Yu’s.

Also check out the official and unofficial manuals, as they make great reference material.


Going Pro

Several GameMaker games have become major commercial successes, and there are many other polished GameMaker games that are great examples of what is possible with GM:S.

Polished Games

Spelunky — The original version of Spelunky was created with GameMaker; the newer XBLA and new PC version were not. While it’s a commercial success, the version created with GameMaker is free.

A Nation of Wind — This game is a hidden gem, and definitely worth checking out.

Dustforce — Released to Steam, this was not a huge success commercially, but it’s a great game nonetheless!

Commercial Hits

Hotline Miami

Gunpoint

Stealth Bastard Deluxe

Aces of the Luftwaffe


Conclusion

GameMaker: Studio is great for newbies and pros alike. Its great code and asset management features, combined with its relatively low price tag, makes it great for small teams and solo indie developers who have a decent amount of programming experience, and its accessibility and event and action based drag-and-drop system make it great for those with little or no programming experience.

If you want to give it a try for yourself, head to http://www.yoyogames.com/studio/download and get started!

I hope you enjoyed reading this roundup and now have a good idea of how to get started with GM:S. If you feel I’ve missed something, or you’d like some more info, feel free to drop me a comment. Good luck with your game development journey!

Overview

GameMaker Language – Руководство для начинающих.Это руководство познакомит вас с основами GameMaker Language.

Введение

Добро пожаловать! Это руководство предназначено для новичков, у которых практически нет опыта работы с GML или программирования в целом. Он познакомит вас с основами программирования и как работает GML. После этого руководства, вы сможете использовать GML для эффективного создания собственных игр!

Добавьте эту страницу в закладки (Нажмите CTRL + D) так как это руководство довольно длинное, вы сможете закрыть его и вернутся к нему потом. Будет отлично, если вы прочитаете его залпом.

Рекомендую читать его именно там, это руководство было перенесено туда и не будет удалено из Steam!

События


Множество событий на выбор

Вы помещаете код внутри события, и этот код работает в зависимости от типа события, в который вы его поместили. В GameMaker есть много событий, которые вы можете выбрать.

Вот краткое введение в события, которые мы будем использовать больше всего:

Create (Создание)

Код внутри события Create выполняется только один раз: когда экземпляр объекта, запускающий код, сначала создается. Здесь вы можете инициализировать большую часть основных переменных и/или придания движению объекту.

Step (Шаг)

Самое важное и наиболее часто используемое событие – событие Step запускается каждый шаг – если для вашей скорости игры/комнаты установлено значение 30, событие Step будет выполняться 30 раз в секунду. Это можно использовать для вещей, которые должны, повторятся постоянно.

Draw (Рисование)

Это событие используется для отрисовки. Например, такие функции, как draw_sprite, который используется для рисования спрайта, или draw_rectangle, который используется для рисования прямоугольника, работают только в событии Draw. Экземпляр объекта не будет отрисовываться (т.е. встроенный спрайт в сам объект), при условии если в событие Draw “что-то” есть, поэтому чтобы избежать этого – используют draw_self().

Alarms (Таймер)

События таймера запускаются после их установки. Поэтому, если я установил Alarm 0 до 60 в событии Create, код внутри события Alarm 0 будет запущен через 60 шагов.

Collision (Столкновение)

Добавляя событие столкновения, вы можете выбрать объект для создания события. Это событие будет выполняться только тогда, когда экземпляр, запускающий код, сталкивается с любым экземпляром объекта, указанным при создании события столкновения.

Переменные

Переменные – это контейнеры, содержащие некоторые значения/информацию. У них есть имя. Например, переменная с именем player_health может содержать 100, или переменная с именем player_name может содержать имя игрока («Питер», «Линдси» и т. д.). Зависит только от вас, что вы хотите назвать переменными и, что вы хотите хранить внутри них.

Переменная в GML может хранить:

  1. Численные значения – 100, 45.534, -42.2
  2. Строковые значения – “Учитель”, “Питер”
  3. Логические значения – true или false

Например:

Инициализация:

price = 20;

Здесь мы инициализировали переменную с именем price, которая содержит 20 в качестве значения. Если переменная уже была инициализирована ранее, то эта будет изменять ее значение до 20.

Примечание: в GML не обязательно помещать точку с запятой (;) после каждого утверждения. Поэтому не стесняйтесь пропустить её и сосредоточиться на главном коде.

Есть много способов присвоения значения…

price = 4 * 5; price = 40 / 2;

Чтобы увеличить значение…

price += 20;

Чтобы уменьшить значение…

price -= 20;

Чтобы умножить или разделить…

price *= 2; price /= 2;

Использование:

Также вы можете использовать переменные в математических выражениях…

a = 4; b = 5; c = a + b;

Здесь c будет хранить 9 из-за выражения a + b (что означает, что 4 + 5 как a равно 4, а b равно 5).

Различные типы переменных

Локальные переменные
Эти переменные инициализируются ключевым словом var. Они сбрасываются, когда событие было инициализировано в конце. Они могут использоваться только внутри события, если только не инициализированы снова.

var price = 2;

Этот код инициализирует локальную переменную price. Предположим, что событие, в котором находился этот код, было событием Step; то переменная может использоваться только в событии Step. Если вы попытаетесь использовать её без инициализации в другом событии, то она вернет ошибку, поскольку она там не существует.

Переменные экземпляра
Это обычные переменные, которые инициализируются путем присвоения значения.

price = 20;

Доступ к этим переменным возможен во всех событиях объекта/экземпляра, после того, как они был инициализированы.

Глобальные переменные
Это переменные, к которым могут получить доступ все объекты в вашей игре – отсюда и название «global». Существует два способа создания таких переменных:

Инициализация с помощью ключевого слова globalvar…

globalvar price; price = 2;

Как только переменная была инициализирована через globalvar, она может использоваться любым экземпляром, присутствующим в комнате.

или использовать с global. prefix…

global.price = 2;

Таким образом, вам не нужно инициализировать переменную с помощью globalvar, но вы должны использовать global. prefix каждый раз, когда вы хотите использовать эту переменную.

Встроенные переменные

Есть также некоторые встроенные переменные, которые означают что-то особенное в GameMaker. Вот несколько примеров…

Встроенные переменные экземпляра
Это встроенные переменные, которые уникальны для каждого экземпляра. Они также могут быть известны как свойства экземпляра. Вот несколько важных примеров…

x: горизонтальное расположение экземпляра внутри комнаты (в пикселях) y: вертикальное расположение экземпляра внутри комнаты (в пикселях) speed: скорость экземпляра (в пикселях на шаг) direction: направление, в котором экземпляр перемещается (в градусах), по умолчанию: 0 hspeed: горизонтальная скорость (в пикселях/шаг) vspeed: вертикальная скорость (в пикселях / шаг) image_angle: вращение спрайта (в градусах), по умолчанию: 0 image_xscale: горизонтальное масштабирование спрайта, по умолчанию: 1 image_yscale: вертикальное масштабирование спрайта, по умолчанию: 1 image_index: суб-изображения спрайта, который отображает экземпляр image_speed: скорость, с которой спрайт меняет свои суб-изображения sprite_index: спрайт, используемый экземпляром

Вы можете изменять или использовать эти переменные так же, как обычные.

//изменить местоположение на 200, 150 x = 200; y = 150; //сделать спрайт в 2 раза больше image_xscale = 2; image_yscale = 2; //вращение спрайта на 180 градусов (половину) image_angle = 180;

Текст, который появляется после //, является комментарием. Это не влияет на код; он там, чтобы вы могли объяснить, что делает ваш код, или писать важные вещи, которые вы хотели бы запомнить, глядя на ваш код.

Вы также можете написать многострочные комментарии – просто запустите их с /* и закончите с помощью */.

Встроенные глобальные переменные

Эти встроенные переменные, которые являются глобальными для каждого экземпляра.
Вот несколько примеров…

room_speed: количество шагов, выполняемых комнатой за одну секунду, по умолчанию: 30 score: счет в вашей игре, может хранить любое числовое значение, хотя health: здоровье вашего игрока, тоже может хранить любое числовое значение lives: количество жизней, может также хранить любое числовое значение

Вот список всех встроенных переменных в GameMaker.[gamemaker.wikia.com]

Функции

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

function(arg0, arg1, arg2…);

…но если он также возвращает что-то после выполнения действия, и вы хотите сохранить его в переменной, вы делаете это так…

variable = function(arg0, arg1, arg2…);

Функция может и не может содержать аргументы.

Вот несколько примеров…

instance_create_layer(x, y, layer, object); Что он делает: создает экземпляр объекта в позиции x, y внутри слоя instance_create_layer(48, 48, “Instances”, obj_enemy); Что он возвращает: ID экземпляра созданного экземпляра enemy_id = instance_create_layer(48, 48, “Instances”, obj_enemy); draw_sprite(sprite, sub-image, x, y); Что он делает: Рисует суб-изображение спрайта в позиции x, y draw_sprite(spr_ball, 0, x+5, y+5); Ничего не возвращает. random(number); Ничего не делает. Что он возвращает: возвращает случайное действительное число между 0 и числом. speed = random(5);

Условия – оператор if

Условия используются для управления выполнением некоторого кода. Используя условия, вы можете контролировать, работает ли фрагмент кода на основе условий. if оператор являются наиболее часто используемыми условиями. Используя if вы можете убедиться, что часть кода работает только при условии, что само условие или набор условий – истина (true).

Пример

Допустим, вы делаете игру, и вы делаете магазин. Здесь игрок должен купить некоторые улучшения. Первое улучшение – улучшение оружия. Оно стоит 200 монет. Таким образом, игрок может купить его только в том случае, если это условие выполнено, то есть если у них есть как минимум 200 монет. В таком случае мы можем использовать условие if:

if (coins>=200) { //купить улучшение }

Знак > открывается в сторону, которая больше, и = конечно же, означает равно. Итак, проверяя, if coins>=200, мы проверяем, больше ли 200 монет или они равны 200.

Таким образом, игрок может купить улучшение только в том случае, если у него достаточно монет. Но что, если он этого не сделает? Мы должны уведомить его, что ему нужно больше монет. Но это нужно только тогда, когда условие не выполняется. Для этого мы используем else.

if (coins>=200){ //купить улучшение } else{ //уведомить, что недостаточно монет }

Код после else выполняется только тогда, когда предыдущее условие if вернуло false. Поэтому, если у игрока меньше 200 монет, он будут уведомлен об этом.

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

Таким образом, вы можете добавить больше else и добавить разный код для разных условий:

if (condition0){ //code0 } else if (condition1){ //code1 } else if (condition2){ //code2 } else{ //code3 }

Если condition0 истинно, code0 будет запущен, а остальная часть оператора if будет пропущена. Но если condition0 является ложным, оно перейдет к condition1. Если оно истинное, он выполнит code1 и остановится. Но если он тоже ложный, тогда он перейдет в condition2. Если это правда, code2 будет запущен, но если нет, оператор if, наконец, перейдет к последней части и увидит, что нет условия, и выполнится code3.

Применение

В предыдущем примере мы проверили, были ли монеты больше либо равны 200. Но условия могут использоваться многими другими путями.

Проверка равного значения: if (money==400) Для того чтобы это условие было истинным, money должна быть равна 400. Проверка меньшего значения: if (money<50)   Для того чтобы это условие было истинным, деньги должны быть меньше 50 (не более 49,99..) Проверка, что что-то не равно: if (name!=”CURSE”) Если имя игрока CURSE, это условие вернет false. Для того, чтобы это условие работало, name не должно быть равно значению.   Другой пример: if (lives!=3) Верно, только если lives не равно 3. Проверка логического значения на истинность: if (paused==true) или if (paused) Истинно только тогда, когда переменная истинна, здесь это – paused.   Вы можете пропустить часть “== true” и просто ввести имя переменной чтобы проверить, истина ли это. Проверка логического значения на ложность: if (paused==false) или if (!paused) Истинно, если указанная переменная имеет значение false. Восклицательный знак (!) можно использовать в качестве префикса, что бы перевернуть его. Поэтому, если условие ложно, оно вернет true..

Условия и Функции

Функции также могут использоваться внутри условий. Их можно либо проверять как логические значения (возврат true или false), либо через возврат определенного значения (числа/строки).

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

place_meeting()

Функция place_meeting() может использоваться для проверки наличия столкновений между экземпляром, выполняющим код, и указанным объектом/экземпляром в позиции. Например,

код внутри obj_player: place_meeting(x, y, obj_wall);

Эта функция вернет true, если obj_wall сталкивается с obj_player в позиции последнего. Таким образом, чтобы проверить наличие коллизий и выполнить некоторый код, надо поставить эту функцию в условие:

obj_player событие “Step”: if (place_meeting(x, y, obj_wall)){ speed = 0; }

Когда происходит столкновение между obj_wall и obj_player, он устанавливает speed до 0.

instance_exists()

Функция instance_exists() возвращает true, если экземпляр указанного объекта присутствует внутри комнаты.

Событие “Step”: if (instance_exists(obj_player)){ score += 1; }

Вышеприведенный код проверяет, существует ли экземпляр obj_player в комнате, и если это истина то, добавляет 1 к score.

floor()

Функция floor() заполняет число, указанное в его круглых скобках, и возвращает результат. Например, 4.94 станет 4, 1.13 станет 1 и так далее.

if (floor(image_index)==2){ image_index = 10; }

image_index хранит индекс суб-изображения, на котором в данный момент находится спрайт. Суб-изображения находятся в целых числах, но переменная image_index – нет. Поэтому, прежде чем проверять, какой суб-образ включен, вам нужно заполнить переменную.

Условия – оператор switch

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

В операторе switch вы сначала указываете переменную, функцию или комбинацию внутри математическом выражении. Затем вы перечисляете все возможные случаи. Оператор switch вычисляет указанное выражение и переходит к случаю, соответствующему результату. Он выполняет код, следующий за случаем, пока не будет найден разрыв.

Вот пример:

switch(level){ case 1: level_name = “Overworld”; break; case 2: level_name = “Underground”; break; case 3: level_name = “Water World”; break; case 4: level_name = “Castle”; break; default: level_name = “Unknown”; }

В этом примере level – это переменная, которая содержит номер уровня, на котором игрок находится в данный момент. Когда level равен 1, он переключится в case 1. Он будет запускать код, где он устанавливает level_name для «Overworld». Затем он сталкивается с break и останавливает код.

Если вы не используете break перед запуском другого случая, он будет продолжать выполнять все случаи до тех пор, пока не будет найден разрыв.

Аналогично, когда level равен 2, будет выполняться случай 2. То же самое для случаев 3 и 4.

Но что, если level не соответствует ни одному из этих случаев? В такой ситуации switch перейдет к части default и запустит код идущий после него.

Функция repeat

Функция repeat() может повторять набор операторов определенное количество раз и используется так же, как и оператор if. Вот пример:

repeat(5){ coins += 1; }

Вы знаете, что coins += 1: добавляет 1 к переменной coins. Но поскольку мы используем repeat(5) перед ним, оператор будет выполняться 5 раз, в конечном итоге будет добавляться 5 к переменной coins (1 * 5 = 5).

Функция repeat() представляет собой своего рода цикл, потому что он продолжает цикл, пока он не достигнет конца. Продолжайте читать, чтобы узнать больше о циклах.

Цикл while

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

Циклы называются так, потому что они цикличны. Циклы как оператор if, в них есть условие которое должно быть выполнено для исполнения кода. Здесь рассмотрим оператор if в сравнении с циклом while:

if (money > 40){ //код } while (money > 40){ //код }

Оператор if проверяет, больше ли money, чем 40, а затем выполняет код. Цикл while проверяет так же, но разница в том, как работает цикл.

Когда условие, указанное для цикла, становится истинным, выполняется идущий после него код, и когда этот блок кода заканчивается, он возвращается к условию и проверяет его снова. Если условие истина, то он снова выполняет код. Затем снова и снова, и если это истина, снова выполняет код. Он продолжает это делать, проверяет условие, а затем код, и так пока условие не станет ложным.

Давайте возьмем пример выше. Скажем, значение money становится больше 40. Цикл while выполнит код, и продолжит делать это до тех пор, пока условие не станет ложным. Для того, чтобы условие оказалось ложным, стоимость денег должна быть ниже или равна 40.

while (money > 40){ //код money -= 1; }

Теперь все в порядке. Если мы уменьшаем значение money на каждый цикл, в какой-то момент оно должно опускаться ниже 40 и останавливать цикл.

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

Цикл do…while

Это еще один цикл и вариант цикла while. Посмотрите как он выглядит, прежде чем я объясню как он работает:

do { //код } while (условие);

Не пугайтесь. Это очень просто.

Помните, как в цикле while мы использовали проверку условия перед выполнением кода?

while (условие){ //код }

В цикле do…while часть while(условие) переместилась в нижнюю часть, после блока кода, и был заменен на do:

while (условие) do{
//код
} while (условие);

Это так потому, что цикл do..while сначала выполняет весь код, который находится в блоке кода, а затем проверяет условие, чтобы убедиться, что это истина, и должен ли он снова выполнить цикл. Если это так, он возвращается наверх и выполняет блок кода. Затем снова переходит к условию. Таким образом, он продолжает цикл до тех пор, пока условие не станет ложным, разница состоит в том, что он сначала выполняет блок кода, даже не проверяя условие.

Точка с запятой (;) должна быть в конце цикла do…while, потому что без нее конечная часть while(условие) может запутаться с запуском другого цикла while.

Цикл do…until

Цикл do…until совпадает с циклом do…while, причем разница заключается в том, что проверка условия do…until перевернута. Поэтому в do…while цикл будет работать снова, если условие было истинным, но в do…until цикл будет выполняться только в том случае, если условие было ложным.

coins = 5; do{ coins++; }until (coins==10);

Это так же просто, как сказать: “Продолжайте добавлять 1 к coins, пока они не станут равны 10″. Будет продолжать добавлять 1 к монетам, и когда данное условие станет истинным, когда монеты будут равны 10, тогда цикл будет остановлен.

В GameMaker следует использовать do…until, но не do…while.

Цикл for

Цикл for аналогичен циклу while, так как он сначала проверяет условие, и только потом продолжает цикл до тех пор, пока условие не станет ложным. Но у него есть еще несколько функций. Взгляните на его синтаксис:

for(init; condition; increment) { //код }

Тут вы можете определить состояние посередине. Но что это всё такое?

В основном это для переменной цикла. Переменная цикла в цикле for – это переменная, которая определяет сколько раз повторится цикл. А теперь больше объяснений.

init – здесь вы инициализируете свою переменную цикла, так как в ней указывается имя и значение. Выполняется в начале цикла.

condition – это условие, которое определит, выполняется ли цикл.

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

for(i=0; i<3; i++) { //код }

Вот подробное объяснение того, как будет работать этот цикл:

Сначала я инициализирую переменную цикла i с значением 0. Затем это условие проверяется, будет ли i меньше 3. Это означает, что это условие истинна, код выполнится. Как только блок кода завершит выполнение, увеличение будет запущенно: это означает, что i будет увеличиваться на 1 (i ++).

Теперь блок кода завершил своё выполнение, и i был увеличен на 1, что означает, что теперь он равен 1 (0 + 1). Инициализация будет оставлена, поскольку она работает только в начале цикле. Поэтому он перейдет к условию и проверит, меньше ли i, чем 3. Поскольку 1 меньше чем 3, условие будет истинным, и код будет выполнен.

Опять же, после выполнения блока кода, 1 будет добавлен к i, теперь он равен 2. Затем он перейдет к условию, и поскольку 2 меньше чем 3, условие станет истинным, и код будет выполнен снова. Тогда i станет 3 (2 + 1), а затем условие станет ложным, потому что i не меньше 3, оно равно 3. Теперь цикл остановится.

Итак, цикл будет работать три раза:

1-ый цикл: i равен 0. i<3 = истина, выполняется. i++. 2-ой цикл: i равен 1. i<3 = истина, выполняется. i++. 3-ий цикл: i равен 2. i<3 = истина, выполняется. i++. 4-ый цикл: i равен 3. i<3 = ложь, не выполняется.

Если вы не поняли, попробуйте перечитать, это может помочь.

Вот еще один пример цикла for:

for(i=3; i>0; i–) { //код }

Начинается с 3 и продолжает уменьшаться на 1, пока не станет больше 0. Можете рассчитать, сколько раз цикл будет выполнятся? Попробуйте рассчитать и напишите свой ответ в комментариях!

Массивы

Помните, как работают переменные? Вы можете дать им имя и сохранить в них некоторое значение…

coins = 10;

Это количество монет только одного игрока. Но что, если игроков 4, вам нужно хранить значение для каждого, и у них есть какое-то количество монет? Как бы вы это сделали?

coins0 = 10; coins1 = 5; coins2 = 12; coins3 = 7;

Сделать вот так, верно? Хранить все эти значения в разных переменных? Это будет работать верно, но есть и другой, более лучший способ сделать это: использовать массивы.

coins[0] = 10; coins[1] = 5; coins[2] = 12; coins[3] = 7;

Массивы похожи на переменные, у них также есть имя и хранятся некоторые значения, но в отличие от переменных они могут хранить несколько переменных (элементов) под тем же именем.

Чтобы назначить или получить доступ к элементу внутри массива, поместите идентификатор элемента (число) в квадратные скобки после имени массива. Вот так:

array[id] = value; variable = array[id];

Поэтому в предыдущем примере я добавил четыре элемента (0, 1, 2, 3) к массивам. Если я хочу сохранить второй элемент (со значением 5) к переменной с именем player_2, я сделаю следующее:

player_2 = coins[1];

Вы также можете использовать переменную вместо идентификатора элемента внутри квадратных скобок, потому что главное – это значение, а не ключевое слово. Поэтому я могу сделать так:

i = 1;
player_2 = coins[i];

Также вы можете использовать массивы внутри цикла:

for(i=0; i<3; i++) {
money[i] = coins[i];
}

Вышеупомянутый код выполняет ту же функцию, что и этот:

money[0] = coins[0]; money[1] = coins[1]; money[2] = coins[2];

Поскольку цикл будет выполняться только 3 раза, когда переменная цикла i будет равна 0, 1 и 2 соответственно, первые три элемента массива money станут равными первым трем элементам массива coins.

Заключение

Это всё для основ.

У вас есть вопросы или какие-нибудь предложения? Не стесняйтесь комментировать ниже. Я отвечу на ваш комментарий, как только смогу!

  • Автор оригинального руководства[gdpalace.wordpress.com]
  • Оригинал руководства на Английском[gdpalace.wordpress.com]
  • Видео-курс по GMS на Udemy (англ.)[gdpalace.wordpress.com]
  • Discord сервер, где вам могут помочь с GMS. (англ.)[discord.gg]
  • Версия этого руководства на GitBook[darkpro1337.gitbook.io]

Если вы находите ошибки в переводе, оставляйте поправки в комментарии.

Для таких людей будет создана отдельная секция в этом руководстве, с благодарностями. Я тоже человек и не владею чистым Английским, я буду вам очень признателен за помощь. Алсо,
более лучшие и удобные формулировки приветствуются.

Удачного вам геймдева! 🙂

ResourcesGame Design

Disclosure: This post may contain affiliate links. That means if you buy something we get a small commission at no extra cost to you(learn more)

GameMaker Studio is a powerful 2D engine developed by YoYo Games. With its drag-and-drop interface and a host of features, GameMaker simply makes game development easy.

Hit titles like Hotline Miami and Hyper Light Drifter have helped popularize GameMaker. It’s now supported by a sizable community of 2D game developers with new devs joining all the time.

With cross-platform support this program can deploy to every major platform, saving developers time by giving them access to several markets simultaneously. It also has its own scripting language—Game Maker Language—that can be used to create almost anything.

To get started learning this incredible program we have this list of tutorials on GameMaker so you can dive right into creating your dream game as soon as possible.

We’ve provided a variety of tutorials that cover several game genres so there’s guaranteed to be something in here for everyone.

Your First Game

Check Out This Tutorial

This tutorial created from the folks at GameMaker studios will walk you through the basics for a top-down action game.

You’ll start with player movement and work your way into more advanced topics.

You’ll learn how to navigate the GameMaker interface and add your own scripts. With only a few lines of code, you’ll be able to move your character around the screen with only a keyboard.

Using a system of Events and Actions, GameMaker makes it easy to program advanced logic too.

Complete Platformer Tutorial

Check Out This Tutorial

Shaun Spalding covers everything you need to get started making your own platformer in GameMaker Studio 2.

In this series Shaun makes use of the newest methods that get beginners up to speed quickly. Aimed at beginners and intermediate users alike, this series will have you leaping over pipes and jumping on Goombas in no time.

You start by setting up your game environment and then move on to player movement. You’ll learn how to create gravity and collisions in fewer than 40 lines of code.

2D Hack-n-Slash

Check Out This Tutorial

Here’s a handy learning tool from HeartBeast that teaches beginners how to make a 2D Hack-n-Slash game in GameMaker Studio 2.

You’ll learn everything from how to animate characters to coding in GameMaker.

With step-by-step instructions you’ll learn the basics of GameMaker while working toward a playable game that you can use in your portfolio.

Over the course of this series you’ll learn many techniques that are applicable to almost any game style too.

And if you like this tutorial check out the instructor’s full pixel art course from Udemy.

Make An RPG in GameMaker

Check Out This Tutorial

Here we have another video from HeartBeast (AKA Benjamin) who covers the basics of building a Role Playing Game.

This is aimed at total beginners who are itching to build their very own classic RPG.

Using retro RPGs like Final Fantasy and Chrono Trigger as a guide, Benjamin will show you how to use tiles to build a room and add collision events.

Next you’ll work on movement and getting your character to respond to input. As you progress through the series you’ll learn how to add custom behaviors and animations via GML.

Melee Attacks

Check Out This Tutorial

This two-part guide by Shaun Spalding takes an in-depth look at melee combat in GameMaker.

The example used is a 2D platformer, but these techniques will work for any game.

Part 1 covers a state-machine to create a basic attack. In part 2 you’ll learn about making combo-chains and linking multiple attacks.

This is a code-heavy tutorial that focuses on the concepts behind creating a melee system. By the end you’ll have a strong understanding of using hit boxes for melee combat along with scripting for your own games.

Shaders: The Basics

Check Out This Tutorial

Shaders are one of the most powerful and versatile tools in a game developer’s toolbox.

They can be used to create a range of effects and are present in most games.

It’s true that shaders are an advanced topic, but the rewards for using them are well worth the trouble of learning how.

In this video HeartBeast will guide you through shaders in GameMaker. He’ll show you how to use the shader editor to add some incredible visual effects to your games.

This tutorial starts with some simple demonstrations and concludes with making a custom greyscale shader in GameMaker.

Water Shader & Physics

Check Out This Tutorial

Most game engines provide some type of physics engine and Game Maker is no exception.

Using physics it’s possible to create a variety of realistic animations and mechanics for your games.

This video, also from Shaun Spalding, concentrates on creating bodies of water for a 2D platformer. Using his own game PokeyPoke as a reference, Shaun will teach you how to implement a complex water effect.

Just note that in the introduction Shaun mentions this video is more focused on concepts rather than implementation.

This point is to get your imagination working and gain more insight into game development.

Farming RPG

Check Out This Tutorial

This tutorial walks you through building an RPG farming sim game. This is aimed at beginners just starting out with GameMaker so it’s pretty easy to get into.

In the early sections you’ll learn all about objects, sprites, and how to set up your project in GameMaker.

FriendlyCosmonaut will first walk you through the fundamentals of using GameMaker Studio before introducing you to opengameart.org, a website where you can find free assets for your games and prototypes.

By the end of this video you’ll learn to code your own animated characters, create a night and day cycle, and grow crops in your game.

Turn-Based RPG

Check Out This Tutorial

Ever since the first RPGs came out on the original NES, turn-based RPGs have been a fan favorite.

They remain a popular goal for beginning 2D developers to this day.

Crafting a turn-based game can be challenging for sure. Luckily you have YouTube and sea of content much like this video by Aidan where you’ll learn how to build a simple 2D RPG.

Starting with movement and collision, you’ll eventually move onto combat, scene transitions, crafting a user interface, and plenty more.

There’s a lot to learn in this series so be prepared to invest some time and keep the coffee pot burning.

Ghost Recording

Check Out This Tutorial

In this more advanced tutorial by GameMaker guru Shaun Spalding, you’ll see first-hand how to create a ghost playback effect.

While Shaun uses a platformer for this demo, the techniques will work universally.

For instance, you could use it to create time trials for a racing game.

Shaun creates this effect by first recording the player’s input via the state of the character and saving it to a JSON file. By retrieving the file we can play back the player’s movements.

Check out the description below the video for the source files if you want to use the same sprites and code. This basically holds a pack of pixel art that makes a great learning resource.

Simple 3D Dungeon

Check Out This Tutorial

Have you ever wanted to create your shooter game in the style of the original Doom or Duke Nukem?

Well now you can thanks to GameMaker and this short video by HeartBeast.

You’ll learn how to design and navigate a 3D maze complete with pixel art and atmospheric effects using textures and sprites provided in the description.

While this isn’t a true 3D environment, it’s a great stylistic choice.

Some players will enjoy the retro look of this kind of game which keeps them popular among game devs.

Box Puzzle Game

Check Out This Tutorial

In this 3-part series by createindiegames you’ll learn how to design a simple puzzle game using GameMaker Studio 2.

This video covers fundamental topics like movement, collision, and animation.

You’ll learn how to use a TileMap and create box objects that the player can push around.

After setting up the player, the instructor will show you how to handle moving the boxes and creating the win scenario.

By the end of the tutorial you’ll have a playable puzzle game ready to go. What’s more, you’ll have all the pieces you need to create additional puzzles and expand your game.

Easy Equipment System

Check Out This Tutorial

Spine is a 2D animation package that aims to make the animation workflow easier.

It pairs nicely with GameMaker and can greatly boost your productivity when it comes to animation.

Spine packs a variety of tools and you’ll learn many of them here. When you’re done, you can export your work it and use it in GameMaker.

This video by developer Tainted Lost will show you how to use Spine and GameMaker to build a basic equipment system. Using Spine with GameMaker will make building new, exciting features far less painful.

Text Boxes

Check Out This Tutorial

Text is a feature of most games and for some, like RPG’s, it’s a core part of the gameplay.

Story-driven games allow you to express more complex ideas and create characters that your players will learn to love.

In this video by Shawn Spalding you’ll learn how to make custom text dialogue in GameMaker Studio 2. Use it to build an epic world and full of emotion and depth.

Some developers may find that writing stories for their game worlds is just as fun as coding them. Adding prose to your game will help the players form a connection with your characters.

Networking for Beginners

Check Out This Tutorial

This video from Benjamin is a gentle introduction to networking with GameMaker. Use it to explore the fundamentals of developing online multiplayer games.

You won’t actually be making a game in this tutorial; you’ll just be setting up a connection between two computers and sending some data back and forth.

This is, however, the bare minimum needed to build an online game. Once you understand the basics of sending data over this connection, you can expand to more advanced topics like shooting a gun or sending an instant message.

Zelda-Style Hearts

Check Out This Tutorial

The Legend of Zelda is still one of the most popular games of all time.

In this video by Synthetic Pixel Games you’ll learn how to implement a Zelda-style health system all on your own.

Using only three sprites you’ll follow the process of how to add and remove hearts using increments in half-hearts. The graphics are implemented as part of the UI so they’ll follow the player around the map.

Add some style to your 2D adventure game with these Zelda-style hearts, or create some basic pixel graphics to change those hearts into anything of your choosing.

How To Make Flappy Bird

Check Out This Tutorial

Flappy Bird is a remarkably easy game to recreate. You’ll learn that firsthand in this tutorial by Overnight Gamemaker.

Targeted at beginners, this video will go step-by-step through building a Flappy clone. Follow along as the developer builds this simple game on the fly using GameMaker Studio 2.

This project covers a lot of ground from animation to scrolling backgrounds and a few other areas. When you’re finished you’ll have a deployable game ready to add to your portfolio.

Make Asteroids!

Check Out This Tutorial

This tutorial is an excellent starting point for those looking to learn GameMaker Studio and create their own arcade games.

This time you’ll be reconstructing the Atari classic Asteroids.

Follow along with the instructor from Ask Gamedev to learn the ins and outs of GameMaker including how to use sprites, objects, events, and action blocks.

By the end you’ll have a fully playable Asteroids game that you can share with friends or goof around with by yourself.

You’ll also have a solid foundation to start building your future with GameMaker.


Author: Josh Petty

Josh is an artist and game developer who specializes in sci-fi, fantasy, and abstract art. His work employs vibrant colors and combines elements of glitch art, outrun, retro-gamming, neo-geo, and conceptual art. He trained as an oil painter before picking up 3D modeling, animation, and programming. He now runs Brain Jar, a small game development studio that focuses on experimental, narrative-driven content. You can learn more on the website or on Twitter @brainjargames.


Понравилась статья? Поделить с друзьями:
  • Haihua cd 9 инструкция по применению на русском
  • Насос свияга м инструкция по эксплуатации
  • Руководство города магнитогорска
  • Музей имени пушкина руководство
  • Амикацин инструкция по применению уколы взрослым от чего помогает взрослым