Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Сообщения за день
 

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 22.02.2011, 01:54
forgottensmile вне форума Посмотреть профиль Отправить личное сообщение для forgottensmile Найти все сообщения от forgottensmile
  № 1  
Ответить с цитированием
forgottensmile

Регистрация: Feb 2011
Сообщений: 22
По умолчанию Движение множества символов

Здравствуйте!
Начал осваивать flash + actionscript 3.0 и столкнулся с проблемкой
Имею поле 800x700px, на котором постепенно появляются (выходят из-за границы поля) символы (для простоты, представляют собой небольшие прямоугольнички, рисуемые в actionscript)
создаю класс, в который засовываю массив этих символов, в этом же классе добавляю обработчик на ENTER_FRAME и реализую перемещение каждого из символов, в цикле пробегая по массиву
таким образом при количестве в 100 символов, все начинает безбожно тормозить (около 15фпс), а если усложнить и добавить анимацию в символы, то вообще беда
Как по правильному реализуется перемещение множества объектов на сцене? какие-то подводные камни? оптимизация?
Дайте совет
Спасибо

Старый 22.02.2011, 09:03
elcard вне форума Посмотреть профиль Отправить личное сообщение для elcard Найти все сообщения от elcard
  № 2  
Ответить с цитированием
elcard

Регистрация: Jan 2009
Сообщений: 51
Сразу бы код выкладывали, раз вопрос про оптимизацию.

Старый 22.02.2011, 09:35
Division вне форума Посмотреть профиль Отправить личное сообщение для Division Найти все сообщения от Division
  № 3  
Ответить с цитированием
Division
 
Аватар для Division

Регистрация: Jul 2008
Адрес: Украина, Херсон
Сообщений: 635
Отправить сообщение для Division с помощью ICQ
cacheAsBitmap возможно поможет. А вообще рендер у флеша софтварный и медленный
__________________
while(1) {}

Старый 22.02.2011, 09:36
forgottensmile вне форума Посмотреть профиль Отправить личное сообщение для forgottensmile Найти все сообщения от forgottensmile
  № 4  
Ответить с цитированием
forgottensmile

Регистрация: Feb 2011
Сообщений: 22
ничего сверхъестественного

Код AS3:
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);
		}
	}
CreepNamed представляет собой символ Creep с привязанным к нему текстовым полем

Код AS3:
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;
		}
	}
Ну и сам Creep

Код AS3:
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;
		}
	}

Старый 22.02.2011, 09:39
forgottensmile вне форума Посмотреть профиль Отправить личное сообщение для forgottensmile Найти все сообщения от forgottensmile
  № 5  
Ответить с цитированием
forgottensmile

Регистрация: Feb 2011
Сообщений: 22
то есть суть в том, что создается некое подобие игрушки Crimsonland, наверное все знают) так вот оригинал конечно был нефлешовый, но там одновременно на экране собиралось 100-200 монстриков, причем все активно шевелилось, пересчитывалось и т.д.
пытаясь повторить то же самое во флеше получаю дикие тормоза элементарно при перемещении сотни прямоугольничков

Старый 22.02.2011, 10:13
ЗлОй ПрОграММер вне форума Посмотреть профиль Отправить личное сообщение для ЗлОй ПрОграММер Найти все сообщения от ЗлОй ПрОграММер
  № 6  
Ответить с цитированием
ЗлОй ПрОграММер

Регистрация: Nov 2010
Сообщений: 434
может лучше сделать класс для каждого символа и в нём прописать движение, тормозить тогда возможно не будет

Старый 22.02.2011, 10:17
КорДум вне форума Посмотреть профиль Отправить личное сообщение для КорДум Найти все сообщения от КорДум
  № 7  
Ответить с цитированием
КорДум
 
Аватар для КорДум

блогер
Регистрация: Jan 2008
Адрес: syktyvkar
Сообщений: 3,803
Записей в блоге: 10
Один общий цикл enterFrame, где двигать все объекты сразу. Ну кэширование поставить.
Цитата:
может лучше сделать класс для каждого символа и в нём прописать движение
Не лучше.
__________________
тут я

Старый 22.02.2011, 21:40
forgottensmile вне форума Посмотреть профиль Отправить личное сообщение для forgottensmile Найти все сообщения от forgottensmile
  № 8  
Ответить с цитированием
forgottensmile

Регистрация: Feb 2011
Сообщений: 22
Цитата:
Сообщение от КорДум Посмотреть сообщение
Один общий цикл enterFrame, где двигать все объекты сразу
Собственно в классе CreepCrowd так и сделано в функции moveCreep
На сцене создается один объект CreepCrowd и внутри него в enterFrame все это хозяйство крутится
А насчет кеширования можно по подробнее?)

хммм...взял тестовый пример с частицами, включив отображение области перерисовки, заметил, что перерисовывается вся область экрана, что не есть гуд
попробовал избавиться от класса с символами, ради эксперимента, поместив создание и перемещение всех символов прямо в кадре на таймлайне, и результат на лицо: экран стал перерисовываться не полностью, а фрагментами с наибольшим скоплением символов, в результате был получен ОЧЕНЬ большой прирост производительности

однако применяя данный подход к текущему случаю, прироста производительности ровным образом не наблюдается совсем....интересно почему


Последний раз редактировалось forgottensmile; 22.02.2011 в 23:23.
Старый 23.02.2011, 21:32
dimarik вне форума Посмотреть профиль Отправить личное сообщение для dimarik Найти все сообщения от dimarik
  № 9  
Ответить с цитированием
dimarik
.
 
Аватар для dimarik

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
cacheAsBitmap помогает только при translate-преобразованиях (изменяются x, y). Остальные преобразования — rotation, scale и skew вынуждают FP заново рендерить из вектора.
__________________
Воспитан в TimeZero. Работаю в Mail.ru.

Старый 23.02.2011, 21:57
mikhailk вне форума Посмотреть профиль Отправить личное сообщение для mikhailk Найти все сообщения от mikhailk
  № 10  
Ответить с цитированием
mikhailk
 
Аватар для mikhailk

Регистрация: Nov 2009
Адрес: СПб
Сообщений: 2,236
Кстати, на мой взгляд, все, что не требует векторных преобразований в процессе визуализации, надо гнать в растр. Лучше самостоятельно. Векторное дерево с cashAsBitmap и оно же собранное и целиком записанное как битмап - две большие разницы.

Но к рассматриваемому случаю это не относится.
Вопрос к автору - если убрать текст (вообще), производительность повышается? Если повышается, можно попробовать заэмбедить шрифт в тексфилд. Если не повышается - подумать, как уменьшить количество вычислений. Тут, опять же, можно заменить сложные вычисления на простые (itemNamed.x += 2; ) и посмотреть, как все шевелится. Если 100 пустых квадратов без текста, передвигаемые за итерацию на 2 пикселя, не будут шевелиться - значит достигнут предел производительности ФП.

Добавлено через 22 минуты
на самом деле я вот тут запустил 1000 полосочек в упрощенном режиме, тормозов нет вообще:

Код AS3:
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;
		}
 
	}
 
}
Добавлено через 28 минут
Вот пример, если лень компилировать:
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.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


Часовой пояс GMT +4, время: 10:54.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.