Статьи

Использование API проигрывателя YouTube с ActionScript 3.0

Хотя все больше и больше людей развивается с AS3, некоторые технологии остаются в AS2. Это заставляет нас находить быстрые и простые способы использования этих технологий в наших проектах. Одной из таких технологий является YouTube.

Текущий проигрыватель YouTube все еще находится в AS2, и до тех пор, пока он не обновится до AS3, мы должны создать оболочку, позволяющую загружать видео в наши проекты. Помните, что кража фида FLV противоречит положениям и условиям YouTube , поэтому давайте сделаем это правильно, используя хромированный или хромированный плеер.




Это может показаться немного, но у вас есть проигрыватель YouTube (хромированный и хромированный), загруженный в приложение AS3.

Это учебник для продвинутых и продвинутых Actioncripters (но не пугайтесь, если вы ни один, у вас нет времени, чтобы начать учиться), так как мы собираемся использовать и AS2, и AS3. Стоит кратко прочитать пункты ниже:

  • Стоит ознакомиться с документацией API YouTube Player . Он доступен в Google Code и содержит хорошее объяснение того, как использовать Player Player, а также примеры реализации AS2 и AS3.
  • Из этого туториала вы узнаете, как создать набор компонентов, которые вы можете использовать в своих проектах AS3 в будущем. Это гораздо удобнее, чем просто показать, как вы можете ввести игрока в приложение, а затем оставить вас в нем.

Чтобы заставить это работать, мы создадим SWF-файл с AS2, который будет загружаться в проигрыватель. Затем мы создадим набор классов AS3, которые позволят нам использовать код как простые компоненты, которые мы можем добавить в наши приложения. Недостатком использования обертки является то, что помимо импорта классов, которые мы собираемся создать в AS3, нам также потребуется ввести обертку SWF, чтобы мы могли загружать ее через наши классы.

Первое, что нам нужно сделать, это создать нашу оболочку AS2. Я собираюсь показать вам, как создать оболочку, используя класс, это означает, что вы можете скомпилировать ее, используя Flash IDE или MTASC . Итак, откройте ваш любимый редактор Actionscript 2 и давайте начнем писать класс AS2. Мы собираемся начать с создания класса YouTube Player, который затем будем использовать в нашей оболочке, поэтому создайте новый файл с именем YouTubePlayer.as и начните с добавления простого класса:

1
2
3
4
5
6
7
class YouTubePlayer
{
    public function YouTubePlayer()
    {
 
    }
}

План состоит в том, чтобы иметь класс, который позволяет нам просто загружать проигрыватель YouTube, а затем легко получать доступ и изменять некоторые свойства, такие как автоматическое воспроизведение, HD / HQ и т. Д. Кроме того, мы будем использовать наш класс, чтобы остановить и уничтожить игрока, когда мы будем готовы загрузить другого. Первое, что мы делаем, это создаем некоторые публичные переменные, которые позволят нам настроить плеер:

01
02
03
04
05
06
07
08
09
10
11
12
13
class YouTubePlayer
{
    public var autoPlay:Boolean = true;
    public var chromeless:Boolean = false;
    public var pars:String = ‘autoplay=0&loop=0&rel=0&showsearch=0&hd=1’;
    public var playerWidth:Number = 425;
    public var playerHeight:Number = 344;
 
    public function YouTubePlayer()
    {
 
    }
}

Поскольку мы собираемся загружать SWF-файл с YouTube, мы должны убедиться, что наш SWF-файл позволяет SWF-плееру YouTube получать доступ к определенным свойствам в нашей оболочке. Для этого мы используем функцию с именем System.security.allowDomain () в нашем конструкторе:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
class YouTubePlayer
{
    public var autoPlay:Boolean = true;
    public var chromeless:Boolean = false;
    public var pars:String = ‘autoplay=0&loop=0&rel=0&showsearch=0&hd=1’;
    public var playerWidth:Number = 425;
    public var playerHeight:Number = 344;
 
    public function YouTubePlayer()
    {
        System.security.allowDomain(‘www.youtube.com’);
        System.security.allowDomain(‘youtube.com’);
        System.security.allowDomain(‘s.ytimg.com’);
        System.security.allowDomain(‘i.ytimg.com’);
    }
}

В AS2 мы можем только создавать экранные объекты, добавляя их на сцену. Мы также изменим наш конструктор и добавим новую приватную переменную, которая позволит нам передать фрагмент ролика в качестве родительского, в который мы загрузим проигрыватель:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
class YouTubePlayer
{
    public var autoPlay:Boolean = true;
    public var chromeless:Boolean = false;
    public var pars:String = ‘autoplay=0&loop=0&rel=0&showsearch=0&hd=1’;
    public var playerWidth:Number = 425;
    public var playerHeight:Number = 344;
 
    private var parent:MovieClip;
 
    public function YouTubePlayer(parent:MovieClip)
    {
        System.security.allowDomain(‘www.youtube.com’);
        System.security.allowDomain(‘youtube.com’);
        System.security.allowDomain(‘s.ytimg.com’);
        System.security.allowDomain(‘i.ytimg.com’);
 
        this.parent = parent;
    }
}

