Войти на сайт
×
ТЕМА: Time Management (ACE)
Time Management (ACE) 11 года 2 нед. назад #66148
|
Название: Time Management (ACE)
Автор: caveman Версия: 1.0 Тип: работа с переменными и свитчами
Описание:
Написал небольшой, но, потенциально полезный скриптик для управления временем. Он умеет считывать с одного или нескольких файлов формата csv (строки из слов, разделенных точкой с запятой - трансформируется из Excel через Save as csv; а эксель, или calc - просто для удобства редактирования) набор данных по управлению переменными, свитчами и селфсвитчами в реальном времени (точность до секунды) и сходу применять их в игре, в том же реальном времени от начала игры/запуска файла. Кроме этого, он поддерживает циклический запуск этого набора в заданном в нем же промежутке времени. Вроде пока всё. Если ничего непонятно, поясню словами и демкой: * Я хочу сделать демку, которая изображает два дня в лесу. * Я хочу удобно управлять временами дня (хотя бы через screen color tone), погодой и событиями в течении этого времени. * Я хочу думать в реальном времени, а не в фреймах, например, пусть мои сутки длятся 2 минуты. - Я составляю 2 файлика (в экселе, так мне удобно) - тут приведу отконверченный в csv вариант обработки переменных, свитчей и селфсвитчей, предварительно настроенных в проекте для времен дня и погоды. Файлик для огорода в демке. ЗЫ: если видите пусто между двумя ";", то там ячейка попросту пуста - Я добавляю скрипт, что внизу под спойлером, чуть выше Main. - Я добавляю в авторане первой (и единственной) карты вызов $time_owner.add_manager(1) $time_owner.add_manager(2) $time_owner.reload(1, "test") - тут файл погоды и времени дня $time_owner.reload(2, "farm") - тут обработка роста овощей $time_owner.start_all - для простоты - запускаю всё, можно запускать и по отдельности, командой $time_owner.start(1) - Я запускаю демо и радуюсь Теперь разберем файлик, вот он: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] Name;forest;;;;;; Cycling;yes;;;;;; Time;0:00:00;0:04:00;;;;; Commands;;;;;;; Время;Тип;Id;Значение;Map_id;Event _id;Letter;Comment 0:00:00;Variable;1;1;;;;morning 0:00:30;Variable;1;2;;;;day 0:01:00;Variable;1;3;;;;evening 0:01:30;Variable;1;4;;;;night 0:02:00;Variable;1;1;;;;morning 0:02:30;Variable;1;2;;;;day 0:03:00;Variable;1;3;;;;evening 0:03:30;Variable;1;4;;;;night 0:00:02;variable;2;1;;;;music day 0:01:10;variable;2;2;;;;music night 0:02:02;variable;2;1;;;;music day 0:03:10;variable;2;2;;;;music night 0:02:40;Variable;3;1;;;;rain 0:03:25;Variable;3;2;;;;no rain 0:01:00;Variable;4;1;;;;fog 0:01:35;Variable;4;2;;;;no fog 0:02:10;Variable;4;1;;;;fog 0:03:20;Variable;4;2;;;;no fog 0:01:40;Switch;1;True;;;;crow 0:02:10;Switch;1;FALSE;;;;no crow 0:00:05;SelfSwitch;;True;1;3;A;squirrel 0:01:10;SelfSwitch;;FALSE;1;3;A;squirrel 0:03:35;SelfSwitch;;True;1;3;A;squirrel 0:03:58;SelfSwitch;;FALSE;1;3;A;squirrel Первая строка в нем - заголовок. Он ни к чему не обязывает, и просто служит мне для удобства. Вторая строка показывает, запускаю ли я обработку файла циклически (yes/no). Третья строка задает время начала запуска и окончания запуска (очень полезно для циклических запусков). Четвертая и пятая - просто для удобства в экселе. А далее начинаются команды (значения нечувствительны к регистру) Время; - время срабатывания в формате hh:mm:ss Тип; - тип (Variable, Switch, SelfSwitch) Id; - номер переменной или свитча, для SelfSwitch бесполезно Значение; - значение переменной/свитча. Для variable это - число; для остальных вариантов - True или False Map_id; - номер карты, актуален для селфсвитча Event_id; - номер события, актуален для селфсвитча Letter; - буква-селфсвитч (A,B,C,D), актуален для селфсвитча Comment - комментарий (для удобства) Если хотите русские надписи в файлах - сохраняйте их в utf-8 (эксель предлагает по умолчанию в cyrillic) Вот он сам: ВНИМАНИЕ: Спойлер! [ Нажмите, чтобы развернуть ][ Нажмите, чтобы скрыть ] =begin
========================== Time management by caveman ==========================
Скрипт позволяет настроить поведение переменных, переключателей и локальных
переключателей в реальном времени в одном или несколько файлов .csv,
например, для задания смены времен дня, ночи, поведения NPC и прочего.
Файл изначально набивается в excel или calc, для удобста (впрочем,
можно это сделать и в блокноте, соблюдая формат, описанный ниже):
Name;forest;;;;;; - название для удобства чтения
Cycling;yes;;;;;; - признак, запускать ли обработку циклически
Time;0:00:00;0:04:00;;;;; - начало и окончание запуска (для циклов особенно полезно)
Commands;;;;;;; - для удобства чтения
Время;Тип;Id;Значение;Map_id;Event _id;Letter;Comment - описание команд, для удобства чтения
0:00:00;Variable;1;1;;;;morning
0:00:30;Variable;1;2;;;;day
0:01:40;Switch;1;True;;;;crow
0:02:10;Switch;1;FALSE;;;;no crow
0:03:35;SelfSwitch;;True;1;3;A;squirrel
0:03:58;SelfSwitch;;FALSE;1;3;A;squirrel
Выше примеры задания обработки данных, для переменной (Variable),
переключателя (Switch) и локального переключателя (SelfSwitch).
- Время в формате hh:mm:ss
- Название типа переключателя нечувствительно к регистру
- Для переменных и переключателей обязательно задать Id
- Для локального переключателя обязательно задать номер карты, номер события и
букву (А-D), впрочем, скрипт поддержит и расширение (A-Z) для них.
- Последнее слово в строке - необязательный комментарий
NB: ruby не кушает русские символы, сохраненые не в utf-8, так что либо
пишите на латинице, либо сохраняйтся файл csv в utf-8.
Использование в событиях примерно такое:
$time_owner.add_manager(1) - добавить первый менеджер
$time_owner.add_manager(2) - добавить еще один
$time_owner.reload(1, "test") - загрузить данные в первый менеджер
$time_owner.reload(2, "farm") - загрузить данные во второй менеджер
$time_owner.start_all - для простоты - запускаю всё, можно запускать и
по отдельности, например, командой $time_owner.start(1)
Описание методов в комментах к классу Time_Owner в конце скрипта.
После запуска менеджера, он ведет отсчет с того момента, когда он
запущен и выполняет простановку значений переменным, переключателям и
локальным переключателям в соответствующее время.
=end
class Time_Command
attr_accessor :affect_type # 0 - variable, 1 - switch, 2 - self switch
# для selfswitch
attr_accessor :map_id
attr_accessor :event_id
attr_accessor :letter
attr_accessor :ss_value
# для switch
attr_accessor :switch_id
attr_accessor :s_value
# для variable
attr_accessor :var_id
attr_accessor :v_value
attr_accessor :need_refresh # true (пока)
attr_accessor :time # в секундах
attr_accessor :is_used # уже пройдено
def initialize
self.need_refresh = true
end
end
class Time_Manager
attr_accessor :id # id
attr_accessor :start_time # в секундах
attr_accessor :end_time # в секундах
attr_accessor :cur_time # в секундах
attr_accessor :real_start_time # в секундах
attr_accessor :need_cycle # запускать циклически
attr_accessor :commands # список команд
attr_accessor :is_started
def initialize(id)
self.id = id
self.commands =[]
@regexp = /\A(.*?);(.*?);(.*?);(.*?);(.*?);(.*?);(.*?);(.*?)\Z/
end
#==========================================================#
#========== Загрузка из файла =============================#
#==========================================================#
def reload(filename)
if FileTest.exist?(sprintf("%s.csv",filename))
self.commands = []
file=File.open(sprintf("%s.csv",filename),"r")
load_timing(file)
file.close
# p self.commands
end
end
def load_timing(file)
@lines = file.readlines
@line = 0
@line += 1 # название
# цикличность
@lines[@line].gsub(@regexp) do
self.need_cycle = $2.to_s.upcase == "YES"
end
@line += 1
# время начала и конца
@lines[@line].gsub(@regexp) do
self.start_time = extract_time($2.to_s)
self.end_time = extract_time($3.to_s)
end
@line += 3 # пропуск строк "команды" и "заголовки"
while @line < @lines.length
@lines[@line].gsub(@regexp) do
command = Time_Command.new
command.time = extract_time($1.to_s)
p $1.to_s
case $2.to_s.upcase
when "VARIABLE"
command.affect_type = 0
command.var_id = $3.to_i
command.v_value = $4.to_i
when "SWITCH"
command.affect_type = 1
command.switch_id = $3.to_i
command.s_value = $4.to_s.upcase == "TRUE"
when "SELFSWITCH"
command.affect_type = 2
command.ss_value = $4.to_s.upcase == "TRUE"
command.map_id = $5.to_i
command.event_id = $6.to_i
command.letter = $7.to_s
else
p 'неверный тип!'
end
self.commands.push(command)
end
@line += 1
end
end
def extract_time(str)
# выцепим время из строки вида hh:mm:ss
str.gsub(/\A(.+?)\:(.+?)\:(.+?)\Z/) do
hh = $1.to_i
mm = $2.to_i
ss = $3.to_i
return hh * 60 * 60 + mm * 60 + ss
end
end
#==========================================================#
#========== Управление ====================================#
#==========================================================#
def start
self.cur_time = 0
self.real_start_time = Graphics.frame_count / Graphics.frame_rate
self.is_started = true
end
def stop
self.is_started = false
end
def reset
stop
start
end
#==========================================================#
#========== Автоапдейт ====================================#
#==========================================================#
def update
if is_started
flag = false # рефрешить ли карту
@total_sec = Graphics.frame_count / Graphics.frame_rate
# время тут - сдвиг от запуска
self.cur_time = @total_sec - self.real_start_time
# для циклического запуска, проверяем конец цикла, сбрасываем всё
if self.need_cycle && self.cur_time >= self.end_time
for c in self.commands
c.is_used = false
end
self.cur_time = 0
self.real_start_time = Graphics.frame_count / Graphics.frame_rate
end
# просматриваем команды с точным временем
for c in self.commands
if !c.is_used
if c.time <= self.cur_time
call_command(c)
c.is_used = true
flag = true
end
end
end
if flag
$game_map.need_refresh = true
end
end
end
def call_command(c)
if c.affect_type == 0
$game_variables[c.var_id] = c.v_value
elsif c.affect_type == 1
$game_switches[c.switch_id] = c.s_value
elsif c.affect_type == 2
key = [c.map_id, c.event_id, c.letter]
$game_self_switches[key] = c.ss_value
end
end
end
class Time_Owner
attr_accessor :time_managers
def initialize
self.time_managers = []
end
# добавить менеджер c кодом id для последующего обращения к нему
def add_manager(id)
self.time_managers.push(Time_Manager.new(id))
end
# удалить менеджер c кодом id
def remove_manager(id)
for m in self.time_managers
if m.id == id
delete(m)
end
end
end
# загрузить в менеджер с кодом id данные из файла filename
def reload(id, filename)
for m in self.time_managers
if m.id == id
m.reload(filename)
end
end
end
# запустить менеджер с кодом id
def start(id)
for m in self.time_managers
if m.id == id
m.start
end
end
end
# запустить все менеджеры
def start_all
for m in self.time_managers
m.start
end
end
# остановить менеджер с кодом id
def stop(id)
for m in self.time_managers
if m.id == id
m.stop
end
end
end
# остановить все менеджеры
def stop_all
for m in self.time_managers
m.stop
end
end
# перезапустить менеджер с кодом id
def reset(id)
stop(id)
start(id)
end
# перезапустить все менеджеры
def reset_all
stop_all
start_all
end
def update
for m in self.time_managers
m.update
end
end
end
class Scene_Base
alias tm_update update
def update
tm_update
if $time_owner != nil
$time_owner.update
end
end
end
class Scene_Title
alias tm_start start
def start
$time_owner = Time_Owner.new
tm_start
end
end Демо c маленьким огородом, настроенным в файле, тут: yadi.sk/d/GQWprgqLDzwWX |
Администратор запретил публиковать записи гостям.
За этот пост поблагодарили: DeadElf79
|
Модераторы: NeKotZima
Время создания страницы: 0.199 секунд