[Event][AS]スクリーンセーバー作りました。>>Re-BUILD

先日、東京てらこ 15で発表してきたお話をメモ。

本題は、スクリーンセーバーDL用の特設サイト作りましたよってお話。
Re-BUILD

////////////////////////////////////////////////////////////////////////////
まず最初からスクリーンセーバーを作ろうと思ったわけじゃなくって。。
以前から考えてたネタをワンダフル用に作ってたら、アレもコレもとだんだんと手がこんできたので、これスクリーンセーバーにすればいいんじゃね、と。
じゃあSWFをスクリーンセーバーにするにはどうすりゃいいの?ってことで調べてみました。

ざくっとググって以下の二つが見つかりました。

1)は完全無料でいろいろかゆいとこに手が届くような感じだけどmac用は不可
とりあえずwin用にはこっちを使いました。

2)はwin/macどちらも対応で、低機能の無料版と高機能の有料版があるんだけど無料版ではOSX10.6用(64bit版)の対応はできない、と。
win用/mac用で個々にライセンスが分かれていて各ライセンスが19,800円
win/mac、まとめて買うと34,800円。
mac用にはこっちの有料版を使いました。
・・・えぇ、mac用のライセンス買いましたよ。19,800円。

////////////////////////////////////////////////////////////////////////////
あと製作に関する裏話的なこと。

もともとは数年前にみた海外のサイト(たぶん製作会社だったと思う。。)で、地平線がみえるようなシンプルなランドスケープなデザインに、ランダムに家がでてきてスクロールして流れていくようなやつをみたときに、こういうの作ってみたいなーと思ってたのが最初。
(当のサイトはググっても見つけられず。。思い出補正でぜんぜん違うものかも。。)

なんとなくChemical Brothers – Star Guitarを思い出した人もいるかも
Chemical Brothers – Star Guitar
これ、好きなんです。DVD持ってます。

あと、groovisions – GRV2196を思い出した人もいるかも
GRV2196
これ、好きなんです。DVD持ってます。

++++++++++++++++++++++++++++++++++++++++++++
GRV2196はyoutubeになかったけどGRV2126を発見。
これは観てなかったのだけど、トラックの形とかそっくりだったw
(トラックは軽トラの側面画像を適当にトレースしてたんだけどね)

////////////////////////////////////////////////////////////////////////////
元になるソースはwonderflにアップしてあります。
(実際にスクリーンセーバーに使ってるものとはちょっと違います)
なにげに車を描画するクラスがボリュームありますw

Re-BUILD – wonderfl build flash online

[AS]Embedした複数の画像(クラス)を連番(文字列)で参照したい場合の方法

たとえば、aImage00.png,aImage01.png,aImage02.pngって画像をEmbedで埋め込んだ場合に、クラス名をfor文とかでまわすにはどうすればいいかということ。

二通りのやり方があるみたい。
まずは、ここの記事に教えていただきました。
[Embed]したものを動的に使いたいとき:TWO HEARTS

ポイントはstaticにして、配列アクセス演算子を使うということ。
直感的に納得できる感じ。
↓サンプルソース

package assetImage
{
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.getDefinitionByName;
	
	public class Main2 extends Sprite 
	{
		[Embed(source = 'asset/aImage00.png')] private static var AImage0:Class;
		[Embed(source = 'asset/aImage01.png')] private static var AImage1:Class;
		[Embed(source = 'asset/aImage02.png')] private static var AImage2:Class;
		
		public function Main2():void 
		{
			for (var i:int =  0; i < 3; i++)
			{
				var bm:Bitmap = new Main2["AImage" + i];
				addChild(bm).x = bm.width * i + 20 * i;
			}
		}
	}
}

つづいて、getDefinitionByNameを使う方法
ここで教えていただきました。
■ 埋め込みアセットクラスをgetDefinitionByName()で参照する :棚からパルチャギ

こっちは埋め込むクラス名に対して、埋め込んだ場所のクラスをパッケージから書いたりとと直感的には全くわからない仕様。
(どうもmxmlのお作法もまざってるっぽい)
↓サンプルソース

package assetImage
{
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.utils.getDefinitionByName;
	
	public class Main extends Sprite 
	{
		[Embed(source = 'asset/aImage00.png')] private var AImage0:Class;
		[Embed(source = 'asset/aImage01.png')] private var AImage1:Class;
		[Embed(source = 'asset/aImage02.png')] private var AImage2:Class;
		
		public function Main():void 
		{
			for (var i:int =  0; i < 3; i++)
			{
				var bm:Bitmap = new (getDefinitionByName("assetImage.Main_AImage"+i) as Class);
				addChild(bm).x = bm.width * i + 20 * i;
			}
		}
	}
}

とりあえずどっちでもよさげ。

[AS]FlashIDEでのカラー効果→「スタイル:着色」内の各項目をASでコントロールするには?

世の中に記事がなさそうだったのでメモ。
考えればすぐわかりそうだけど、ちょっと迷った。

MovieClipの色変更したいときは、変更したい色情報を持ったColorTransformインスタンスを生成、
DisplayObject.transform.colorTransformに突っ込んであげればよい。

//オレンジ色を四角を生成
var mc:MovieClip = new MovieClip();
mc.graphics.beginFill(0xFFCC00);
mc.graphics.drawRect(0,0,100,100);
addChild(mc);

//白くする
var ct:ColorTransform =  new ColorTransform(1,1,1,1,255,255,255,0);
mc.transform.colorTransform = ct;

ColorTransformのコンストラクタに与える引数の各項目に関しては、”FlashIDEでのカラー効果→「スタイル:詳細」”のパラメータと一致する。
(どの項目がどれにあたるかはリファレンス参照)

ところがColorTransformでは「スタイル:着色」にある「濃淡」の項目がまかなえない。(と思う)
では濃淡項目はAS的になんになるのか?

たぶんColorクラスのbreigtnessプロパティと思う。
なのでColorクラスを使う。
Colorクラスは、ColorTransformクラスを継承したクラスなので、同じように設定可能。
以下のようにすればOK。

import fl.motion.Color;

//オレンジ色を四角を生成
var mc:MovieClip = new MovieClip();
mc.graphics.beginFill(0xFFCC00);
mc.graphics.drawRect(0,0,100,100);
addChild(mc);

//濃度50%で白くする
var col:Color =  new Color(1,1,1,1,255,255,255,0);
col.brightness = 0.5;
mc.transform.colorTransform = col;

[AS3][?]画像ファイルをEmbedしても正常に表示できないことがある

(まだ、ちゃんと検証してないけど)
FlashCS4で発生した奇奇怪怪な現象。

よく似た画像ファイル2枚をEmbedで埋め込むと1枚しか表示されない。
さらにどっちが表示されるかは、パブリッシュするたびに異なる。

発生した条件。
画像の縦横幅が同じ。
ファイルサイズの誤差が1kb未満
(例:24kbと24.5kbとか)
もちろんこの二つのファイル名は変えてある。

どうもFlash側でこの条件のファイルは同じ画像と認識されてるくさい。
で、結果的には、前のエントリと似たようなことになるんではないかと思う。
あとでちゃんと調べる。

つまりは、IDEでEmbedなんて使うなってことらしい。

[AS][?]画像のEmbedは1回しか使えない?

よくわからんけど、他のクラスでEmbed済みの画像を別のクラスでEmbedしても表示もされなかった。
エラーも出ないから、かなりはまった。
とりあえず、あとで検証する。

[Event][AS] Airアプリ「Twittenorion」

先日、東京てらこ 9に参加してきました。
Twitterで何かつくろうってテーマだったのAirアプリを作ってみました。

「Twittenorion」

タイトルどおりTweetのテキストでテノリオンするという感じです。
SEARCH WORDを入力しSEARCHボタンを押すと、入力してワードでのTwitterで検索を行い結果の20件をランダムで順番に表示さいていきます。
DRUM KITのON/OFFの際にはドラムパターンがランダムに変更されます。
BPMにあわせて流れる文字の速度が変化します。
集中したいときの作業用BGMになるかなってつもりで作りました。
 
以下からDLできますので、気になった人は試してみてくださいませ。
DownLoad : Twittenorion
 
 

またてらこでの発表資料のスライドもアップしておきます。
東京てらこ vol.9 発表資料
(キーボードのカーソルキーでスライドの操作ができます)
 
 

・キーボードから任意の文字を入力できるようにしたものをwonderflにアップしました。

Twittenorion – wonderfl build flash online

 
 

[AS]TypeError: Error #1006: frame1 は関数ではありません。 at _fla::MainTimeline/frame1()、となった場合の対処方法

MovieClipにおいて、特定のフレームのフレームアクションを実行することができるメソッドがあります。
任意のフレームのスクリプトを実行:frame + “フレーム数” + ();

たとえば、ステージに_mcというインスタンス名でMovieClipが配置してある場合。
(_mcには1,2,3フレームにスクリプトが書いてある)
frame+フレーム数というメソッドを実行することができます。

//_mc:ステージに配置してあるMovieClipインスタンスで
//1,2,3フレームにスクリプトが書いてあり、内容は以下の通り
//1フレーム目には、trace("_mc 1フレーム");
//2フレーム目には、trace("_mc 2フレーム");
//3フレーム目には、trace("_mc 3フレーム");