Теперь нам нужно создать новую приватную переменную для загрузчика фрагмента ролика и создать новый экземпляр класса MovieClipLoader () ; мы будем использовать это для загрузки проигрывателя YouTube. Мы также добавляем новую личную переменную с именем player, так как это будет нашей ссылкой на YouTube Player, частную переменную с именем videoId , приватную переменную с именем removePlayer , публичную переменную с именем addEventListener , приватную переменную с именем dispatchEvent и другую частную переменную с именем интервалы, которые будет инициализирован как новый массив:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class YouTubePlayer
{
    public var autoPlay:Boolean = true;
    public var chromeless:Boolean = false;
    public var pars:String = ‘autoplay=0&loop=0&rel=0&showsearch=0&hd=1’;
    public var playerWidth:Number = 425;
    public var playerHeight:Number = 344;
     
    public var addEventListener:Function;
 
    private var intervals:Array = [ ];
 
    private var parent:MovieClip;
    private var loader:MovieClipLoader;
    private var player:MovieClip;
    private var videoId:String;
    private var removePlayer:Boolean;
    private var dispatchEvent:Function;
 
    public function YouTubePlayer(parent:MovieClip)
    {
        System.security.allowDomain(‘www.youtube.com’);
        System.security.allowDomain(‘youtube.com’);
        System.security.allowDomain(‘s.ytimg.com’);
        System.security.allowDomain(‘i.ytimg.com’);
 
        this.parent = parent;
 
        loader = new MovieClipLoader();
    }
}

Итак, теперь мы готовы приступить к созданию нашей функции, которую мы будем использовать для загрузки видео с YouTube. Мы передадим строку, которая будет содержать идентификатор видео YouTube.

Давайте создадим новую функцию с именем init () . Эта функция будет принимать один параметр: идентификатор видео YouTube:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
public function init(videoId:String):Void
{
    this.videoId = videoId;
 
    if ( player )
    {
        removePlayer = true;
         
        if ( player.getPlayerState() != 1 )
        {
            // destroyPlayer();
        }
        else
        {
            player.stopVideo();
        }
    }
    else
    {
        loadVideo();
    }
}

Поэтому первое, что мы делаем в этой функции, это сохраняем идентификатор видео в нашей переменной класса. Так как этот класс будет обрабатывать создание и уничтожение игрока, мы должны проверить, существует ли игрок уже перед созданием. Если он существует, мы проверяем, играет ли он (т.е. у игрока будет состояние 1); если это так, мы говорим, чтобы это прекратилось; в противном случае мы уничтожаем игрока. Мы устанавливаем для нашего класса var removePlayer значение true, так как это будет использовано позже в нашем классе.

Мы начнем с загрузки в плеер, а затем перейдем к его уничтожению. Давайте создадим функцию loadVideo () :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
private function loadVideo():Void
{
    var url:String = ( chromeless ? ‘http://www.youtube.com/apiplayer’ : ‘http://www.youtube.com/v/’ + videoId + ‘&’ + pars );
 
    player = parent.createEmptyMovieClip( ‘Player’ + ( new Date().getTime() ), parent.getNextHighestDepth() );
 
    parent._visible = false;
 
    loader.addListener({ onLoadInit: loadInit() });
 
    loader.unloadClip( player );
 
    loader.loadClip( url, player );
}

Первое, что мы делаем, это определяем, загружаем ли мы в хромированный или хромированный плеер, мы используем открытый класс var chromeless, чтобы определить это. Затем мы создаем новый фрагмент ролика в нашем родительском фрагменте, который мы будем использовать для помещения плеера. В AS2 иногда возникают проблемы с созданием видеоклипов, когда они только что были удалены (этот видеоклип будет удален до загрузки другого плеера), поэтому я использую небольшой трюк, который добавляет временную метку к названию видеоклипа, чтобы Flash не не жалуюсь Затем я прячу родителя, когда мы готовимся загрузить плеер.

Теперь нам нужно инициализировать загрузчик, добавить к нему прослушиватель, удалить все ссылки, которые загрузчик имеет на наш проигрыватель (если мы его уже создали), и затем мы получим загрузчик, чтобы загрузить проигрыватель YouTube в наш мувиклип.

Теперь мы создадим нашу функцию loadInit (), которая будет запущена после загрузки SWF и готовности:

1
2
3
4
private function loadInit():Void
{
    intervals.push( setInterval( Delegate.create( this, checkPlayerLoaded ) , 500 ) );
}

Одним из достоинств AS3 является то, что большинство классов и компонентов имеют возможность отправлять события, что позволяет добавлять прослушиватели событий в этот класс. Однако в AS2 это было не так популярно. То же самое относится и к YouTube Player, поэтому нам нужно запускать функцию через определенные промежутки времени, чтобы мы могли проверить, готов ли YouTube Player.

Вы заметите, что я использовал функцию Delegate.create () . Вам нужно будет импортировать это из mx.utils.Delegate, и это очень важно. Класс Delegate позволяет загрузить функцию, которая находится в определенной области видимости. Вы видите в AS2, когда вы запускаете функцию (например, через тайм-аут, интервал или onRelease), она запускается из области вызова. Если фрагмент ролика имеет функцию onRelease и внутри этой функции он вызывает другую функцию, AS2 не будет искать эту функцию внутри класса, а скорее внутри фрагмента ролика. Поэтому вам нужно использовать делегат, чтобы сообщить AS2, где искать эту функцию. Веселье.

Теперь мы создаем функцию checkPlayerLoaded (), которая проверит, готов ли плеер YouTube:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private function checkPlayerLoaded():Void
{
    if ( player.isPlayerLoaded() )
    {
        if ( chromeless )
        {
            player.loadVideoById( videoId );
        }
 
        player.addEventListener( ‘onStateChange’, Delegate.create( this, onPlayerStateChanged ) );
        player.addEventListener( ‘onError’, Delegate.create( this, onPlayerError ) );
 
        resizePlayer( playerWidth, playerHeight );
 
        parent._visible = true;
 
        for ( var i:Number = 0; i < intervals.length; i++ )
        {
            clearInterval( intervals[ i ] );
        }
 
        onPlayerReady();
    }
}

Первое, что мы делаем, это проверяем, загружен ли плеер. Мы используем isPlayerLoaded () проигрывателя YouTube, чтобы проверить, готов ли проигрыватель. Если это не так, интервал просто запустит эту функцию снова, пока игрок не будет готов. Как только это произойдет , мы проверяем, загрузили ли мы проигрыватель без Chrome, и если у нас есть, мы используем функцию loadVideoById (), чтобы загрузить видео, поскольку у проигрывателя без хрома есть еще несколько функций.

Затем мы назначаем некоторых слушателей событий игроку, поскольку хотим знать, есть ли какие-либо ошибки и изменилось ли состояние игрока. Затем мы изменяем размеры проигрывателя до желаемой высоты и ширины, затем показываем родителя, затем удаляем все интервалы и, наконец, запускаем функцию, которая объявляет, что наш проигрыватель готов.

Итак, работая вниз, мы сначала создадим функцию прослушивания изменения состояния onPlayerStateChanged () :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
private function onPlayerStateChanged(state:Number):Void
{
    switch ( state )
    {
        case 0:
        // ended
 
        if ( removePlayer )
        {
            // destroyPlayer();
        }
 
        break;
 
        case 1:
        // playing
 
        break;
 
        case 2:
        // paused
 
        break;
 
        case 3:
        // buffering
 
        break;
 
        case 4:
        // fudge knows
 
        break;
 
        case 5:
        // video queued
 
        break;
    }
}

Теперь следующее состояние нашего класса зависит от того, нравится ли вам код. Так как эта функция прослушивает состояние проигрывателя, некоторые могут просто захотеть прослушать те, которые важны для них, и создать функции, относящиеся к состоянию. Другие, как я, будут отправлять события, что делает этот компонент очень полезным. Теперь нам нужно внести некоторые изменения в класс и импортировать класс EventDispatcher , импортировав его из «mx.events.EventDispatcher». Затем нам также нужно добавить ‘EventDispatcher.initialize (this)’ в конструктор, поэтому класс должен выглядеть так:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import mx.events.EventDispatcher;
import mx.utils.Delegate;
 
class YouTubePlayer
{
    public var autoPlay:Boolean = true;
    public var chromeless:Boolean = false;
    public var pars:String = ‘autoplay=0&loop=0&rel=0&showsearch=0&hd=1’;
    public var playerWidth:Number = 425;
    public var playerHeight:Number = 344;
     
    public var addEventListener:Function;
     
    private var intervals:Array = [ ];
 
    private var parent:MovieClip;
    private var loader:MovieClipLoader;
    private var player:MovieClip;
    private var videoId:String;
    private var removePlayer:Boolean;
    private var dispatchEvent:Function;
 
    public function YouTubePlayer(parent:MovieClip)
    {
        EventDispatcher.initialize( this );
 
        System.security.allowDomain( ‘*’ );
        System.security.allowDomain( ‘www.youtube.com’ );
        System.security.allowDomain( ‘youtube.com’ );
        System.security.allowDomain( ‘s.ytimg.com’ );
        System.security.allowDomain( ‘i.ytimg.com’ );
 
        this.parent = parent;
 
        loader = new MovieClipLoader();
    }
 
    public function init(videoId:String):Void
    {
        this.videoId = videoId;
 
        if ( player )
        {
            removePlayer = true;
 
            if ( player.getPlayerState() != 1 )
            {
                // destroyPlayer();
            }
            else
            {
                player.stopVideo();
            }
        }
        else
        {
            loadVideo();
        }
    }
 
    private function loadVideo():Void
    {
        var url:String = ( chromeless ? ‘http://www.youtube.com/apiplayer’ : ‘http://www.youtube.com/v/’ + videoId + ‘&’ + pars );
 
        player = parent.createEmptyMovieClip( ‘Player’ + ( new Date().getTime() ), parent.getNextHighestDepth() );
 
        parent._visible = false;
 
        loader.addListener({ onLoadInit: loadInit() });
 
        loader.unloadClip( player );
 
        loader.loadClip( url, player );
    }
 
    private function loadInit():Void
    {
        intervals.push( setInterval( Delegate.create( this, checkPlayerLoaded ) , 500 ) );
    }
 
    private function checkPlayerLoaded():Void
    {
        if ( player.isPlayerLoaded() )
        {
            if ( chromeless )
            {
                player.loadVideoById( videoId );
            }
 
            player.addEventListener( ‘onStateChange’, Delegate.create( this, onPlayerStateChanged ) );
            player.addEventListener( ‘onError’, Delegate.create( this, onPlayerError ) );
 
            resizePlayer( playerWidth, playerHeight );
 
            parent._visible = true;
 
            for ( var i:Number = 0; i < intervals.length; i++ )
            {
                clearInterval( intervals[ i ] );
            }
 
            onPlayerReady();
        }
    }
 
    private function onPlayerStateChanged(state:Number):Void
    {
        switch ( state )
        {
            case 0:
            // ended
 
            if ( removePlayer )
            {
                // destroyPlayer();
            }
 
            break;
 
            case 1:
            // playing
 
            break;
 
            case 2:
            // paused
 
            break;
 
            case 3:
            // buffering
 
            break;
 
            case 5:
            // video queued
 
            break;
        }
    }
}

Теперь мы готовы создать несколько событий.

Поскольку мы пытаемся сделать этот код как можно более привлекательным, имеет смысл хранить наши события в виде статических строк внутри класса, а не писать их вручную. Создайте новый файл с именем YouTubePlayerEvents.as и используйте для него следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
class YouTubePlayerEvent
{
    public static var STATE_CHANGED:String = ‘onStateChange’;
    public static var ERROR:String = ‘onError’;
    public static var PLAYER_PLAYING:String = ‘playerPlaying’;
    public static var PLAYER_ENDED:String = ‘playerEnded’;
    public static var PLAYER_PAUSED:String = ‘playerPaused’;
    public static var PLAYER_QUEUED:String = ‘playerQueued’;
    public static var PLAYER_BUFFERING:String = ‘playerBuffering’;
    public static var PLAYER_NOT_STARTED:String = ‘playerNotStarted’;
 
    public var type:String;
 
    public function YouTubePlayerEvent(type:String)
    {
        this.type = type;
    }
}

Теперь, когда у нас есть все события игрока в классе, первое, что мы должны сделать, это обновить наш код функции checkPlayerLoaded () :

1
2
player.addEventListener( YouTubePlayerEvent.STATE_CHANGED, Delegate.create( this, onPlayerStateChanged ) );
player.addEventListener( YouTubePlayerEvent.ERROR, Delegate.create( this, onPlayerError ) );

Теперь нам нужно отправлять события каждый раз, когда меняется состояние игрока или если возникает ошибка, поэтому мы обновляем onPlayerStateChanged () :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
private function onPlayerStateChanged(state:Number):Void
{
    switch ( state )
    {
        case 0:
        // ended
 
        if ( removePlayer )
        {
            // destroyPlayer();
        }
 
        dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_ENDED ) );
 
        break;
 
        case 1:
        // playing
 
        dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PLAYING ) );
 
        break;
 
        case 2:
        // paused
 
        dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PAUSED ) );
 
        break;
 
        case 3:
        // buffering
 
        dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_BUFFERING ) );
 
        break;
 
        case 5:
        // video queued
 
        dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_QUEUED ) );
 
        break;
    }
}

Прежде чем мы закончим, нам нужно добавить функцию onPlayerError () и получить ее для отправки события:

1
2
3
4
private function onPlayerError():Void
{
    dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.ERROR ) );
}

Теперь мы создадим функцию, которая обрабатывает изменение размера нашего игрока. Это удобно, потому что время от времени вам нужно будет изменять размер вашего плеера, поэтому создайте resizePlayer () и поместите в него следующее:

1
2
3
4
5
6
7
public function resizePlayer(width:Number, height:Number):Void
{
    if ( player.isPlayerLoaded() )
    {
        player.setSize( width, height );
    }
}

Мы создаем эту функцию и делаем ее общедоступной. Это потому, что вы снова можете создать проект, который требует изменения размера проигрывателя во время воспроизведения или без загрузки другого видео. Опять же, мы используем функцию API проигрывателя YouTube, которая позволяет нам изменять размеры проигрывателя, просто вызывая setSize () .

Теперь мы переходим к нашей последней функции создания, которая называется onPlayerReady () . Эта функция просто проверит, хотим ли мы, чтобы наш проигрыватель запускался автоматически, и если это так, начните играть. Вы заметите, что можете передать переменную «autoplay» при загрузке плеера, однако это относится только к хромированному плееру. Поэтому мне было проще просто установить его на «0» и использовать публичное логическое значение, чтобы установить, будет ли проигрыватель играть автоматически или нет:

1
2
3
4
5
6
7
private function onPlayerReady():Void
{
    if ( autoPlay )
    {
        player.playVideo();
    }
}

Хорошо, теперь мы дошли до того, что можем проверить игрока. Как вы можете видеть, я оставил функцию destroyPlayer () закомментированной, чтобы ее можно было протестировать без жалоб на Flash. Итак, вот наш класс:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import mx.events.EventDispatcher;
import mx.utils.Delegate;
 
import YouTubePlayerEvent;
 
class YouTubePlayer
{
    public var autoPlay:Boolean = true;
    public var chromeless:Boolean = false;
    public var pars:String = ‘autoplay=0&loop=0&rel=0&showsearch=0&hd=1’;
    public var playerWidth:Number = 425;
    public var playerHeight:Number = 344;
 
    public var addEventListener:Function;
 
    private var intervals:Array = [ ];
 
    private var parent:MovieClip;
    private var loader:MovieClipLoader;
    private var player:MovieClip;
    private var videoId:String;
    private var removePlayer:Boolean;
    private var dispatchEvent:Function;
 
    public function YouTubePlayer(parent:MovieClip)
    {
        EventDispatcher.initialize( this );
         
        System.security.allowDomain( ‘*’ );
        System.security.allowDomain( ‘www.youtube.com’ );
        System.security.allowDomain( ‘youtube.com’ );
        System.security.allowDomain( ‘s.ytimg.com’ );
        System.security.allowDomain( ‘i.ytimg.com’ );
 
        this.parent = parent;
 
        loader = new MovieClipLoader();
    }
 
    public function init(videoId:String):Void
    {
        this.videoId = videoId;
 
        if ( player )
        {
            removePlayer = true;
 
            if ( player.getPlayerState() != 1 )
            {
                //destroyPlayer();
            }
            else
            {
                player.stopVideo();
            }
        }
        else
        {
            loadVideo();
        }
    }
 
