Гхм... Надо было сразу скинуть игру - комп накрылся((( Хорошо еще будет, если я свою игру не потеряю(
PS: пишу с сотового.
Вид для печати
Гхм... Надо было сразу скинуть игру - комп накрылся((( Хорошо еще будет, если я свою игру не потеряю(
PS: пишу с сотового.
Titus, разбирал func WaitTime( seconds ) из util.gs. При применении в коде WaitTime( 10 ), например:
SamplePlay(13); // проигрываем 13 эффект (длительность 10 сек.)
MusicVolume( 30 ); // делаем тише основную музыку по громкости 30%
WaitTime( 10 ) // ждем 10 сек
MusicVolume( 100 ); // делаем основную музыку по громкости 100%
Обратил внимание, что во время паузы 10 сек, Диззи кроме ходьбы и прыжков, остальные команды/функции не работают. Почему? Просто хотелось чтобы по истечению 10 сек, основная музыка вернулась на 100%.
------------
Нашел еще счетчик:
/////////////////////////////////////////////////////////////////////////////////
// Gameplay time counter
/////////////////////////////////////////////////////////////////////////////////
int g_timer_lasttick;
// call on begin game callback (BeginNewGame) to reset timer
func TimerReset()
{
g_timer_lasttick = 0;
GameSet(G_TIMER,0);
}
// call on load callback (LoadUserData)
func TimerOnLoad()
{
g_timer_lasttick = 0;
}
// update, call on the game update handler
func TimerUpdate()
{
if(g_timer_lasttick==0) g_timer_lasttick = gs_time();
timer_currenttick = gs_time();
delta = timer_currenttick - g_timer_lasttick;
timer = GameGet(G_TIMER);
if(delta>0) timer += delta;
GameSet(G_TIMER,timer);
g_timer_lasttick = timer_currenttick;
}
// call with reference paramters to get the play time
func TimerGetTime( hours, minutes, seconds )
{
timer = GameGet(G_TIMER)/1000; // seconds
*hours = timer / 3600;
*minutes = (timer / 60) % 60;
*seconds = timer % 60;
}
// debug display of the elapsed time
func TimerPrint()
{
h=0; m=0; s=0;
TimerGetTime(&h,&m,&s);
println(h,":",m,":",s);
}
Может лучше это использовать? Но тогда хотелось бы твоих комментариев, для лучшего понимая сути (с примером хотелось бы).
Логично, что все останавливается, ведь ты ждешь истечения определенного времени, и работают фоном только хендлеры, которые вызываются движком.
Для затихания и нарастания громкости музыки используй функцию MusicFade(fadeout, fadein), где:
fadeout - время затухания музыки в секундах
fadein - время нарастания музыки в секундах
'Когда начинает играть новая музыка, старая затихает в течении заданного временного интервала fadeout. Громкость же новой музыки, соответственно, возрастает за время интервала fadein.'
Titus, да с fade'ами все понятно. Дело в другом. Музыка одна. Задача чтобы по истечению 10 сек музыка выровнялась по громкости на 100%. Т.е. как я понял WaitTime это для всего, а нужно привязать только к времени звучание эффекта, ну чтобы пока проигрывался эффект 10 сек., музыка звучала тише, а по истечению 10 сек, вернулась громкость на место.
Вот поэтому и подумалось, что может прикрутить сторонний счетчик времени, но пока не могу вникнуть - это оно или нет.
Продолжения перевода статей по редактору более не предвидится? :(
Titus, я пытался сделать так:
func ActionObject_3050 ( idx )
{
if(ObjGet(ObjFind(3050),O_STATUS)==0)
{
SamplePlay(13);
MusicVolume( 30 );
ObjSet(ObjFind(3050),O_STATUS,1);
WaitTime( 10 );
MusicVolume( 100 );
}
else
{
SampleStopAll(13); // почему-то просто SampleStop не работает...
ObjSet(ObjFind(3050),O_STATUS,0);
MusicVolume( 100 );
}
}
Например:
Подхожу к объекту 3050, нажимаю энтер, включается динамик и бла-бла 10 сек. Если во время звучания семпла еще раз энтер, то стоп.
Мб бы и сделал, помнится с началом цикла переводов я сперва пробовал ковырять редактор.
Думаю что для начала что-то короткое бы сделал.
Начинай) Для начального этапа там переведено достаточно)
---------- Post added at 17:17 ---------- Previous post was at 16:33 ----------
Да, если ты хочешь по прекращению заданного интервала времени, не останавливая на это время игру, совершить какое-то действие, нужно вводить специальный сервер обработки событий по таймеру. Подумаю над этим.
Titus, угу, именно так. Я привел простенький пример. Ну а там уже как хош можно крутить под свои дела.
Titus, да, раскурил. Нужно главу про звук перевести. Теперь понял. Ну а второй параметр это не обязательный - опциональный? (0 - один раз проиграть, если не указывать, то 0, а если указать 1 то по кругу)
---------- Post added at 17:04 ---------- Previous post was at 16:56 ----------
проясни, а если объявить в sound.gs
#def FX_MUSIC 13
после def это индекс или как?
запутался я чот совсем....
Titus, в моем случае, конечно, подходит SampleStopAll, и все работает прекрасно. Но таки хочется докопаться до сути именно SampleStop. От такой я тупоупоротый :)
Мой мозг твою конструкцию принимает вот так:
func ActionObject_3050 ( idx )
{
if(ObjGet(ObjFind(3050),O_STATUS)==0)
{
SamplePlay(FX_MUSIC);
midx = SamplePlay(FX_MUSIC);
ObjSet(ObjFind(3050),O_STATUS,1);
}
else
{
SampleStop( midx );
ObjSet(ObjFind(3050),O_STATUS,0);
}
}
И оно тупо вываливает игру по событию else c ошибкой BADTYPE бла-бла. Я б забил, но уже принципиально интересно. Я тупо потерял день из-за одной тупейшей команды... :)))
В твоем случае лучше использовать остановку всех самплов)
Во-первых, из этих строк:
первая строка лишнаяКод:SamplePlay(FX_MUSIC);
midx = SamplePlay(FX_MUSIC);
во-вторых, нельзя сохранять индекс мелодии в переменной, которая является локальной, и пропадает при выходе из функции. Это значение надо либо сохранять в глобальных переменных, либо останавливать все семплы. Потому что, у тебя в функции используется либо вызыв проигрывания мелодии, либо ее выключение. В случае выключения переменная midx не инициализирована, т.к. она локальная для этой функции, и при входе в функцию неопределена, и это конечно дает ошибку.
---------- Post added at 23:44 ---------- Previous post was at 23:43 ----------
Не потерял, а потратил на тренировку и обучение)
Titus, ты, наверное, забыл еще исправить мой скрипт на правильный (с коментариями), чтобы лучше воспринимать написаное тобой, да? :) Или я много хочу?
Я не буду использовать остановку всех сэмплов. Ибо дойду до конца. Или с твоей помощью или народным способом - перебором всего возможного.
Потерял. Это не тренировка. Это не мое. Я больше скриптов разобрал и написал, чем с этой долбаной СамплеСтоп долбаюсь. Не хватает хороших готовых примеров.
Итак, новинка - возможность запускать отложенные функции.
Для начала добавляем в файл def.gs следующие строки:
В данном случае мы вводим три новых игровых переменных с номерами 100, 101, 102 (или любые другие свободные для вашей игры номера глобальных игровых переменных). Эти переменные нам необходимы не только для реализации механизма запускоа отложенных функций, но и для корректного сохранения состояния в файле отгрузок.Код:#def G_TICKS 100 // Счетчик игрового времени
#def G_TFUNC 101 // Идентификатор отложенной функции
#def G_TVALUE 102 // Время вызова отложенной функции
Переменная G_TICKS - это дополнительный таймер, приращиваемый каждый игровой фрейм (1/36 секунды для стандартных настроек). Этот счетчик инкрементируется в хендлере HandlerGameUpdate(), который вызывается только во время игрового процесса, тогда как в режиме меню он не вызывается, и счетчик, как нам и требуется, не инкрементируется.
Переменная G_TFUNC содержит ID (по простому - номер) отложенной функции. Почему номер, а не имя? Все потому, что стандартный файл отгрузок не умеет сохранять строковые величины, и для упрощения каждой отложенной функции присваевается уникальный номер.
Переменная G_TVALUE - это время вызыва отложенной функции.
Далее, добавляем в файл handlers.gs в функцию HandlerGameUpdate() после строк:
следующий фрагмент:Код:// update some particluar object(s) that need to be updated no matter in what room we are
// ...
Далее, в файл utils.gs добавляем функцию:Код:TValue = GameGet(G_TVALUE); // Получить время вызова отложенной функции
if (TValue) // Если время = 0, то нет отложенных функций
{
if (TValue <= GameGet(G_TICKS)) // Если текущее время достигло времени вызова функции, то
CallTimeFunc(); // вызвать обработчик отложенных функций
}
GameSet(G_TICKS, GameGet(G_TICKS) + 1); // Прирастить счетчик игрового времени
Ну и, наконец, добавим в игру простой пример.Код://///////////////////////////////////////////////////////////////////////////////
//
// Store time function delay and ID
//
/////////////////////////////////////////////////////////////////////////////////
func TimeFuncSet(fid, fdelay)
{
GameSet(G_TFUNC, fid); // Сохранить ID отложенной функции в переменной G_TFUNC
GameSet(G_TVALUE, GameGet(G_TICKS) + fdelay); // Сохранить время вызыва отложенной функции в переменной G_TVALUE
}
В требуемое место игры в файле game.gs сперва добавляем первый запрос отложенной функции:
А так же добавляем в тот же файл game.gs обработчик отложенных функций:Код:TimeFuncSet(TM_FIRSTFUNC, 5*36); // Запросить функцию TM_FIRSTFUNC через 5 секунд
Как видно из примера, сперва запрашивается отложенная функция TM_FIRSTFUNC через интервал 5 секунд. В этой функции игрока подбрасывает наверх и звучит звук, а так же сразу запрашивается следующая отложенная функция TM_SECONDFINC через интервал 10 секунц. В этой функции у игрока убавляется 30 единиц энергии и так же звучит звук, после чего отложенные функции отключаются.Код://///////////////////////////////////////////////////////////////////////////////
//
// Time Functions (non-latent)
//
/////////////////////////////////////////////////////////////////////////////////
#def TM_FIRSTFUNC 1
#def TM_SECONDFUNC 2
// ... etc
func CallTimeFunc()
{
TFunc = GameGet(G_TFUNC); // Получить ID вызываемой функции
if (TFunc == 1) // TM_FIRSTFUNC
{
println("First Time Call"); // [отладочная информация]
CM_EnterJump(0, 10); // Прыжок вверх
SamplePlay(1); // Включить звук №1
TimeFuncSet(TM_SECONDFUNC, 10*36); // Запросить функцию TM_SECONDFUNC через 10 секунд
return; // Выход
}
if (TFunc == 2) // TM_SECONDFINC
{
println("Second Time Call"); // [отладочная информация]
PlayerSet(P_LIFE,PlayerGet(P_LIFE)-30); // Отнять у Диззи 30 единиц энергии
SamplePlay(2); // Включить звук №2
GameSet(G_TVALUE, 0); // Отключить запрос временных функций
return; // Выход
}
// ... etc
GameSet(G_TVALUE, 0); // Отключить запрос временных функций
// (заглушка для неправильных ID функций)
}
Замечание: поскольку, обработчик отложенных функций не фоновой (non-latent), то из него НЕ ДОЛЖНЫ вызываться фоновые (latent) функции. При желании вызвать фоновые функции, следует пользоваться конструкцией ScrRequest(). Однако, т.к. отложенная функция может вызваться в любой момент, в независимости от игровой ситуации (кроме нахождения в меню), отложенными функциями следует пользоваться с большой аккуратностью, чтобы не испортить ход игры.
Так же статья опубликована на DizziAge-форуме
О, чудо! С этим нужно было переспать....
Завел в gamedef.gs
#def G_FXМ 100
и конструкция
func ActionObject_3050 ( idx )
{
if(ObjGet(ObjFind(3050),O_STATUS)==0)
{
G_FXM = SamplePlay(FX_MUSIC);
ObjSet(ObjFind(3050),O_STATUS,1);
}
else
{
SampleStop(G_FXM);
ObjSet(ObjFind(3050),O_STATUS,0);
}
}
заработала как нужно.
Теперь будем разбирать китайские письмена что выше. Спасибо.
---------- Post added at 09:48 ---------- Previous post was at 09:41 ----------
Titus, а разве в game.gs можно заносить
#def TM_FIRSTFUNC 1
#def TM_SECONDFUNC 2
переменные?
афигеть.....
Только не в gamedef.gs, а в def.gs.
И не 100, т.к. 100, 101 и 102 уже занято тем, что я описал выше, а, например 104.
Далее - то, что у тебя - не могло заработать) Так как G_FXM - это не переменная, а константа)
---------- Post added at 12:16 ---------- Previous post was at 12:15 ----------
Можно. Это не переменные, а, скажем так, константы. Все файлы .gs равнозначные.
Titus, но оно работает. у меня пока не занято 100, поскольку я еще разбираю твой пример и не вносил.
Твоя конструкция равносильна:
100 = SamplePlay(FX_MUSIC);
и
SampleStop(100);
что является абсурдом, и выдаст ошибку компиляции.
Обьяснение одно - ты не там или неправильно прописал #def G_FXМ 100, в связи с чем G_FXM воспринимается компилятором не как константа, а как локальная переменная.
Titus, проверил еще раз. Все, как описано выше. Только теперь по событию else игра не вываливается с ошибкой, а выключает эффект. Ну смысл мне обманывать?
---------- Post added at 11:21 ---------- Previous post was at 11:13 ----------
Ну и наверное последнее, это SampleVolume( percent ). Можно ли как-то эту команду привязать только к одному спецэффекту, а не ко всем происходящим в игре сразу?
Пришли-ка мне свою программу)
---------- Post added at 14:42 ---------- Previous post was at 13:26 ----------
Разобрался.
Оказывается в языке GS9, в отличие от Си, глобальные определения НЕ являются константами, хотя рекомендуется использовать их только в роли констант.
9.COMPILE DIRECTIVES
yuriyЦитата:
Even if the defines are actually global variables, it is recomended to be treated as constants and not change their values. There is more about those defines, but for the level of this book, this is enough.
Для проверки можешь заменить #def G_FXМ 100 на #def G_FXМ 123456789, и все равно будет работать.
Но конструкция все равно неправильная. Попробуй отпишись в середине проигрывания звука, а потом перезапусти игру и загрузи отгрузку. Посмотри, что получится)
Titus, а если в def.gs перенести, то конструкция будет правильной? (ну или приведи пример)
Придумал вариант без всех этих наворотов:
Добавляем в файл utils.gs следующую функцию:
Система проигрывания семплов на движке DizzyAge устроена следующим образом. Есть 16 голосов, по каждому из которых может играть свой семпл. Т.е. одновременно можно включить на проигрывание не более 16 перекрывающихся семплов. Если вы включили 17-й, а те 16 все еще играют, то будет ошибка.Код://///////////////////////////////////////////////////////////////////////////////
//
// Stop a voices, played specified sample
//
/////////////////////////////////////////////////////////////////////////////////
func SampleStopByID(sid)
{
for (i=SOUND_VOICES-1; i>=0; i--) // Перебираем все голоса от 0 до SOUND_VOICES (по умолчанию 16)
{
if (SamplePlaying(i) == sid) // Если в данном голосе звучит семпл с ID = sid,
SampleStop(i); // то останавливаем его звучание
}
}
Вышеприведенная функция работает очень просто. Перебираются все 16 голосов, и ищется, на каком из них играет семпл с заданным ID, и, соответствующие голоса (а их может быть несколько) выключаются.
---------- Post added at 15:08 ---------- Previous post was at 15:03 ----------
Нет, неправильной, т.к. все файлы с расширением .gs равнозначны.
---------- Post added at 15:15 ---------- Previous post was at 15:08 ----------
Как я понимаю, нельзя)
т.е. это будет верно?
func ActionObject_3050 ( idx )
{
if(ObjGet(ObjFind(3050),O_STATUS)==0)
{
SamplePlay(13);
ObjSet(ObjFind(3050),O_STATUS,1);
}
else
{
SampleStopByID(13);
ObjSet(ObjFind(3050),O_STATUS,0);
}
}
---------- Post added at 13:18 ---------- Previous post was at 13:17 ----------
Это очень не гибко.
Верно. Но все равно проверь.
---------- Post added at 15:28 ---------- Previous post was at 15:26 ----------
Сделай несколько звуков с разной громкостью. Благо, их количество не ограничено.
---------- Post added at 15:30 ---------- Previous post was at 15:28 ----------
Кстати, учти, что проигрываемые в данный момент звуки, вроде бы не запоминаются в файле отгрузки. Выбери длинный звук и проверь.
Titus, да работает, работает как написано выше. Абы глюков не было.
Не получится. Играет семпл, игрок выходит в другую комнату. Уменьшаться по громкости должен только один семпл (текущий). Если сделать разные..... стоп. Хотя есть варианты.... тока сейчас не получится проверить, это уже дома. Аудишн нужен.
да, при записи игры (когда проигрывается сэмп) и после загрузки - сэмп уже не звучит. Но ничего не мешает вкл. проигрывание заново.
Titus, блин, это 3-4 трека огг лепить (пусть хоть по 1 метру), вес только растет. Вот это не гибкость. Вот чего нельзя типа SampleVolume (sample_id, percent) сделать? Чтобы sample_id был опциональным как loop ???
Да и вообще движок очень куцый по сравнению с теми вещами что описаны в играх.
---------- Post added at 14:09 ---------- Previous post was at 14:00 ----------
Titus, походу это
func FX_Stop(fx)
{
if(fx==-1) return -1;
while(true)
{
v = FX_Playing(fx);
if(v==-1) return;
SampleStop(v);
}
}
делает то же самое, что и SampleStopByID
Что скажешь?
да, уже заметил
func FX_Playing(fx)
{
if(fx==-1) return -1;
for(v=0;v<SOUND_VOICES;v++)
if(SamplePlaying(v)==fx) return v;
return -1;
}
да в tos залез
FX_Playing(fx) - выдает номер голоса, по которому играет заданный эффект. Однако, если эффект играет в нескольких голосах одновременно, то будет выдан номер только одного из этих голосов. Так что фактически FX_Stop() делает тоже самое, что и у меня, только выключает одну копию звука, а у меня выключает все)
---------- Post added at 17:00 ---------- Previous post was at 16:50 ----------
Единственное, моя функция не проверяет ошибки, но судя по всему это и не требуется.