_mc.frame1(); //出力:_mc 1フレーム
_mc.frame2(); //出力:_mc 2フレーム
_mc.frame3(); //出力:_mc 3フレーム

このとき以下のようなエラーが発生するときがある。

TypeError: Error #1006: frame1 は関数ではありません。
at _fla::MainTimeline/frame1()

このときの原因の一つは、実行対象のMovieClipにリンケージ指定されているということ。
リンケージ指定した状態で、任意のフレームのスクリプトを実行しようと上記のようなエラーになるらしい。

また、動的に生成したMovieClipインスタンスについても、addFrameScript()メソッドでフレームにスクリプトを追加した場合についても、同じ結果になるようす。

以下、例

var mc:MovieClip = new MovieClip();
addChild(mc);
//ムービークリップの1フレーム目にファンクション:testを追加
mc.addFrameScript(0,test);
function test():void{
	trace("mc script")
}
mc.frame1()//上記のようなエラーが発生する

ということは、動的に生成したmcにaddFrameScript()でファンクションを追加しても実行する術はないということ!?
まぁ理由はわからないけどそんな挙動をするみたい。
まぁ、こんなのそうそう使わないけども。

[AS][?]FlashIDEでドキュメントクラスをSpriteに設定した場合の怪

一般的にMovieClipとSpriteの違いは、

・MovieClip:タイムラインを持てる。
・Sprite:タイムラインを持てない。

リファレンスを見てもMovieClipはSpriteのサブクラスであり、タイムライン操作についてのメソッドが追加されたものとなっている。

////////////////////////////////////////////////////////////////////////
・そもそも「タイムラインを持っている」とは具体的に何なのか?
フレームを2フレーム以上持っている状態を指すらしい。
参考:ActionScript3.0入門ノート|Spriteの作成と表示

つまり
・MovieClip:フレームを2フレーム以上持てる。
・Sprite:フレームを1フレームだけ持てる。
こういうことになるのでしょう。

////////////////////////////////////////////////////////////////////////
・ここで疑問なのです。
FlashIDEではドキュメントクラスをSpriteを継承したクラスを指定することができますよね。
この場合、メインタイムラインはSprite扱いということになると思うのですが、実際はそうではないようです。
以下の画像のような状態の場合、

これをパブリッシュすると、青い四角が点滅する状態となります。
ドキュメントクラスをSpirteにしているのに、メインタイムラインは2フレーム目以降も繰り返し再生されているのです。
ちなみに、この際フレームにstop();等のスクリプトを書くと、errorとなります。
これは、フレームにスクリプトが書けるのはMovieClipだけだからという理由です。
具体的にはフレームにスクリプトを書くという行為は、内部的にはaddFrameScript()というメソッドで実装されているようで、SpirteにはこのaddFrameScript()メソッドが定義されていないから、ということのようです。

つまり、ドキュメントクラスをSpriteで定義した場合(のメインタイムライン)は、完全なSpriteでもなく、またMovieClipでもないというような中途半端な存在に思えるのです。

////////////////////////////////////////////////////////////////////////
ちなみにMovieClipとしてライブラリに登録したシンボルの基本クラスをSpriteとし、
そのシンボルのタイムラインを10フレームにした場合について、
(下画像参照)

このシンボルをステージに置いた場合のシンボルの挙動はどうなると思いますか?
先ほどのように2フレーム目以降が繰り返し再生されるのでしょうか?

答えは、黒いシェイプは点滅しません。
1フレーム目のみが描画された状態でstop();状態となり、2フレーム目以降は無視されているようです。
これが本来のSpriteの挙動であると思います。

////////////////////////////////////////////////////////////////////////
メインタイムラインだけが特別な扱いになっているのでしょうか?
こういうもんだと思えば実害は無いのですが、なんか気持ち悪いですよね。
この理由をご存知の方いましたら是非ご教授くださいませ。

テスト環境:winXP FlashCS5

[AS]ActionScript3.0のコーディングスタイルの規約(FlexSDKにおける規約)

Adobe推奨が以下のリンク
Flex SDKコード記述に関する規則とベストプラクティス