    private function loadVideo():Void
    {
        var url:String = ( chromeless ? ‘http://www.youtube.com/apiplayer’ : ‘http://www.youtube.com/v/’ + videoId + ‘&’ + pars );
 
        player = parent.createEmptyMovieClip( ‘Player’ + ( new Date().getTime() ), parent.getNextHighestDepth() );
 
        parent._visible = false;
 
        loader.addListener({ onLoadInit: loadInit() });
 
        loader.unloadClip( player );
 
        loader.loadClip( url, player );
    }
 
    private function loadInit():Void
    {
        intervals.push( setInterval( Delegate.create( this, checkPlayerLoaded ) , 500 ) );
    }
 
    private function checkPlayerLoaded():Void
    {
        if ( player.isPlayerLoaded() )
        {
            if ( chromeless )
            {
                player.loadVideoById( videoId );
            }
 
            player.addEventListener( YouTubePlayerEvent.STATE_CHANGED, Delegate.create( this, onPlayerStateChanged ) );
            player.addEventListener( YouTubePlayerEvent.ERROR, Delegate.create( this, onPlayerError ) );
 
            resizePlayer( playerWidth, playerHeight );
 
            parent._visible = true;
 
            for ( var i:Number = 0; i < intervals.length; i++ )
            {
                clearInterval( intervals[ i ] );
            }
 
            onPlayerReady();
        }
    }
 
    private function onPlayerStateChanged(state:Number):Void
    {
        switch ( state )
        {
            case 0:
            // ended
 
            if ( removePlayer )
            {
                //destroyPlayer();
            }
 
            dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_ENDED ) );
 
            break;
 
            case 1:
            // playing
 
            dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PLAYING ) );
 
            break;
 
            case 2:
            // paused
 
            dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PAUSED ) );
 
            break;
 
            case 3:
            // buffering
 
            dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_BUFFERING ) );
 
            break;
 
            case 5:
            // video queued
 
            dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_QUEUED ) );
 
            break;
        }
    }
 
    private function onPlayerError():Void
    {
        dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.ERROR ) );
    }
 
    public function resizePlayer(width:Number, height:Number):Void
    {
        if ( player.isPlayerLoaded() )
        {
            player.setSize( width, height );
        }
    }
 
    private function onPlayerReady():Void
    {
        if ( autoPlay )
        {
            player.playVideo();
        }
    }
}

Теперь, используя MTASC или IDE, быстро создайте класс / ключевой кадр и добавьте к нему следующее:

1
2
3
4
5
6
7
var player = new YouTubePlayer( this );
 
player.autoPlay = false;
player.playerWidth = Stage.width;
player.playerHeight = Stage.height;
 
player.init( ‘R7yfISlGLNU’ );

Вы должны увидеть что-то вроде этого:


Так что там вы должны увидеть хороший YouTube Player с надписью «Я на лодке» на Лонели Айленд (стоит посмотреть). Вы заметите, что, как только вы начнете играть, он автоматически включит HD, хорошо, а?

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

Многие обертки плеера YouTube AS3 полагаются на AS3, чтобы удалить плеер и добавить его снова. Однако у AS3 действительно плохая сборка мусора, это означает, что происходят ошибки, например, звук не перестает воспроизводиться или вы не можете загрузить новый плеер, потому что предыдущий еще не был удален. Я делаю все это в AS2, так как это намного проще, чище и быстрее.

Поэтому нам просто нужна наша обертка AS2 для уничтожения текущего игрока, чтобы мы могли затем загрузить нового, поэтому давайте создадим функцию destroyPlayer () :

1
2
3
4
5
6
private function destroyPlayer():Void
{
    intervals.push( setInterval( Delegate.create( this, checkPlayerDestroyed ), 500 ) );
 
    removePlayer = false;
}

Теперь это выглядит примерно так же, как функция loadInit (), но мы не собираемся начинать уничтожать плеер до тех пор, пока не будет запущен интервал, поэтому создайте новую функцию с именем checkPlayerDestroyed () :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private function checkPlayerDestroyed():Void
{
    if ( !player )
    {
        for ( var i:Number = 0; i < intervals.length; i++ )
        {
            clearInterval( intervals[ i ] );
        }
 
        init( videoId, true );
    }
    else
    {
        for ( var players:String in parent )
        {
            parent[ players ].destroy();
 
            removeMovieClip( parent[ players ] );
            unloadMovie( parent[ players ] );
        }
 
        player = null;
    }
}

Здесь мы проверяем, существует ли плеер, если он существует, то мы просматриваем наш родитель и уничтожаем каждый его экземпляр (используя функцию destroy () YouTube Player). Еще раз, потому что AS2 немного медленный в такого рода вещах, мы объявляем плеер как нулевой. Как только интервал будет запущен снова и игрок будет удален, мы удаляем интервалы и затем запускаем функцию init (), передавая ID видео.

Так что теперь мы можем изменить наш тестовый файл, который мы использовали на первом этапе, и настроить его с помощью кнопки, чтобы при нажатии этой кнопки было загружено другое видео:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
var holder = this.createEmptyMovieClip( ‘holder’, this.getNextHighestDepth() );
var button = this.createEmptyMovieClip( ‘button’, this.getNextHighestDepth() );
var player = new YouTubePlayer( holder );
 
with ( button )
{
    beginFill( 0xFF0000 );
    moveTo( 0, 0 );
    lineTo( 100, 0 );
    lineTo( 100, 100 );
    lineTo( 0, 100 );
    lineTo( 0, 0 );
    endFill();
    _x = 500;
}
 
button.onRelease = function():Void
{
    player.init( ‘sGTAnXqn9Jc’ );
}
 
player.autoPlay = false;
player.playerWidth = 500;
player.playerHeight = Stage.height;
 
player.init( ‘R7yfISlGLNU’ );

