PDA

Просмотр полной версии : Перебор экземпляров класса


KingMaks
07.03.2013, 23:10
допустим есть класс Player и я создал 3 экземпляра этого класса, класс НЕ расширяет мувиклип.
Как мне перебрать все экземпляры класса? переменные не помещал в массив, называл каждую своим именем:)

GBee
08.03.2013, 00:01
поместить в массив или в модный в узких кругах вектор :)

Bgg
08.03.2013, 00:28
Кто/что создает экземпляры, тот/то и их и перебирает.

mikhailk
08.03.2013, 00:31
Вообще-то, если все они в одном контейнере валяются, то можно массивов не создавать, а прекрасно перебирать детей контейнера.

Вопрос - зачем это нужно, сколько их там может быть, какая нужна скорость доступа и т.д.

KingMaks
08.03.2013, 01:46
Вообще-то, если все они в одном контейнере валяются, то можно массивов не создавать, а прекрасно перебирать детей контейнера.

Вопрос - зачем это нужно, сколько их там может быть, какая нужна скорость доступа и т.д.
Нужно, чтоб для каждого игрока вызвать функцию update, которая находиться в классе игрок, а сколько игроков, заранее неизвестно, можно добавлять, можно удалять.
А чилдов перебирать можно, вроде, только если экземпляры класса мувиклипы??

mikhailk
08.03.2013, 10:25
А чилдов перебирать можно, вроде, только если экземпляры класса мувиклипы??


for (var i:int=0;i<container.numChildren;i++)
{
var gamer:Gamer = container.getChildAt(i) as Gamer;
if (gamer) gamer.update();
}


Но в Вашем случае (обновление юнитов по событию или таймеру) типовым решением является массив.

caseyryan
08.03.2013, 10:49
А чилдов перебирать можно, вроде, только если экземпляры класса мувиклипы??
Откуда такая информация? Программы на ас3 можно создавать вообще не используя мувиклипов.
Детьми могут быть любые наследники класса DisplayObject, сюда относятся и Sprite и Shape и Bitmap и любые свои классы, так или иначе унаследованные от DisplayObject
Нужно, чтоб для каждого игрока вызвать функцию update, которая находиться в классе игрок
Самый разумный способ - положить их все в массив и в цикле вызывать функцию update для каждго

KingMaks
08.03.2013, 15:08
Самый разумный способ - положить их все в массив и в цикле вызывать функцию update для каждго
Помнится в С++ можно было создавать переменную в классе, чтоб она была одной для всех объектов данного класса, было бы неплохо внутри класса счетчик создать, в конструкторе +1, а вот как насчет деструктора? и вообще можно ли так в экшн скрипте?

AlexLucas
08.03.2013, 15:38
Помнится в С++ можно было создавать переменную в классе, чтоб она была одной для всех объектов данного класса,
Статичные переменные вам в помощь
public static var numObjects:int = 0;

caseyryan
08.03.2013, 17:23
Помнится в С++ можно было создавать переменную в классе чтоб она была одной для всех объектов данного класса
Статичные переменные вам в помощь
Честно сказать, с С++ не знаком, но если речь о статических свойствах, то это не правда. Статические свойства вообще не относятся к экземплярам. Они относятся к самим классам. И из статических методов нельзя вызывать не статические свойства / методы. Так что это вообще к данное теме не относится.
а вот как насчет деструктора? и вообще можно ли так в экшн скрипте?
В ас3 нет деструкторов. Тут есть автоматический сборщик мусора. Чтобы объект стал доступным для сборки мусора, нужно удалить на него все ссылки. Для этого часто создают методы, в которых зануляются все сссылки на объекты созданные внутри экземпляра.

mikhailk
08.03.2013, 17:53
Помнится в С++ можно было создавать переменную в классе, чтоб она была одной для всех объектов данного класса, было бы неплохо внутри класса счетчик создать, в конструкторе +1, а вот как насчет деструктора? и вообще можно ли так в экшн скрипте?

Про статические переменные - да, на уровне класса.
Можно там и массив поместить. И каждый создаваемый экземпляр в конструкторе туда класть, а при удалении - изымать. Не уверен, что сообщество это одобрит, но так делать, конечно, можно.

Деструктора как такового в AS3 нет, но многие пишут и я лично для сложных объектов - тоже пишу. Чищу листенеры и битмапы, останавливаю таймеры. Единственная разница - в С++ деструктор вызывался автоматически, а в AS3 деструктор нужно вызвать явно, либо, если это экранный объект, можно повесить его на событие удаления со сцены. Я вызываю явно.