あくまでFlexSDK用っぽいので、FlashIDEがこれに準拠するかといったら微妙っぽい。
たとえば、{で改行をどこにいれるかという点では、
FlashIDEで、function生成のショートカットキーESC+f+nで生成されるコードは、

function  () {
    //処理
}

規約では、{を整列させると書かれている

function  ()
{
    //処理
}

とはいれ、それ以外の部分は大体真似していいんじゃないかと。

◆気になった部分だけmemo
・new Array() → []
・new Object() → {}
・if(flag == true) → if(flag) (flag:Boolean,Object)
・as演算子よりもキャストを使う
・単純な条件はifよりも三項演算子を使う (ifより遅くなるんじゃないの?)
・if文が(全ての項目のステートメントが)一項目のときはブロック{}を書かない
・for、while、do文では必ずブロック{}を書く
・protected override → override protected
・static public → pubilc static
・定数は全てstaticとする
・変数を初期化するときはコンストラクタではなく宣言時にする。

?なところもあるけど一通り目を通しておいてもよさげ。

[AS][オレオレライブラリ]シフトキー(ctrlキー)を押してる、押してないを判定してくれるクラス

製作の上であったら便利かな、と思ったのでクラス化。

◆動機
たとえば、あるボタンを押したら外部読み込み開始するとしたら、それが失敗したときなどを考慮してにエラー処理を実装しますよね。
この実装のチェックとしては、わざとエラーが起こる状態を再現してテストしなくちゃいけない。
たとえば、読み込むべきURLが外部xmlに記述してあって、それが存在しないURLだった場合のエラー処理だったら、わざとxmlに記述されたURLを間違えたものに書き換えてチェックとか。
というようなことを以前はやってました。
が、いちいちファイル書き換えてチェックするのが面倒。

そこで、
もしshiftキーを押しながらクリックしたら、存在しないURLを読みにいくようなロジックを最初から組んどけばテスト簡単じゃね?
お客さんにエラー時の動作処理をみてもらうときも、お客さんの負担減るんじゃね?

ってことで、shiftキーとctrlキーが押されてるかどうかを判定するクラスを作りました。
Singletonで作ってあるので、最初に初期化しちゃえば、どこからでも参照可能。
消すときも、Singletonなのでクラス名で検索書ければどこで使ってるかが一目瞭然(のはず)。

使い方は以下のような感じ

//準備
//ステージに追加、これだけでOK
addChild(AddKeyDownUtil.getInstance());

//使い方、以下のプロパティを参照して、true/falseを取得できる
//シフトキーが押されてたら、true,押されてなかったらflaseを返す
AddKeyDownUtil.getInstance().isShiftDown;//戻り値:Boolean
//コントロールキーが押されてたら、true,押されてなかったらflaseを返す
AddKeyDownUtil.getInstance().isCtrlDown;//戻り値:Boolean

//使用例)
//_btnがクリックされたときにシフトキーが押されているかいないかで処理を分岐
_btn.addEventListener(MouseEvent.CLICK, clickHandler);
private function clickHandler(e:MouseEvent):void {
    if(AddKeyDownUtil.getInstance().isShiftDown){
        //シフトキーが押されていた場合に実行したい処理
    }else{
        //シフトキーが押されていない場合に実行したい処理
    }
}

クラスファイルは以下の通り

package bz393.util {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
	
	/**
	 * ...
	 * @author 393
	 */
	public class AddKeyDownUtil extends Sprite{
				
		public static var instance:AddKeyDownUtil;
		public var isShiftDown:Boolean = false;
		public var isCtrlDown:Boolean = false;
		
		public function AddKeyDownUtil(enforcer:SingletonEnforcer) { };
		
		public static function getInstance():AddKeyDownUtil {
			if (!AddKeyDownUtil.instance) {
				AddKeyDownUtil.instance = new AddKeyDownUtil(new SingletonEnforcer());
				AddKeyDownUtil.instance.addEventListener(Event.ADDED_TO_STAGE,init);
			}
			return AddKeyDownUtil.instance;
		}
		
		static private function init(e:Event):void {
			AddKeyDownUtil.instance.removeEventListener(Event.ADDED_TO_STAGE, init);
			
			AddKeyDownUtil.getInstance().stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHander);
			AddKeyDownUtil.getInstance().stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHander);
		}
		
		static private function keyDownHander(e:KeyboardEvent):void {
			switch (e.keyCode) {
				case Keyboard.SHIFT:
				AddKeyDownUtil.instance.isShiftDown = true;
				break;
				case Keyboard.CONTROL:
				AddKeyDownUtil.instance.isCtrlDown = true;
				break;
			}
		}
		
		static private function keyUpHander(e:KeyboardEvent):void {
			switch (e.keyCode) {
				case Keyboard.SHIFT:
				AddKeyDownUtil.instance.isShiftDown = false;
				break;
				case Keyboard.CONTROL:
				AddKeyDownUtil.instance.isCtrlDown = false;
				break;
			}
		}
	}

}
class SingletonEnforcer {
};