Итак, мы имеем:


И последнее, но не менее важное: нам нужно помешать игроку играть, поэтому мы добавляем функцию stop () в конец нашего класса, вот так:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
import mx.events.EventDispatcher;
import mx.utils.Delegate;
 
import YouTubePlayerEvent;
 
class YouTubePlayer
{
    public var autoPlay:Boolean = true;
    public var chromeless:Boolean = false;
    public var pars:String = ‘autoplay=0&loop=0&rel=0&showsearch=0&hd=1’;
    public var playerWidth:Number = 425;
    public var playerHeight:Number = 344;
 
    public var addEventListener:Function;
 
    private var intervals:Array = [ ];
 
    private var parent:MovieClip;
    private var loader:MovieClipLoader;
    private var player:MovieClip;
    private var videoId:String;
    private var removePlayer:Boolean;
    private var dispatchEvent:Function;
 
    public function YouTubePlayer(parent:MovieClip)
    {
        EventDispatcher.initialize( this );
 
        System.security.allowDomain( ‘*’ );
        System.security.allowDomain( ‘www.youtube.com’ );
        System.security.allowDomain( ‘youtube.com’ );
        System.security.allowDomain( ‘s.ytimg.com’ );
        System.security.allowDomain( ‘i.ytimg.com’ );
 
        this.parent = parent;
 
        loader = new MovieClipLoader();
    }
 
    public function init(videoId:String):Void
    {
        this.videoId = videoId;
 
        if ( player )
        {
            removePlayer = true;
 
            if ( player.getPlayerState() != 1 )
            {
                destroyPlayer();
            }
            else
            {
                player.stopVideo();
            }
        }
        else
        {
            loadVideo();
        }
    }
 
    private function loadVideo():Void
    {
        var url:String = ( chromeless ? ‘http://www.youtube.com/apiplayer’ : ‘http://www.youtube.com/v/’ + videoId + ‘&’ + pars );
 
        player = parent.createEmptyMovieClip( ‘Player’ + ( new Date().getTime() ), parent.getNextHighestDepth() );
 
        parent._visible = false;
 
        loader.addListener({ onLoadInit: loadInit() });
 
        loader.unloadClip( player );
 
        loader.loadClip( url, player );
    }
 
    private function loadInit():Void
    {
        intervals.push( setInterval( Delegate.create( this, checkPlayerLoaded ) , 500 ) );
    }
 
    private function checkPlayerLoaded():Void
    {
        if ( player.isPlayerLoaded() )
        {
            if ( chromeless )
            {
                player.loadVideoById( videoId );
            }
 
            player.addEventListener( YouTubePlayerEvent.STATE_CHANGED, Delegate.create( this, onPlayerStateChanged ) );
            player.addEventListener( YouTubePlayerEvent.ERROR, Delegate.create( this, onPlayerError ) );
 
            resizePlayer( playerWidth, playerHeight );
 
            parent._visible = true;
 
            for ( var i:Number = 0; i < intervals.length; i++ )
            {
                clearInterval( intervals[ i ] );
            }
 
            onPlayerReady();
        }
    }
 
    private function onPlayerStateChanged(state:Number):Void
    {
        switch ( state )
        {
            case 0:
            // ended
 
            if ( removePlayer )
            {
                destroyPlayer();
            }
 
            dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_ENDED ) );
 
            break;
 
            case 1:
            // playing
 
            dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PLAYING ) );
 
            break;
 
            case 2:
            // paused
 
            dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_PAUSED ) );
 
            break;
 
            case 3:
            // buffering
 
            dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_BUFFERING ) );
 
            break;
 
            case 5:
            // video queued
 
            dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.PLAYER_QUEUED ) );
 
            break;
        }
    }
 
    private function onPlayerError():Void
    {
        dispatchEvent( new YouTubePlayerEvent( YouTubePlayerEvent.ERROR ) );
    }
 
    public function resizePlayer(width:Number, height:Number):Void
    {
        if ( player.isPlayerLoaded() )
        {
            player.setSize( width, height );
        }
    }
 
    private function onPlayerReady():Void
    {
        if ( autoPlay )
        {
            player.playVideo();
        }
    }
 
    private function destroyPlayer():Void
    {
        intervals.push( setInterval( Delegate.create( this, checkPlayerDestroyed ), 500 ) );
 
        removePlayer = false;
    }
 
    private function checkPlayerDestroyed():Void
    {
        if ( !player )
        {
            for ( var i:Number = 0; i < intervals.length; i++ )
            {
                clearInterval( intervals[ i ] );
            }
 
            init( videoId );
        }
        else
        {
            for ( var players:String in parent )
            {
                parent[ players ].destroy();
 
                removeMovieClip( parent[ players ] );
                unloadMovie( parent[ players ] );
            }
 
            player = null;
        }
    }
 
    public function stop():Void
    {
        removePlayer = false;
         
        player.stopVideo();
    }
}

Итак, у нас есть класс YouTube Player! Всякий раз, когда вам нужно использовать YouTube Player в AS2, вы можете использовать это! Simples.

Теперь, когда наш класс готов, нам просто нужно создать оболочку, которую мы собираемся загрузить через AS3, чтобы мы могли использовать проигрыватель. Связь между оберткой (встроенной в AS2) и кодом AS3 будет осуществляться с помощью FlashCon’s LocalConnection . Теперь вместо того, чтобы писать свой собственный класс локальных соединений, я использую отличный класс gSkinner.com SWFBridge . Так что получите себе копию и будьте готовы создать один финальный класс AS2.

Давайте создадим новый файл класса с именем YouTubePlayerWrapper.as и настроим класс:

