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

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

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 14.02.2014, 18:17
australian incognito вне форума Посмотреть профиль Отправить личное сообщение для australian incognito Найти все сообщения от australian incognito
  № 1  
Ответить с цитированием
australian incognito
 
Аватар для australian incognito

Регистрация: Sep 2005
Адрес: Минск
Сообщений: 389
Post Работа с массивами [UPDATE]

Задам вопрос в контексте недавно созданной темы: http://www.flasher.ru/forum/showthread.php?t=206574
Ниже описан применяемый мной алгоритм, но главный вопрос: почему при трейсе 'rand num' не совпадают с 'res num'? Как сделать, чтобы совпадали и логика, заложенная ниже работала верно?
Код AS3:
import flash.events.Event;
 
var objNum:Number = 10;
var objArr:Array = new Array();
var enabledObjArr:Array = new Array();
var prevObjArr:Array = new Array();
//
var entFrParam:Number = 0;
var entFrParamMax:Number = 60;
 
function mainFunc(e:Event):void
{
	var i:int;
	//
	if (entFrParam++ == entFrParamMax)
	{
		trace("\n\n///////// rand num:")
		//
		entFrParam = 0;
		//
		prevObjArr = getRandElements(objArr,4,prevObjArr);
		//
		for (i = 0; i < prevObjArr.length; i++)
		{
			//trace(prevObjArr[i].name)
			enabledObjArr.push(prevObjArr[i]);
			//
			trace(prevObjArr[i].name);
		}
		trace("///////// res num:")
	}
	//
	for (i = 0; i < enabledObjArr.length; i++)
	{
		process(enabledObjArr[i], 60);
		//
		if (enabledObjArr[i].degree >= 360)
		{
			trace(enabledObjArr[i].name);
			//
			enabledObjArr.shift();
		}
	}
}
 
function getRandElements(arr:Array, n:int, exclude:Array):Array
{
	var i:int;
	var tmp:Array = arr.concat();
	var res:Array = [];
 
	// убираем исключаемые
	for (i = 0; i < exclude.length; i++)
	{
		tmp.splice(tmp.indexOf(exclude[i]), 1);
	}
	// выбираем из оставшихся рандомно
	for (i = 0; i < n; i++)
	{
		var rnd:int = Math.random() * tmp.length;
		res.push(tmp[rnd]);
		tmp.splice(rnd, 1);
	}
 
	// возвращаем нужный массив
	return res;
}
 
function process(obj:Object, speed:Number)
{
	obj.degree +=  speed;
}
 
for (var i = 0; i < objNum; i++)
{
	objArr[i] = new Object();
	objArr[i].name = i;
	objArr[i].degree = 0;
}
//
this.addEventListener(Event.ENTER_FRAME, mainFunc);

Старый 14.02.2014, 20:48
silin вне форума Посмотреть профиль Посетить домашнюю страницу silin Найти все сообщения от silin
  № 2  
Ответить с цитированием
silin
 
Аватар для silin

блогер
Регистрация: Mar 2003
Адрес: Моск. обл.
Сообщений: 5,269
Записей в блоге: 6
на каждом 60м такте вы генерите выборку prevObjArr и все ее элементы добавляете в enabledObjArr
на каждом же такте каждому элементу enabledObjArr увеличиваем degree и при достижении этим degree значения 360 смотрим трейс этого элемента, удаляя при этом первый элемент enabledObjArr
ну т.е. где-то до шестого такта (degree<360) мы не видим никакго трейса, а потом видим некий сумбур, организованный с помощью enabledObjArr.shift() в цикле, а дальше снова ничего не видим ( enabledObjArr пуст) до следующего 60го такта..

что за "логика" тут реализована и почему эти трейсы должны совпадать не оч. понятно

Старый 14.02.2014, 22:45
australian incognito вне форума Посмотреть профиль Отправить личное сообщение для australian incognito Найти все сообщения от australian incognito
  № 3  
Ответить с цитированием
australian incognito
 
Аватар для australian incognito

