Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   [РЕШЕНО] Рекурсивно найти на сцене ребенка с заданным ID (http://www.flasher.ru/forum/showthread.php?t=212855)

caseyryan 16.05.2016 20:46

[РЕШЕНО] Рекурсивно найти на сцене ребенка с заданным ID
 
У меня что-то совсем мозг поплыл, уже час не могу решить задачу, которая казалась простецкой.
В общем, суть такая, есть в каком-то контейнере ребенок, у которого есть поле ID с определенным значением. Контейнер не известен, а как корневой объект для начала поиска берется stage. Собственно, как рекурсивно обойти всех детей stage и найти этого ребенка, если известен только его ID?
Это нужно для получения ссылки на этого ребенка.
п.с. Просьба не писать, что можно было положить их всех в массив, чтобы сохранить ссылки и т.п., так как задача совершенно другая. Мне нужно максимально изолировать игровой тутор от основной логики игры, поэтому пепердавать туда какие-либо ссылки я не хочу.

undefined 16.05.2016 20:58

Код AS3:

function getChildById(container:DisplayObjectContainer,id:String=""):DisplayObject {
var res:DisplayObject;
for(var i:uint=0;i<container.numChildren;i++) {
if (container.getChildAt(i).id==id) return container.getChildAt(i);
if (container.getChildAt(i) is DisplayObjectContainer) {
res=getChildById(container.getChildAt(i),id);
}
}
return res;
}

ПС:код не тестил.

Tails 16.05.2016 21:10

undefined,
Так работать не будет, точнее будет ошибка компиляций, так-как у дисплей объектов нет поля id.
Тут надо использовать метод hasOwnProperty(), который принадлежит Object и не подсвечивается в редакторе FD.

caseyryan,
Сходи поспи :)

undefined 16.05.2016 21:13

я идею показать хотел.Для кейси причесать напильником не должно представлять труда :D

caseyryan 16.05.2016 21:15

Цитата:

Сообщение от Tails (Сообщение 1194092)
caseyryan,
Сходи поспи :)

Я ж уснуть не смогу, пока не сделаю :D

п.с. Серег, твой способ не работает. Там же переназначение res при каждой итерации. Что-то простая задачка превратилась в какую-то кашу) Видимо действительно лучше на утро оставить

undefined 16.05.2016 21:19

а ну да, надо его присваивать только если res==null
Код AS3:

if (container.getChildAt(i) is DisplayObjectContainer && !res) {
res=getChildById(container.getChildAt(i),id);
}

Добавлено через 4 минуты
проверил - вроде ищет:
Код AS3:

import flash.display.DisplayObjectContainer;
 
function getChildById(container:DisplayObjectContainer,id:String=""):DisplayObject {
var res:DisplayObject;
for(var i:uint=0;i<container.numChildren;i++) {
if (container.getChildAt(i).name==id) return container.getChildAt(i);
if (container.getChildAt(i) is DisplayObjectContainer && !res) {
res=getChildById(container.getChildAt(i) as DisplayObjectContainer,id);
}
}
return res;
}


caseyryan 16.05.2016 21:24

Все, вопрос решен)
Код AS3:

/**
 * рекурсивно возвращает из всего списка дисплей объектов тот,
 * у которого tutorID соответствует нужному
 * @param        container корневой контейнер для поиска
 * @param        tutorID нужный идентификатор
 * @return
 */

private static function getITutorByID(container:DisplayObjectContainer, tutorID:String):ITutor {
 
        var numChildren:int = container.numChildren;
        if (container is ITutor) {
                var iTutor:ITutor = container as ITutor;
                if (iTutor.tutorID == tutorID) return iTutor;
        }
        for (var i:int = 0; i < numChildren; i++) {
                var child:DisplayObject = container.getChildAt(i) as DisplayObject;
                if (child is DisplayObjectContainer) {
                        iTutor = getITutorByID(child as DisplayObjectContainer, tutorID);
                        if (iTutor) return iTutor;
                } else {
                        if (child is ITutor) {
                                iTutor = child as ITutor;
                                if (iTutor.tutorID == tutorID) return iTutor;
                        }
                }
        }
        return null;
}

на сколько он кривой посмотрю завтра) На сегодня работает, и могу теперь спокойно лечь спать :D

undefined 16.05.2016 21:25

только проверку на существование id поменяй

caseyryan 16.05.2016 21:29

Спасибо) Завтра сравню со своим, посмотрю какой лучше использовать

undefined 16.05.2016 21:37

а как это можно менять тему топика?

caseyryan 16.05.2016 21:39

Цитата:

Сообщение от undefined (Сообщение 1194100)
а как это можно менять тему топика?

Первое сообщение редактируешь - расширенный режим. И там меняется

undefined 16.05.2016 21:40

о, спасибо давно искал)

faraday 19.05.2016 20:02

