ActionScript3でオブジェクトを複数条件ソートする時のメモ。
sortOn() を使うと一発でできるのでラクチンです。
しかし条件の指定をちょっと変えると結果が全然違ってくるので注意です。
下の例では全て「y」「x」の順にソートしています。
var list:Array = [ new Point(5, 5), new Point(0, 10), new Point(10, 10), new Point(10, 0) ]; list.sortOn( ["y", "x"] ); // 文字列比較で小さい順に並べている。文字列だから「10<5」になる。 // (x=10, y=0),(x=0, y=10),(x=10, y=10),(x=5, y=5) list.sortOn( ["y", "x"], Array.DESCENDING ); // 降順ソート。こちらも文字列だから「10<5」になる。 // (x=5, y=5),(x=10, y=10),(x=0, y=10),(x=10, y=0) list.sortOn( ["y", "x"], [Array.NUMERIC, Array.NUMERIC] ); // どちらも数値としてソート // (x=10, y=0),(x=5, y=5),(x=0, y=10),(x=10, y=10) list.sortOn( ["y", "x"], [Array.DESCENDING | Array.NUMERIC, Array.NUMERIC] ); // 「y」は「数値で降順」、「x」は「数値で昇順」 // (x=0, y=10),(x=10, y=10),(x=5, y=5),(x=10, y=0) list.sortOn( ["y", "x"], [Array.DESCENDING|Array.NUMERIC, Array.DESCENDING|Array.NUMERIC] ); // どちらも「数値で降順」 // (x=10, y=10),(x=0, y=10),(x=5, y=5),(x=10, y=0)
Array.CASEINSENSITIVE | 大文字と小文字を区別しないソート |
---|---|
Array.DESCENDING | 降順のソート順 |
Array.UNIQUESORT | 一意性ソート要件 |
Array.RETURNINDEXEDARRAY | sort() メソッドまたは sortOn() メソッドの呼び出し結果としてインデックス付き配列を返す |
Array.NUMERIC | 数値によるソート |
Array.UNIQUESORT はちょっと特殊で、ソート対象に同じ値が混ざっていないかチェックします。
同じ値が混ざっている場合は並び替えをせず「0」を返します。
ここ数日 Flashでちょっとハマったこと。
Progression便利かもしれないけど、ハマることも多いですね……。
自分的にはcommand系しか活用してないから、
シーンとか余計ややこしくなるし省くのが一番良いという結論にw
作ろうとしたらProgressionプロジェクトの新規作成のところで何故かAdobeAIRが選べない。
おかしいなーと思いつつAdobe Flash Support Centerから
Adobe Flash CS4 Professional Update (10.0.2) 05/13/2009
を落としてきてインストールしたら選べるようになりました。
あれ?前に作ったのってマシン環境新しくする前だったっけ?
吉里吉里で使うボタン画像は横方向に連結したものを使います。
Photoshopでも作れるのですが透明部分を含んでいる場合に結合が面倒なので
(どこが境目かわかりにくいから)
画像連結ツールを作ってしまいました。
ダウンロードしたファイルをダブルクリックするとインストーラーが立ち上がります。
AdobeAIRがない環境では AdobeAIRも一緒にインストールされます。
「発行者:不明」になってますが気にしないでください。
スタートメニューのプログラムに 画像連結「むすびちゃん」 が登録されます。
連結方向、ファイル名修飾、保存先を設定し、
連結した画像をまとめてドロップするだけです。
入力対応画像フォーマットは PNG / JPEG / GIF で、出力は PNGのみです。
特徴としては透過PNGにも対応しています。
画像連結ツールっていくつかあるんですが、
透過PNGには対応していなかったり、
画像選択が面倒だったり、
自分に合うのがなかったのです。
もっとお気楽極楽に使えるものがほしい!
そんな願いの篭もったツールです。
もっとみんなが作ったえろげがほしい!
そんな願いも篭もってます。
コマンドリストを実行している時、
途中のコマンドの結果によって分岐させたい時の方法。
var hogeCommand:HogeCommand = new HogeCommand(); var serial:SerialList = new SerialList(); serial.addCommand( hogeCommand ); serial.addCommand( new Func( function():void { // コマンドの結果で分岐 if ( hogeCommand.value ) { serial.insertCommand( new Trace("コマンドを挟む")); } })); serial.execute();
HogeCommandクラスの実行結果を受け取りたいので
インスタンスを先に作っておきます。
var hogeCommand:HogeCommand = new HogeCommand();
今回のキモ「insertCommand」です。
これにより動的にコマンドを挿入させることができます。
// コマンドの結果で分岐 if ( hogeCommand.value ) { serial.insertCommand( new Trace("コマンドを挟む")); }
このやり方についてはIs It So Easy?さんが詳しく書かれています。
this.parentで挿入することも出来るんですねー。
![]() |
[改訂版]ActionScript3.0プログラミング入門 for Adobe Flash CS4/CS3 ビー・エヌ・エヌ新社 2009-07-23 |
いったい何がキッカケだったのかまったくわからないけど、ある日突然出てきたエラー。
Resource.as、行 44
1004: 名前空間が見つからないか、コンパイル時定数ではありません。
progression_internal static const $collection:IdGroupCollection = new IdGroupCollection();
いろいろ試して、音声ファイルがリンケージされていると発生することがわかりました。
下記のようにごく一般的なファイルを普通にリンケージしただけえす。
ファイル:testse.wav
クラス:testse
基本クラス:flash.media.Sound
「最初のフレームに書き出し」のチェックを外すとエラーは出ません。
しかし上記チェックを外すわけにもいかず色々試していたら、
Index.asに下記の行を追加したらエラーが出なくなりました。
function hogehoge():void { getResourceById("hoge").data; }
この関数はどこからも呼ばれませんが、記述しておくだけで良いようです。
バグなのか仕様なのかはわかりませんが、公式のフォーラムに報告しておきました。
![]() |
ActionScript 3.0 エラーアーカイブス コンパイルエラー・コンパイラ警告・ランタイムエラーの解法 大重美幸 ソシム 2009-09-09 |
Progressionのリソースキャッシュと、複数ファイル読み込みの組み合わせが
便利すぎて思わず漏らしてしまいそうです(チョロリ)。あっ。
外部画像を読み込んで一覧表示させるものを作ってまして、
各サムネイル内で読み込むようにしてたんですが、
最初にまとめて読むように変更しました。
というのも、リソースキャッシュのおかげで
画像の流用がすごく簡単に行えるようになったからです。
リソースキャッシュについては以前かいたこの日記を参照。
Progressionが備えているURLアンカー(URLの後の「#~」)によるページ遷移は
フルFlashサイトを作る際にはとても便利で素晴らしいのですが、
ブログパーツやメニューのみFlashにしている場合は誤動作の原因になる場合もあります。
今日まさにそれでハマっていたので対処法をメモっておきます。
ドキュメントクラス「Index.as」内の下記の箇所を書き換えれば
無効にすることができます。
protected override function atReady():void { // manager.sync = true; manager.sync = false; // manager.goto( manager.syncedSceneId ); manager.goto( new SceneId('/index') ); }
manager.syncというプロパティが関係するらしいので「false」にします。
manager.syncedSceneIdもURLアンカーによる場所が格納されているぽいので、
移動先も強制的に「/index」にしてしまいます。
もっとエレガントな方法もありそうですが、とりあえずこれで対処できました。
![]() |
リトルアンカー(限定版) D3PUBLISHER 2009-04-23 |
Progression4から搭載されたResource関連がとても便利なのでメモ。
これまでも外部ファイル(swf、画像、mp3など)を読み込んで使い回す
ということは出来ましたが、それなりに手間がかかりました。
Progression4からはそれらを管理するResource系のクラスが登場し、
かなりシンプルになったようです。
michinoko blogさんで書かれていたことを参考に書いてみました。
今回は簡単なカスタムコマンドを作ってみます。
プロジェクトを作成すると「templates」フォルダに様々なテンプレートが作成されます。
「src」フォルダに「MyCommand.as」を複製し、名前を「HokutoCommand.as」に変更します。
※本当は「classes」などのフォルダを作ってまとめたほうが良いのですが割愛します。
package { import jp.progression.casts.*; import jp.progression.commands.display.*; import jp.progression.commands.lists.*; import jp.progression.commands.net.*; import jp.progression.commands.tweens.*; import jp.progression.commands.*; import jp.progression.data.*; import jp.progression.events.*; import jp.progression.scenes.*; public class MyCommand extends Command { public function MyCommand( initObject:Object = null ) { super( _execute, _interrupt, initObject ); } private function _execute():void { executeComplete(); } private function _interrupt():void { } public override function clone():Command { return new MyCommand( this ); } } }
それでは北斗百烈拳ならぬ、北斗十烈拳を繰り出すコマンドに書き換えます。
「MyCommand」になっている箇所を「HokutoCommand」に書き換えたり、いろいろ。
package { import flash.display.DisplayObjectContainer; import flash.display.MovieClip; import jp.progression.commands.*; import jp.progression.commands.lists.SerialList; public class HokutoCommand extends Command { private var $myStage:DisplayObjectContainer; /******************************* * コンストラクタ * @param myStage 「あた!」の配置先 */ public function HokutoCommand( myStage:DisplayObjectContainer, initObject:Object = null ) { super( _execute, _interrupt, initObject ); $myStage = myStage; } /******************************* * 処理実行 */ private function _execute():void { // 直列実行コマンド var serialList:SerialList = new SerialList(); // 「あた!」を配置して 0.2秒待つをくり返す serialList.addCommand( new Func( addAta )); serialList.addCommand( new Wait( 0.2 )); ~略~ serialList.addCommand( new Func( addAta )); serialList.addCommand( new Wait( 0.2 )); // カスタムコマンド終了関数 serialList.addCommand( new Func( executeComplete )); // 終了処理 serialList.addCommand( new Func( _endExec )); // 直列処理開始 serialList.execute(); } /******************************* * 「あた!」を配置する関数 */ private function addAta():void { // ata_mcをランダム位置に貼りつける var mc:MovieClip = new ata_mc(); mc.x = (Math.random() * 300) + 50; mc.y = (Math.random() * 200) + 50; $myStage.addChild( mc ); } /******************************* * 終了処理 */ private _endExec():void { $myStage = null; } /******************************* * 処理中断 */ private function _interrupt():void { // 中断時は終了と同じことをさせる _endExec(); } /******************************* * 複製 */ public override function clone():Command { return new HokutoCommand( $myStage, this ); } } }
長く見えるかもしれませんがやってることはいたって単純。
/******************************* * コンストラクタ * @param myStage 「あた!」の配置先 */ public function HokutoCommand( myStage:DisplayObjectContainer, initObject:Object = null ) { super( _execute, _interrupt, initObject ); $myStage = myStage; }
コンストラクタでは「あた!」を配置させる場所を保存しているだけです。
initObjectと、super()は定型文と思ってそのままにしてください。
// 「あた!」を配置して 0.2秒待つをくり返す serialList.addCommand( new Func( addAta )); serialList.addCommand( new Wait( 0.2 ));
SerialListは直列処理を実現してくれるクラスです。
Funcクラスは関数を実行するためだけのものです。Commandクラスを継承しています。
addAta()内で「あた!」を配置し、Waitクラスで0.2秒待機させています。
// カスタムコマンド終了関数 serialList.addCommand( new Func( executeComplete ));
executeComplete()はとても大切な関数で、
カスタムコマンドの処理が完了したことを上位オブジェクトに通知します。
これを実行しないと上位オブジェクトは次の処理に移りません。
// 終了処理 serialList.addCommand( new Func( _endExec ));
/******************************* * 終了処理 */ private _endExec():void { $myStage = null; }
executeComplete()で終了の通知は行きますが、
その後は自分でキレイに掃除しなくてはいけません。
やらなくても構いませんがメモリリークの原因になります。
_endExec()(名前は任意)は中断処理でも呼ばれます。
コマンドが中断された際も掃除をしておかないとメモリリークの原因になります。
/******************************* * 処理中断 */ private function _interrupt():void { // 中断時は終了と同じことをさせる _endExec(); }
clone()は同じパラメータを与えられたコマンドを複製しますが、
まぁほとんど使うことはないと思います。
コンストラクタと同じ関数名、引数を与えればよいです。
/******************************* * 複製 */ public override function clone():Command { return new HokutoCommand( $myStage, this ); }
実際の処理を書く_execute()と、終了処理を書く_endExec()以外は
ほとんどテンプレートのままで、クラス名にあわせてコンストラクタ名や
引数が変わるくらいです。
(上記2つの関数名は任意)
大切なことは、処理が終わったらexecuteComplete()を実行すること。
その後に終了処理をするということです。
executeComplete()は終了を通知するだけの、いわばdispatchEvent()のようなものです。
それでは実際にカスタムコマンドを使ってみましょう。
「IndexScene.as」から呼び出します。
~略~ /********************************* * ボタン押した */ private function _onClick( e:MouseEvent ):void { // 北斗十烈拳を実行した後、「終わった」を表示 var serialList:SerialList = new SerialList(); serialList.addCommand( new HokutoCommand( this.container ), new Func( _owatta ) ); serialList.execute(); } /********************************* * 終わったァ! */ private function _owatta():void { var owatta:MovieClip = new owatta_mc(); owatta.x = 200; owatta.y = 150; this.container.addChild( owatta ); } ~略~
めちゃくちゃシンプルです。
カスタムコマンドを実行しているのはこの行だけ。
「あた!」を配置する場所を指定しています。
initObjectは不要です。
new HokutoCommand( this.container ),
「北斗十烈拳」をクリックすると始まります。
今回のソースファイルをアップしましたので、試してみたい方はどうぞ。
※他の環境で動作するかはテストしてません。
![]() |
Adobe Flash CS4 詳細!ActionScript3.0入門ノート[完全改訂版](CD-ROM付) ソーテック社 2009-08-01 |