Регистрация: Sep 2005
Адрес: Минск
Сообщений: 389
Предполагаемая логика следующая:
  1. есть некий массив objArr на 10 обьектов
  2. с итерацией в 60 кадров мы делаем из него рандомную выборку на 4 обьекта (исключая совпадение с 4-мя объектами предыдущей итерации). 4 этих объекта мы помещаем в массив enabledObjArr, чтобы можно было проводить с ними дальнейшие манипуляции.
  3. с итерацией в 1 кадр мы наращиваем параметр degree каждого из инициализированных обьектов из массива enabledObjArr до 360 с некоторой заданной скоростью (в нашем случае 60)
  4. по достижению параметром degree отметки в 360 мы удаляем обьект из массива enabledObjArr, тем самым исключив наращивание параметра.
  5. удаляется нарощенный до 360 обьект с помощью shift, т.к. первым достигнет 360 именно тот обьект, который был добавлен первым в массив (тут я могу ошибаться, но вроде как это очевидно).
так почему же должны совпадать выводы трейсом rand num и res num?
Первое (rand num) нам показывает случайную выборку из 4 чисел в нужной последовательности, которые мы активировали в п. 2. Допустим это обьекты № 3, 7, 1, 5.
По моей логике у обьекта №3 у первого из четырех параметр degree начнет прирост и соответственно у него же первым достигнет 360. Соответственно он первым и должен быть удален из массива и выведен первым в res num.
Так это задумывалось.
Спасибо тем, кто осилил это длинное обьяснение.

Добавлено через 9 минут
Еще хочу добавить более цельную концепцию того, что бы я хотел видеть по итогу.
Предположим есть 10 обьектов. Каждый при инициализации отрисовывает круг с некоторой скоростью.
При 60 fps задача такая: каждую секунду из 10 обьектов выбирать 4 (не пересекающихся с объектами прошлой итерации) и наращивать в них угол до 360 градусов (т.е. по-сути, отрисовывать круг). На этом все, как только круг отрисован, обьекты можно опять обнулять (градусы = 0) и ждать следующей операции по инициализации 4 рандомных обьектов. Получается каждую секунду мы отрисовываем 4 из 10 круга, которые по завершению отрисовки исчезают. Объекты текущей итерации не совпадают с обьектами из предыдущей. На этом все.

Старый 14.02.2014, 23:53
silin вне форума Посмотреть профиль Посетить домашнюю страницу silin Найти все сообщения от silin
  № 4  
Ответить с цитированием
silin
 
Аватар для silin

блогер
Регистрация: Mar 2003
Адрес: Моск. обл.
Сообщений: 5,269
Записей в блоге: 6
ну примерно так все и происходит, только смотреть надо как-то аккуратнее что ли
да, и еще одна ловушка: операции типа удаления элементов массива в цикле по индексу - при удалении все индексы смещаются, а это не всегда легко можно учесть
Код AS3:
function mainFunc(e:Event):void
{
	var i:int;
	if (entFrParam++ == entFrParamMax)
	{
		trace("------60----prevObjArr:")
		entFrParam = 0;
		prevObjArr = getRandElements(objArr, 4, prevObjArr);
		enabledObjArr = prevObjArr.concat();
		for (i = 0; i < prevObjArr.length; i++)
		{
			trace(prevObjArr[i].name);
		}
	}
	if (!enabledObjArr.length) return;
	trace("------1-----enabledObjArr:")
 
	for (i = 0; i < enabledObjArr.length; i++)
	{
		trace(enabledObjArr[i].name);
	}
	for (i = 0; i < enabledObjArr.length; i++)
	{
		process(enabledObjArr[i], 60);
		if (enabledObjArr[i].degree >= 360)
		{
			enabledObjArr.splice(i--, 1);
		}
	}
}
зы
ну и, конечно, разруливать функционал объектов какими-то внешними функциями в циклах это, имхо, путь к вывиху мозга..
насоздавал, а дальше когда надо и кого надо запустил, все остальное объект в состоянии решить и сделать сам:
Код AS3:
package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;
 
 
	public class Main extends Sprite
	{
 
		private var objNum:Number = 10;
		private var objArr:Array = [];
		private var prevObjArr:Array = [];
 
		public function Main():void
		{
 
			for (var i:int = 0; i < objNum; i++)
			{
				var obj:Obj = new Obj(i);
 
				obj.x = 100 + Math.random() * 200;
				obj.y = 100 + Math.random() * 200;
				objArr.push(obj);
				addChild(obj);
			}
			var timer:Timer = new Timer(1000);
			timer.addEventListener(TimerEvent.TIMER, timer_timer);
			timer.start();
		}
 
		private function timer_timer(e:TimerEvent):void 
		{
			prevObjArr = getRandElements(objArr, 4, prevObjArr);
			trace( "prevObjArr : " + prevObjArr );
			for (var i:int = 0; i < prevObjArr.length; i++)
			{
				prevObjArr[i].start();
			}
		}
 
 
 
		private function getRandElements(arr:Array, n:int, exclude:Array):Array
		{
			var i:int;
			var tmp:Array = arr.concat();
			var res:Array = [];
 
			// убираем исключаемые
			for (i = 0; i < exclude.length; i++)
			{
				tmp.splice(tmp.indexOf(exclude[i]), 1);
			}
			// выбираем из оставшихся рандомно
			for (i = 0; i < n; i++)
			{
				var rnd:int = Math.random() * tmp.length;
				res.push(tmp[rnd]);
				tmp.splice(rnd, 1);
			}
 
			// возвращаем нужный массив
			return res;
		}
 
	}
 
}
import flash.display.Sprite;
import flash.events.Event;
 
