|
|
|||||
Регистрация: Feb 2011
Сообщений: 22
|
Движение множества символов
Здравствуйте!
Начал осваивать flash + actionscript 3.0 и столкнулся с проблемкой Имею поле 800x700px, на котором постепенно появляются (выходят из-за границы поля) символы (для простоты, представляют собой небольшие прямоугольнички, рисуемые в actionscript) создаю класс, в который засовываю массив этих символов, в этом же классе добавляю обработчик на ENTER_FRAME и реализую перемещение каждого из символов, в цикле пробегая по массиву таким образом при количестве в 100 символов, все начинает безбожно тормозить (около 15фпс), а если усложнить и добавить анимацию в символы, то вообще беда Как по правильному реализуется перемещение множества объектов на сцене? какие-то подводные камни? оптимизация? Дайте совет Спасибо |
|
|||||
Регистрация: Jan 2009
Сообщений: 51
|
Сразу бы код выкладывали, раз вопрос про оптимизацию.
|
|
|||||
cacheAsBitmap возможно поможет. А вообще рендер у флеша софтварный и медленный
__________________
while(1) {} |
|
|||||
Регистрация: Feb 2011
Сообщений: 22
|
ничего сверхъестественного
import flash.display.Sprite; import flash.events.Event; import flash.geom.Point; import flash.display.MovieClip; import com.greensock.*; import com.greensock.easing.*; import hype.extended.layout.ShapeLayout; import hype.extended.behavior.VariableVibration; import hype.framework.core.ObjectPool; public class CreepCrowd extends Sprite { private var creeps:Array = []; private var targetPointX:Number; private var targetPointY:Number; private var respawnZone:MovieClip; private var respawnZoneLayout:ShapeLayout; public function CreepCrowd(respawnZone:MovieClip, targetPointX:Number, targetPointY:Number, num:Number=100) { this.respawnZone = respawnZone; this.targetPointX = targetPointX; this.targetPointY = targetPointY; respawnZoneLayout = new ShapeLayout(respawnZone); createNamedCreeps(num); addEventListener(Event.ENTER_FRAME, moveCreep); } public function moveCreep(e:Event):void { for each (var itemNamed:CreepNamed in creeps) { var item:Creep = itemNamed.getCreep(); var point:Point = item.globalToLocal(new Point(targetPointX, targetPointY)); if (point.y > 2) { item.rotation += item.getRotationSpeed(); } else if (point.y < -2){ item.rotation -= item.getRotationSpeed(); } itemNamed.x += Math.cos(item.rotation * (Math.PI / 180)) * item.getSpeed(); itemNamed.y += Math.sin(item.rotation * (Math.PI / 180)) * item.getSpeed(); } } private function createNamedCreeps(num:Number):void { for (var i:int = 0; i < num; i++) { var creepNamed:CreepNamed = new CreepNamed(); var creep:Creep = creepNamed.getCreep(); creep.rotation = Math.random() * 360; creep.setSpeed(Math.random() * 0.5 + 0.2); creep.setRotationSpeed(Math.random() * 3 + 2); respawnZoneLayout.applyLayout(creepNamed); addChild(creepNamed); creeps.push(creepNamed); } } public function getCreepArray():Array { return creeps; } public function killCreep(creep:CreepNamed):void { removeChild(creep); creeps.splice(creeps.indexOf(creep), 1); } } import flash.display.Sprite; import flash.text.*; import flash.ui.Keyboard; public class CreepNamed extends Sprite { private var creep:Creep; private var txt:String; public function CreepNamed(coord_x:int = 0, coord_y:int = 0) { x = coord_x; y = coord_y; creep = new Creep(); creep.x = coord_x; creep.y = coord_y; txt = new String(); for (var i=0; i<5; i++) { txt = txt.concat(String.fromCharCode(Math.random() * 10 + 80)).toLowerCase(); } var txtField:TextField = new TextField(); txtField.text = txt; txtField.textColor = 0xFFFFFF; txtField.width = 50; txtField.height = 20; txtField.mouseEnabled = false; txtField.type = TextFieldType.DYNAMIC; txtField.x = creep.x - 20; txtField.y = creep.y - 25; addChild(creep); addChild(txtField); } public function getCreep():Creep { return creep; } public function getText():String { return txt; } } import flash.display.MovieClip; import flash.text.*; import flash.ui.Keyboard; public class Creep extends MovieClip { private var speed:Number; private var rotationSpeed:uint; public function Creep() { graphics.beginFill(0x000000); graphics.drawRect( -5, 0, 10, 2); graphics.endFill(); } public function setSpeed(speed:Number):void { this.speed = speed; } public function getSpeed():Number { return speed; } public function setRotationSpeed(rotationSpeed:uint):void { this.rotationSpeed = rotationSpeed; } public function getRotationSpeed():uint { return rotationSpeed; } } |
|
|||||
Регистрация: Feb 2011
Сообщений: 22
|
то есть суть в том, что создается некое подобие игрушки Crimsonland, наверное все знают) так вот оригинал конечно был нефлешовый, но там одновременно на экране собиралось 100-200 монстриков, причем все активно шевелилось, пересчитывалось и т.д.
пытаясь повторить то же самое во флеше получаю дикие тормоза элементарно при перемещении сотни прямоугольничков |
|
|||||
Регистрация: Nov 2010
Сообщений: 434
|
может лучше сделать класс для каждого символа и в нём прописать движение, тормозить тогда возможно не будет
|
|
|||||
Регистрация: Feb 2011
Сообщений: 22
|
Собственно в классе CreepCrowd так и сделано в функции moveCreep
На сцене создается один объект CreepCrowd и внутри него в enterFrame все это хозяйство крутится А насчет кеширования можно по подробнее?) хммм...взял тестовый пример с частицами, включив отображение области перерисовки, заметил, что перерисовывается вся область экрана, что не есть гуд попробовал избавиться от класса с символами, ради эксперимента, поместив создание и перемещение всех символов прямо в кадре на таймлайне, и результат на лицо: экран стал перерисовываться не полностью, а фрагментами с наибольшим скоплением символов, в результате был получен ОЧЕНЬ большой прирост производительности однако применяя данный подход к текущему случаю, прироста производительности ровным образом не наблюдается совсем....интересно почему Последний раз редактировалось forgottensmile; 22.02.2011 в 23:23. |
|
|||||
.
|
cacheAsBitmap помогает только при translate-преобразованиях (изменяются x, y). Остальные преобразования — rotation, scale и skew вынуждают FP заново рендерить из вектора.
|
|
|||||
Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
|
Кстати, на мой взгляд, все, что не требует векторных преобразований в процессе визуализации, надо гнать в растр. Лучше самостоятельно. Векторное дерево с cashAsBitmap и оно же собранное и целиком записанное как битмап - две большие разницы.
Но к рассматриваемому случаю это не относится. Вопрос к автору - если убрать текст (вообще), производительность повышается? Если повышается, можно попробовать заэмбедить шрифт в тексфилд. Если не повышается - подумать, как уменьшить количество вычислений. Тут, опять же, можно заменить сложные вычисления на простые (itemNamed.x += 2; ) и посмотреть, как все шевелится. Если 100 пустых квадратов без текста, передвигаемые за итерацию на 2 пикселя, не будут шевелиться - значит достигнут предел производительности ФП. Добавлено через 22 минуты на самом деле я вот тут запустил 1000 полосочек в упрощенном режиме, тормозов нет вообще: package { import flash.display.Sprite; import flash.events.Event; public class Main extends Sprite { private var clips:Array = new Array(); public function Main():void { if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point ClipForMoving.xBound = 700; ClipForMoving.yBound = 500; for (var i:int = 0; i < 1000; i++) { var startX:int = 50 + int(Math.random() * 600); var startY:int = 50 + int(Math.random() * 400); var dX:int = -10 + int(Math.random() * 20); var dY:int = -10 + int(Math.random() * 20); var rotationSpeed:int = 1 + int(Math.random() * 90); var clipForMoving:ClipForMoving = new ClipForMoving(startX, startY, dX, dY, rotationSpeed); addChild(clipForMoving); clips.push(clipForMoving); } addEventListener(Event.ENTER_FRAME, onEnterFrame); } private function onEnterFrame(e:Event) : void { var clipsCount:int = clips.length; for (var i:int = 0; i < clipsCount; i++) { clips[i].move(); } } } } package { import flash.display.Sprite; public class ClipForMoving extends Sprite { public static var xBound:int; public static var yBound:int; private var dX:int; private var dY:int; private var rotationSpeed:int; public function ClipForMoving(x:int,y:int,dX:int,dY:int,rotationSpeed:int) { this.x = x; this.y = y; this.dX = dX; this.dY = dY; this.rotationSpeed = rotationSpeed; graphics.beginFill(0xff0000); graphics.drawRect( -5, 0, 10, 2); graphics.endFill(); } public function move() : void { this.x += dX; if (this.x > xBound && dX > 0) dX = -dX; if (this.x < 0 && dX < 0) dX = -dX; this.y += dY; if (this.y > yBound && dY > 0) dY = -dY; if (this.y < 0 && dY < 0) dY = -dY; this.rotation += rotationSpeed; } } } Вот пример, если лень компилировать: http://mikhailk.ru/testing/clipMoving/ Добавлено через 1 час 24 минуты Стало интересно, попробовал с текстом, производительность упала примерно в 6 раз. http://mikhailk.ru/testing/clipMoving/withText.html Последний раз редактировалось mikhailk; 23.02.2011 в 23:22. |
Часовой пояс GMT +4, время: 10:54. |
|
« Предыдущая тема | Следующая тема » |
|
|