Думаю, то что я хочу описать сегодня, можно вновь отнести к этой теме. И так, чем же ещё может быть полезен вызов скрипта внутри ивента?
Не давно, для проекта на готв, я написал небольшую систему бросания динамита. На её примере и будет построена эта статья. Однако оговорюсь сразу, что тут мной были использованы несколько скриптов, но в целом они не так важны.
Скрипт на локальные переключатели и, скрипт с которым мне помог Липтон:
class Game_Event < Game_Character
attr_reader :event
end
В чём же тут смысл? Смысл в том, чтобы реализовать ивент, который будет изображать из себя бросаемый объект и проверять область вокруг на предмет чего-либо. В моём случае, ивент искал в небольшом квадрате вокруг себя, ивенты с определённым названием (тут мне помог скрипт от Липтона). Но точно так же можно проверить, определённый регион или ещё что-то в этом роде.
Думаю, как реализована возможность положить динамит, понять легко, но всё же поясню немного:
$game_map.events[$tnt_id].set_direction(2)
$game_map.events[$tnt_id].moveto($game_player.x, $game_player.y)
Switch_Core.turn_on($tnt_id,"A")
if $tnt_id == 1
$tnt_id += 1
else
$tnt_id -= 1
end
Что тут собственно происходит? Первыми двумя строчками, мы приводим событие в нужное нам положение.
$game_map.events[$tnt_id].set_direction(2) - заставляет ивент с указанным id встать лицом вниз(ибо именно в таком положении динамит не зажжён в моём чарсете). Так же есть варианты: 4: влево, 6: вправо, 8: вверх.
$tnt_id - это глобальная переменная, которую я заранее объявил в скриптах. Вы можете с таким же успехом использовать и $game_variables[n], просто мне не хотелось лишний раз их трогать.
Switch_Core.turn_on($tnt_id,"A") - команда скрипта, на локальные переключатели. Собственно, она включает локальный переключатель "А", для указанного ивента. На странице с которым и описаны все возможности взаимодействия.
if $tnt_id == 1 # - эта конструкция, даёт нам возможность одновременно использовать сразу два динамита.
$tnt_id += 1 # если глобальная переменная равна 1 то мы прибавляем к ней 1
else # и отнимаем 1, если не равна.
$tnt_id -= 1 # таким образом, когда мы пытаемся сделать что-то с динамитом,
end # используется не занятый пока что ивент.
Ну и, главное, в конце не забыть уменьшить число динамита у нас в кармане на 1, это можно сделать командой ивента. Собственно, теперь, когда мы научились класть динамит, приступим к более сложной процедуре. К его броску.
x = $game_player.x
y = $game_player.y
$game_map.events[$tnt_id].moveto(x, y)
$game_map.events[$tnt_id].set_graphic("!Drop", 0)
case $game_player.direction
when 2
i = 3
i -= 1 until $game_map.check_passage(x, y+i, 0xF)
$game_map.events[$tnt_id].jump(0, i)
when 4
i = -3
i += 1 until $game_map.check_passage(x+i, y, 0xF)
$game_map.events[$tnt_id].jump(i, 0)
when 6
i = 3
i -= 1 until $game_map.check_passage(x+i, y, 0xF)
$game_map.events[$tnt_id].jump(i, 0)
when 8
i = -3
i += 1 until $game_map.check_passage(x, y+i, 0xF)
$game_map.events[$tnt_id].jump(0, i)
end
Switch_Core.turn_on($tnt_id,"B")
Что бы понять, что происходит выше, нам надо ответить себе на вопрос: "Что происходит, когда мы что-то бросаем?". Всё верно - предмет летит с заданной нами силой и падает. А если встречает стену, то ударяется об неё и остаётся там, конечно же можно ещё и сделать что бы при ударе о стену объект летел обратно по инерции, но я не стал заморачиваться. Так же, эта команда не рассматривает вариант столкновения с ивентами, к сожалению.
Но рассмотрим подробнее сам код. Так-как начальная точка полёта, это местоположение игрока, то мы должны переместить ивент на его клетку. Строки: x = $game_player.x и y = $game_player.y, позволяют нам записать в локальные (то есть уникальный для этой команды вызова скрипта и не доступные больше ниоткуда) переменные позицию игрока по x и y.
Дальше, мы, используя уже записанные координаты, перемещаем ивент на позицию игрока и задаём ему графику динамита:
$game_map.events[$tnt_id].moveto(x, y)
$game_map.events[$tnt_id].set_graphic("!Drop", 0)
Используя, уже знакомую нам конструкцию case, определяем в какую сторону смотрит игрок и куда он, соответственно, бросит динамит. Однако, кроме задать направление полёта, мы должны задать его траекторию. И, в зависимости от того, как близко игрок будет к непроходимому участку, надо поменять эту самую траекторию (естественно, с точки зрения логики, траектория должна изменяться непосредственно во время полёта, но об этом как-нибудь в другой раз). Рассмотрим вариант, с положением игрока лицом вниз. Для этого есть такая строчка: i -= 1 until $game_map.check_passage(x, y+i, 0xF), где i - это объявленная чуть выше локальная переменная со значением три. Until же, это конструкция, на вроде case, только работающая несколько другим способом. Обычно, она выглядит почти как Case:
until выражение
команда
end
Однако, её задача заключается в том, чтобы выполнять команду внутри, до тех пор, пока выражение не станет "true" - то есть истинным.
Например:
until a != 2 #до тех пор, пока "а", не равно двум.
а + 1 #прибавляем к "а" единицу.
end
Однако, внутри моего вызова используется модификатор until. Его удобно использовать, если надо выполнить всего одну команду внутри проверки.
Например:
а + 1 until a != 2 # Многократно прибавляем к "а" единицу, пока она не станет ровна двум.
Или же, конкретно в моём случае, вот такая загагулина:
i -= 1 until $game_map.check_passage(x, y+i, 0xF)
$game_map.check_passage(x, y, 0xF) - команда на проверку проходимости заданной координатами клетки.
Найдя клетку, в заданном диапазоне, куда может приземлиться динамит, мы отправляем его в полёт, командой прыжка ивента: $game_map.events[$tnt_id].jump(0, i).
Сделав всё это, мы, опять же используя команду из скрипта на локальные переключатели, включаем страницу с переключателем "B", где уже и описываем сам взрыв.
Что бы не загружать лишний раз систему, сам взрыв я реализовал по средствам заданного у ивента маршрута. Там нас интересуют опять же, строки вызова скрипта. Их пять:
$deev_x = $game_map.events[1].x - записывает в глобальную переменную координату x ивента с указанным номером (опять же, тут можно использовать и $game_variables, если вы не хотите заморачиваться с объявлением собственных переменных).
$deev_y = $game_map.events[1].y - делает то же, для координаты у.
$game_map.events[1].moveto(22, 15) - перемещает в сторону "взорвавшийся" ивент.
$game_temp.reserve_common_event(5) - вызывает глобальный ивент, где обрабатываются последствия взрыва.
Switch_Core.toggle(1,"B") - выключает локальный переключатель "В" у ивента, что автоматически возвращает его на пустую страницу.
А вот, что внутри глобального ивента, что должен обработать последствия взрыва:
x = $deev_x
y = $deev_y
for e in [x+1, x-1, x]
for i in [y+1, y-1, y]
id = $game_map.event_id_xy(e, i)
if id != 0
Switch_Core.toggle(id,"A") if $game_map.events[id].event.name == "block"
end
end
end
x = $deev_x и y = $deev_y в данном случае, строки нужные лишь для удобства работы дальше. В принципе, мы могли бы использовать и значения из глобальных переменных, но у локальных просто название короче.
for e in [x+1, x-1, x] - эта строка поочерёдно задаёт переменной значения внутри квадратных скобок и выполняет команду дальше.
for i in [y+1, y-1, y] - делает то же и самое, а так как она внутри предыдущей команды, то мы получаем блок из координат, примерно такого вида:
id = $game_map.event_id_xy(e, i) - одновременно объявляет новую локальную переменную и задаёт ей значение id ивента, по координатам.
Switch_Core.toggle(id,"A") if $game_map.events[id].event.name == "block" - проверяет имя ивента, если оно соответствует тому, что нам нужно, то активирует локальный переключатель A у ивента с объявленным ранее id.
if id != 0 - спасает от ошибки, в выше описанной строке, если ивента в координатах не оказалось.
В общем, на этом в целом-то всё. Более подробно можно посмотреть в демке, доступной по старой ссылке
и тут. События камней я специально немного переписал, что бы можно было вернуть их обратно. Это вызвало небольшой графический косяк, но он не характерен для рабочей версии ивентов, так что можно не волноваться об этом.
Засим, откланяюсь и попрошу писать комментарии в случае если что-то будет непонятно или есть предложения по улучшению.
P.S. Рекомендую так же ознакомиться с разделом "управляющие структуры" в русско язычной справке по VX Ace, которую можно найти по ссылке у меня в подписи.
Переименовать эту тему что-ли в "Лаборатория Демия"...