![]() |
Проектирование текстового квеста
Друзья! Ещё раз спасибо за терпеливые объяснения. Делал по заветам мэтров, на сегодня имею:
1. кнопки - экземпляры класса MenuButton, которые умеют нажиматься и посылать по клику событие, содержащее свой номер (id:uint задаётся в конструкторе как входной аргумент); 2. меню - экземпляры класса Menu, которое строится с заданным кол-вом кнопок в колонку, создаёт и добавляет в себя сами кнопки и слушает события от них (даже успешно их принимает). Само пока правда ничего никому не посылает. 3. класс MainView, назначенный корневым DOC всего приложения (сей факт был отмечен банкетом), который пока что ничего особо не умеет, лишь помещает в себя это самое меню в порядке теста. Одно пока не получается: как заставить всё это работать на практике! Делал всё, ориентируясь на вот эти установки: Цитата:
Цитата:
У нас по ходу выполнения какого-то отвлечённого кода возникает момент, когда юзера надо спросить, да или нет. Получается, соблюдая цитированные выше принципы, мы должны "попросить" корневой DOC сделать и поместить в себя меню. Я ещё понимаю, что всё это "мясо" с инфой, необходимой для создания кнопок, можно "протащить" и через класс MainView... Понимаю, что корневой DOC может вызвать метод по созданию меню и помещению его в себя. Но как он поймёт, о чём именно мы спросили пользователя, и как практически обрабатывать события, получаемые от меню? Или это меню нужно "готовить" в одном месте, а через DOC - только выводить на экран? Поясните плиз или киньте ссылку с примером. И ещё одна тривиальная вещь у меня в голову не может уложиться. Какой смысл строить взаимодействие с визуальными компонентами посредством механизма событий? Понятно, что если мы говорим об обработке каких-то действий от пользователя, то без событий не обойтись. Но если, например, мы строим то же меню, то почему обязательно нужно слать ивент контейнеру? Почему нельзя в контейнере сделать публичным сам метод и вызвать его из любого места программы напрямую? |
Я даже не очень понял, о чем ты спрашиваешь((
Цитата:
Код AS3:
То есть ты перепоручаешь все строительные работы профессионалам; твое дело задать вопрос и суметь получить ответ. На всякий случай намекну: надо еще спросить так, чтобы твоему герою никто голову не отрубил, пока игрок думает, действительно ли он хочет выбросить из инвентаря эти "поношенные обмотки", то есть надо/не надо остановить происходящее на экране на время диалога с пользователем. Цитата:
|
Цитата:
Я понял, как делать иерархическую систему для создания компонентов и вывода их на экран: MainView создаёт экземпляр класса Menu с некими входными параметрами и добавляет его в себя. Экземпляр Menu, используя эти параметры, создаёт и добавляет в себя экземпляры Button. Button-ы честно моргают при наведении и нажимаются при клике, даже посылают событие ButtonEvent, которое улавливается экземпляром Menu, о чём делается сообщение в консоль. А вот, блин, как связать всё это удовольствие с нужными действиями и "повесить" на нужные мне кнопки функции запуска, загрузки, выхода и т.п., вот до этого мне чего-то не допереть, уж простите. То есть меню корректно создаётся как объект на экране, но вот как использовать его "в боевом режиме" я не понимаю. :( |
Цитата:
Код AS3:
|
Партизан, спасибо, ясности стало больше. Но, по всей видимости, мой пример с главным меню всё-таки тоже неудачный, и не отражает специфики проблемы. Потому что оно всегда создаётся самим корневым DOC-ом и содержит фиксированное количество кнопок с известными заранее действиями.
Попробую ещё ближе к моему реальному проекту. Это - текстовый квест. Основная механика такова, что выбрав очередное действие, пользователь видит некий арт на бэкграунде, получает порцию текста в окно вывода текста, а также меню с вариантами дальнейших действий. Кликает на вариант и всё повторяется. Поэтому подобные меню появляются часто, но в первом случае там будет условно "пойти налево", "пойти прямо" и "пойти направо", а в следующую итерацию - "дать в лоб", "тихо обойти" и "попытаться охмурить" (причём последний вариант доступен только в случае, если герой - противоположного с NPC пола). Таким образом, каждый раз меняется количество опций, а также функции, которые будут выполняться при клике на тот или иной пункт. И аналогично, ни хрена я не понимаю, как тест выдавать. Пока сделал объект-область вывода, куда воткнул дочерний TextField, создал экземпляр в MainView. А как туда реальный текст посылать, да ещё с вариативным форматированием - опять туплю. Ведь текст создаётся в другом месте. Вернее сказать так: в процессе выполнения кода, обрабатывающего результат очередной итерации, появляется строковый id, по которому из XML с фразами на заданном языке вытаскивается нужный кусок текста. В консоль его прекрасно вывожу, а так отправить в окно вывода - не пойму. Такое ощущение, что упускаю какую-то очень простую и важную вещь во всём этом хозяйстве, без которой пазл не складывается и каменный цветок не выходит. Просьба пояснить, если я ещё неутомил своим ламерством :rolleyes: Спасибо. |
Партизан — Запутаешь человека) Подписываешься на MenuEvent.Select, а потом спрашиваешь какого же оно типа))
Appleman — Ну вобщем, подписываешься либо на каждый тип события, либо передаешь в Событии строку, что же именно выбрал юзер. Можно не городить свой кастомный MenuEvent, взять DataEvent из коробки, у него есть свойство для транспортировки data типа String. Добавлено через 13 минут Ох же шь... Ну, тут тебе надо хорошенько продумать саму механику квестов, с таким то ветвлением.. То есть, на каждую стадию у тебя должен быть текст, описывающий ситуацию и к нему набор вариантов действий с какими-то ID (здесь может быть просто a, b, c), и к каждому варианту — адрес следующей стадии, то есть куда перейти в случае выбора этого варианта. Тогда получится запрограммировать механику абстрактно, то есть универсально для всех стадий, а не расписывать В КОДЕ каждый поворот сюжета)) |
Цитата:
|
Цитата:
Вот я кое-что из этой механики уже запрограммировал, но весь вывод пока только в консоль через trace. Теперь мучаюсь с выводом на экран в рабочем режиме (это даже для дальнейшей разработки и отладки нужно). |
Как мне кажется, тебе нужен класс - наследник спрайта - представляющий собственно слайд (или как там это называется в скроллерах), кадр, шаг игры. Не данные, про которые ты говоришь — это в Модели, а именно визуалку. То есть то, что отображает твой CurrentState в виде фоновой картинки и "диалога". Скажем, StateView. Он, естественно, может включать в себя отдельные компоненты, то же "меню" (хотя мне в этом контексте название "меню" не нравится, сбивает, даже если технически оно правильное; я бы назвал "диалог" — и у тебя наверняка будут именно диалоги персонажа с неписями, и они будут точно также "оформлены"). Вот его тебе и надо учить показывать кликабельные варианты. Не надо пихать всю ответственность в мейнВью.
Что конкретно то не получается с выводом текста? Текстфилд, конечно, штука капризная и нужен некоторый опыт чтобы его настраивать как хочется.. но не настолько же, чтобы вообще текст вывести не получалось? |
Цитата:
Цитата:
Цитата:
Можно мне в режиме дурака для примера кусочек кода, показывающего взаимодействие корневого DOC и условного StateView? Я верно понимаю, что в мы передаём в экземпляр StateView ссылку на MainView, первым делом записываем её в приватную константу и "добавляемся" в неё: Код AS3:
|
Нет.
Хотя поначалу тебе всегда будет хотеться сделать все задом наперед, аж на уровне подсознания. Но "иерархия" подразумевает, что никакое _gameview.addChild(this); невозможно в принципе. Потому что это приказ родителям от ребенка. В иерархии приказывает тот, кто стоит выше. Он создает себе инструмент и управляет им. Если инструмент считает, что он знает больше, он посылает событие родителям "вас вызывают в школу". Но даже в этом случае родители сами решают, что всвязи с этим предпринять. Нормальный код выглядит примерно так: Код AS3:
Добавлено через 23 минуты "И теперь уже прямо в StateView, не отходя от кассы, мы можем создавать объект TextField и, написав несложный метод, выводить в него тексты" Добавлено через 36 минут Цитата:
В моем примере _стейтВью один и всегда добавлен на сцену; но даже если бы это было не так, МейнВью ЗНАЛ бы, что перед созданием нового стейтВью надо удалить старый — они в его руках, он их создает и разрушает. Добавлено через 43 минуты Новый экземпляр нужно создавать тогда, когда необходимо сохранить старый. Если старый не нужен, он очищается и строится заново. "Используется повторно". |
Цитата:
Хорошо, а если у нас ситуация, когда стейт не меняется? Я уже спрашивал на счёт отправки содержимого в TextField. Все компоненты - на своих местах, без изменений. Но в TextField нужно поочерёдно вывести 4 куска текста, причём некоторые - со своим TextFormat-ом. Как это делается, если id текстов определяются в model? Как их "переправить" в МэйнВью вместе с форматами? Цитата:
|
2) Ну, форматирование текста можно задавать с помощью html, какой-никакой а в AS3 он есть. То есть уже в xml можно хранить текст отформатированным. Либо, как вариант, утвердить несколько конкретных форматов и размечать текст своим способом (заключать в теги со "своими" застолбленными именами, типа <boldred/>), а потом парсить и назначать этим кускам нужный, заранее известный ТекстФормат.
1) Ну не меняется стейт и не меняется, другое событие значит пошлешь) 0) У всех лопается, это ж не банер "Осенние скидки купи сейчас по летним ценам". Спрашивай что непонятно, а то широкими то мазками я горазд размахивать, мне ж отсюда не видно, в чем у тебя затык. Я вот уже не могу без MVC представить архитектуру, а ты ведь по-настоящему не углублялся в эту тему? К тому же, никто кроме тебя не знает, что за фантазии тебя обуревают. "Стейт не меняется а текст меняется". Так что, картинка на фоне не меняется чтоли? Ну, СтейтВью как-то должен с этим разобраться, для него не должно быть проблемы понять, что картинка та же) Но если все тоньше и это именно НЕ новый стейт, то все-равно это какое-то изменение в модели и она должна об этом сообщить заинтересованным лицам (Вью). У тебя щас проблема наверное в том, что идей много а окончательной формы пока не видно. Задача твоя как проектировщика определить некие стандарты: что выводиться на экран будет то-то и то-то, таким вот образом раз, и вот таким образом два. Есть вот такой стиль, и вот такой, и нужен еще третий. Найти в куче идей какие-то общие моменты, чтобы разные интересные штуки можно было оформить каким-то общим способом, чтобы этих способов было не 100500 а 5-7. Это важно и для игрока, чтобы его не ошарашивал интерфейс, хаотически меняющийся на каждом слайде. Важно сформулировать, какие именно возможности тебе нужны от движка, иначе на любое решение ты будешь восклицать "а если мне захочется еще и вот так!", и тогда конца-края вообще не дождешься. |
Цитата:
Наверное, я зашёл немного не с той стороны - начал писать код в том порядке, в каком его увидит будущий игрок: сначала главное меню, потом брифинг и т.п. А начинать наверное нужно всё-таки с основного геймплея, а все эти рюшки потом навесить. Цитата:
Цитата:
Итак, на старте рассчитываем начальные параметры обеих сторон, выводим игроку полную инфо о своём герое, а также инфо о противнике, но "отфильтрованную" через степень знания о нём. Рисуем картинку, всякие полоски здоровья и т.п. Каждая итерация состоит из следующего. Игроку предлагается выбрать одно из действий. Общий список - достаточно большой, но доступность каждого определяется рядом условий и в конечном счёте зависит от свойств персонажа и противника, экипированных предметов и т.п. Причём я различал понятие "возможности" и "доступности". Если не выполняются критерии возможности, то действие не выводится вовсе, а если действие возможно, но недоступно в данным момент, то оно выводится в диалог, но в неактивном виде. Чтобы избежать излишнего "мяса", меню действий я планировал двухуровневое, т.е. для каждого действия есть признак принадлежности к определённой группе. Когда игрок выбрал желаемое действие, игра должна рассчитать непосредственный результат в виде изменения свойств обоих участников (да, схватки только один-на-один), вывести соответствующие текста, обновить картинку. Далее следует реакция соперника, варианты которой выбираются в ответ на действие игрока из некого списка доступных вариантов, в зависимости от свойств NPC. Здесь игрок уже ничего активно не противопоставляет, только получает инфо. Дальше опять обновляем свойства, картинки, двигаем вперёд игровое время. Затем всё повторяется. Как-то так, если отбросить все усложнения, которые разумеется, также планируются: всякие бафы/дебафы, проверки на специфические свойства и т.п. Наверное, в текущей версии только возможность смены инвентаря нужно добавить. |
рекомендую замечательную статью (MVC, часть 1: про дубовый стол и сиськи), которая должна ответить на некоторые вопросы.
И, да, не стесняйтесь зарисовывать архитектуру снова и снова. |
Цитата:
P.S. и да, кто мой предыдущий пространный пост прочитал, просьба не воспринимать всерьёз мои опусы про ненадобность контроллера. Я его почему-то воспринимал, как реализацию управления со стороны игрока, а перечитав любезно порекомендованную статью об MVC, понял, что сморозил сущую глупость. Добавлено через 2 часа 46 минут Начал, пыхтя, продумывать архитектуру в стиле MVC... Возник первый содержательный вопрос. Планируя Вью, нужно ли различать такие понятия как условно "разметка экрана" и "обновление данных из модели"? У нас есть ряд компонентов, которые, с одной стороны, непосредственно связаны с обновляющимися данными модели (тот же TextField для вывода основного текста), а с другой - сам объект (но не текст внутри) - находится на одном и том же месте от начала и до конца игры. Что с таким делать? Добавлено через 2 часа 54 минуты ...и ещё вопрос. Я выше жаловался на плохое понимание разницы между "data" и "model". Прокомментируйте, плиз, мои мысли. Сейчас у меня в пакете data есть класс Character, который содержит все свойства персонажа. Причём они, эти свойства, могут изменяться в процессе игры, что в свою очередь, находит отражение в отображаемом игроку содержании. Правильно я понимаю, что в таком случае, мой Character - уже по этому признаку никакой на фиг не data, а model в чистом виде? А если так, то и создавать его должен главный контроллер в начале работы с добавлением всяких событий на обновление и т.п. так? В этом случае становится вообще непонятно, нужен ли мне класс Character в том виде, в котором он у меня есть... |
Я обычно стараюсь не усложнять и проектирую в основном так - сначала создаю сущностную диаграмму - это когда ты программу расписываешь на сущности, объекты и их взаимодействия. Ну. например, в твоем случае, это, насколько я понял, --
персонаж(я), вещи, враг, поле. 4 сущности. Они зарисовываются в виде кружочков. Далее обозначаем отношения - вещи носятся на персонаже и влияют на характеристики. Поле содержит в себе персонажа и врага. Персонаж сражается с врагом. Далее рядом с кружочками выписываем свойства - у персонажа это характеристики (ну там сила, скорость передвижения, вещи(массив)), у врага, видимо, тоже (скорее всего персонаж и враг это два экземпляра одного класса герой, или как минимум наследуются от одного класса, так как имеют много общих свойств). Выглядеть это должно примерно так https://4.downloader.disk.yandex.ru/...ize=XXL&crop=0 и на всякий случай ссылкой не стоит сильно заморачиваться и усложнять - наоборот, схема должна быть простой и наглядной, чтобы впоследствии при одном взгляде на нее было примерно понятно. Если интеренсо, почитай про ER-диаграммы. Далее уже рисуем UML на этой основе. Разделяем сущности на классы, разделяем каждую сущность на модель - описание состояния объекта, его свойства, вьювер - отображение состояния объекта и контроллер - изменение состояния объекта. Важно помнить, что изменяем мы именно состояние, а отображаем уже по факту изменения состояния. Так будет проще потом изменять и меньше вероятности потерять связь с Подитожим. Разделяем программу на объекты, а каждый объект отдельно по модели MVC. Профит. По крайней мере, примерно так делаю обычно я. |
ZergMaster, спасибо. Общая концепция понятна. Я из того, что ты написал, одну вещь уточнить хотел бы. Если для каждого обособленного объекта делать свою полную триаду MVC, то нужно налаживать какую-то иерархию и взаимодействие между ними. И если с Вью более-менее понятно, то как обрабатывать взаимодействие контроллеров? Вообще, насколько это жёсткое требование? Мне пока придумалось иметь один главный контроллер, свои модели на каждый объект и вьюшки, связанные с ними...
И ещё один вопрос для общего понимания. Если у нас есть несколько сильно отличающихся по механике и интерфейсу режимов игры, например, сам игровой процесс и окно инвентаря, где шмотки перетаскивать, то правильно я думаю, что с т.з. разработки - это фактически 2 независимые "игры" со своим MVC? |
Appleman добавил картинку в прошлый пост. Куда-то она делась.
Ну да, иерархия. Но всегда есть главный вьювер, главная модель и главный контроллер. У меня как правило они вложены друг в друга по принципу деревьев - в основном для читабельности. Ты начни с того, чтобы сделать одну главную модель, одну главную вьюху этой модели и один контроллер. А дальше уже будешь добавлять по мере необходимости. Добавлено через 10 минут На самом деле, конечно, совсем не обязательно делать для каждого объекта свою триаду. Я бы сказал - не надо. Можно для группы схожих объектов. Или вообще по одной на всю программу (что бывает тоже редко, так как получается слишком много кода в одном месте.. удобно его разложить по полочкам все-таки). А может модель MVC реализовываться вообще только для части программы - где это удобно. Но это все придет в будущем, а пока лучше делать по одной главной. Тут нет каких-то особых правил. Главное - изучить общую концепцию на собственном опыте и в будущем применять его для удобства своего и своих близких (что тоже важно, чтобы читающий за тобой программист не проклинал тебя слишком сильно) |
Цитата:
В разных режимах приложения одни и те же действия пользователя должны интерпретироваться по-разному. Яркий пример — нажатия клавиш. Во время игры клавиши со стрелками вверх/вниз могут передвигать игрока по карте, а когда на экране Меню — обеспечивают переход между вариантами; в окне настроек могут менять громкость звука и т.п. Удобно пихать эту интерпретацию в контроллеры: имеется ввиду, что для каждого состояния программы существует свой контроллер, который просто не слушает то что не надо и вызывает правильные методы в Модели в ответ на то, что слушает. А поскольку "состояния" так или иначе завязаны на то, что показывает сейчас Вью — Меню, Инвентарь, Диалог, Настройки, Видеозаставка, Поединок — удобно все их делать отдельными Вью со своими контроллерами. А вот насчет множества Моделей это перебор. Ну, или они могут быть как части одной Модели: ты можешь считать что твой Character это CharacterModel, смысл от этого не очень поменяется, разве что возникнет вопрос "а как быть с CharacterController? Что он должен делать?" )) При разделениях Моделей на множество важно осознавать, насколько они зависимы друг от друга всмысле обмена данными. В режиме поединка тебе постоянно надо иметь данные о персонаже и оппоненте "вместе", да еще и об их аммуниции; а вот глобальное меню игры здесь вроде как совсем не при делах — оно может быть отдельной триадой, так как его данные абсолютно обособлены. |
Спасибо, очень доходчиво.
Цитата:
Цитата:
Ещё с позволения несколько вопросов. Я пока единственное, что реально написал из будущей MVC - это все три класса со ссылками друг на друга "по классике", плюс в Model создал метод setup, который рассчитывает стартовые значения свойств и т.п. Хотел сделать примерно то же самое с GameView, но возник вопрос. Опять на счёт иерархии отображения :). В методе View.setup я хотел сразу создать основные экранные объекты, начиная с моей любимой области для вывода текста. Для этого изготовил новый класс MainTextArea, расширяющий Sprite - контейнер. Внутрь воткнул простенький прямоугольник (в дальнейшем будет окно с "красивой" рамкой), а поверх него в том же контейнере - объект TetxField для вывода собственно текста. GameView добавил его в список отображения, на экране окно появилось, слава аллаху. Решил сразу попрактиковаться и написать метод, который по получении соответствующего события от Модели будет выводить текст. Вот тут началась фигня. Ибо записать напрямую MainTextArea.text я не могу, т.к. это Sprite. Делать область вывода как "голый" TextField совсем без контейнера как-то тоже не хочется - мало ли чего в ней ещё потребуется наворотить... Прикинул вариант написать собственный метод для GameView, получающий по событию текст, чтобы потом "отправить" его в MainTextArea... И тут мне пришло в голову красивое в своей простоте решение. А может быть пусть сам экземпляр MainTextArea слушает события от модели и выводит текст, который его попросят? Плюс в том, что во-первых, мы сокращаем длину канала взаимодействия, т.к. данные от модели не нужно будет "протаскивать" через главный Вью, а во-вторых, планируемые функции подпадают под ответственность класса MainTextArea - выводить тексты. При этом, замечу, поскольку экземпляр MainTextArea - это креатура GameView, значит последний при необходимости может изменить или удалить его, т.е. иерархия не нарушается. Корректное это решение или всё-таки иерархия нарушается? Прокомментируйте, пожалуйста. И второе. Во всех примерах MVC, которые я видел, весь код модели был помещён непосредственно в класс Model. В результате даже для простеньких игрушек в нём набиралось прилично разных функций. А если проект будет покрупнее, то там будет просто "мясо"... Верно я понимаю, что "главная" модель должна выглядеть как такой распределитель обязанностей, который получает команды от контроллера и "раздаёт" их разным специализированным классам для выполнения конкретных вычислений? |
Да, все верно, главная содержит в себе глобальные параметры и приватные экземпляры дочерних моделей, доступ к которым осуществляется по геттерам.
|
Цитата:
|
Цитата:
Цитата:
Просьба прокомментировать моё решение на счёт окончательной "разблюдовки" MVC. Поскольку, я напоминаю, у меня текстовый квест, то основных "интерактивных" областей на экране всегда три: область вывода текста, "уголок" героя, где изменяющийся портрет, всякие полоски здоровья, баффы/дебаффы и т.п. и такой же "уголок" соперника. Я рассудил так. Коль они у меня всю дорогу находятся каждый на своём месте, то хрена ли я буду лепить отдельные вьюшки! Это же не RTS, где враги прут пачками и каждый экземпляр нужно отрисовать... И оставил я один контроллер и одну вьюшку. И небольшой практический вопрос, который меня поставил в тупик. Довольно часто встречается ситуация, когда нужно вывести порцию текста игроку, что-то по мелочам обновить, а затем, когда он осознает увиденное и кликнет, выводить текст и обновлять экран дальше. Естественно, чтобы он сообразил, что игра не зависла, а ждёт от него действие, я сделал класс ClickToContinue, который выводит соответствующее сообщение на выбранном языке, красиво мерцающее на видном месте. Но вот внедрение его в мою MVC вызвало затруднение. Вроде как сам клик ловить в контроллере - не дело, это прерогатива вьюшки. Значит, контроллер "дёргает" вьюшку и говорит "давай тормози до клика". Вьюшка берёт под козырёк и вываливает на сцену мой красивый ClickToContinue. А вот потом что? Что делать с кликом, который вьюшка поймала? |
Цитата:
Может это и не совсем правильно, но у меня для этих целей обычно служит такой специальный классик-объектик, который называется как-нибудь на вроде "информационное окно", или "окно сообщений". Оно может инициализироваться на главной сценей, принимая в себя верхний слой. А потом, в любом месте кода, я просто, обращаясь к этому классу, дергаю функцию "показать окно", передавая её label - текст, который нужно вывезти, и, если нужно, индентификатор картинки и т.п. А иногда это просто обычный класс-Sprite, и в любом месте кода я создаю новый его экземпляр, передавая в конструктор label и тут же добавляю его на сцену. А все остальное проиходит внутри этого класса и он ничего не знает о том, откуда его вызывают и кто, и зачем. Все, что он умеет - это отобразить графику, встроенную в него - окно с полупрозрачным фоном, отобразить текст, пришедший в конструктору, и удалить сам себя. Да, такой подход часто ругают, но я люблю удаляющие сами себя классы, это очень удобно)) У него просто есть приватная функция remove(), которая вызывается при нажатии на крестик либо ВНЕ окна, и которая выглядит таким образом: Код AS3:
то есть, в моем случае, вся идея сводится к тому, чтобы иметь некий классик, который вообще ни сном не духом о том - куда его добавляют, какая там невероятная космическая архитектура реализована в приложении и тому подобное - он просто существует сам в себе. Просто объектик со своей внутренней логикой. И это позволяет его применять в любом проекте, просто создав его экземпляр, передав ему текст и добавив на сцену. Все остальное же он делает сам. |
Цитата:
И в этом методе есть очень большая проблема. Отсутствует проверка на наличие parent. Если экземпляр не будет никуда добавлен, то при вызове всё сразу отвалится с null pointer исключением. Лучше уж так: Код AS3:
|
А мне вот последнее время перестает нравится суть контроллера, который слушает вьюшку, потом вносит изменения в модель, а та в свою очередь возвращает изменения во вью. Как то много лишних действий, нет?
|
caseyryan да, совершенно верно, забыл указать это. Так как зачастую выходит, что кроме удаления себя со сцены происходит еще некоторое количество действий, то этот метод может выглядеть так
Код AS3:
Godwarlock так у нас же может быть множество вьюшек. И таким образом, когда контролер изменяет модель, они ничего не знают о том - сколько вьюх и вообще что там творится снаружи, а модель просто рассылает события. А потом уж кто их поймает - тот и использует. В этом то вся и красота mvc, и если такой системы не будет, то да, это будет уже не mvc. Такая модель особенно актуальна, когда у нас неограниченное и, быть может, даже неизвестное количество вьюшек, которые должны отображать одну и ту же инфу. |
Цитата:
По поводу click to continue — а Модели то есть вообще дело до этого? До того что пауза. В ней что-то происходит? Или она составила кадр, известила вьюху и спит пока не скажут давай следующий кадр? |
Цитата:
Вообще вижу тут выше дискуссию на счёт нужности контроллера. Испытываю примерно те же ощущения, правда, пока особо не выпендривась, т.к. нужно хоть что-то рабочее написать, прежде чем делать выводы. Но вот взять, например, мою типичную ситуацию с выводом диалога выбора дальнейших действий игроком. По задумке модель берёт весь массив действий и, используя свою логику, фильтрует его в зависимости от состояния игровых параметров. Отфильтрованный массив по событию забирает вью, чтобы вывести игроку. В контроллере висит слушатель события выбора действия. Когда игрок делает свой выбор, вью принимает его и отправляет в контроллер. Контроллер же, не приходя в сознание, отправляет идентификатор действия обратно в модель (он ваще не понимает, что это за фигня к нему прилетела!), чтобы там это действие было обработано. Спрашивается, на фига тащить всё через контроллер, если можно сразу из вьюхи принять в модель? |
Цитата:
На самом деле, конечно, можно и напрямую. Да порядка не будет тогда. По сути, это как и с названиями функций и переменных - не обязательно их называть как-то понятно, можно просто "а", "b", "c". Не обязательно соблюдать конвенцию формата кода, не обязательно избегать комментариев, делая сам код читабельным без них. Не обязательно вообще писать в классах - зачем, когда можно писать в нужном кадре нужного символа?)) Все это не обязательно и, в принципе, для того, чтобы написать пару скриптов или пару кнопок - это не нужно. Но как только проект разрастается, ты бы хотел знать, что моделью у тебя управляет только контроллер и никак иначе. Как только проект становится большим, тебя успокаивает уверенность в том, что вьюха ничего не знает о контроллере и слушает только модель. Ты знаешь, что у тебя не остается рудиментарных вызовов не пойми откуда не пойми чего. Ты уверен, что никакая нечисть не забредет а мир твоего кода. Хотя нет, конечно, неизбежно забредет, но тебе будет гораздо проще её найти, если будет порядок. Ты будешь четко в курсе кто чем управляет и кто что использует. Это удобно. Только лишь для этого, как мне кажется. Ну и, конечно, полиморфизма ради.=) |
У Модели нет ссылки на Вью.
Не, я понимаю что у тебя при таком ответе первая мысль будет "ну так давай дадим ей ссылку". Тут вопрос то в том, MVC или не MVC. Так же как заявление Godwarlock выше. Если ты не понял, зачем ТАК сделано в MVC, то ты просто еще не понял MVC, тут нечего стыдиться))) Вообще, "Правильно" всегда включает в себя "Чтобы работало", но "Чтобы работало" вовсе не всегда "Правильно". MVC всегда кажется избыточно сложным, кажется что его правила придуманы так, чтобы все усложнить на ровном месте. И ключевое слово здесь — "на ровном месте". Знаешь пословицу — "гладко было на бумаге, да забыли про овраги"? Реальность такова, что место нифига не ровное. Последнее, о чем думает молодой программист, это ошибки, а тем более СИТУАЦИИ, в которых что-то может пойти не так. А еще есть такая мерзкая тема, как защита от взлома. Я вобщем хотел сказать, что пока для тебя ВСЁ приложение умещается в задачу "послать событие вот тут", место кажется ровным и понятным. И начинать с этого вполне нормально, если что. Если MVC непонятно, забей на него до поры до времени. Если амбиции не позволяют, штурмуй дальше. Сразу скажу: вся красота и опрятность MVC проявляется, когда написано полсотни классов хотя бы по 300 строк кода и архитектура типа "всё в кучу" уже тупо не помещается в голове. У Модели нет ссылки на Вью, потому что Вью может заменяться в любой момент. У Модели нет ссылки на Контроллер, потому что Контроллеры могут заменяться в любой момент. Чтобы об этом помнить, надо как минимум представлять себе СИТУАЦИИ, когда Вью и Контроллеры должны заменяться. Если в твоей голове по отношению к этому приложению нет идей таких ситуаций, у тебя не будут возникать подобные мысли, верно? И тогда сама идея MVC становится какой-то муторной и бессмысленной. Это только первое положение MVC само собой моментально укладывается в голову — что есть Модель которая все расчитывает и есть Вью которая всё отображает. Потому что это естественное положение вещей. Но дальше в MVC еще много чего, что так вот сходу на голову не налазит. Это нормально. |
Цитата:
Цитата:
|
Цитата:
Цитата:
Если тебя смущает доступность методов Модели контроллеру, то ты на верном пути. Здесь обычно всплывает тема Интерфейсов, то есть контроллер может иметь ссылку на Модель не как на тип (класс) Модель, с полным доступом ко всем ее пабликам, а только на Интерфейс, в котором перечислены только те методы, которые можно дергать ДАННОМУ контроллеру. Точно так же Вью может иметь ссылку на Модель как на Интерфейс, в котором перечислены только те геттеры, которые позволено дергать ДАННОЙ Вью. И она никаким образом не узнает о существовании каких-то еще пабликов у этой Модели. Это, в частности, важный момент защиты данных, ибо Вью у нас душа-на-распашку, заходите люди добрые, берите что хотите — до любого визуального объекта можно добраться через дерево Дисплейлиста, каким бы "приватным" он не был объявлен. Но в Модель никто не имеет права соваться. |
Друзья! Двинулся дальше в разработке и серьёзно застрял (как обычно) :) Need help. Я уже раньше поднимал тему формулировки условий, но только теперь практически дошёл до этого момента. Итак, имеем по-прежнему мини-игру - схватку один-на-один в жанре текстового квеста, хотя для обсуждаемого вопроса это в данный момент не принципиально. В каждую фазу игрок выбирает одно из доступных действий. Мне видится следующая реализация. Планирую создать отдельный класс действия (да, я помню, что в отсутствие изменяемых свойств вполне вероятно, их удобнее будет реализовать статической таблицей, но пока точно удобнее классом), где "живут" значимые для игровой механики свойства. Будучи выбранным, нужный экземпляр отправляется в качестве аргумента в метод-обработчик модели, где будут обрабатываться его результаты. Но до этого этапа мне не дойти. Проблема в том, что условия доступности разных действий сильно варьируются и вообще достаточно разнообразны сами по себе. Например, чтобы действие было доступно для выбора, может одновременно требоваться определённый пол или раса персонажа, значение свойства или навыка, определённый предмет экипировки в наличии. А другое может иметь в числе условий значения каких-то свойств противника и, например, время суток. Естественно, все значения, фигурирующие в числе условий - это свойства тех или иных игровых объектов. Вопрос, как всё это на абстрактном уровне "уложить" в код. Я уверен, что данный вопрос многократно решён. Спасибо.
|
самый очевидный вариант - это иметь в каждом действии функцию "доступность", которая будет сверяться с моделью по всем требуемым параметрам перед тем, как предложить себя игроку. Но, возможно, есть варианты покрасивше. Вконтакте api, например, помню, была интересная реализация проверки разрешений через 8ричные числа или как-то так. Может, кто подскажет.
|
Цитата:
п.с. Небольшой офтоп, но эта тема сама по себе уже превратилась в текстовый квест) Называется "догадайся о чем спрашивает автор". Слишком много текста. Вопросы надо как-то по-лаконичнее формулировать |
Цитата:
Про маску спасибо. Помню, я её использовал для сверки, но для меня всегда было загадкой, как же она на самом деле работает. Может кто-нибудь рассказать на простеньком примере? Было бы очень интересно. |
Не, ну я тоже могу только строить предположения)) Мне видится так, что на сцене нарисованы два чувака — Вражина и Герой, написано последнее действие Вражины (или целый лог действий) типа "Серый Волк плюнул в лицо Красной Шапочке" и дальше список вариантов действий Кра.Ша., один из которых должен выбрать Игрок. Мне вот только непонятно, этот список ИЗНАЧАЛЬНЫЙ, неотфильтрованный, он всегда вообще один и тот же? То есть в нем изначально записаны вообще ВСЕ варианты, возможные в игре? Или он индивидуальный для каждого эпизода "большого" сюжета? Если второе, то получается он должен поставляться вместе с квестом в виде скажем XML, типа
Код:
<action id="000001" name="Ударить ножом в глаз"> |
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
Цитата:
|
| Часовой пояс GMT +4, время: 19:13. |
Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.