|
0 Всего найдено: 49
TeNoR
Сообщение
01/03/2009 12:01
Копия темы
Реализация динамики теней Сталкиваюсь с этим в первые, сделал наброски по определению hitTest() и LineTo(), но нагрузка на SWF ужасная, чтобы определить круговое касание линий объектов (360 градусов относительно центра) требуется ждать до 30ти секунд (через цикл перебора for) и то, из-за нагрузки на Flash Player срабатывает через раз. Требуемая картина примерно таковая: Есть подвижный mc (вид сверху), требуемая задача реализовать тени против объёктов попадающих в радиус, где центром является подвижный mc. Единственное чего прошу идей или советов для оптимальной реализации... заранее спасибо.
Zloba
Сообщение
01/03/2009 12:04
Копия темы
Дак и спрашивают какие зы For не самый тормозной ненадо. Это версия цикла со встроенным итератором поэтмоу его и используют
TeNoR
Сообщение
01/03/2009 12:16
Копия темы
не имеет значения, тормоза из-за большой нагрузки мувиков за короткий период времени. даже при минимальной кратности к 360 градусам (допустим 60 линий) вызывают жуткую нагрузку, к тому же требование к задачи 30 кадров в секунду. А так AS2
Saint_Partizan
Сообщение
01/03/2009 12:18
Копия темы
Можно подробнее описать как у вас сейчас реализовано? Код например... Объекты статичны? Что в итоге хотите получить... А то не очень понимаю зачем lineTo()...
TeNoR
Сообщение
01/03/2009 12:25
Копия темы
lineTo() помогает осуществить направление линий относительно объекта в указанную координатную точку, в общих чертах требуется определить 3 точки соприкосновения для реализации тени: пустота, первое прикосновение с единичным объектом и конечное соприкосновение с единичным объектом (примерно требуется реализовать программную теневую маску (круг камеры относительно объекта).
TeNoR
Сообщение
01/03/2009 12:31
Копия темы
for(var i=1; i<=180; i++){ // 180 лини this.createEmptyMovieClip("mc"+i, i+1); eval("mc"+i).lineStyle(3, 0xFF0000, 100); eval("mc"+i).moveTo(mc._x, mc._y); eval("mc"+i).lineTo(200*Math.cos((Math.PI*2/180 )*i)+mc._x, 200*Math.sin((Math.PI*2/180)*i)+mc._y); // создание окружности по lineTo(), центр которого объект mc. if (eval("mc"+i).myHitTest(w, 1)) { // Само прикосновение линии с объектом eval("mc"+i)._alpha=30; }else{ eval("mc"+i)._alpha=10; } } MovieClip.prototype.myHitTest = function(clip:MovieClip, n:Number):Boolean { // Ручная функция hitTest() if (n == undefined) { var n:Number = 2; } var coord1:Object = this.getBounds(_root); var coord2:Object = clip.getBounds(_root); var square1:Number = Math.abs((coord1.xMax-coord1.xMin)*(coord1.yM ax-coord1.yMin)); var square2:Number = Math.abs((coord2.xMax-coord2.xMin)*(coord2.yM ax-coord2.yMin)); var coord:Object = square1>square2 ? coord2 : coord1; for (var i = coord.xMin+n/2; i<=coord.xMax; i += n) { for (var j = coord.yMin+n/2; j<=coord.yMax; j += n) { if (((clip.hitTest(i, j, true) ? 1 : 0)+(this.hitTest(i, j, true) ? 1 : 0)) == 2) { return true; } } } return false; };
TeNoR
Сообщение
01/03/2009 12:35
Копия темы
смысл в том, что тени должны падать относительно объекта, т.е. объект источник света upd: бинарный метод не подходит, перечислять 300*300 (по радиусу 150, учитывая, что минимальное расстояние 1н пиксель) будет более хучшим вариантом (учитывая, что изменения теней должно происходить за 1/20~1/30 секунды)
gaen
Сообщение
01/03/2009 12:41
Копия темы
Оптимизация номер раз: имея координаты объекта относительно источника света, определяем угол. Дальше смотрим от этого угла в разные стороны, пока не перестанем натыкаться на объект. Это позволяет не сканировать направления, в которых ничего нет. Оптимизация номер два: величина, на которую изменяется угол, изначально взять побольше, градусов 30 например. В общем подобрать максимальный угол, который не сможет перескочить объект. Как только видим что проскочили нужную границу, уменьшаем в 2 раза и начинаем двигаться в обратную сторону. И так пока не определим угол с нужной точностью. Это и есть тот самый бинарный поиск.
cleptoman
Сообщение
01/03/2009 12:42
Копия темы
это все канечно прекрасно, но непонятна задача этих манипуляций.. если нужно нарисовать тень, то фильтр (если плеер < 8 версии, то можно в принципе и ручками нарисовать, если очень захотеть) в фильтре есть параметры, а именно радиус и угол...и то и другое можно получить из разности координат объекта и источника света.
stepdev
Сообщение
01/03/2009 12:43
Копия темы
в флэше не разбираюсь но по алгоритму можно сделать чуть по другому, если исходить что объекты занимают меньшую площадь, то можно взять bound rect, и сканировать линиями внутри него, для каждого объекта, т.е. будт два цикла, один для перечисления объектов, другой для сканирования соприкосновения
v1per
Сообщение
01/03/2009 12:44
Копия темы
ужас какой! у вас eval больше чем хиттест тормозит это точно
v1per
Сообщение
01/03/2009 12:45
Копия темы
трассировка лучей один из самых ёмких вычислительных процессов, в вашем случае скорее подойдёт вариант с расчётом координат тени и её размера на основе положения объекта и источника тени
gaen
Сообщение
01/03/2009 12:47
Копия темы
Кстати да, запоминайте ссылку на мувик вместо того чтобы каждый раз напрягать eval, это ужасная функция! var mc:MovieClip = this["mc"+i]; mc.lineStyle... mc.moveTo... if(mc.myHitTest...)
stepdev
Сообщение
01/03/2009 12:47
Копия темы
кстати флэш же насколько я понимаю векторный, а можно в нем проходить по контрольным точкам объекта? типа myobj.vertex[n]
TeNoR
Сообщение
01/03/2009 12:53
Копия темы
>> Оптимизация номер раз: имея координаты объекта относительно источника света, определяем угол. Дальше смотрим от этого угла в разные стороны, пока не перестанем натыкаться на объект. Это позволяет не сканировать направления, в которых ничего нет. Вариант оптимален, если объектов не большое количество. Этот способ усложняет тормоза. >> Оптимизация номер два: величина, на которую изменяется угол, изначально взять побольше. Градусов 30 например. Как только видим что проскочили нужную границу, уменьшаем в 2 раза и начинаем двигаться в обратную сторону. И так пока не определим угол с нужной точностью. Это и есть тот самый бинарный поиск. Не подходит... если учитывать что не теневой угол будет слишком маленьким, алгоритм избыточен.
v1per
Сообщение
01/03/2009 12:54
Копия темы
а лучше при создании этих mc+i сразу забивать их в массив со ссылками, а потом уже обращаться к массиву
v1per
Сообщение
01/03/2009 12:56
Копия темы
во флеше можно и пиксельные шейдеры делать, вопрос только в том, хватит ли процессора пользователя)
gaen
Сообщение
01/03/2009 12:57
Копия темы
Если объектов много и они наслаиваются друг на друга то пожалуй да. Вы меня прямо заинтриговали, попробую написать трассировку на досуге :)
stepdev
Сообщение
01/03/2009 13:01
Копия темы
я имею ввиду что векторные объекты состоят из контрольных точек которые соединяются прямыми, таким образом получается полигон, если проходиться по объектам и для каждого объекта проходиться по точкам (коих для прямоугольника всего 4), то получается и достаточное быстродействие и точность.
Saint_Partizan
Сообщение
01/03/2009 13:02
Копия темы
нда... 1. Разбить объекты на отдельные мувики... (можно поместить в контейнер и вытащить for'ом ссылки на эти объекты) 2. Вам тень нужна или то что мы все видим? Если тень, дублируете мувик, и располагаете его дальше объекта под тем же углом учитывая scale. 3. HitTest в таких количествах да еще и во вложенных циклах смертелен :) 4. Прочтите хелп по Point, Math.atan2(), Matrix. Да, кстати... можете попробовать с bitmapData повозиться... если на разные объекты не представляется возможным разбить. Думаю там быстрее чуть должно быть. + в том что не придется все время hitTest() напрягать.
Saint_Partizan
Сообщение
01/03/2009 13:14
Копия темы
И еще.... объясните плз конечную цель... Я все понять не могу чего вы добиваетесь таким подходом.... Особенно "вид сверху" непонятен... Эта точка будет источником света??
TeNoR
Сообщение
01/03/2009 13:21
Копия темы
спасибо, я уже придумал такой вариант, что две линии объекта будут меняться в зависимости от положения источника света. Осталось привязать к геометрии окружности.
TeNoR
Сообщение
01/03/2009 13:22
Копия темы
основа тормозов не в eval(), скрипт на быструю руку написал...
TeNoR
Сообщение
01/03/2009 13:30
Копия темы
всем спасибо, все свободны =) вы меня натолкнули на такой подход: у каждого объекта будет изначальна тень (линии), которые будут поворачиваться в зависимости от источника света (мувика), это и будет самый скоростной и оптимальный эффект "тенизации" хотя, ради интереса, хотелось бы разработать движок получения тени для одного лишь мувика, опираясь на источник света.
Saint_Partizan
Сообщение
01/03/2009 18:33
Копия темы
Короче зацепила меня ваша задача :) Но чет я пива уже перепил.... :) Но есть начало, с которого можете двинуться... Вот код (AS3 правда... но там не используется ничего того чего нет в AS2 Shape только переделаете и все) работает быстро... В общих чертах, нужно из массива angle выбрать только по две точки на объект мин\макс удлинить линию до "за экраном", нарисовать фигуру из четырех точек и залить заливкой... И собственно все... В этом коде я просто самое начало реализации привел... Это быстрее, чем hitTest(), потому как работаем с простыми массивами. Если объекты(от которых тень) не будут сдвигаться, обход битмапа не нужно больше делать... это опять же производительность. В коде я просто для примера отрисовал 2700 линий до объекта от "источника света"... :) Зацените скорость :))))) import flash.display.BitmapData; import flash.geom.Rectangle; var bmd:BitmapData=new BitmapData(550,400,true,0); var rect:Rectangle=new Rectangle(100,120,60,20); var rect1:Rectangle=new Rectangle(400,320,60,20); bmd.fillRect(rect, 0xFFFF0000); bmd.fillRect(rect1, 0xFFFF0000); var sz=bmd.width*bmd.height; var center:Object={x:bmd.width/2,y:bmd.height/2}; var v=0; var h=0; //точка "света" bmd.setPixel32(center.x,center.y,0xFF0000FF) // массив не пустых точек var dots_arr:Array=new Array(); // обход массива BitmapData на наличие объекта. for (var i=0; i<sz; i++) { h++; if (h>bmd.width) { h=0; v++; } if (bmd.getPixel32(h,v)!=0) { dots_arr.push({x:h,y:v}); } } var angle:Array=new Array(); var indx=0; var stg:Shape=new Shape(); stg.graphics.lineStyle(0,0); for each(var j in dots_arr){ angle.push({a:radToDeg (Math.atan2(center.y-j.y,center.x-j.x))+180,i :indx}); stg.graphics.moveTo(center.x,center.y); stg.graphics.lineTo(j.x,j.y); indx++; } stg.graphics.endFill(); addChild(stg) function radToDeg (rad : Number) : Number { return (rad * 180) / Math.PI; } var bm:Bitmap=new Bitmap(bmd); addChild(bm);
Saint_Partizan
Сообщение
01/03/2009 19:17
Копия темы
а вот собсна и тени :) Но нужно найти только по два угла на объект.... я сейчас чет не соображаю как из более 3000 углов выбрать по 2 на объект... одно радует это точно решаемо :))))) import flash.display.BitmapData; import flash.geom.Rectangle; var bmd:BitmapData=new BitmapData(550,400,true,0); var rect:Rectangle=new Rectangle(100,120,60,20); var rect1:Rectangle=new Rectangle(400,320,60,20); var rect2:Rectangle=new Rectangle(400,220,40,20); bmd.fillRect(rect, 0xFFFF0000); bmd.fillRect(rect1, 0xFFFF0000); bmd.fillRect(rect2, 0xFFFF0000); var sz=bmd.width*bmd.height; var center:Object={x:bmd.width/2,y:bmd.height/2}; var v=0; var h=0; //точка "света" // массив не пустых точек var dots_arr:Array=new Array(); // обход массива BitmapData на наличие объекта. for (var i=0; i<sz; i++) { h++; if (h>bmd.width) { h=0; v++; } if (bmd.getPixel32(h,v)!=0) { dots_arr.push({x:h,y:v}); } } bmd.setPixel32(center.x,center.y,0xFF0000FF); bmd.setPixel32(center.x+1,center.y,0xFF0000FF ); bmd.setPixel32(center.x,center.y+1,0xFF0000FF ); bmd.setPixel32(center.x+1,center.y+1,0xFF0000 FF); var angle:Array=new Array(); var indx=0; var stg:Shape=new Shape(); stg.graphics.lineStyle(0,0); for each (var j in dots_arr) { //angle.push({a:radToDeg (Math.atan2(center.y-j.y,center.x-j.x))+180,i :indx}); var pnt:Point=new Point(); pnt=Point.polar(200,Math.atan2(-(center.y-j.y ),-(center.x-j.x))); stg.graphics.moveTo(j.x,j.y); pnt.offset(j.x,j.y) stg.graphics.lineTo(pnt.x,pnt.y); indx++; } stg.graphics.endFill(); addChild(stg); function radToDeg(rad : Number):Number { return (rad * 180) / Math.PI; } var bm:Bitmap=new Bitmap(bmd); addChild(bm);
TeNoR
Сообщение
01/03/2009 19:29
Копия темы
спасибо большое за наводку (с битмапом работал не часто), придумал примерный способ (если по углам объектов расставить точки и задать начальные линии, которые будут вращаться противоположно относительно источника света, в определённом радиусе, с дальнейшей заливкой). теперь больше мучает вопрос по геометрии относительно круглого объекта (который должен давать тень), хотя можно обойти поворотом 2х точек относительно источника света.
Saint_Partizan
Сообщение
01/03/2009 19:36
Копия темы
не ну смотрите сами конечно... но вот что у меня получилось в последнем примере...
Saint_Partizan
Сообщение
01/03/2009 19:37
Копия темы
Просто если что непонятно по коду, спрашивайте.... для того мы все тут и сидим :)))
TeNoR
Сообщение
01/03/2009 19:40
Копия темы
хотя меня пугает алгоритм нахождения углов (по затрате времени), в любом случае большое спасибо
TeNoR
Сообщение
01/03/2009 19:47
Копия темы
я имел ввиду, что задать постоянное угловое отношение круглому объекту не выйдет (если источник света будет двигаться)
Saint_Partizan
Сообщение
01/03/2009 19:48
Копия темы
Вот на этом я сейчас и упал :)))) Но это не очень большая проблема, и если ее решить(а решить ее конечно же можно, но не под пивом :))))) ), то будет очень хорошее решение. В вашем решении есть один большой недостаток... на каждом объекте придется буквально вручную делать эту самую тень... А если объектом будет овал? :)
TeNoR
Сообщение
01/03/2009 19:54
Копия темы
0
>> А если объектом будет овал? :) 1: задать две точки (равноотдалённых друг от друга), которые будут вращаться относительно объекта света. 2: шестиугольник как вариант) |
Выразить восторг, поругаться или предложить что-нибудь можно на форуме |
Для обсуждения этого сервиса так же есть темы на фрилансе по поиску , флудотопу ,и по удалённым сообщениям ,и по Актуальным/популярным темам , и по топу "кто кому больше наотвечал" |