Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Визард на входе - это квест? (http://www.flasher.ru/forum/showthread.php?t=140526)

mikhailk 01.06.2010 17:48

Визард на входе - это квест?
 
Собственно, делаю входного обучающего визарда для приложения (ну, это когда чучело при первой загрузке вылазит "здравствуй, дорогой друг, нажми на эту пимпочку, чтобы завертелась каруселька, а теперь вот на эту кнопочку..." и потом изредка уже по событиям - "поздравляю, ты собрал свои первые денежки, положи их вот в этот ящичек...").

Поймал себя на мысли, что фактически это квест. Т.е., лучше сразу писать класс квеста (с механизмом контроля событий, которые должны произойти), а потом уже на основе его вылепить обучающего визарда.

Кто как этих обучающих визардов делает?

Psycho Tiger 02.06.2010 00:28

Приходилось делать на не больших играх его только, поэтому хватало одного мувика, лежащего поверх всего, которого ставил на нужный кадр. Добавлял после того, как всё написано - так что синглтоном, за это меня можно бить по рукам =) Хотя, проект уже написан и расширению не подлежал - почему нет?..

mikhailk 03.06.2010 00:47

Уже слепил квестом )))
Расписал ожидаемые игровые события и реакцию на них в зависимости от состояния/этапа квеста. Немного запахло конечными автоматами, но в меру. )

Получилось, что каждый новый пользователь получает на входе стартовый квест, который должен пройти.

Посмотрю теперь, как все это отработает на реальных пользователях...

s8000_1 04.06.2010 17:49

mikhailk, а как вы стрелочки привязваете к объектам? Ну т. е. примерно так "тыкни на эту кнопку", стрелочка, указывающая на кнопку.

mikhailk 05.06.2010 00:29

примерно так (это описание одного шага)

Код AS3:

<step stepNumber="0" mousePositionX="165" mousePositionY="215" 
                action="viewImmediately"
                waitingAction="openObjectControlInterface"
                waitingParameter="Farm"        >
        <stepTitle>Приветствуем Вас в игре "..."!!!</stepTitle>
        <stepText>Сейчас Вам нужно произвести первый товар. Нажмите здесь, чтобы запустить производство.</stepText>
</step>

В ланном случае квестер запускается на шаге 0, показывает лопух со стрелочкой, привязанный к заданным координатам, и ждет, пока будет открыт интерфейс производства первого товара на ферме.

s8000_1 05.06.2010 02:52

Я еще встретился с проблемой, когда идет "откат" на шаг назад. Например - есть выпадающий список. Сначала стрелка должна показать на этот список, потом на элемент в нем.

Если вдруг игрок не нажал нужный элемент, и меню закрылось, то стрелка должна снова вернуться в состояние "показать на кнопку открывающую меню". В результате я запутался с событиями вьюверов. Когда именно они должны переключать состояния. Как вы такого рода конфликты решаете, можно поинтересоваться?

Еще одна проблема - скрыть/показать элементы интерфейса в зависимости от состояния тутора. Чтобы описать это в общем, надо давать какие-то глобальные id вьюверам, чтобы в xml квестов прописать что-нибудь типа <hideElems>id1,id2,...</hideElems>. Но я эту задачу в общем так и не поборол...

PS. На пользователях любой туториал работает более, чем хорошо :)

Psycho Tiger 05.06.2010 12:52

mikhailk, поделитесь реализацией, интересно взглянуть.

mikhailk 05.06.2010 14:25

Механизм в бета-тестировании, ногами не пинать ))


Код AS3:

package main {
    import flash.display.*;
        import flash.text.*;
        import flash.events.*;       
        import main.*;       
 
        public class AppQuester extends Sprite {
 
                private var questStep;
                private var questContent:XMLList;
                private var questName:String;
                private var questWaitingAction:String;
                private var questWaitingParameter:String;
                private var questStepNumber:int;
                private var containers:Object;
 
                public function AppQuester(_containers,questInfo) {
 
                        // Для последующей передачи ссылки на враппер при необходимости
                        containers = _containers;
 
                        // Получаем данные по квесту                       
                        var questArr:Array = questInfo.split("|");
                        questName = questArr[0];
                        questStepNumber = int(questArr[1]);
                        questContent = GlobalQuestData.elements(questName);
 
                        // Если квест есть и шаг требует вывода на экран - выводим
                        if (questContent!=null) {                                       
                                var action:String = questContent.step[questStepNumber].attribute("action");
                                switch(action) {
                                        case "viewImmediately": showQuestStep(); break;
                                }
                        }
                }
 
                public function checkEvent(eventData) {
                        if (eventData.action.toString()==questWaitingAction && eventData.parameter.toString()==questWaitingParameter) {        // получили ожидаемое действие пользователя
 
                                // Если было открыто - убираем с экрана (позже поставим нормальное удаление)
                                if (questStep) questStep.y = -2000;
 
                                // Переходим к следующему шагу
                                // и выполняем действие, заложенное на этом шаге
                                questStepNumber++;
                                showQuestStep();
 
                        }
                }
 
 
 
                private function showQuestStep() {
 
                        // Запоминаем действие и параметр, который ждем
                        questWaitingAction = questContent.step[questStepNumber].attribute("waitingAction");
                        questWaitingParameter = questContent.step[questStepNumber].attribute("waitingParameter");
 
                        // Если требуется закрыть все окна - закрываем
                        if (questContent.step[questStepNumber].attribute("closeBefore").toString()=="closeAllComplexInterfaces") {
                                var appEvent = new AppEvent("closeAllComplexInterfaces","",true)
                                dispatchEvent(appEvent);       
                        }
                        // Если требуется записать статус - записываем
                        if (questContent.step[questStepNumber].attribute("saveStatus").toString()!="") {
                                var requestData = { questStatus : questContent.step[questStepNumber].attribute("saveStatus") };
                                var connDB = new DataConnectorDB(containers.wrapper,"saveQuestStatus",requestData);
                        }
 
                        // Открываем лопух правильной формы и ориентации
                        var windowsVariant:String = questContent.step[questStepNumber].attribute("windowVariant").toString();
                        switch(windowsVariant) {
                                case "flipX" :        questStep = new QuestStepFlipX();
                                                                break;
                                case "info" :        questStep = new QuestInfo();
                                                                break;
                                case "title" :        questStep = new QuestTitle();
                                                                break;
                                default:        questStep = new QuestStep();               
                        }
 
                        // Позиционируем лопух и заполняем контентом
                        questStep.x = questContent.step[questStepNumber].attribute("mousePositionX");
                        questStep.y = questContent.step[questStepNumber].attribute("mousePositionY");
                        questStep.stepTitle.htmlText = "<b>" + questContent.step[questStepNumber].stepTitle + "</b>";
                        questStep.stepText.htmlText = questContent.step[questStepNumber].stepText;
 
                        questStep.btnClose.addEventListener(MouseEvent.CLICK,closeStep);
 
                        addChild(questStep);                       
                }
 
                private function closeStep(e:Event) {
                        removeChild(e.target.parent);
                }               
 
 
        }
}

Квест прописан в таблице пользователя в виде тесковой строки questName|questStep. GlobalQuestData - это глобальный объект вида:

Код AS3:

 
package {
    public var GlobalQuestData:XML =
                <quests>
 
                        <startQuest>
 
                                <step stepNumber="0" mousePositionX="165" mousePositionY="215"
                                                action="viewImmediately" condition="noCondition" item="noItem"
                                                waitingAction="openObjectControlInterface"
                                                waitingParameter="Farm"        >
                                        <stepTitle>Приветствуем Вас в игре "Поездатый товарняк"!!!</stepTitle>
                                        <stepText>Сейчас Вам нужно произвести первый товар. Нажмите здесь, чтобы запустить производство.</stepText>
                                </step>
 
                                <step stepNumber="1" mousePositionX="655" mousePositionY="220"
                                                windowVariant="flipX"
                                                waitingAction="startManufacture"
                                                waitingParameter=""        >
                                        <stepTitle>Всю эту продукцию Вы можете производить</stepTitle>
                                        <stepText>Нажмите здесь, чтобы начать производство риса.</stepText>
                                </step>
 
...
 
 
 
                        </startQuest>
 
 
 
                </quests>        ;
}


При загрузке приложения, смотрим, нет ли у пользователя активного квеста и на каком шаге. Если есть - порождаем объект класса AppQuester.

В необходимых точках приложения, вызываем метод checkEvent, который проверяет, не ожидает ли квест этого события.

Psycho Tiger 06.06.2010 15:21

Понятно, спасибо. Ещё бы взглянуть в действии :)
И да, типизация явно хромает.

mikhailk 06.06.2010 23:38

про типизацию - это да ))
не могу себя заставить, а IDE не требует.

Кстати, специально не занимался, но какой тип правильнее установить для переменной questStep?

Что касается наблюдения в действии - этот квестер стоит на входе в товарняке (ВК). Сейчас, правда, приложение не работает, там что-то с сервером.

При создании профиля юзеру назначается квест "startQuest|0" и вперед.


Часовой пояс GMT +4, время: 03:39.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.