1
2
3
4
5
6
7
class YouTubePlayerWrapper
{
    public function YouTubePlayerWrapper(parent:MovieClip)
    {
 
    }
}

Итак, начнем с настройки переменных нашего класса и конструктора:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import com.gskinner.utils.SWFBridgeAS2;
 
import mx.utils.Delegate;
 
import YouTubePlayer;
import YouTubePlayerEvent;
 
class YouTubePlayerWrapper
{
    static var BRIDGE_NAME:String = ‘YouTubePlayerWrapperBridge’;
 
    private var parent:MovieClip;
    private var player:YouTubePlayer;
    private var bridge:SWFBridgeAS2;
 
    public function YouTubePlayerWrapper(parent:MovieClip)
    {
        Stage.scaleMode = ‘noScale’;
        Stage.align = ‘TL’;
 
        System.security.allowDomain( ‘*’ );
        System.security.allowDomain( ‘www.youtube.com’ );
        System.security.allowDomain( ‘youtube.com’ );
        System.security.allowDomain( ‘s.ytimg.com’ );
        System.security.allowDomain( ‘i.ytimg.com’ );
 
        this.parent = parent;
 
        init();
    }
}

Первая переменная, которую мы создаем, является статической ссылкой на имя моста локального соединения. Затем мы создаем приватные переменные, которые ссылаются на родителя, игрока и мост, который мы собираемся создать. Поскольку эта обертка будет использоваться для создания проигрывателя любого размера, нам нужно установить режим масштабирования сцены и выровнять его так, чтобы изменение размера было простым и не растягивало игрока. Опять же, нам нужно добавить настройки безопасности системы, чтобы Flash Player не жаловался. Наконец, мы добавляем родительскую ссылку класса и затем запускаем функцию init () .

Теперь мы создадим нашу функцию init () :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
private function init():Void
{
    var playerHolder:MovieClip = parent.createEmptyMovieClip( ‘playerHolder’, parent.getNextHighestDepth() );
 
    bridge = new SWFBridgeAS2( BRIDGE_NAME, this );
 
    bridge.addEventListener( ‘connect’, this );
 
    player = new YouTubePlayer( playerHolder );
 
    player.addEventListener( YouTubePlayerEvent.PLAYER_ENDED, Delegate.create( this, sendEvent ) );
    player.addEventListener( YouTubePlayerEvent.PLAYER_PLAYING, Delegate.create( this, sendEvent ) );
    player.addEventListener( YouTubePlayerEvent.PLAYER_PAUSED, Delegate.create( this, sendEvent ) );
    player.addEventListener( YouTubePlayerEvent.PLAYER_BUFFERING, Delegate.create( this, sendEvent ) );
    player.addEventListener( YouTubePlayerEvent.PLAYER_QUEUED, Delegate.create( this, sendEvent ) );
    player.addEventListener( YouTubePlayerEvent.PLAYER_NOT_STARTED, Delegate.create( this, sendEvent ) );
}

Вот лишь краткий обзор функции: мы создаем небольшую подставку для нашего игрока, затем мы инициализируем мост, где первая переменная — это имя моста, а вторая — область действия функций, которые может запустить мост, — это этот класс. Затем мы инициализируем проигрыватель и применяем к нему слушателей событий. Вот где события, отправляемые игроком, удобны, так как мы можем затем добавить эти события в наш код AS3.

Теперь мы создадим функцию sendEvent (), которая будет передавать события в наш код AS3:

1
2
3
4
private function sendEvent(e:YouTubePlayerEvent):Void
{
    bridge.send( ‘sendEvent’, e.type );
}

Теперь нам нужно добавить функции, которые нам нужно будет вызывать из кода AS3, поэтому мы добавим playVideo () , resizePlayer () и stopVideo () :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
public function playVideo(videoId:String, playerWidth:Number, playerHeight:Number, autoPlay:Boolean, pars:String, chromeless:Boolean):Void
{
    player.autoPlay = ( autoPlay !== false ? true : false );
    player.chromeless = ( chromeless ? chromeless : false );
    player.pars = ( pars ? pars : player.pars );
    player.playerWidth = ( playerWidth ? playerWidth : player.playerWidth );
    player.playerHeight = ( playerHeight ? playerHeight : player.playerHeight );
 
    player.init( videoId );
}
 
public function resizePlayer(width:Number, height:Number):Void
{
    player.resizePlayer( width, height );
}
 
public function stopVideo():Void
{
    player.stop();
}

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

Похоже, что наша оболочка готова, так же, как мы сделали с нашими тестами этапа, нам нужно скомпилировать эту оболочку в SWF. Давайте сделаем это и назовем его «YouTubePlayerWrapper.swf». Класс обертки должен быть таким:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import com.gskinner.utils.SWFBridgeAS2;
 
import mx.utils.Delegate;
 
import YouTubePlayer;
import YouTubePlayerEvent;
 
class YouTubePlayerWrapper
{
    static var BRIDGE_NAME:String = ‘YouTubePlayerWrapperBridge’;
 
    private var parent:MovieClip;
    private var player:YouTubePlayer;
    private var bridge:SWFBridgeAS2;
 
    public function YouTubePlayerWrapper(parent:MovieClip)
    {
        Stage.scaleMode = ‘noScale’;
        Stage.align = ‘TL’;
 
        System.security.allowDomain( ‘*’ );
        System.security.allowDomain( ‘www.youtube.com’ );
        System.security.allowDomain( ‘youtube.com’ );
        System.security.allowDomain( ‘s.ytimg.com’ );
        System.security.allowDomain( ‘i.ytimg.com’ );
 
        this.parent = parent;
 
        init();
    }
 