//////////////////
class Obj extends Sprite 
{
	public var degree:Number = 0;
	public var id:int;
	public var speed:Number = 0.2;
	public var radius:Number = 10;
	public function Obj(id:int) 
	{
		super();
		this.id = id;
	}
	public function start():void
	{
		degree = 0;
		graphics.clear();
		graphics.lineStyle(0);
		graphics.moveTo(radius * Math.cos(degree), radius * Math.sin(degree));
		addEventListener(Event.ENTER_FRAME, process);
	}
 
	private function process(e:Event):void 
	{
		degree += speed;
		graphics.lineTo(radius * Math.cos(degree), radius * Math.sin(degree));
		if (degree >= 2 * Math.PI)
		{
			// останавливаем
			removeEventListener(Event.ENTER_FRAME, process);
			// ну и что-там еще надо..
			graphics.clear();
		}
	}
 
	override public function toString():String
	{
		return "obj_" + id;
	}
 
}


Последний раз редактировалось silin; 15.02.2014 в 00:20.
Старый 15.02.2014, 00:21
australian incognito вне форума Посмотреть профиль Отправить личное сообщение для australian incognito Найти все сообщения от australian incognito
  № 5  
Ответить с цитированием
australian incognito
 
Аватар для australian incognito

Регистрация: Sep 2005
Адрес: Минск
Сообщений: 389
Цитата:
Сообщение от silin Посмотреть сообщение
ну примерно так все и происходит, только смотреть надо как-то аккуратнее что ли
Код AS3:
function mainFunc(e:Event):void
{
	var i:int;
	if (entFrParam++ == entFrParamMax)
	{
		trace("------60----prevObjArr:")
		entFrParam = 0;
		prevObjArr = getRandElements(objArr, 4, prevObjArr);
		enabledObjArr = prevObjArr.concat();
		for (i = 0; i < prevObjArr.length; i++)
		{
			trace(prevObjArr[i].name);
		}
	}
	if (!enabledObjArr.length) return;
	trace("------1-----enabledObjArr:")
 
	for (i = 0; i < enabledObjArr.length; i++)
	{
		trace(enabledObjArr[i].name);
	}
	for (i = 0; i < enabledObjArr.length; i++)
	{
		process(enabledObjArr[i], 60);
		if (enabledObjArr[i].degree >= 360)
		{
			enabledObjArr.splice(i--, 1);
		}
	}
}
При подмене моей функции на вашу, все держится неплохо 2-3 цикла, потом сбивается по каким-то непонятным причинам... Как будто часть объектов массива enabledObjArr исчезает сама собой.

На самом деле костыль с функциями в цикле придуман был условно, чтобы максимально быстро передать суть требуемого алгоритма.

Старый 15.02.2014, 00:43
silin вне форума Посмотреть профиль Посетить домашнюю страницу silin Найти все сообщения от silin
  № 6  
Ответить с цитированием
silin
 
Аватар для silin

блогер
Регистрация: Mar 2003
Адрес: Моск. обл.
Сообщений: 5,269
Записей в блоге: 6
>> потом сбивается по каким-то непонятным причинам..
думаю, по причине, что во вновь выбранной партии могут быть экземпляры с ненулевым degree или что-то в этом роде..., отслеживать такие штуки в этих циклах с динамическими объектами как-то безидейно совсем
вот так, может быть