AlexLucas
08.03.2013, 17:58
Так что это вообще к данное теме не относится.
Разве ?
public class MyObject
{
public static var objects:Vector.<MyObject> = new Vector.<MyObject>();
public function MyObject() {
objects.push(this);
}
}

public class Main extends Sprite
{

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);
for (var i:int = 0; i < 5; i++)
var myobj:MyObject = new MyObject();

for (i = 0; i < MyObject.objects.length; i++) {
trace(MyObject.objects[i]);
}

}

}
}

И вот так можно сохранять и получать все объекты нужного типа. Не по феншую, но работает.

mikhailk
08.03.2013, 18:10
Ох, точно не по феншую. :D

Добавлено через 6 минут
Мне все-таки ближе метафора контейнера.

Есть класс-контейнер, в нем приватный массив, этот класс имеет методы создания и удаления объектов, при создании объектов они заносятся в массив и добавляются детьми в контейнер, при удалении - удаляются из контейнера и из массива.

Такой подход, помимо простоты, позволяет сэкономить на слушателях, поскольку появляется возможность не развешивать слушателей на каждый создаваемый объект, а повесить все слушателей на контейнер. Исчезает головняк с отписыванием объектов от слушателей перед удалением.

caseyryan
08.03.2013, 18:22
И вот так можно сохранять и получать все объекты нужного типа. Не по феншую, но работает.
Это жесть конечно )
Не представляю ситуации, когда это может понадобиться
Я обычно делаю статиеский класс, в котором добавляется enterFrame, и уже этому классу передаю экземпляры того, что нужно обновлять по энтер фрейму

iflamberg
08.03.2013, 18:31
Почему не по феншую? Что вам не нравится? Очень удобно в некоторых случаях. У меня, например, так расширены все звуки. Когда игра ставится на паузу, вызывается статический метод MySound.pause(), который перебирает статический же массив со всеми звуками и всех их отстанавливает.

mikhailk
08.03.2013, 18:43
У меня, например, так расширены все звуки. Когда игра ставится на паузу, вызывается статический метод MySound.pause(), который перебирает статический же массив со всеми звуками и всех их отстанавливает.

А я, кстати, с каналами работаю.
Проще зафейдить и вообще.

Но тут скорее дело в другом, на мой взгляд. Сущность должна делать то, что должна, и не должна, что не должна. Звук должен звучать, а саундпроцессор должен регулировать громкость, запускать звуки-музыку и останавливать звуки-музыку.

Но - сугубо имхо. Не настаиваю.

GBee
09.03.2013, 01:56
Я соглашусь с iflambergом, хоть и не люблю его стиль общения :). Вполне себе вариант. Решает поставленную задачу? Да. можно сразу забацать статический апдейт. Ну и сам вектор заприватить.

caseyryan
09.03.2013, 11:07
Все это создаст офигенную связанность в программе. Да еще и будет непонятно как туда эти объекты попадают. Уже представляю себе весь гемор, который ждет того, кому прийдется потом разбирать этот код. Лучше все-таки сделать класс, которому будет передаваться то, что нужно обновлять покадрово.
Когда игра ставится на паузу, вызывается статический метод MySound.pause(), который перебирает статический же массив со всеми звуками и всех их отстанавливает.
Не проще ли через SoundMixer звуками управлять?

iflamberg
09.03.2013, 22:33
2GBee: а в этом-то топике, что не так с моим стилем общения? "Почему не по феншую? Что вам не нравится?" - это что ли? Ну так я тут без всякого сарказма спросил, мне действительно интересно, что думают другие люди по поводу такой конструкции.

2caseyryan: а где связанность? Связанность, это когда у тебя все объекты программы тесно переплелись друг с другом перекрестными ссылками. Или нет? А тут как раз наоборот, совершенно все звуки держатся в одном статическом классе, контроллерам не нужно даже на него ссылку держать. Написал SoundController.pause() - все звуковые каналы остановились, записали позицию звуковой дорожки. Написал SoundContoller.resume() - начали проигрывание с той же позиции.

Точно так же, у меня, скажем пишется стратегическая игрушка. Там много объектов на сцене разной природы - частицы, анимированные задники, юниты. Все они у меня реализуют интерфейс IPauseble и при добавлении на сцену добавляют себя в статический PauseController. По destroy() - убирают себя. И это простенькая конструкция позволяет остановить все объекты совершенно разной природы на сцене одной командой и не хранить при этом в контроллере битвы кучу лишних ссылок.

А SoundMixer не дает отдельно стопить музыки и звуки. И не позволяет после паузы продолжить звуки с того же места. Меня лично бесит, когда нажимаешь паузу во время какого-нибудь взрыва, потом отжимаешь, и наблюдаешь безвучно нарастающий шар огня. Неестественно.