    private function init():Void
    {
        var playerHolder:MovieClip = parent.createEmptyMovieClip( ‘playerHolder’, parent.getNextHighestDepth() );
 
        bridge = new SWFBridgeAS2( BRIDGE_NAME, this );
 
        bridge.addEventListener( ‘connect’, this );
 
        player = new YouTubePlayer( playerHolder );
 
        player.addEventListener( YouTubePlayerEvent.PLAYER_ENDED, Delegate.create( this, sendEvent ) );
        player.addEventListener( YouTubePlayerEvent.PLAYER_PLAYING, Delegate.create( this, sendEvent ) );
        player.addEventListener( YouTubePlayerEvent.PLAYER_PAUSED, Delegate.create( this, sendEvent ) );
        player.addEventListener( YouTubePlayerEvent.PLAYER_BUFFERING, Delegate.create( this, sendEvent ) );
        player.addEventListener( YouTubePlayerEvent.PLAYER_QUEUED, Delegate.create( this, sendEvent ) );
        player.addEventListener( YouTubePlayerEvent.PLAYER_NOT_STARTED, Delegate.create( this, sendEvent ) );
    }
 
    private function sendEvent(e:YouTubePlayerEvent):Void
    {
        bridge.send( ‘sendEvent’, e.type );
    }
 
    public function playVideo(videoId:String, playerWidth:Number, playerHeight:Number, autoPlay:Boolean, pars:String, chromeless:Boolean):Void
    {
        player.autoPlay = ( autoPlay !== false ? true : false );
        player.chromeless = ( chromeless ? chromeless : false );
        player.pars = ( pars ? pars : player.pars );
        player.playerWidth = ( playerWidth ? playerWidth : player.playerWidth );
        player.playerHeight = ( playerHeight ? playerHeight : player.playerHeight );
 
        player.init( videoId );
    }
 
    public function resizePlayer(width:Number, height:Number):Void
    {
        player.resizePlayer( width, height );
    }
 
    public function stopVideo():Void
    {
        player.stop();
    }
}

Мы сейчас дома! Итак, чтобы просто проверить этого плохого парня, нам просто нужно создать небольшой класс в AS3, чтобы использовать эту оболочку. Я бы создал новый проект в вашем любимом редакторе AS3 и получил бы копию вашего YouTubePlayerWrapper.swf в папке проекта AS3. Затем мы просто создаем класс, который загружает SWF, создает соединение и затем отправляет переменные для функции playVideo () . Не забудьте импортировать gSkinner.com SWFBridge в код AS3:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package
{
    import com.gskinner.utils.SWFBridgeAS3;
 
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.net.URLRequest;
 
    [SWF( width=’600′, height=’400′, frameRate=’30’, backgroundColor=’#000000′ )]
 
    public class App extends Sprite
    {
        public static const BRIDGE_NAME:String = ‘YouTubePlayerWrapperBridge’;
 
        private var player:Loader;
        private var bridge:SWFBridgeAS3;
        private var videoId:String;
        private var loaded:Boolean;
 
        public function App()
        {
            init( ‘f8nNOQOh7dc’ );
        }
 
        public function init(videoId:String):void
        {
            this.videoId = videoId;
 
            if ( !loaded )
            {
                var request:URLRequest = new URLRequest( ‘assets/swf/YouTubePlayerWrapper.swf’ );
 
                player = new Loader();
 
                addChild( player );
 
                player.contentLoaderInfo.addEventListener( Event.INIT, handlePlayerLoadedComplete );
 
                player.load( request );
            }
            else
            {
                handlePlayerLoadedComplete();
            }
        }
 
        public function play(videoId:String):void
        {
            bridge.send( ‘playVideo’, videoId, stage.stageWidth, stage.stageHeight, false, null, false );
        }
 
        public function stop():void
        {
            bridge.send( ‘stopVideo’ );
        }
 
        public function handlePlayerLoadedComplete(e:Event=null):void
        {
            if ( bridge )
            {
                handleBridgeConnect();
            }
            else
            {
                bridge = new SWFBridgeAS3( BRIDGE_NAME, this );
 
                bridge.addEventListener( Event.CONNECT, handleBridgeConnect );
            }
        }
 
        public function sendEvent(e:String):void
        {
            trace( e );
        }
 
        private function handleBridgeConnect(e:Event=null):void
        {
            loaded = true;
 
            play( videoId );
        }
    }
}

Это код, который вы должны понимать, но только для быстрого ознакомления: основная функция, которая загружает проигрыватель, называется init () , я поместил это в конструктор, чтобы он фактически загружал видео, а не ждал, пока он будет уволена. Функция init () помещает идентификатор видео в переменную класса, затем проверяет, загружен ли проигрыватель. Если это так, то он продолжает посылать команду через соединение, в противном случае он просто загружает ее, используя стандартный загрузчик Flash. После того, как проигрыватель загружен и инициализирован, мы создаем соединение и, когда все готово, передаем начальный идентификатор видео проигрывателю. Там у нас есть наш YouTube Player, доступный как компонент AS3!

Итак, у нас есть наш AS3 YouTube Player Player, но веселье не должно останавливаться на достигнутом. Помните, что оболочка AS2 передает все события локальному соединению, я оставил sendEvent (), чтобы просто отследить событие, поскольку теперь вы можете настроить его для своих собственных действий. Я мог бы, например, заставить его отправлять события, и это очень помогло бы, когда дело доходит до правильного кодирования в AS3. Наслаждаться.