Господа, возник вопрос. Заранее скажу: я только начал изучать среду. Так вот. Решил запилить диалоговую систему по принципу: 1)Подходишь к объекту, нажимаешь [клавиша] 2)Появляется прямоугольник и на нём проигрывается какой-то текст. Первый абзац появился, проигрался, исчез, за ним второй, исчезает потом третий и т.д. 3)Когда реплик больше нет, пропадает сам прямоугольник
Я привязал диалоговое окно к верху окна приложения.
Принцип простой. Реализовывал через событие Draw GUI:
Код
var S= distance_to_object(object_player); if (S<=3 and keyboard_check_pressed(vk_enter)) script0();
Так вот в чём проблема. Персонаж подходит, я нажимаю [клавиша], диалоговый прямоугольник появляется, но тут же исчезает. И вот я здесь. У меня будет два вопроса, если позволите:
1) как сделать так, чтобы прямоугольник появлялся и исчезал, когда это надо (может команда какая есть, или способ более удобный и умный, заранее предусмотренный, просто я ещё только постигаю GameMaker, раньше только с C++ и Java работал.
2) и второй вопрос и разряда "так, на будущее". Как сделать так, чтобы буквы строчки текста выходили не все сразу, а одна за одной?
GameMakerBeginner, а keyboard_check_pressed() срабатывает не только ли тогда, когда клавиша pressed (нажата) ? Попробуй подержать Enter подольше, напиши о результате
keyboard_check_pressed() срабатывает не только ли тогда, когда клавиша pressed (нажата) ?
Я это уже пробовал. Не работает. Только если поставить
Код
keyboard_check()
или
Код
keyboard_check_direct()
и удерживать клавишу, то получится. Но ты же не будешь для диалога держать всё время клавишу. Может быть надо как-то через объект или что-то другое делать?
Сообщение отредактировал GameMakerBeginner - Вторник, 11 Февраля 2020, 01:17
GameMakerBeginner, а, это же всё в цикле происходит, отрисовка? Тогда сделай флажок типа talking (ну или как хочешь назови, лишь бы понятно было). И вот когда нажимаешь клавишу, присваивай true, когда завершаешь диалог -- false. А, ну и условие поменяй с if (S<=3 and keyboard_check_pressed(vk_enter)) на if (S<=3 and talking).
for (int i = 1; i < main_string.length() + 1; i++) { sub_string = main_string.substr(0, i); // Получаем подстроку, каждый раз бОльшую на один символ, пока не дойдём до размера изначальной строки. std::cout << sub_string << std::endl; // Это заменить на отрисовку на экране. // А тут добавить задержку, например. }
В чём идея? Мы не дорисовываем символ каждый раз, а перерисовываем всю текущую строчку, каждый раз увеличивая её на один символ. Идея же понятна? Вывод:
H He Hel Hell Hello Hello Hello W Hello Wo Hello Wor Hello Worl Hello World Hello World!
Сообщение отредактировал DivES - Вторник, 11 Февраля 2020, 17:07
Спасибо большое. Теперь более-менее понятно. С пропуском диалога я что-нибудь уже придумаю, но есть ли команда какая, которая делает задержку, как в C++
Код
Sleep();
Я могу сделать через alarm, но если существует команда, то зачем мучиться ?
Добавлено (12 Февраля 2020, 01:02) ---------------------------------------------
ЦитатаDivES ()
А тут добавить задержку, например.
Это оказалось сложнее, чем я думал, ведь команды как в C++ здесь просто нет. Так, попробовал я через alarm. Штука полезная, но одно но. Она не работает в событии Draw. Т.е. если вызвать её из Draw, она ничего не сделает. А именно это мне и надо, чтобы она прибавила две строки между собой через 0,5 секунд. Если не лень, почитайте. Я скину код, а вы посмотрите, там много скриптов.
Create:
Код
dialog = false; text1 = "Привет, Сава!"; raz = 0;
Draw GUI:
Код
dialog_script();
dialog_script:
Код
var S= distance_to_object(object_player); if (S<=3 and keyboard_check_pressed(vk_enter)) dialog=true;
if (dialog) { blackrec(); //просто рисует диалоговое окно draw_set_color(c_white); draw_set_font(font_det); draw_set_halign(fa_left); //настройки шрифта if(raz==1) { script2(); } //здесь пытаюсь сделать алгоритм плавного появления, ниже строчки для тупо вывода (чтоб я проверил, что хоть это работает) if(raz==2) { draw_text(window_get_width()-window_get_width()+padding*2, window_get_height()-window_get_height()+padding*2, "Вот");} if(raz==3) { draw_text(window_get_width()-window_get_width()+padding*2, window_get_height()-window_get_height()+padding*2, "конец сообщения..");} if(raz==4) { dialog = false; raz=0;}
if(keyboard_check_pressed(vk_enter)) {raz++;}
}
script2:
Код
var exist="Привет, Сава"; var i=0; var exx; var ee=""; for(i=1; i<=string_width(exist); i++) { exx=string_char_at(exist,i); ee+=exx;
GameMakerBeginner, выглядит правильно, вроде бы! Просто я не работал в Game Maker Studio, не могу чего-либо посоветовать. А информация по задержке не нагуглилась, к сожалению
Так, отвечу сразу двоим. DivES, я попробовал вставить sleep(), но она видимо существовала только в прошлых версиях. Gent, ну да, наверное стоит этим воспользоваться, но я вставляю alarm в draw и он его просто игнорирует. Может вы знаете в чем дело?
GameMakerBeginner, насколько помню событие draw работает аналогично step, выполняется каждый фрейм. Если написать в draw только alarm[0] = 60, то событие никогда никогда не выполнится, т.к. таймер каждый раз будет обновляться.
Хммм.. кстати спасибо. Я не знал такого ( я ж только начинаю ) Я о том, что Draw выполняется каждый фрейм. Я уже наверное с таким фактом знаю решение. Но тогда можете объяснить, почему если я напишу в draw alarm[0]=3*room_speed; , а в аларме напишу что-нибудь типа прибавить единицу, то почему он не будет каждый фрейм ( каждый вызов ) ждать ещё 3 секунды, чтобы пойти дальше на следующий вызов. Я просто думаю пока , что если мы вызвали аларм, программа будет ждать его выполнения.
я нажимаю [клавиша], диалоговый прямоугольник появляется, но тут же исчезает
Код
var S= distance_to_object(object_player); if (S<=3 and keyboard_check_pressed(vk_enter)) script0();
Это оно отвечает? Если да, то не верно.
Простой вариант(костыль): 1. Создаёшь переменную типа isDialog = false; 2. В рисовании script0(); меняешь на isDialog = true 3. Следующей строкой(там же в рисовании) дописываешь if (isDialog) script0();
1. Создаёшь массив curDialog = [noone, -1]; Первый элемент означает ID экземпляра/объекта с которым игрок взаимодействует Второй элемент хранит в себе ID скрипта, который рисует окно диалога.
2. В шаге пишешь:
Код
//Если объект игрока очень близко и Enter нажат... if(distance_to_object(object_player) < 4 and keyboard_check_pressed(vk_enter)) curDialog = [object_player, script0];//Записываем в массив object и id скрипта.
//Если (диалог уже начат и игрок уже НЕ близко) или нажат Enter... if ((instance_exists(curDialog[0]) and distance_to_object(object_player) > 3) or keyboard_check_pressed(vk_enter)) curDialog = [noone, -1];//сбрасываем переменную диалога
3. В рисовании:
Код
//Если диалог начат... if(curDialog[1] > -1) execute_script(curDialog[1], id, curDialog[0]);//вызываем скрипт рисования диалога + передаём ему id собеседников
Этот способ хорош тем что он быстрый, гибкий, простой(минимум кода), если у тебя всего одно окно и взаимодействие только с одним игроком - используй первый.
Добавлено (12 Февраля 2020, 19:16) ---------------------------------------------
ЦитатаGent ()
Если написать в draw только alarm[0] = 60, то событие никогда никогда не выполнится, т.к. таймер каждый раз будет обновляться
Спасибо Quad69. Мне там сверху с первым вопросом немного помогли уже, я как раз в коде использовал такой же способ, как ваш первый. А насчёт задержки ещё не пробовал, но надеюсь сработает. Если предыдущий автор прав и draw выполняется каждый фрейм, то можно завести в Create переменную скажем Zader=0; в Draw пишем, что
Код
if(Zader%60==0) "наша строка с пустым stringom" += "буква из нашей желаемой фразы с индексом Zader/60; Zader++; draw_text(x,y,"string, который заполняется""
. У меня 60 кадров в секунду, тогда каждый кадр он прибавляет один к Zader, а когда он равен 60, 120, 180 и т.д он добавляет к тексту 1, 2, 3 букву соответственно с разницей в секунду. Надеюсь понятно. Но сразу попробую вот эту команду, что вы скинули.
Ну и я так понимаю что в вашей задержке alarm нужно оставить пустым?
Сообщение отредактировал GameMakerBeginner - Среда, 12 Февраля 2020, 20:46
GameMakerBeginner, Как вариант, можно создать переменную массив. В первой ячейке храните текст который должен выводиться, во второй - текущее время(current_time) Далее с помощью не сложных подсчетов (current_time - значениеВторойЯчейки div 200) выводите часть строки на экран.
Код
//Событие Создания typedText = ["", 0];
Код
//Событие N if (был_открыт_диалог) typedText = ["Какой то текст 123.", current_time];
Код
//Событие Рисования if (typedText[0] != "") draw_text(x, y, string_copy(typedText[0], 0, clamp((current_time - typedText[1]) div 200, 0, string_length(typedText[0]))))
Либо просто записывать во вторую ячейку 0 и каждые N времени увеличивать её значение на 1. Вместо тех подсчетов просто использовать её значение. Но используя current_time, можно добавлять задержку перед выводом.
Добавлено (12 Февраля 2020, 21:20) ---------------------------------------------
ЦитатаGameMakerBeginner ()
Ну и я так понимаю что в вашей задержке alarm нужно оставить пустым?
Какой? То что я написал if (alarm[0] == -1) alarm[0] = 60; это решение той проблемы "если писать alarm в Draw, то он никогда не выполнится". Вообще аларм это обычная переменная(массив), значения которой постоянно уменьшаются на 1 каждый шаг. Когда оно достигнет 0 - выполняется нужный код.
Диалоговая система почти готова, осталось разобраться с устройством GMS2. Я например в коде обратился к скрипту script2("My text"); и вот вопрос. Как мне в скрипте обратится к этому тексту, что написан в скобках, чтобы поработать с ним в моём скрипте. (Если кому интересно, , то это для того, чтобы сделать скрипт красивого появления букв многоразовым шаблоном) Спасибо всем, кто помог мне пропитаться этим движком. Без вас я бы долго ничего не понял. Это будет наверно не последний вопрос, так что, надеюсь, вам нравиться подсказывать мне.