а почему кстати используешь кастомный класс для контейнеров тутора? как я понимаю это обычные displayObjectContainer, например с кнопками. тогда и связанность меньше.
И не лучше ли хранить весь путь от стейжа, например stage.win1.panel2.btn1, чем пытаться все это кодировать в id кнопки, которая может и не знать где лежит, и как себя отличить от остальных. да и поиск будет быстрее. надо только дать имена контейнерам
Код AS3:

        static public function targetByPath(child:DisplayObjectContainer,path:Array):DisplayObject {
                        var childName:String = path.shift();
                        if (!childName) return child;
                        return findByPath(child.getChildByName(childName),path);
                }
                static public function pathByTarget(target:DisplayObject):Array {
                        var path:Array = [];
                        while (target!=stage) {
                                path.unshift(target.name)
                                target = target.parent;
                        }
                        return path.join('.');
                }


caseyryan 20.05.2016 08:22

Цитата:

а почему кстати используешь кастомный класс для контейнеров тутора?
Это не класс, а интерфейс. Поэтому он и называется ITutor. Дело в том, что это могут быть и не дисплей объекты, но методы set tutorID и get tutorID у них быть обязаны. Эти свойства им адаются сразу в конструкторе. Этот метод ищет ITutor'ы в дисплей листе. Некоторые могут присылаться с данными в команде от модели. Все должно работать так же

Цитата:

И не лучше ли хранить весь путь от стейжа, например stage.win1.panel2.btn1
Конечно нет. У меня Tutorial вообще не сзязан с игрой. Я могу его запросто перетащить в другую игру и только инструкции внутри переписать под нее. А если я сделаю так, то появится ненужная связанность. Да еще и не надежно прописывать такие "хардкодные" пути

Я делал много разных туторов для разных игр, и наконец пришел к решению, которое дает игроку одновременно и определенную свободу действий (все кнопки которые прямо не запрещены (кстати для запрета, достаточно внести ее tutorID в массив "шага" туториала), будут нажиматься и он сможет походить туда-сюда, что-то попутно поделать, например обыскать ящики), и в то же время не дает ему сильно отойти в сторону от заданий тутора. Никаких черных экранов с дыркой, в которой кнопка. Тут много опиций. Тутор можно легко превратить в полноценный игровой процесс с подсказками. Для этого и нужно, чтобы был общий интерфейс для разных типов объектов

Цитата:

да и поиск будет быстрее. надо только дать имена контейнерам
Этот поиск укладывается в тысячные доли секунды. Объектов на сцене всего пара сотен. Явно не самое слабое место в игре. Игрок даже не заметит никаких задержек, так что о скорости поиска я вообще не парюсь

faraday 20.05.2016 13:38

Спасибо, надо будет попробовать такую схему, без дырок) но все же как например указать id такого объекта stage.win1.panel2.btn1, тут большоая вложенность, и видно что btn1 может быть тысяча, а нужно из них заблокировать только одну например. И кстати что по свободе действий? по моей статистики проходят раза в 4 хуже, чем когда ведешь до конца. тут же не просто блокирование кнопок, а целые цепочки действий и переходов между ними

caseyryan 22.05.2016 09:41

Цитата:

надо будет попробовать такую схему, без дырок) но все же как например указать id такого объекта stage.win1.panel2.btn1, тут большоая вложенность
Можно конкретно в месте создания этой кнопки задать ей другой tutorID, например "thatVeryButton", который перепишет то, что задано в конструкторе. И тогда в туторе просто указать в шаге thatVeryButton, который и будет указывать именно на ту кнопку.

Цитата:

И кстати что по свободе действий? по моей статистики проходят раза в 4 хуже, чем когда ведешь до конца. тут же не просто блокирование кнопок, а целые цепочки действий и переходов между ними
Да тут в принципе тоже самое и получается. Разница лишь в том, что игрок может вместо тупого щелканья по подсвеченным кнопкам, что-то еще сделать. Я в тутор добавляют разный интерактив, вроде разговора с NPC, или обыска разных предметов (в меру конечно, чтобы не сильно отвлекался). Можно что-то разгромить. Но в итоге, когда игрок что-то там поделает, ему все равно придется завершить этап тутора. Там, к примеру, есть двери, ведущие в другие комнаты, и пока завершенный этап тутора не пошлет команду открыть эту дверь, игрок туда зайти не сможет. В общем, не полная свобода, но более свободно, чем в классическом варианте. Игру еще не выпустили, но на своих знакомых друзьях и близких я уже этот тутор опробовал. Прошли без проблем даже те, кто вообще не играет в игры. Как будет после запуска, еще предстоит узнать. Но пока я позитивно настроен по поводу этой схемы :)

faraday 22.05.2016 15:25

Спасибо)

caseyryan 23.05.2016 14:28

всегда пожалуйста)


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

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