![]() |
|
||||||||||
|
|
|
|||||
|
Регистрация: Feb 2011
Сообщений: 431
|
Доброго времени суток.
Столкнулся с задачей сгруппировать объекты на сцене, чтобы их можно было вместе растягивать, крутить и перемещать. И в принципе есть два решения : 1) Засовывать их в новый Sprite. Это облегчит существенно процесс вращения и растягивания, но для того чтобы добавить элемент в группу, нужно будет его "изъять" со сцены (заморочка с add(remove)Element / add(remove)Child во флексе) и добавить в мувик, при этом подгонять ему новые координаты чтобы визуально он остался на той же позиции. А в случае с вложенными группами это может превратиться в нехилый геморрой. Также что касается растягивания (поэкспериментировал со спрайтами) , то тоже всё автоматом будет сжиматься / растягиваться. 2) Объединять их в группы с помощью ассоциативных массивов. Т.е. каждому элементу задать свой groupID, и при клике на него, выделять всю группу (перетаскивать / вращать итд). Существенно упрощает работу с координатами, в принципе я реализовал в этом случае всё кроме вращения. Но при вращении придётся вращать каждый элемент вокруг своей оси и вокруг центра тяжести группы (который можно будет перетаскивать), что обещает доставить немало хлопот. При растягивании придётся учитывать смещение по x и y и изменение ширины/высоты. Кроме того, при операциях с целой группой придётся в цикле проматывать все элементы : скажем, при перетаскивании придётся обновлять координаты всех элементов группы, и элементов вложенных групп, итд. У меня вопрос - какой из вариантов будет жрать меньше ресурсов? Конечно многое зависит от реализации, но всё же? И может есть третий вариант, который намного проще и я попусту бьюсь головой об батарею ? Заранее спасибо. Последний раз редактировалось AlexLucas; 15.11.2012 в 15:01. |
|
|||||
|
Регистрация: Nov 2010
Сообщений: 497
|
Цитата:
Цитата:
В вашем случае правильное решение не заботится пока о быстродействии отрисовки, но принять меры для возможности замены способа отображения (спрайт или отедльные спрайты на экране) без изменения остальной логики. Простыми словами, отделить Model+Controller от View. Model от изменения способа отображения у вас измениться не должен. А потом уже по месту решать, что делать со view. Цитата:
Все ваши действия делаются элементарным домножением слева на матрицу трансформации. Т.е. была у объекта матрица Mo, стала Mt*Mo, где Mt - матрица преобразования. Для поворотов/сдвигов строится легко. Для перекоса (skew) повернутой группы (в координатах группы) чуть-чуть сложнее (добавится обратная матрица текущего преобразования группы). Соответственно, если у вас объекты собраны в одну группу, умножается только матрица группы. Если разобрана - матрицы отдельных элементов группы. Mt в этом случае - одна для всех таких элементов вне зависимости от вложенности! Ну и на всякий случай - никакой магии там нет. Эффективная матрица для объектов в группе строится путем умножения на внешние матрицы групп . Т.е. в одном случае у вас было Mg1*Mg2*Mob=Mobj1 (g1, g2 - группы, Mob- матрица трансформации объекта в группе g2, Mg2 - трансформация группы g2 относительно g1, Mg1 - трансформация g1 относительно сцены, Mobj1 - трансформация объекта относительно сцены). Очевидно, что из этого следует, что (Mt*Mg1)*(Mg2*Mob)=Mt*(Mg1*Mg2*Mob)=Mt*Mobj1, так что с точки зрения чистой математики без разницы, кого на что домножать.С точки зрения реализации я бы хранил отдельные матрицы трансформации для групп и объектов внутри группы. Для визуализации - как угодно. Можно складывать в спрайты (может быть, ставить им cacheAsBitmap). Можно раскладывать индивидуальные листья, вычисляя эффективную матрицу. Для трансформаций есть небольшое отличие, связанное с точностью вычислений. При использовании индивидуальных матриц из-за потери точности объекты внутри группы могут начать "разъезжаться" относительно друг друга. Т.е. после какого-то количества поворотов, например, квадрат перекосится. Причем вернуть объекты "в исходное состояние" уже не получится. А в группе (с отдельной матрицей) можно будет сбросить трансформацию группы и объекты станут квадратными. Хотя вы артефакты из-за точности вряд ли заметите, чтобы что-то накопилось, нужно быть или очень везучим (чтобы сразу создать матрицу трансформации, которая даст артефакт), или очень долго и нудно крутить объект (миллионы и миллиарды раз). Всякие rotation/scaleX/scaleY/x/y у визуального объекта вам не нужны. Совсем. Вам нужны матрицы. При желании преводить координаты из одних систем в другие (ну мало ли где нужно, для вывода на экран, например) используются те же матрицы преобразования объектов. В матрицах все прекрасно пишется и работает. Прием все операции (повотот, сдвиг, масштабирование, перекос (skew)) - все это домножения на матрицы, только матрицы разные. Соответственно, выбор и формирование матрицы делается при выборе операции, а затем на модель просто применяется операция (applyTransform(Matrix), например). |
|
|||||
|
Регистрация: Feb 2011
Сообщений: 431
|
Ну архитектура моего приложения скорее MVP чем MVC.
А что касается матриц, ведь всё кроме skew и shear можно осуществить элементарным rotation / x / y / scale. Вы видимо объяснили мне как растягивать пропорционально целую группу элементов, но я так и не понял : К примеру растягиваем группу с width 200 и height 300 так что в итоге её width изменяется на 10, height на 20. Какую матрицу применить ко всем элементам этой группы чтобы они также пропорционально растянулись ? Сделал но при scaleX и Y текстовых полей текст искажается ( в растре) / меняет размер шрифта (в векторе) Последний раз редактировалось AlexLucas; 16.11.2012 в 20:25. |
|
|||||
|
Регистрация: Nov 2010
Сообщений: 497
|
Конкретная архитектура не слишком принципиальна. Главное, чтобы вид был отделен от модели и его было просто поменять. Матрицами проще работать, чем scale/x/y/rotation. Через них все преобразования делаются единообразно и комбинации преобразований тоже легко выражаются. Через x/y/scale/rotation повотор вокруг произвольной точки, например, не так просто делается (для уже повернутого объекта).
Со скейлом все просто. Пусть мы скейлим относительно точки x, y. Тогда матрица будет |1 0 x| |sx 0 0| |1 0 -x| |0 1 y| * |0 sy 0| * |0 1 -y| = Ms |0 0 1| |0 0 1| |0 0 1| sx = 210 / 200, sy = 320 / 300 С текстом не совсем понятно, что именно вы хотите. Я бы как раз ожидал, что после скейла текст пропорционально уменьшится вместе со всеми остальными объектами группы. А иначе я нарисую кнопку, поскейлю, и она разъедется. Хотя вообще это тоже не большая проблема. Тоже решается матрицами . Пусть Mf - эффективная матрица текстового поля (либо просто матрица, либо произведение всег групп на собственную матрицу, если работать с раздельными матрицами). Тогда вычисляем "систему координат" текстового поля в экранных координатах. xs, ys - единичные вектора текстового поля в экранной системе координат. x', y' - нормирующие коэффициенты (вы же хотите, чтобы длины единичных отрезков сохранялись, поэтому они так и выбраны). Поэтому нужно еще домножить матрицу трансформации справа (именно справа!) на Mt. А еще умножить "исходную" ширину текстового поля на x' и высоту на y' (потому что относительно текста они изменились). Итоговая матрица для вывода текста будет (Mf * Mt). Все преобразования меняют только Mf! Mt (а также x' и y') вычисляются только в момент вывода текста на экран (при рендеринге) и пересчитывается при изменении Mf. Очевидно, что текст "относительно группы" при таких требованиях может выглядеть совершенно не так, как относительно экрана. Последний раз редактировалось maxkar; 17.11.2012 в 16:21. |
![]() |
![]() |
Часовой пояс GMT +4, время: 10:48. |
|
|
« Предыдущая тема | Следующая тема » |
|
|