PDA

Просмотр полной версии : события из подгруженного клипа


meiciuc
13.10.2006, 17:17
Здравствуйте.

Есть два клипа loader & loaded.
Прошу, не обращайте внимание, что скрипт для Loader написан в АС1 - это по-быстрому для наглядности и здесь проблем нет

import mx.events.EventDispatcher;
import mx.utils.Delegate;

var dispatchEvent:Function;
var removeEventListener:Function;
var addEventListener:Function;

var game:MovieClip = createEmptyMovieClip("game_mc",0);
var mclListener:Object = new Object();
mclListener.onLoadInit = function()
{
game.addEventListener("fromGame", Delegate.create(this, gameHandler));
}


var ml:MovieClipLoader = new MovieClipLoader();
ml.addListener(mclListener);
ml.loadClip("loaded.swf", game);

function gameHandler(o:Object):Void
{
trace("fromGame");
}


проблема во втором, подгружаемом клипе. Вопрос в следующем, как сделать так (если это вообще возможно), чтоб код, генерирующий события, прописывать не в _root (иначе loader ничего не увидит).


это то, что в loaded - но мне не очень нравится работа с рутом.

import mx.events.EventDispatcher;

var dispatchEvent:Function;
var removeEventListener:Function;
var addEventListener:Function;

EventDispatcher.initialize(this);

onMouseDown = function()
{
dispatchEvent({target:this, type:"fromGame"});
}


Спасибо

etc
13.10.2006, 17:43
А что ты хочешь оставить в _root? Если уж так хочется, то можешь юзать LocalConnection…

з.Ы. Delegate.create(this,gameHandler) — ссылка будет на mclListener внутри gameHandler. Я не вижу смысла в создании Listener-а, почему бы не подписать самого себя на события MovieClipLoader-а?

meiciuc
13.10.2006, 17:57
__etc, код для лоадера грязен, он лишь для экспериментов. Там и делегат я случайно всунул - по-привычке из АС2. Проблема у меня с подгружаемым - и то теоритическая. В руте подгружаемого клипа я хотел бы оставить только инициализацию класса и все. Но, понятно, что в таком случае loader должен подписываться на события примерно так game.B.addEventListener(тра-ла-ла). Т.е. я должен знать имя объекта класса внутри loaded - а вот этого-то я и не хочу знать.

etc
13.10.2006, 18:08
Тогда сделайте один общий класс, у которого одно из статических свойств ссылается на интерфейс. А в loaded.swf напишите класс, реализующий данный интерфейс и замените ссылку в общем классе на данный.
Если непонятно, я объясню на примере.

meiciuc
13.10.2006, 18:17
интересно для меня. К сожалению, я довольно плохо разбираюсь в интерфейсах (во всяком случае с данным их назначением). Не могли бы для примера дать пару строк принципиального кода?

etc
13.10.2006, 18:30
У нас есть интерфейс IGameClass:
interface IGameClass {
public function addEventListener():Void;
public function removeEventListener():Void;
}
Есть класс LinkExchanger, хранящий ссылку на интерфейс GameClass:
import IGameClass;
class LinkExchanger {
public static var game:IGameClass;
}
Есть класс GameClass, реализующий IGameClass:
import LinkExchanger;
import IGameClass;
import mx.events.EventDispatcher;
class GameClass implements IGameClass {

private var dispatchEvent:Function;

public function GameClass() {
EventDispatcher.initialize(this);
LinkExchanger.game = this;
Mouse.addListener(this);
}

public function addEventListener():Void {
// EventDispatcher native code
}

public function removeEventListener():Void {
// EventDispatcher native code
}

private function toString():String {
return 'GameClass';
}

private function onMouseDown():Void {
this.dispatchEvent({type:'onGameEvent'});
}

}
В load.swf:
import GameClass;
new GameClass();
В loader.swf:
import LinkExchanger;
import IGameClass;
clip = this.createEmptyMovieClip('clip_mc',0);
mcl = new MovieClipLoader();
mcl.addListener(this);
onLoadInit = function() {
trace(LinkExchanger.game); // GameClass
LinkExchanger.game.addEventListener('onGameEvent',this);
}
onGameEvent = function(e:Object) {
trace('Game event called from external swf');
}
mcl.loadClip('load.swf',clip);
Нужно помнить, что в интерфейсах могут быть только методы, никаких свойств. Т.е. обращаться к свойствам GameClass нельзя, но можно вызывать его методы. А лучше подписаться на события, что и требовалось.

На выходе в loader.swf не должно быть класса GameClass.

meiciuc
13.10.2006, 18:31
спасибо, дальше разберусь.

etc
13.10.2006, 18:52
Да, необходимые методы для общения нужно описать в интерфейсе и реализовать в классе…

meiciuc
13.10.2006, 19:04
это уже понятно, спасибо еще раз. Интуитивно понимаю, что интерфейсы - мощная штука, но вот вразумительных объяснений не находил. Теперь, на конкретном примере, разберусь.

silin
13.10.2006, 19:05
сори если не в тему (тут такие механизмы в ход пошли..), но если ворос тока в том 'чтоб код, генерирующий события, прописывать не в _root ', то я не вижу почему бы его не прописыать где угодно, а вещать заставить третий объект, в глобале например

loader:
AsBroadcaster.initialize(_global.broadcaster={});
_global.broadcaster.addListener(this);
function fromGame(){
trace("fromGame");
}
var game=createEmptyMovieClip("game_mc",0).loadMovie("loaded.swf");
laoded:
var game=new GameClass();
GameClass:
class GameClass{
function GameClass(){
Mouse.addListener(this);
}
function onMouseDown(){
_global.broadcaster.broadcastMessage("fromGame");
}
}

etc
13.10.2006, 19:07
Я думаю, что автору темы и _global не особо хочется юзать 8)
И потом, нужно аккуратнее лазить в _global, чтобы не убить классы…
Да и broadcaster — аналог моего LinkExchanger…

з.Ы. Это первый случай, когда я ощутил пользу интерфейсов :D

meiciuc
13.10.2006, 19:15
спасибо, но нет. Смысл - уйти в максимально возможно чистый для АС2 ООП. _global, по понятным причинам, в его концепцию не вписывается.