Просмотр полной версии : Ссылка на stage
Appleman
31.10.2017, 19:00
Друзья, подскажите ещё один маленький технический момент, пожалуйста. Часто приходится что-то центровать по размерам сцены и вообще с этими размерами взаимодействовать, причём подобные ситуации возникают в разных классах. Ловить в каждом событие ADDED_TO_STAGE - муторно. Как лучше организовать и хранить ссылку на экземпляр stage для быстрого к ней доступа? И откуда её "протягивать"?
Спасибо.
caseyryan
31.10.2017, 19:31
Лучше подписываться каждый раз и делать вычисления по событию.
Если муторно делать это каждый раз, то вместо Sprite можно создать свой класс наследник, и в нем сделать нужные подписки, а потом просто наследовать свои классы от него и перезаписывать метод onAdded, который можно поменить модификатором доступа protected
Если хранить где-то ссылку на stage, то это приведет к дополнительной связанности. Уже нельзя будет просто скопировать какой-то класс из одного проекта в другой. Нужно будет и тот, что хранит stage тянуть, это во-первых, а во вторых ссылка может в какой-то момент, по разным причинам теряться, что приведет к рантайм ошибкам, тогда как по событию, stage будет доступен 100%
Appleman
31.10.2017, 21:57
Спасибо. Значит, будем терпеливо добывать свою ссылку в каждом заинтересованном классе.
"Муторно" :)
А знаешь как я делаю? У меня главная Вью подписана на событие RESIZE от stage, и когда это событие случается, Вью вызывает метод resize() у всех своих модулей, передавая им размеры (не размеры стейджа, а пересчитывает ИХ, модулей, размеры и задает им эти новые).
1) Если модуль будет сам себя пересчитывать так, как хочется ему, а не хозяину, этот модуль нельзя будет использовать в других приложениях или даже в других задачах этого приложения. Для примера доведем до абсурда — написал бы я кнопку, которая спрашивает размеры стейджа и задает себе размеры в зависимости от них, а так же свои координаты на экране (иначе я не знаю зачем вообще иметь ссылку на стейдж). Ну и куда я смогу использовать такую кнопку, кроме одного-единственного случая?
2) Если модуль будет реагировать только на ADDED_TO_STAGE, то при изменении размеров приложения все расползется.
3) Модуль понятия не имеет о том, что творится вокруг него. Это знает хозяин. Может, хозяину пришлось раздвинуть текстовое поле чтобы вместить новый текст, или еще какие пертурбации произошли. У хозяина должна быть возможность изменить размеры и координаты любого модуля. Иерархия и контроль.
4) Модуль должен уметь менять свои размеры без деформации (scale) — в разумных пределах конечно — при необходимости буквально перерисовывая заново какие-то свои элементы. Та же кнопка должна уметь быть любой ширины и любой высоты (не связано друг с другом), но не меньше какого-то разумного минимума (особенно если она с лейблом). Более сложный модуль должен уметь менять размеры, поддерживая какой-то приличный вид, передвигая, перерисовывая, меняя размеры текстфилдов и, в самом ужасном случае, даже добавлять полосы прокрутки, если уместить все свои элементы в заданном размере он не в состоянии.
Это все в идеале, конечно. В реальности такие страсти не всегда нужны; однако при написании игры тебе, как ни крути, придется заморочиться красивым заполнением экрана в режиме фуллскрин. А экраны сейчас какого только разрешения не бывают.
Appleman
31.10.2017, 23:43
А откуда твоя главная вьюха "знает", в каких пределах и на какие значения должны измениться те или иные компоненты? Или это для каждого проекта в зависимости от разметки экрана прописывается?
Если честно, я про RESIZE сцены пока вообще не думал. А привязка к stage потребовалась, чтобы центровать меню по высоте. Ведь в нём кол-во кнопок может меняться от случая к случаю, а значит, и координата y должна подстраиваться. Плюс ширина кнопок подбираться под самый длинный из лэйблов.
ZergMaster
01.11.2017, 00:18
Я кстати тоже делал подобным образом, только более варварски. У меня были в главной вьюхе (main) были private static переменные mainWidth и mainHeight, у которых были только геттеры. И точно также по событию Event.RESIZE у каждого ребенка вызывалась функция .resize(). По разному я делал - иногда width и height были статическими переменными мэйна, иногда - передавались в каждого ребенка. Кажется, тогда я так и не определился, какой вариант оптимальнее)) Хотя сейчас кажется очевидным, что можно по ресайзу менять эти переменные в модели, которая будет рассылать события по всем и вся.
ApplemanА откуда твоя главная вьюха "знает", в каких пределах и на какие значения должны измениться те или иные компоненты?
главная вьюха об этом ничего не знает. Она даже может не знать, сколько этих самых дочерних вьюх, если рассматривать вариант с моделью. В каждом спрайте, который имплементирует iResizeble, своя соб ственная функция resize(), в которую либо приходят размеры стейджа, либо она их забирает из модели и уже самостоятельно принимает решение об изменении.
Добавлено через 3 минуты
хотя блин, что я говорю, ведь каждый спрайт имеет доступ к stage.stageWidth и stageHeight)) Правда, это если он добавлен на сцену. А у меня просто размер менялся из js окружения, поэтому параметры ширины приходили из ExternalInterface
Конечно, Вьюха знает. Это ее единственная ответственность, расположить все красиво на экране.
Но для этого не нужна ссылка на стейдж. Ну то есть, она нужна Вью, и Вью ее получает один раз при добавлении на сцену. Далее Вью создает экземпляры своих модулей. Допустим, у тебя есть вверху полоса интерфейса с каким-то заголовком и парой кнопок (например, вызов глобального Меню, он же канает и за общую Паузу в игре, и, допустим, вызов окна Инвентаря и вызов окна Задания), и внизу полоса интерфейса со всякими данными о состоянии персонажа. А в центре окно текущего стейта — Поединок, или Торговля, или Диалог. Вот три модуля, верхний, нижний и центральный. Вью знает размер стейджа. Вью знает, что верхняя полоса должна быть 24 пикселя высотой, а нижняя 36, и их высота постоянна, её нельзя менять, а вот центральный модуль "подвижен". Так она вычисляет высоту центрального модуля, stage.stageHeight - 24 - 36; Так же узнает координаты Y для центрального модуля и для нижнего: 24 и stage.stageHeight - 36. Ширина всех модулей одинакова — stage.stageWidth. Все эти расчеты помещаются в метод ресайз(), чтобы можно было пересчитать в любой момент, если размеры сцены поменяются. После пересчета у модулей вызываются их методы ресайз(), в которые передаются новые значения.
Горизонтальные модули пытаются подстроиться под изменение ширины (высоту они не меняют по определению). Допустим, в модуле одна кнопка должна быть прижата к левому краю, а вторая — к правому. А посередине какой-то текст. Левую кнопку мы не трогаем, а правой надо пересчитать координату Х, верно? Затем мы узнаем ширину оставшегося пространства между кнопками и подстраиваем ширину текстфилда. УзнаЁм, влазит ли текст; если нет то меняем размер шрифта, пока не влезет.
Это все только звучит страшно; на деле ты бы все это же проворачивал, имея ссылку на стейдж чтобы спросить его размеры, а здесь получаешь размеры в метод ресайз() от Хозяина компонента, вот и вся разница. Но мимимишность использования такого компонента на порядок выше, чем если он сам будет звонить в генштаб по каждому поводу кроме тех, когда надо.
нужно оперировать анкерами(пределами) и точками опоры, а не ссылками на родителя/сцену и только при добавлении/изменении куда-то значения анкеров и точек опоры переводить в координаты и размер
посмотри API Flex https://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/core/UIComponent.html или Unity UI https://docs.unity3d.com/ScriptReference/RectTransform.html или Node в cocos2d http://www.cocos2d-x.org/reference/native-cpp/V3.0alpha0/d3/d82/classcocos2d_1_1_node.html
Appleman
01.11.2017, 17:24
Конечно, Вьюха знает. Это ее единственная ответственность, расположить все красиво на экране. Но для этого не нужна ссылка на стейдж. Ну то есть, она нужна Вью, и Вью ее получает один раз при добавлении на сцену. Далее Вью создает экземпляры своих модулей.
Получается, все ключевые размеры основных компонентов хранятся в главной вью, верно? Иначе как она узнает, что такой-то компонент имеет фиксированную высоту в столько-то пикселей. И тогда выходит, что размеры компонентам также передаёт в конструктор вью, так?
Nooob, спасибо, читаю.
ZergMaster
01.11.2017, 19:21
Appleman думаю, все же, компонент сам хранит свои размеры и координаты относительно размера приложения. Хранить положения и размеры всех дочерних вьюх в главной - это абсурд))
Имхо, флекс и прочие системы с использованием лейаутов и кучей компонентов слишком избыточен для игры; да и универсальности здесь особой не требуется, как в какой-нибудь библиотеке GUI-компонентов для разработки разных приложений. У игр обычно.. весьма специфический дизайн, далекий от графических примитивов, часто на 100% отрисованый в битмапах.
Получается, все ключевые размеры основных компонентов хранятся в главной вью, верно? Иначе как она узнает, что такой-то компонент имеет фиксированную высоту в столько-то пикселей. И тогда выходит, что размеры компонентам также передаёт в конструктор вью, так?А где им еще храниться, есть варианты? В самих себе?)
"Как она узнает".. ей не надо узнавать, это ты пишешь её и её компоненты. Не доводи до абсурда. Если же вдруг понадобится неизвестная заранее ЗАМЕНА одного компонента другим с неизвестной высотой/шириной, или просто не хочется хардкодить (забивать точные значения вместо "реальных" свойств), то всегда можно спросить именно свойство после ресайза. Если компонент не может изменять высоту, он ее и не изменит при ресайзе. То есть, в моем примере ты задавал бы координату Y центральному модулю как _topPane.height, а не тупо "24". И если в какой-то момент тебе пришлось бы вставить туда другую панель, высотой 30, центральному модулю пришлось бы слегка сжаться.
размеры компонентам также передаёт в конструктор вьюСначала в конструктор, текущие на момент создания, а потом в метод ресайз(w, h). Понятно, что код в конструкторе не дублирует код в ресайз(), а просто вызывает его с этими начальными параметрами.
ZergMaster, Вы меня пугаете. То есть, НЕ абсурд для Вас — когда никто понятия не имеет, какого размера штуки вываливаются на экран, и в каких местах?
Имхо, флекс и прочие системы с использованием лейаутов и кучей компонентов слишком избыточен для игры; да и универсальности здесь особой не требуется, как в какой-нибудь библиотеке GUI-компонентов для разработки разных приложений. У игр обычно.. весьма специфический дизайн, далекий от графических примитивов, часто на 100% отрисованый в битмапах.
Большинство игровых движков используют такой подход для верстки ui. Я не говорю что нужно использовать флекс или писать кучу компонентов, я советую использовать подход с анкерами для решения подобных задач.
undefined
02.11.2017, 00:15
а никто не подскажет чего-нибудь легковесного для оформления ui с помощью лейаутов(можно на js раз уж флэш похоронили)?Флекс и в самом деле сильно монструозен.
ZergMaster
02.11.2017, 01:00
Wolsh ну, тут, конечно, все зависит от задачи. Мне, как правило, хватает пропорций. Главной вьюхе не надо знать, где находятся дочерние, достаточно передать им свой размер. А они, исходя из этого размера, располагаются на сцене. Например произошел ресайз и по событию обновились глобальные width и height. Какая-нибудь дочерняя вьюшка, например аватарка пользователя, по событию приняла глобальные width и height и делает свой ресайз, в котором может быть наворочено куча всего. Например, она располагается на 10 пикселей от правого края и 10 пикселей сверху, принимает ширину 1/10 от сцены (но не меньше и не больше от крайних). А другая вьюха, какой-нибудь прогрессбар здоровья, висит на 10 пикселей от верхнего края и располагается в точке width/2 и так далее.
Нет, конечно, дисплей обжект контейнер все равно будет знать, где находятся его дети, я, конечно, имею ввиду то, что он их не располагает, а весь лэйаут происходит внутри компонента. Зачастую это удобно. Да, конечно, что касается кнопок меню, или каких-либо иконок в ряд или любых других списков - они просчитываются в зависимости друг от друга. Но главная сцена, как правило, все равно не располагает их. Она передает своим размеры в компонент "меню", который уже внутри себя располагает взаимозависимо кноки.
Или, вы хотите сказать, что главная сцена (вьюха) у вас содержит в себе большой-пребольшой метод resize, который занимает всеми этими расчетами и располагает всех детей в зависимости друг от друга? У меня этот метод в этом случае так разрастался, что я довольно быстро стал всю эту логику прятать в детей.
Добавлено через 5 минут
undefined для флеша - feathers (https://feathersui.com/ui-components/) на старлинге предназначена для построения интерфейсов.
Или, вы хотите сказать, что главная сцена (вьюха) у вас содержит в себе большой-пребольшой метод resize, который занимает всеми этими расчетами и располагает всех детей в зависимости друг от друга?Ну, у меня никогда "аватарка пользователя" или кнопка меню не окажется в главной Вью. Возможно, дело в этом. Вью имеет дело с тремя-пятью детьми, а те расставляют по местам своих детей, те — своих, и т.д. Положением и размером картинки-стейта кнопки занимается класс Кнопка, положением и размером Кнопки занимается класс Меню, положением и размером Меню занимается класс PopupLayer, а вот им управляет Вью. И даже игровое окно Вью не будет сама собирать по кусочкам, это будет какой-нибудь ГеймВью, который в свою очередь будет создавать три-четыре модуля и управлять ими (звучало хорошее слово "разметка"). А те уже тусовать внутри себя другие модули с иконками, аватарками и тп. То есть всегда, когда я пишу визуальный модуль, я закладываю в него возможность такого "умного" масштабирования без растягивания, искажения элементов. Поэтому и слово использую ресайз, а иногда и более точное rebuild. Потому что это не scale. Но инициировать этот ребилд может только хозяин компонента, потому что только он знает, что там творится вокруг. И даже если в результате какой-то внутренней жизни ребенка его вдруг раздуло (пришел новый текст например, или дизайнер заложил в него такую анимацию), ребенок должен сообщить об этом родителю, а не тупо занять под себя весь экран (что неизбежно в предлагаемой тобой парадигме "я сам!").
Я щас приведу пример одной поучительной ситуации, безотносительно всех этих умных вещей и религиозных догматов про иерархию и т.п. Почему нельзя ребёнкам самим подстраивать себя под стейдж (хотя для меня это очевидная вещь, но что ж делать...) Простой пример без всяких "потому что умные люди придумали умную вещь".
Представь. Написал ты игру по этой своей системе. Классная игра, и тебе удалось ее впарить какому-то гейм-порталу. И приходит от них ответ: Дружище, такое дело. Все эти ваши игрульки у нас на сайте загружаются в ротатор (проектор?). И поскольку игрулек много, там в проекторе слева есть такая панель со списком. А внизу — так уж повелось — у нас крутятся банеры. Вопрос: ты с чего вообще решил, что стейдж принадлежит тебе? Теперь пожалуйста возьми и перепиши свою игру так, чтобы она подстраивалась не под стейдж, а под Мейн, которому мы задаем размеры в своем проекторе-загрузчике.
Как думаешь, легко будет переписать ВСЮ игру так, чтобы каждый ее элемент подстраивался не под стейдж, на который у него автоматически есть ссылка, а под Мейн, который, строго говоря, и размеров то собственных на самом деле не имеет (в отличии от стейджа), а полностью зависит от добавленного в него контента. Представь, как ты будешь протаскивать в КАЖДУЮ фигулину ссылку на Мейн?
В чем мораль то. Стейдж не является частью вашего приложения. Он полностью независим и никак вашим кодом не управляется. Вы даже размер ему задать не можете. Даже те настройки, которые вы можете сделать из своего кода — stageAlign, scaleMode — относятся не к стейдж, а к тому как стейдж будет вертеть вашим Мейном. Стейдж всегда один для всего, что загружено в флэш-плеер, а загружено в него может быть далеко не только ваше приложение. Короче, размер вашего приложения может быть совсем не таким же, как у стейджа, и координаты вашего приложения на стейдже могут быть вовсе не (0, 0).
ZergMaster
02.11.2017, 09:11
Wolsh про пример - понятно. Главный ресайз от стеджа то никак не зависит - он может сработать как от события .RESIZE, так и от ExternalInterface, приняв в себя ширину и высоту.
Ну, про аватарку это ж я примеру ради. Речь о том, что в моем случае, ГеймВью, создав три-четыре модуля, не расставляет и не управляет ими, они просто сами знают, какую часть экрана занимают и в какой относительной точке находятся. Ведь пропорционально приложение то все равно должно быть постоянным. Если нам при каждом ресайзе надо полностью перестраивать их расположение, составляя разные узоры или что-то в этом духе - тогда конечно, без логики в родителе не обойтись. Просто, как правило, этого не требуется.
Я думая, что мой подход очень похож на то, о чем вы говорите, просто я стараюсь все, что возможно - спрятать в ресайзы детей. Пусть сами занимаются своим расположением, чай не маленькие.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.