Код AS3:
private function mainFunc(e:Event):void
{
	var i:int;
	if (entFrParam++ == entFrParamMax)
	{
		trace("------60----prevObjArr:")
		entFrParam = 0;
		prevObjArr = getRandElements(objArr, 4, prevObjArr);
		enabledObjArr = prevObjArr.concat();
		for (i = 0; i < prevObjArr.length; i++)
		{
			prevObjArr[i].degree = 0;
			trace(prevObjArr[i].name);
		}
	}
	if (!enabledObjArr.length) return;
	trace("------1-----enabledObjArr:")
	var tmp:Array = [];
	for (i = 0; i < enabledObjArr.length; i++)
	{
		trace(enabledObjArr[i].name);
		process(enabledObjArr[i], 60);
		if (enabledObjArr[i].degree < 360)
		{
			tmp.push(enabledObjArr[i]);
		}
	}
	enabledObjArr = tmp;
 
}
UPD. плюс удаление из массива в цикле по его индексу, это чаще всего головоломка, которую легче обойти, чем решать


Последний раз редактировалось silin; 15.02.2014 в 00:56.
Старый 17.02.2014, 02:09
australian incognito вне форума Посмотреть профиль Отправить личное сообщение для australian incognito Найти все сообщения от australian incognito
  № 7  
Ответить с цитированием
australian incognito
 
Аватар для australian incognito

Регистрация: Sep 2005
Адрес: Минск
Сообщений: 389
Цитата:
Сообщение от silin Посмотреть сообщение
>>
думаю, по причине, что во вновь выбранной партии могут быть экземпляры с ненулевым degree или что-то в этом роде..., отслеживать такие штуки в этих циклах с динамическими объектами как-то безидейно совсем
Беда в том, что в моей рабочей версии кода - параметр degree наращивается вновь созданному классу Circle, у которого параметр degree по дефолту нулевой... Я бы и рад показать рабочую версию, но там слишком много не относящегося к вопросу кода, без которого не будет работать ничего. Базовую версию в первом посте я написал как "выжимку" нужного кода для того, чтобы не быть совсем абстрактным... Так вот уже на первой итерации у меня 360 градусов второй обьект никогда не достигает, он как будто вообще не создавался. А 4-й достигает 360, но с отставанием в один кадр (возможно, это результат исчезновения второго обьекта, но далеко не факт).
Вы красиво обошли подсчет угла переопределением нужного массива и обратным сравнением вот тут:
Код AS3:
if (enabledObjArr[i].degree < 360)
		{
			tmp.push(enabledObjArr[i]);
		}
Но в моем случае мне просто необходимо по выполнению условия
Код AS3:
if (enabledObjArr[i].degree >= 360)
		{
		  //// some code
		}
выполнять некие дополнительные действия. Но именно это условие дает выпадение элемента массива и непонятную ошибку.

Старый 17.02.2014, 08:57
silin вне форума Посмотреть профиль Посетить домашнюю страницу silin Найти все сообщения от silin
  № 8  
Ответить с цитированием
silin
 
Аватар для silin

блогер
Регистрация: Mar 2003
Адрес: Моск. обл.
Сообщений: 5,269
Записей в блоге: 6
>>Но в моем случае мне просто необходимо по выполнению условия выполнять некие дополнительные действия.

в этом же 'сортировочном' цикле положите их в другой список, с которым сотворите эти доп. действия, не путаясь в индексах
Код AS3:
var tmp:Array = [];
var tmp1:Array = [];
for (i = 0; i < enabledObjArr.length; i++)
{
 
	process(enabledObjArr[i], 60);
	if (enabledObjArr[i].degree < 360)
	{
		tmp.push(enabledObjArr[i]);
	}else
	{
		tmp1.push(enabledObjArr[i]);
	}
}
Добавлено через 12 минут
зы. ну и повторюсь, совершенно непонятно стремление разместить логику, которая может(должна) быть 'на борту' самих объектов, в каких-то внешних циклах..

Старый 23.02.2014, 01:00
australian incognito вне форума Посмотреть профиль Отправить личное сообщение для australian incognito Найти все сообщения от australian incognito
  № 9  
Ответить с цитированием
australian incognito
 
Аватар для australian incognito

Регистрация: Sep 2005
Адрес: Минск
Сообщений: 389
Цитата:
Сообщение от silin Посмотреть сообщение
зы. ну и повторюсь, совершенно непонятно стремление разместить логику, которая может(должна) быть 'на борту' самих объектов, в каких-то внешних циклах..
Спасибо за этот совет. Он заставил пересмотреть внутреннюю иерархию классов и методов. Теперь все намного удобнее и логичнее + нет геммора с массивами!

Создать новую тему Ответ Часовой пояс GMT +4, время: 18:09.
Быстрый переход
  « Предыдущая тема | Следующая тема »  

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

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


 


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


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