Всем доброго времени суток. Сегодняшний урок я хотел бы посвятить такой интересной игровой особенности, как перемотка времени. То есть мы заставим нашего героя двигаться в обратном направлении по уже пройденному им пути.
Для начала, как обычно, займемся созданием спрайтов. Их у нас будет три:
spr_wall,
spr_hero и
spr_effect.
Спрайт
spr_wall представляет собой квадрат размером
32х32 и будет обозначать стены и поверхности.
spr_hero, это герой нашей игры, который так же представляет собой квадрат 32х32, но с нарисованной на нем рожицей. И, наконец,
spr_effect – это спрайт, который будет использоваться нами для создания эффекта перемотки времени. Он представляет собой квадрат размером 32х32,
с примененным к нему эффектом анимации Disappear распространенным на 8 кадров.
Со спрайтами закончили, переходим к программированию.
Создадим объекты
obj_wall,
obj_hero и
obj_effect, указав им соответствующие спрайты. Заходим в свойства объекта
obj_wall и делаем его твердым (solid).
Затем заходим в
obj_effect и добавляем событие
Animation end. В этом событии прописываем одну строчку кода:
Тем самым мы удаляем данный объект, когда его анимация проходит все кадры. Помимо этого поставим у
obj_effect свойство
Depth равное 1. Это перенесет наш эффект на задний план по сравнению с другими объектами. В дальнейшем вам станет понятно зачем мы все это сделали, а пока переходим к главному объекту -
obj_hero.
Итак, сначала создадим простейшее управление для героя. Я не буду заострять на этом особое внимание, так как это не является целью данного урока.
Создадим событие
step и пропишем в нем следующий код:
Code
gravity_direction = 270
if place_free(x,y+1)
gravity = 1
else
gravity = 0
Эти строки задают направление гравитации и её силу. Если под героем пусто, то гравитация равна 1, иначе гравитация отсутствует, т.е. равна 0.
Теперь добавим событие столкновения с
obj_wall и пропишем там:
Code
move_contact_solid(direction,-1)
vspeed = 0
Этот код не даст герою провалиться сквозь землю и стабильно опустит его на неё.
Теперь научим героя ходить в разные стороны и прыгать. Для этого создадим три события: нажатие на клавиши
Left,
Right и
Up.
В событии нажатия на
Left пропишем:
Code
if place_free(x-4,y)
x -= 4
Аналогичный код в событии нажатия на
Right, только с другим направлением.
Code
if place_free(x+4,y)
x += 4
Эти строки двигают героя влево и вправо, если перед героем нет никаких препятствий.
И, наконец, по нажатию на
Up, сделаем прыжок.
Code
if !place_free(x,y+1)
vspeed = -10
Эти строки придают герою вертикальную скорость, если под ним находится поверхность.
А теперь приступим к самому интересному. В событии
Create, всё у того же объекта
obj_hero пропишем следующий код:
Code
for (i=0; i<=100; i+=1)
{
xmas[i]=noone
ymas[i]=noone
}
j=100
i=100
backtime=false
sila=0
Для начала, в цикле задаем два массива, в которые мы будем записывать координаты, по которым движется наш герой. Соответственно чем больше размерность массива, тем длиннее путь мы можем записать. Я ограничился значением в 100.
Далее переменные
i и
j. Они служат ограничителями при записи и перемотке времени.
Переменная backtime определяет включен ли режим перемотки.
А переменная
sila будет служить нам, чтобы визуально отображать, сколько ещё мы сможем перематывать время.
Теперь переходим в событие
Step и первым дописываем условие для того кода, который у нас уже есть, т.е. для гравитации:
Code
if backtime=false
{
gravity_direction = 270
if place_free(x,y+1)
gravity = 0.5
else
gravity = 0
}
Это значит, что гравитация у нас будет работать только тогда, когда перемотка времени не активирована.
После этого допишем там же следующие строки:
Code
if backtime=false
{
if sila<100
sila+=1
xmas[100]=x
ymas[100]=y
for (i=0; i<=100; i+=1)
if i<=99
{xmas[i]=xmas[i+1]
ymas[i]=ymas[i+1]}
else
{xmas[i]=noone
ymas[i]=noone}
}
Этот кусок кода служит для записи координат героя в массив, а так же он изменяет переменную
sila. Действует весь этот код при условии, что режим перемотки времени не активирован.
Разберем код подробнее.
if sila<100
sila+=1 Тут все понятно, если значение переменной
sila меньше 100, то увеличиваем это значение на единицу, т.е. восстанавливаем энергию для перемотки времени.
xmas[100]=x
ymas[100]=y Эти строки записывают в сотую, последнюю ячейку массива значение координат в которых находится герой.
А дальнейший цикл служит для смещения значения из большей ячейки в меньшую.
for (i=0; i<=100; i+=1)
if i<=99
{xmas[i]=xmas[i+1]
ymas[i]=ymas[i+1]}
else
{xmas[i]=noone
ymas[i]=noone} Пробегаем циклом по всем элементам массива. Если номер ячейки меньше либо равен 99, то записываем в меньшую ячейку значение из соседней, большей:
xmas[i]=xmas[i+1]
ymas[i]=ymas[i+1] Таким образом в ячейку под номером 1, запишется значение из ячейки 2, в а ячейку 2 значение из ячейки 3 и т.д. Дойдя до сотой, последней ячейки, записывать туда будет нечего, потому мы записываем туда пустое значение:
xmas[i]=noone
ymas[i]=noone Тем самым каждый шаг значение ячеек будет динамически меняться, и хранить в себе только определенный промежуток, пройденный героем. Визуально это можно отобразить так:
000000[1]
000001[2]
000012[3]
000123[4] С записью закончили, теперь займемся перемоткой. Для этого создадим новое событие, нажатие и удерживание (keyboard) клавиши
Space и напишем там:
Code
if j>=0
{
gravity = 0
vspeed=0
instance_create(x,y,obj_effect)
sila-=1
backtime=true
if xmas[j]!=noone
{x=xmas[j]
xmas[j]=noone}
if ymas[j]!=noone
{y=ymas[j]
ymas[j]=noone}
j-=1
}
else
backtime=false
Итак, разберем по строкам. Если значение переменной
j больше, либо равно нулю, тогда выполняем перемотку.
Перед этим отключаем гравитацию и обнуляем вертикальную скорость, чтобы исключить какие либо нежелательные смещения героя.
Далее создаем тот самый, созданный нами, эффект перемотки.
instance_create(x,y,obj_effect) Таким образом, при движении героя в обратном направлении, за ним будет тянуться шлейф из созданного нами объекта со спрайтом эффекта.
Следующие строки уменьшают энергию и активируют режим перемотки времени:
sila-=1
backtime=true И, наконец, считывание значений из массива, и присваивание их соответствующим переменным
x и
y.
if xmas[j]!=noone
{x=xmas[j]
xmas[j]=noone}
if ymas[j]!=noone
{y=ymas[j]
ymas[j]=noone}
j-=1 Проверяем, не пустая ли ячейка, если не пустая, то считываем из неё значение в соответствующую переменную и делаем эту ячейку пустой. После чего уменьшаем значение переменной j на единицу, чтобы сместиться на следующую ячейку.
Если значение переменной
j становится меньше 0, то отключаем режим перемотки времени.
С основными аспектами разобрались. Остались мелочи. Сначала поставим ограничение на движения героя влево и вправо, и на прыжок. Для этого в соответствующих событиях первой строкой допишем:
Code
if backtime=false
{код, который уже написан в этих событиях}
Такое же ограничение ставим в событии столкновения со стеной:
Code
if backtime=false
{
move_contact_solid(direction,-1)
vspeed = 0
}
Теперь, добавим событие
release Space, т.е. отпускание клавиши “Пробел”. И пропишем там две строки:
Первая, возвращает нам значение переменной
j в исходное состояние, чтобы при каждом новом нажатии пробела, значения считывались из последней ячейки.
Ну а с переменной
backtime думаю все понятно, отключаем режим перемотки.
Наконец последнее, создадим событие
Draw и напишем там:
draw_healthbar(view_xview[0]+64,view_yview[0]+64,view_xview[0]+256,view_yview[0]+72,sila,c_silver,c_red,c_green,0,0,1)
draw_sprite(sprite_index,0,x,y) Тем самым создадим
healthbar, который будет отображать значение переменной
sila, т.е. будет показывать, сколько осталось энергии для перемотки времени.
А строка
draw_sprite(sprite_index,0,x,y), служит для того, чтобы спрайт нашего героя отображался при событии рисования.
Вот и всё. Теперь строим уровень и наслаждаемся.
Как всегда, исходник по уроку можно скачать тут: