トーンジャンプ
2010 年 1月 22 日 金曜日 kosuke待ち受けFlashを作って気づいたことだが、Device Centralで確認した際、淡いグラデーションの部分にトーンジャンプが見られた。
電話機種のプロファイルで色深度24ビットとなっている機種(つまりフルカラー対応のはず)をいくつか試してみたけど、どれも同じように発生しています。同じファイルを通常のFlash Playerでプレビューするとトーンジャンプは発生していないので、Device Cnntral固有の問題なのかもしれないし、実機でもトーンジャンプするのかもしれない。(トーンジャンプまで再現してるならDevice Centralあっぱれな訳だが。)
このままにしておけないし、そもそもしっかりグラデーションを表示出来る電話機ばかりとは到底思えないっていうのもある。
そこで最終的に使った懐かしの方法を紹介します。最近の環境ではあまり気にしないけれども、GIFファイルを作る際、色数を絞ってディザをノイズで加え擬似的に段調を持たせたことはないでしょうか。あの考えを踏襲してトーンジャンプを軽減させます。
Photoshopでグラデーションの上に新規レイヤーをつくり塗りつぶす。
[フィルター]から[ノイズ]→[ノイズを加える]を実行。
今回は新規レイヤーを白で塗りつぶして、カラーノイズ10%、均等に分布にしました。
このレイヤーを不透明度75%、焼き込み(リニア)でグラデーションと合成する。
若干乱暴な感じですが、今回はこれで大分良くなった。
何にしても、元画像ファイルのグラデーションがPhotoshopやFlashでの作業中トーンジャンプして見えないところがややこしい。
合成方法は千差万別。レイヤーでなくカラーチャンネルにノイズを合成するのもあるだろうし。ケースによって試すべし。
nipx 待ち受けFlash / Heart
2010 年 1月 20 日 水曜日 kosuke
|
イベントフローの確認
2010 年 1月 15 日 金曜日 kosuke普段気にすることはありませんが、addEventListenerのuseCaptureについて。
AS3ではイベントが3段階で処理されている。原則的にイベントはステージから、イベントが発生したオブジェクトに向かい、オブジェクトに辿り着いたら今度はステージに戻ってくる。
入れ子になった表示オブジェクトは、この経路にしたがってイベントをリレーしているわけだ。
普段意識せず、useCapture = false のままに設定しているなら、イベントが発生したオブジェクトの段階か、ステージに戻ってくる段階の通知をキャッチしている。
このことを示した図がリファレンスに書かれている。
イベントフロー
この図はとてもよく説明されているのだけど、実際に動いているもので確認したくて試しました。
Eventオブジェクトには、イベントのリレーを止める、stopPropagationとstopImmediatePropagationってメソッドもあるので、この二つの挙動についても試している。
イベントフローを意識することがあるのは、入れ子になった表示オブジェクトの場合が想定されるので、大きい方から順番にA、B、Cと円を定義して、入れ子にする。
var A:Sprite = new Sprite(); A.name = "A"; var B:Sprite = new Sprite(); B.name = "B"; var C:Sprite = new Sprite(); C.name = "C"; A.graphics.lineStyle(5, 0x000000 ); A.graphics.beginFill( 0x000000, 0 ); A.graphics.drawCircle( 0,0, 100 ); B.graphics.lineStyle(2.5, 0x404040 ); B.graphics.beginFill( 0x404040, 0 ); B.graphics.drawCircle( 0,0, 75 ); C.graphics.lineStyle(1, 0x808080 ); C.graphics.beginFill( 0x808080, 0 ); C.graphics.drawCircle( 0,0, 50 ); //BはAの子、CはBの子 A.addChild( B ); B.addChild( C ); addChild( A ); |
全ての円にキャプチャ段階とターゲット・バブリング段階それぞれにリスナーを定義します。
stopPropagation、stopImmediatePropagationを試すべく、優先順位をつけてリスナーを二つ登録しました。
優先順位の高い方のリスナーは、ラジオボタンに応じてstopPropagation、stopImmediatePropagationが実行されるようにします。
リスナーはテキストエリアに処理された内容を表示します。
//優先度の高いリスナー A.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownCaptureing1, true ); B.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownCaptureing1, true ); C.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownCaptureing1, true ); A.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownTarget1, false ); B.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownTarget1, false ); C.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownTarget1, false ); //優先度の低いリスナー A.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownCaptureing2, true, -1 ); B.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownCaptureing2, true, -1 ); C.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownCaptureing2, true, -1 ); A.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownTarget2, false, -1 ); B.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownTarget2, false, -1 ); C.addEventListener( MouseEvent.MOUSE_DOWN, _onMouseDownTarget2, false, -1 ); private function _onMouseDownCaptureing1(e:MouseEvent):void{ if( group1.selectedData == 1 ) e.stopPropagation(); else if( group1.selectedData == 2 ) e.stopImmediatePropagation(); var str:String = "#1 " + e.currentTarget["name"] + "がキャプチャ段階のリスナーで、" + e.target["name"] + "をターゲットに" + e.type + "イベントを" + _returnPhase(e) + "で処理。"; _field.appendText( str + "\n" ); } private function _onMouseDownTarget1(e:MouseEvent):void{ if( group2.selectedData == 1 ) e.stopPropagation(); else if( group2.selectedData == 2 ) e.stopImmediatePropagation(); var str:String = "#1 " + e.currentTarget["name"] + "がターゲット・バブリング段階のリスナーで、" + e.target["name"] + "をターゲットに" + e.type + "イベントを" + _returnPhase(e) + "で処理。"; _field.appendText( str + "\n" ); } private function _onMouseDownCaptureing2(e:MouseEvent):void{ var str:String = "#2 " + e.currentTarget["name"] + "がキャプチャ段階のリスナーで、" + e.target["name"] + "をターゲットに" + e.type + "イベントを" + _returnPhase(e) + "で処理。"; _field.appendText( str + "\n" ); } private function _onMouseDownTarget2(e:MouseEvent):void{ var str:String = "#2 " + e.currentTarget["name"] + "がターゲット・バブリング段階のリスナーで、" + e.target["name"] + "をターゲットに" + e.type + "イベントを" + _returnPhase(e) + "で処理。"; _field.appendText( str + "\n" ); } private function _returnPhase(e:MouseEvent):String{ return ( EventPhase.AT_TARGET == e.eventPhase ) ? "ターゲット段階" : ( EventPhase.BUBBLING_PHASE == e.eventPhase ) ? "バブリング段階" : "キャプチャ段階"; } |
こちらで試せます。場合によっては意図に反して2回処理されていたみたいな間違いはありそうだね。
こんなものを意識して何か作ることが無いことを祈るばかり。
nipx 待ち受けFlash / Valentine’s Day
2010 年 1月 14 日 木曜日 kosuke
|
新しい試みで、オリジナル 待ち受けFlash を作りました。
Flash Liteは1.1対応で作るのが汎用的と思いますが、ウチのは2.0以上の対応です。
昨今もAS2の仕事があったりするんでそのノウハウを活かそうと考えた。PCでは過去のものになりつつあるAS2も、Flash Liteに置き換えれば前向きに考えられるかと思ったわけです。携帯Flashは全然やってないので実機で充分に動くものになっているか少し不安です。
実機確認は手もとにあったWILLCOM WS011SHのFlash Lite 2.1でしか出来ていないので、もし試されたならご覧いただいた機種や動作状況を教えていただけるとありがたいです。
nipx.jp
2010 年 1月 8 日 金曜日 kosukeCool HomePages.com に nipx.jp 載せてくれたらしい。今日メールがきてた。
作ったの1年前の話なんだが…。ともあれ、ありがとうございました。
スペースシャトルは今年で退役って話なんで来年までにリニューアルしたい。
コメントを記述するなら
2010 年 1月 5 日 火曜日 kosukeFlashで開発する際、コメントってどうしてます?
僕の場合、自分しかさわらない一度っきりのプロジェクトにいちいち緻密にコメントつける必要性は微妙と思いつつも、見直してみると大抵コメントをつけているようです。
最近はどうせコメントをつけるならとASDocに対応した形式で記述するようにしました。
このASDocの書式には結構多様な指定が出来るようになっています。
刺身のつまみたいなもんなんで、全部覚えようなんて気にはまったくならないのだけども、いざ書き出そうって時にエラーってことが頻繁なんで、自分的な要点を記録しておきます。
先にヘルプのインデックスへリンク。
参考:ASDoc の使用
コメントの記述は以下の書式。/** と */ の間にコメントを書く。
コメント行頭の * は無くても問題なく書き出されるような気がしますが、ASDocで解析するのに使うと参考にあるので記述する。この書式をクラスやメソッド、プロパティなどを記述している直前に書く。この位置にコメントを書くことは多いと思うので、どうせならこれにしておくって感じ。
/**
* Main comment text.
*
* @tag Tag text.
*/ |
@の部分がASDocのタグになっていて、ASDocを書き出す時に整形されます。
参考:ASDoc タグ
いろいろありますが、メソッドやコンストラクタの引数用に@param。戻り値用に@return。くらいしか使っていない。自分用にはこの位でいんじゃないかと思います。僕的にコケたところで、getter/setterの場合、ASDocのコメントは1カ所に書きます。
/** * 直線を定義します。 */ public class Line{ /** * 直線を定義します。 * * @param a 直線を(ax + by + c = 0)で表す場合のaです。 * @param b 直線を(ax + by + c = 0)で表す場合のbです。 * @param c 直線を(ax + by + c = 0)で表す場合のcです。 */ public function Line( a:Number, b:Number, c:Number ){ this._a = a; this._b = b; this._c = c; this._update(); } /** * 直線を(ax + by + c = 0)で表す場合のaです。 * @return ax + by + c = 0 の a です。 */ public function get a():Number{ return this._a; } public function set a(n:Number):void{ this._a = n; this._update(); } private var _a:Number; } |
コメントはHTMLタグが使える。
参考:一般に使用される HTML エレメントの一覧
ASDocを書き出した時に改行くらい無いと読みづらいものあるので<p>タグは良く使う。
<br>はうまく利かない気がする。あと<a>タグも使えるので参考がある時は記述しておきますね。
コメントを勢いで書くとよく失敗するのが特殊文字。参考の下にある実体参照は注意した方がいい。< > &みたいなHTMLオーサでもよく使うものはすぐ気づいたのだけど、@(アットマーク)とか*(アスタリスク)ってあまり実体参照で使わないと思うので。これがあると書き出しの時エラーになります。
@ = @
* = ~~ (実体参照じゃないけど、ASDoc書式ではチルダ二つで書く)
コメントの記述はこの位にしてASDocの書き出し方。
Flex SDKとターミナルを使います。
FlashDevelop環境ならGUIからいけるっぽいが、自分はMac環境。Mac版作って欲しい。
なのでここからターミナルの操作要点になります。(自分はこの使い方をいつも忘れるのでこっちの方が重要メモ)
ターミナルを立ち上げたら、asdocの実行ファイルディレクトリに移動します。実行ファイルはFlex SDKのbinディレクトリの中にある。コマンドラインを見ると気分が悪くなる僕みたいな人向けの移動する方法。
ターミナルにcd を入力してbinフォルダをドロップ。
次にコマンドを入力します。
参考: ASDoc ツールの実行
コマンドオプションが沢山ありますが必要に応じて指定します。
僕は書き出すファイルをまとめて-doc-sourcesを指定するだけで書き出してます。
まず、asdocを指定する。./を忘れないように注意。
./asdoc
Flex SDKのバージョンによりますが、FlashPlayer10以降のクラスが含まれる場合(Matrix3DとかVector3Dとか)-target-player オプションを入れます。
参考:Flex Builder 3をFlash Player 10に対応させる
./asdoc -target-player=10.0.12
ライブラリにSWCを使っている場合(Progressionとか)、-library-path オプションを入力してSWCファイルのディレクトリを指定します。これもフォルダドロップでOK。
./asdoc -target-player=10.0.12 -library-path /Users/name/project/libs/
書き出したいディレクトリを-doc-sourcesで指定します。フォルダドロップでOK。
./asdoc -target-player=10.0.12 -library-path /Users/name/project/libs/ -doc-sources /Users/name/project/src/jp/nipx/
これを実行すればbinの中にasdoc-outputフォルダが生成され中にASDocが入っています。
知っておくと便利そうなターミナル操作
Control + A 行頭へ移動
Control + E 行末へ移動
Control + U カーソルより左の文字をすべて消去
Control + W カーソルより左の文字を単語単位で消去
Control + K カーソルより右の文字をすべて消去
(ターミナルの設定 > キーボード > メタキーとしてOptionキーを使用にチェックを入れて)
Option + B 単語単位で左に移動
Option + F 単語単位で右に移動
ところで世に配布されているありがたいライブラリなんかは、間違いなく整然としたコメントがつけられています。
数式と文章って真逆なようでそうでもないものだと思う。わかりやすいソースはわかりやすい言葉で説明できるものだと思いました。
外部SWFに埋め込んだフォントを使う
2010 年 1月 4 日 月曜日 kosuke年末の忘年会で、外部SWFに埋め込んだフォントを使う話題がありました。埋め込んだフォントがうまく有効にならないってことで、その時は多分出来るんじゃない?位に思ってましたけど、やってみたらすんなりとはいかなかったので記録しておきます。
話題に上がったのは、たぶんこういうファイル構成だと思う。
これを前提にして試してみた。
fonts.swfのステージにダイナミックテキストを置いて、ヒラギノ角ゴ Pro W6、ヒラギノ明朝 Pro W6を配置。
両方とも“日本語(かな)(318文字)”を埋め込んでパブリッシュ。
コンストラクタで、
public function Fonts(){ var arr:Array = Font.enumerateFonts( false ); for each( var i:Font in arr ){ trace( i.fontName ); } } |
としてトレースして結果は期待どおり。
続いてpreloader.swfからfonts.swfを読み込んでトレースしてみる。
埋め込みが参照できれば、—▼Preloader▼—の下にフォント名が出力されるはず。
public function Preloader(){ var loader:Loader = new Loader(); loader.load( new URLRequest( "fonts.swf" ) ); loader.contentLoaderInfo.addEventListener( Event.INIT, function(e:Event):void{ trace( "---▼Preloader▼---" ) var arr:Array = Font.enumerateFonts( false ); for each( var i:Font in arr ){ trace( "Preloader:" + i.fontName ); } }); } |
あれ?出力されない…。どうもこの時点でfonts.swfの埋め込みを参照できないっぽい。
で、色々試してみたらFont.registerFont()でグローバルフォントリストに追加しないといけないようだ。
Font.registerFont()にはクラスを渡すことになっているのだけど、今回みたいな一部フォントの場合、どうやればよいか?(フォントシンボルですべての文字を埋め込む場合は、フォントシンボルのクラスでOK。)
これはメタタグを使えばうまくいった。
fonts.swfのダイナミックテキストによる埋め込みをやめて、Embedタグで埋め込む。
public class Fonts extends Sprite{ [Embed(source='../../assets/ヒラギノ角ゴ Pro W6.otf', fontName= "Hiragino Kaku Gothic Pro W6", mimeType='application/x-font', unicodeRange="U+3000-U+303F,U+3041-U+309F,U+30A0-U+30FF,U+FF61-U+FF9F" /* Japanese Kana */ )] private static var HIRAGINO_KAKUGO_PRO_W6:Class; [Embed(source='../../assets/ヒラギノ明朝 Pro W6.otf', fontName= "Hiragino Mincho Pro W6", mimeType='application/x-font', unicodeRange="U+3000-U+303F,U+3041-U+309F,U+30A0-U+30FF,U+FF61-U+FF9F" /* Japanese Kana */ )] private static var HIRAGINO_MINCHO_PRO_W6:Class; public function Fonts(){ Font.registerFont( HIRAGINO_KAKUGO_PRO_W6 ); Font.registerFont( HIRAGINO_MINCHO_PRO_W6 ); } } |
embedの書式について詳しくは、Flexのヘルプ参照。
埋め込みフォントの使用
sourceにはフォントファイルへのパスを書く。相対パスの基準はEmbedを書くasファイルから。
fontNameはasから参照するときのフォント名をつける。上記みたいなそのまんまのネーミングは混乱のもとになる予感。My 〜 とかの方がよさそうな気がする。
unicodeRangeで埋め込む範囲を指定するのだけど、これについては後ほど。
Embedタグの下の変数はEmbed参照用の変数ね。これをFont.registerFontで登録する。
ひとまずこれでPreloaderから参照できるか試してみる。
今度は参照できるようになった。
グローバルに追加されていればindex.swfからも問題なく使える。
public function Index(){ trace( "---▼Index▼---" ); var arr:Array = Font.enumerateFonts( false ); for each( var i:Font in arr ){ trace( "Index:" + i.fontName ); } var field:TextField = new TextField(); field.autoSize = TextFieldAutoSize.CENTER; field.defaultTextFormat = new TextFormat( "Hiragino Mincho Pro W6", 24 ); field.embedFonts = true; field.x = 200; field.y = 138; field.rotation= 15; field.text = "あけましておめでとうございます"; this.addChild( field ); } |
最後にunicodeRangeについて。
埋め込み文字の範囲はこれにUnicodeの文字コードを指定し行うようだ。
指定の仕方は、
文字範囲の設定
に詳しく書かれているようです。
がっつり英語が読めるならこれらしい。
15 Fonts
で論より実践でいきます。上記リンクに記載がありますが、Flex SDKの中に、
flash-unicode-table.xmlってファイルがあって、日本語のかなだけとか、漢字 JIS第一水準みたいなFlashにある文字セットが記載されているのでまとめて埋め込む時はこれを使えばよさそう。
個別の文字だけど、U+3041でいうところの3041の部分、U+~の~が16進数で表された文字コードになっているようなのでActionScriptで以下のような変換を使って出せると思う。
var str:String = "あ"; //Unicode 10進数表記 var num:Number = str.charCodeAt(0); //Unicode 16進数表記 var code:String = num.toString( 16 ); //文字 var txt:String = String.fromCharCode( parseInt( code, 16 ) ); trace( num ); trace( code ); trace( txt ); /* 出力 12354 3042 あ */ |
ってことで、めんどくさいけどいけるんじゃないんですかね。 >> Shuさん
謹賀新年
2010 年 1月 1 日 金曜日 kosukeあけましておめでとうございます。
昨年はお仕事でお世話になったみなさま、どうもありがとうございました。
おかげさまで、無事年を越して新年を迎えました。
ニピクセル、今年もどうぞよろしくお願いいたします。
このブログを読んでいただいている、すべての方へ。
いつもありがとうございます。2BLOGを今年もよろしくお願いします!