Создание игр: космический шутер
Автоматически переведённая страница
К сожалению, на полный ручной перевод у нас не хватает ресурсов.
Если вы увидели ошибку — отправьте пул-риквест с исправлениями (ссылка для редактирования в конце страницы).
Создание игр: космический шутер
Давайте создадим небольшую игру в космосе с шутерами, астероидами, лазерами и враждебными истребителями! В этом руководстве мы научим вас импортировать ресурсы, обрабатывать входные данные пользователей, перемещать объекты и реагировать на столкновения.
Вот что нам нужно сделать:
Импорт текстур
Откройте ct.js и кликните на вкладку "Создать новое". Создайте новый проект, указав его имя (например, "SpaceShooter"), выбрав язык программирования и нажав кнопку "Создать".
Нам понадобятся некоторые спрайты для этой задачи. В верхнем правом углу найдите кнопку "Новый ассет", нажмите ее и выберите "Внутренняя галерея ассетов" в меню.
В галерее найдите пакет ассетов "Kenney's Space Shooter" и добавьте эти (или похожие) текстуры, наведя курсор мыши на нужные текстуры и нажав кнопку импорта в правом верхнем углу:
Когда вы закончите, закройте галерею, нажав на кнопку "X" в правом верхнем углу.
Теперь вы увидите карты для каждой импортированной текстуры. Откройте текстуру PlayerShip
и настройте ее, нажав на ее карту ассета. Мы увидим синюю прозрачную форму, которая определяет коллизию корабля. Форма коллизии определяет, какие области считаются частью корабля, а какие нет. Сейчас она покрывает слишком много пустого пространства, особенно над крыльями. Чтобы исправить это, нам нужно изменить коллизию в настройках в правой колонке.
Сначала нажмите кнопку "По центру", чтобы поставить ось в центр корабля.
Далее выберите «Ломанная / Многоугольник» в качестве формы коллизии под меткой "Маска столкновений". Добавьте пару дополнительных точек и переместите их мышкой так, чтобы получившийся полигон повторял форму корабля.
Нажмите "Применить" и перейдите к следующей текстуре — Laser_Red
. Как и с кораблем, поставьте ее ось в центр, нажав кнопку "По центру". Затем выберите «Круг» в разделе "Маска столкновений" прямо под этой кнопкой. Теперь коллизия в форме круга.
Следующая текстура, Laser_Blue
, также должна быть центрирована. Поскольку форма коллизии должна покрывать все изображение, вы можете нажать кнопку "Заполнить", чтобы автоматизировать этот процесс.
Оба астероида лучше определить как полигоны из-за их вогнутых или острых форм. Установите для них форму коллизии «Ломанная / Многоугольник» и не забудьте поставить их ось в центр.
Форму коллизии Enemy_Red
можно изменить также как и PlayerShip
.
Фоновое изображение может остаться без изменений, так как оно не будет взаимодействовать с другими объектами в игре. Но вы должны перейти к его редактированию и поставить флажок "Использовать как фон?" в настройках слева, чтобы фон, состоящий из тайлов этой текстуры, был бесшовным.
Создание первых шаблонов и размещение вещей
Текстуры сами по себе не имеют особого смысла, и чтобы отобразить их в игре, нам нужно создать шаблоны с этими ресурсами. Шаблоны используются для создания копий, а копии — это те самые объекты, которые вы помещаете в комнаты, которые взаимодействуют друг с другом и реагируют на ваши действия.
Перейдите во вкладку "Ассеты" в верхней части экрана, нажмите кнопку "Новый ассет" и создайте новый шаблон для корабля игрока. Назовите шаблон "PlayerShip" (корабль игрока). Названия шаблонов должны отражать их суть, чтобы вам было проще читать код во время программирования. Если вы забыли изменить название при создании шаблона, вы можете перейти обратно к вкладке "Ассеты", затем щёлкнуть правой кнопкой мыши по шаблону и в выпадающем меню выбрать "переименовать".
Щелкните по большой призрачной кошке в левой колонке, чтобы выбрать текстуру для нее. Нажмите на карту с вашим кораблем — после этого он появится в левой колонке редактора.
Создайте шаблоны для всех остальных текстур, кроме фонового изображения. Фоновые изображения обычно не перемещаются и не взаимодействуют с другими объектами и часто повторяются, поэтому они не являются шаблонами. Мы добавим его позже в комнате.
Вот как должен выглядеть ваш список ресурсов:
Теперь поместим созданные шаблоны на карту. Чтобы создать эту карту или комнату, еще раз нажмите кнопку "Новый ассет" и выберите "Комната". Назовите ее "Main" и создайте.
Здесь мы немного остановимся, чтобы объяснить, как использовать редактор комнат. Более подробное описание можно найти здесь, но пока что нам понадобятся только некоторые инструменты этого редактора. Во-первых, мы должны настроить размер просмотра комнаты в свойствах комнаты, нажав кнопку с шестеренкой в левой панели инструментов. Установите размер 640 на 640 пикселей или другой на ваш выбор.
В ct.js комнаты бесконечны и могут перемещаться в любом направлении. Вы можете помещать объекты внутри и за пределами области просмотра.
Вы можете перемещаться по комнате, удерживая колесо мыши и перетаскивая мышь. Вы также можете изменять масштаб с помощью колесика мыши или с помощью выпадающего меню в верхней панели инструментов. Если вы чувствуете себя дезориентированным, нажмите пункт в меню "Сбросить вид" в выпадающем меню "Масштаб", чтобы вернуться к координатам (0, 0) — или просто нажмите клавишу H
.
Пока что давайте разместим корабль игрока, вражеский корабль и пару астероидов. Выберите инструмент "Добавить копии" в левой панели инструментов, выберите шаблон и поместите его на уровень с помощью щелчка мыши.
Затем добавим фон. Нажмите кнопку "Управление фонами" в левой панели и нажмите кнопку "Добавить фон", затем выберите наш фоновый ресурс. Он появится в основном просмотре как текстура, повторяющаяся по всему экрану.
Хотя фоновые изображения всегда отрисовываются перед копиями с одинаковым уровнем глубины (0
по умолчанию), лучше изменить их уровень глубины. Нажмите кнопку со стрелочкой справа рядом с миниатюрой фона и введите -5
в поле "Глубина". Таким образом, мы сообщаем движку, что этот фон находится ниже, чем другие копии и фоны. Глубина представляет собой третью ось, которая направлена в сторону камеры (на зрителя), а X и Y — в стороны.
После этого сохраните проект и нажмите кнопку "Пуск" в верхнем меню. На этом этапе у вас будет проект игры с неподвижными кораблями и астероидами.
Добавление движения игрока
Обработка входных данных пользователя — это самая важная задача. В этом разделе мы заставим синий корабль двигаться при нажатии стрелок или кнопок WASD на клавиатуре.
Чтобы обработать ввод с клавиатуры, нам нужно включить модуль Keyboard. Перейдите на вкладку «Проект», затем на левую вкладку «Котомоды», затем найдите модуль "Клавиатура" в разделе доступных модулей. Нажмите на него, чтобы включить (он может быть включен по умолчанию — зеленый флажок с маленькой стрелкой указывает на то, что модуль включен). Затем убедитесь, что включены модули Указатель
, random
и place
, поскольку нам они тоже понадобятся позже.
Добавление действий
Действия в ct.js — это объекты, которые группируют различные методы ввода в события и позволяют вам обрабатывать ввод игрока в коде. Дополнительную информацию можно найти здесь.
Пока давайте создадим базовую схему ввода для нашей игры-стрелялки. Откройте вкладку «Проект», а затем вкладку «Действия и методы ввода» слева. Нам нужно будет определить три разных действия: для стрельбы лазерными пулями, для горизонтального движения и для вертикального движения.
Сначала нажмите кнопку «Создать с нуля». Затем введите имя первого действия например "Shoot" (Выстрел). Нажмите кнопку «Добавить метод ввода», чтобы связать конкретные кнопки с вашим действием. Используйте поиск, чтобы быстро отфильтровать доступные методы ввода и найдите соответсвующие названия кнопок. Нажмите кнопку «Добавить действие», чтобы продолжить создание новых действий.
Создайте три действия, как показано на картинке выше. Установите значение множителя равным -1
для keyboard.ArrowUp
, keyboard.KeyW
, keyboard.ArrowLeft
и для keyboard.KeyA
, так что эти кнопки будут двигать корабль в противоположном направлении.
Программирование движения
Вернитесь к "Ассетам", затем щелкните на шаблоне PlayerShip
и перейдите к событию Начало кадра
.
Совет
Событие Начало кадра
происходит каждый кадр перед отрисовкой, в то время как событие Конец кадра
происходит после всех событий Начало кадра
в комнате для отрисовки нового кадра. Событие Создание
происходит при создании новой копии, и событие Уничтожение
происходит до события Конец кадра
, если копия была уничтожена.
Напишите следующий код:
/**
* Move the ship
* See Project > Actions and input methods panel
* and "Actions" in the docs.
*/
this.hspeed = 480 * actions.MoveX.value; // Move by X axis
/**
* Check whether the ship fell off the viewport
*/
if (this.x < 0) { // Have the ship crossed the left border?
this.x = 0; // Go back to the left border
}
if (this.x > camera.width) { // Have the ship crossed the right border?
this.x = camera.width; // Go back to the right border
}
this.move();
# Move the ship
# See Project > Actions and input methods panel
# and "Actions" in the docs.
@hspeed = 480 * actions.MoveX.value # Move by X axis
# Check whether the ship fell off the viewport
if @x < 0 # Have the ship crossed the left border?
@x = 0 # Go back to the left border
if @x > camera.width # Have the ship crossed the right border?
@x = camera.width # Go back to the right border
@move()
Здесь мы используем созданные действия. Во-первых, мы пытаемся горизонтально перемещать корабль (по оси X, строка 6). actions.MoveX.value
вернет 1
, если мы нажимаем правую стрелку клавиатуры или клавишу "D", и будет возвращать -1
, если игрок нажимает левую стрелку или клавишу "A". Если ничего не нажато, он будет возвращать 0
, отключая горизонтальное перемещение.
Затем, мы умножаем наше промежуточное значение скорости на желаемую скорость, 480
.
Наконец мы проверяем, не вышла ли X-координата корабля за пределы камеры. Здесь 0
означает левый бок комнаты, а camera.width
означает горизонтальную ширину камеры, которая соответствует правому краю.
А теперь — самостоятельно!
Добавьте вертикальное перемещение игроку. Затем попробуйте ограничить его движение так, чтобы корабль не мог лететь выше середины камеры.
Перемещающиеся враги и астероиды
Враги тоже должны двигаться. Давайте сделаем так, чтобы наш враждебный корабль перемещался сверху вниз, а астероиды летали в случайном направлении.
Враги
Откройте вкладку "Ассеты", затем щелкните по EnemyShip
. Перейдите к событию "Создание" и добавьте следующий код:
this.speed = 180;
this.direction = 90;
@speed = 180
@direction = 90
Запустите игру и вы увидите как вражеский корабль летит вниз с заданной нами скоростью 180.
Здесь мы используем встроенные переменные для движения. Ручное редактирование координат может быть полезно при обработке ввода игрока, но для большинства задач лучше использовать эти переменные, так как они автоматизируют многие вещи. Например, вам не нужно использовать u.time
, когда есть this.speed
и this.direction
. Здесь this.speed
означает скорость Копии, а this.direction
относится к ее направлению.
Совет
Если вы используете CoffeeScript, то this.speed
является @speed
, this.direction
— @direction
, и т.д. Вы можете писать по-разному!
Совет
В ct.js направление измеряется в градусах, по часовой стрелке. 0° означает вправо, 90° вниз, 180° влево, а 270° вверх.
Если мы перейдем к событию "Начало кадра", мы увидим следующий небольшой код:
this.move();
@move()
В этой строке метод this.move()
использует встроенные переменные и перемещает копию в соответствии с их значениями. Без него переменные this.speed
и this.direction
будут бессмысленны.
Есть еще несколько встроенных переменных, которые вы можете найти на странице шаблоны
.
Мы изменим код события "Начало кадра", чтобы враги уничтожались, если они уходят за пределы экрана.
this.move();
if (this.y > camera.height + 80) {
this.kill = true;
}
@move()
if @y > camera.height + 80
@kill = yes
Попробуйте самостоятельно!
Что если враги могут двигаться диагонально, создавая эффект зигзага?
Астероиды
Астероиды будут содержать один и тот же код Начало кадра
, но их переменная direction
будет определяться случайным образом.
Откройте шаблон Asteroid_Medium
во вкладке "Ассеты", затем введите следующий код в событие Создание
.
this.speed = random.range(60, 180);
this.direction = random.range(90 - 30, 90 + 30);
@speed = random.range(60, 180)
@direction = random.range(90 - 30, 90 + 30)
Событие Начало кадра
будет таким же, как и в EnemyShip
.
this.move();
if (this.y > camera.height + 80) {
this.kill = true;
}
@move()
if @y > camera.height + 80
@kill = true
Повторите то же для другого астероида.
Сохраните проект и нажмите кнопку "Пуск" вверху. Враждебный корабль будет медленно двигаться вниз, а астероиды будут двигаться более хаотично. Если вы обновите страницу, астероиды будут двигаться в новом направлении.
Совет
У вас возникли ошибки с random
? Убедитесь, что вы включили модуль random
в разделе Проект -> Котомоды.
Снаряды & Столкновения
Теперь пора вооружить корабли 😎
Откройте шаблон PlayerShip
и добавьте событие "Нажатеие действия "Shoot"", а затем нажмите "Применить". Теперь внутри события "При нажатии Shoot" добавьте следующий код:
templates.copy('Laser_Blue', this.x, this.y);
templates.copy 'Laser_Blue', @x, @y
Это первая программа, с помощью которой мы создаем новые копии. Хороший старт!
Совет
templates.copy
- это очень важная функция, которая создает новую копию в текущей комнате. Во-первых, мы указываем название шаблона, который нужно скопировать, а затем координаты, по которым нужно создать его, по горизонтали и вертикали соответственно. this.x
означает горизонтальное положение текущей копии, а this.y
- вертикальное.
Сочетая все данные, мы создаем лазерный снаряд прямо под нашим кораблем. Снаряды будут создаваться при нажатии кнопки "Пробел".
Теперь давайте поговорим о самом "Laser_Blue". Мы определим его движение по умолчанию в событии "Создание".
this.speed = 1080;
this.direction = 270;
@speed = 1080
@direction = 270
Следующий шаг - убедиться, что эти лазерные снаряды исчезнут после того, как выйдут из кадра. Поскольку они всегда летят вверх, мы можем написать условие для верхней границы в событии "Начало кадра".
if (this.y < -40) {
this.kill = true;
}
this.move();
if @y < -40
@kill = true
@move()
Следующим шагом является обработка столкновений. Лучше всего обрабатывать логику столкновений в коде противника и кораблей, потому что они будут реагировать по-разному, не перегружая код снаряда.
Откройте шаблон EnemyShip
и создайте событие "Столкновение с шаблоном", выбрав Laser_Blue
. В коде этого события добавьте следующее:
other.kill = true;
this.kill = true;
other.kill = true
@kill = true
Совет
other
— это специальная переменная, на которую можно ссылаться при написании кода событий столкновения. other
относится к другому сталкивающемуся экземпляру. Будьте внимательны к другим локальным переменным, которые могут быть доступны в определенных событиях!
Если корабль сталкивается с лазерным снарядом, то и снаряд, и корабль должны быть уничтожены.
Скопируйте тот же код для Asteroid_Medium
. Нам также понадобится этот код для Asteroid_Big
, но мы сделаем так, чтобы большие астероиды разбивались на два более мелких:
other.kill = true;
this.kill = true;
templates.copy('Asteroid_Medium', this.x, this.y);
templates.copy('Asteroid_Medium', this.x, this.y);
other.kill = true
@kill = true
templates.copy 'Asteroid_Medium', @x, @y
templates.copy 'Asteroid_Medium', @x, @y
Если запустить игру, вы сможете уничтожать вражеские корабли и астероиды. Более крупные астероиды должны разбиваться на более мелкие.
Противник стреляет тоже
Врагу тоже нужно уметь стрелять. Добавьте следующий код в событие Создание
шаблона EnemyShip
:
this.timer1 = 1;
@timer1 = 1
Таким образом, мы настроим таймер, чтобы враг стрелял с определенными интервалами. Переменная timer1
— это специальная переменная, которую ct.js будет автоматически отсчитывать для нас, 1 секунда в секунду. Событие Timer 1
будет активироваться, когда значение достигнет 0. Это означает, что мы подождем 1 секунду, прежде чем стрелять первым выстрелом.
Дайте событию имя, например "Shoot", оставьте флажок проверки UI не выбранным, а затем добавьте следующий код в событие Timer 1
:
this.timer1 = 3;
templates.copy('Laser_Red', this.x, this.y + 32);
@timer1 = 3
templates.copy 'Laser_Red', @x, @y + 32
Когда значение timer1
достигнет нуля, мы вернем его к значению 3 и создадим красный лазерный выстрел. Следующий выстрел будет стрелять через 3 секунды автоматически. Как вы можете видеть, написав this.y + 32
, мы создаем выстрел немного ниже корабля.
Давайте напишем код для красных лазеров. Добавьте следующий код в секцию Создание
класса Laser_Red
:
this.speed = 480;
this.direction = 90;
this.angle = random.deg();
@speed = 480
@direction = 90
@angle = random.deg()
this.angle
вращает текстуру копии. random.deg()
возвращает случайное значение между 0 и 360, что очень удобно для определения угловых значений.
Совет
Есть также this.scale.x
и this.scale.y
, которые позволяют масштабировать копию по горизонтали и вертикали соответственно, а также this.alpha
, который манипулирует ее непрозрачностью (0 означает полностью прозрачное, 1 — полностью непрозрачное).
Код для события Начало кадра
будет следующим:
if (this.y > camera.height + 40) {
this.kill = true;
}
this.move();
this.angle -= 240 * u.time;
if @y > camera.height + 40
@kill = true
@move()
@angle -= 240 * u.time
this.angle -= 240 * u.time
означает, что мы будем вращать копию примерно на 240 градусов каждую секунду. u.time
делает движение более плавным и равномерным, если частота кадров в игре нестабильная.
Мы определим логику уничтожения корабля игрока позже. А сейчас нам нужно добавить генерацию врагов и астероидов во время игрового процесса.
Генерация объектов во времени
Откройте комнату «Main». Удалите существующие астероиды и врагов. Чтобы это сделать воспользуйтесь инструментом "Выделение", выберите копию, нажмите по ней правой кнопкой мыши и выберите пункт "удалить". Чтобы выбрать сразу несколько копий удерживайте клавишу Ctrl
.
Совет
Чтобы ускорить процесс создания и удаление копий используйте инструмент "Добавить копии". Выбрав нужный шаблон из списка вы можете создавать его копии в комнате, а удерживая Ctrl
- удалять.
Далее нажмите кнопку «События» в верхней панели.
Комнаты имеют те же события, что и копии.
Старт комнаты
вызывается при запуске игры или при входе в эту комнату.Начало кадра
вызывается каждый кадр после всех событий копийНачало кадра
.Конец кадра
вызывается после отрисовки всех уровней. Это полезно для обновления интерфейса пользователя.Конец комнаты
вызывается перед выходом из комнаты.
Генерацию врагов сделаем почти такой же, как и снаряды у врагов. Мы создадим несколько таймеров и будем помещать копии выше поля зрения игрока.
Создайте два таймера в коде события «Старт комнаты»:
this.timer1 = 0.3; // asteroid timer
this.timer2 = 3; // enemy timer
# asteroid timer
@timer1 = 0.3
# enemy timer
@timer2 = 3
// asteroid timer
this.timer1 = random.range(0.3, 3);
templates.copy(random.dice('Asteroid_Big', 'Asteroid_Medium'), random(camera.width), -100);
# asteroid timer
@timer1 = random.range 0.3, 3
randomAsteroid = random.dice 'Asteroid_Big', 'Asteroid_Medium'
randomX = random camera.width
templates.copy randomAsteroid, randomX, -100
Затем добавьте событие "Timer 2", дайте ему понятное название например "EnemyCreation" (Создание врагов) и напишите там этот код, чтобы генерировать вражеские корабли со случайным интервалом:
// enemy timer
this.timer2 = random.range(3, 6);
templates.copy('EnemyShip', random(camera.width), -100);
# enemy timer
@timer2 = random.range 3, 6
randomX = random camera.width
templates.copy 'EnemyShip', randomX, -100
Вот всё, что вам нужно для создания астероидов и врагов!
Совет
random.dice
возвращает одно из заданных значений. Вы можете использовать любые значения, включая числа, строки или сложные объекты. Здесь есть 50% вероятность того, что будет возвращена строка 'Asteroid_Big'
, и 50% вероятность того, что будет возвращена строка 'Asteroid_Medium'
.
random.range(a, b)
возвращает случайное число в интервале между a
и b
.
random(b)
возвращает те же значения, что и random.range(0, b)
.
Жизни, счет и графический интерфейс пользователя
Давайте добавим в игру подсчет очков и реакцию корабля игрока на враждебные действия.
Добавление и отрисовка счета
Счет — это числовая переменная, которая хранится глобально. В нашем случае лучше всего разместить её внутри комнаты. Откройте комнату "Main", перейдите в раздел «События» и добавьте этот код в событие «Старт комнаты»:
this.score = 0;
@score = 0
Теперь нам нужно показать этот счёт в игре. Для этого создайте новый шаблон с именем ScoreText
. Затем в выпадающем меню, в левой колонке под призрачным котом, выберите тип шаблона "Текст". Также в правой колонке в разделе "Внешний вид" установите его глубину например 1000, и это большое положительное значение поместит текст поверх других объектов в нашей комнате. Чтобы мы могли видеть текст в редакторе комнаты нужно добавить "текст по умолчанию", здесь можно написать что угодно, но для удобства введите одно из значений которое будет отображать этот шаблон в игре например "Score: 0".
Чтобы созданный нами текст изменял своё значение во время игры и отображал текущий счёт, нужно добавить следующий код:
this.text = 'Score: ' + rooms.current.score;
@text = 'Score: ' + rooms.current.score
Теперь перейдите к шаблону EnemyShip
и в событии Столкновение с шаблоном Laser_Blue
добавьте rooms.current.score += 100;
после строчки, где корабль уничтожается после столкновения с лазерной стрелой. Число 100 означает количество очков которое получит игрок за уничтожение корабля, вы можете изменить его на любое дркгое по вашему желанию. По итогу весь код выглядит так:
other.kill = true;
this.kill = true;
rooms.current.score += 100;
other.kill = true
@kill = true
rooms.current.score += 100
Совет
rooms.current
указывает на текущую комнату.
Сделайте то же самое для астероидов. Измените количество данных очков так, как вам нравится.
Когда вы в редакторе комнаты "Main" поместите ScoreText в левый верхний угол и запустите игру, то сможете заметить небольшую черную цифру, которая меняется при уничтожении астероидов и вражеских кораблей. Но это выглядит не красиво, поэтому сейчас самое время для создания стилей.
Дизайн текста можно изменить с помощью встроенных стилей, которые задают цвет заливки, стиль линии, размер шрифта, тень и т.д. Они создаются в разделе "Ассеты" -> "Новый ассет" -> «Стиль». Вам будет представлен редактор стилей, в левой части которого есть вкладки для настройки свойств, а по центру — предварительный просмотр.
Совет
Если вы не видите текст, возможно цвет текста совпадает с цветом фона. Цвет фона можно изменить в нижней части редактора по кнопке "Сменить цвет фона", а цвет текста - в левой колонке в разделе "Заливка".
Давайте увеличим шрифт и сделаем его жирным. Измените его размер и установите толщину шрифта 800. Затем выровняйте его по левому краю.
Нажмите на вкладку «Заливка», включите ее и выберите тип заливки «Сплошная». Выберите подходящий цвет; я выбрал что-то похожее на цвета игрового корабля.
Добавьте тень или обводку, или и то и другое! Затем примените изменения, нажав кнопку «Применить» в нижнем левом углу.
Назовите созданный стиль ScoreText
. Вы можете изменить имя, щелкнув правой кнопкой мыши по нему в списке ассетов.
Теперь вернитесь к шаблону ScoreText
. Вместо выбора спрайта с иконкой кошки-призрака вы теперь можете выбрать стиль ScoreText
, который мы только что создали.
Если вы вернетесь в главную комнату, счет будет отрисован с учетом вашего созданного стиля. Ура!
Управление жизнями
Управление жизнями похоже на управление очками в игре. Добавьте этот код в Старт комнаты
, чтобы он также хранил количество жизней.
this.lives = 3;
@lives = 3
Теперь сделайте новый шаблон, назовите его LivesText
, измените тип на Text и выберите стиль ScoreText
снова. Установите его глубину в 1000, и добавьте в Конец кадра
:
this.text = 'Lives: ' + rooms.current.lives
@text = 'Lives: ' + rooms.current.lives
Самостоятельно!
Создайте новый стиль и примените его к шаблону LivesText
.
Добавьте копию в комнату в правом верхнем углу, и она будет отображать ваше текущее количество жизней в игре!
Далее мы должны добавить логику, чтобы у корабля игрока отнималась одна жизнь при столкновении. Давайте сгруппируем астероиды и врагов в одну группу столкновений. Это позволит нам писать меньше кода и вносить меньше изменений, если мы добавим больше врагов, ракет или астероидов разного размера.
Чтобы добавить копии в группу столкновений, мы должны написать имя группы в правой колонке редактора шаблонов. Давайте напишем Hostile
в группе. Сделайте это для всех астероидов, вражеского корабля и красных лазеров.
Перейдите к кораблю игрока и создайте новое событие «Столкновение с группой». Укажите Hostile
в текстовом поле. Теперь добавьте этот код в событие Столкновение с группой Hostile
кода корабля игрока:
if(templates.isCopy(other)) {
other.kill = true;
}
rooms.current.lives --;
if (rooms.current.lives <= 0) {
this.kill = true;
u.wait(1000)
.then(() => {
rooms.switch('Main');
});
}
if templates.isCopy(other)
other.kill = true
rooms.current.lives--
if room.lives <= 0
@kill = true
u.wait 1000
.then =>
rooms.switch 'Main'
rooms.switch
отключает текущую комнату и загружает новую. Но из-за того, что мы указали название нашей единственной комнаты "Main", то она просто перезагрузится.
u.wait
— это Promise, который выполняется через заданное количество миллисекунд. Здесь мы ждем одну секунду (1000 миллисекунд) и затем перезагружаем комнату в первом аргументе then()
.
Совет
u.wait
может показаться более удобным способом работы с задержками событий, чем таймеры. Разница заключается в том, что таймеры существуют до тех пор, пока существует их владелец, но u.wait
будет происходить во всех обстоятельствах, даже если копия, которая его вызвала, была удалена из комнаты.
В нашем случае мы хотим перезагрузить комнату, хотя на экране нет кораблей игрока, поэтому мы используем u.wait
. Мы используем таймеры для стрельбы и появления врагов, потому что мы не хотим, чтобы пули внезапно появлялись после уничтожения врагов.
Сохраните проект и протестируйте его. Теперь у вас есть небольшой, но полностью работающий космический шутер! Существует много способов улучшить эту игру дальше:
- отрегулировать существующие значения, такие как скорость врага или очки за победу, для улучшения игрового процесса;
- добавить больше врагов;
- улучшить стрельбу с таймерами, чтобы игрок мог просто держать клавишу «пробел», а не нажимать на нее;
- добавить бонусы и разные виды оружия;
- разработать меню и экран победы;
- добавить звуки;
- создать боссов и союзников.
Вот мой результат дальнейшего улучшения этой игры: Catsteroids.
Вы также можете начать новый проект, если вы не заинтересованы в космических шутерах 😄
Экстра: повторное использование логики с помощью поведений
Если вы создаете много разных типов астероидов, вам может надоесть написание одинаковой логики для настройки начальной скорости и направления, а также для определения момента уничтожения астероидов. К счастью, существует способ быстро создать несколько шаблонов с одной и той же логикой, а именно с помощью поведений!
В вкладке «Ассеты» нажмите на «Новый ассет» и перейдите в раздел «Поведения», затем выберите «Поведение с шаблонами». Назовите его «Настройка астероидов».
Есть поле для добавления пользовательских полей, которые будут доступны для копий, добавляющих это поведение, но пока что мы просто добавим некоторые события. Добавьте событие «Создание» и событие «Начало кадра».
Перейдите в один из шаблонов астероидов и скопируйте код из событий «Создание» и «Начало кадра», а затем вставьте его в события недавно созданного поведения. Теперь перейдите в «Asteroid_Big» и «Asteroid_Medium» и удалите эти два события. Наконец, для каждого астероида перейдите во всплывающее окно справа и нажмите «Добавить поведение», выбрав созданное поведение.
И вот так два астероида ведут себя так же, как и раньше, но теперь их логика объединена в поведении! Теперь, когда вы добавляете новые астероиды, вам просто нужно добавить поведение «Asteroid Setup», и они будут вести себя точно так же, как и другие астероиды! Это также позволяет редактировать поведение всех астероидов в одном месте и уменьшает необходимость поиска скопированного кода в нескольких шаблонах при внесении изменений.