ActionScriptリファレンスをダウンロードする
2009 年 2 月 8 日 日曜日 正宗地下鉄での移動なんかのヒマなとき、ActionScriptリファレンスを読んでたら良いヒマつぶしになるな~、なんて考えたのでActionScriptのリファレンス(ヘルプみたいなもん。ActionScriptの機能や使い方なんかが書かれてある文章)をローカルにダウンロードする方法を考えます。
(続きを読む...)
地下鉄での移動なんかのヒマなとき、ActionScriptリファレンスを読んでたら良いヒマつぶしになるな~、なんて考えたのでActionScriptのリファレンス(ヘルプみたいなもん。ActionScriptの機能や使い方なんかが書かれてある文章)をローカルにダウンロードする方法を考えます。
(続きを読む...)
papervision3Dで輪郭線を表示させてみました。
ちなみに表示されているキャラクターは愛媛県西予市三瓶町のみんなの人気者、おなじみ「げんきくん」を独自で3Dモデル化させたものです。
輪郭線の表示の仕方についてはトゥーンシェーディング等の計算は一切行っていなくて、単に3Dモデリングツールのほうのノウハウなので、ここでは今回使用したMetasequoiaを使った方法を書き留めておきたいと思います。
ついでにMetasequoiaからモデルデータをpapervisionで表示する方法も苦労したので書き記しておきます。
(続きを読む...)
FlashサイトをAS3で構築する上で、とても重要になるフレームワークの中でもひときわ使いやすい、Progressionの勉強会に行ってきました。
たぶんこのブログを見られている方はWEBデザイナーも多いと思うんですけど、WEBデザインの世界では今まであまり馴染みのなかった「フレームワークって何?」ってところから説明した方がいいかもしれません。
フレームワークとはそもそも室町時代に端を発した足軽鉄砲隊隊長による符礼無枠(ふれいむわく 1421~1439)という命令に端を発した云々うそです
ってとこで必死こいて100行ほど「フレームワークとは」みたいな事書いてみたんですけど、そもそもフレームワークって何なのか、そのフレームワークっちゅうもんを使うと何がうれしいのか、は実際にさわってみないとわからないと思ったので言葉の定義はざっくり削除してみました。
ほいでもせっかくなので当ブログでも「Progressionを使ったオレオレサイトの制作事例」を不定期で連載したいと思います(ちょうど制作事例やFPSだけだとネタに困ってたからね)。
今回はProgressionフレームワークの開発者であるniumさんならびにSparkProject、そういった方々と直接の勉強の機会を与えていただいたてら子さん達に感謝感謝です。
ペーパービジョンやボックスツーデー、ツイナーみたいに見た目に訴求するものはないですが、良いフレームワークっちゅうもんはじっくり腰をすえて学ぶと確実に自分自身の制作能力を上げることができます。
なるべく「プログラム書くんだったらこの言葉の意味はわかってて当然」って表現を避けますんで、ぜひとも「フレームワーク」って言葉に馴染みのない方でもこの機会に覚えてもらうとうれしいです。
あと今日何が嬉しかったって、FPS Lite vol.0でお見せしたbox2dを使ったサンプル、あれの反応が聞けて嬉しかった。あんまり嬉しいんで実はあの難しいbox2dの概念を説明するために下書きしてた記事も近々アップしちゃうよ!
(本当、あれもサンプルを普通に使ってるだけなのでお見せするのは恥ずかしい限りなんですけど俺が恥ずかしいのは気にしない方向で。ライブラリの使い方はみんなで共有しちゃいましょう)
SPARK Projectに顔認識用のライブラリがあるので家庭教師のトライにトライしてみました(ややこしい)。
画面に直接マウスで落書きすると、顔の動きに落書きが追随します。
動作にはWEBカメラが必要。あとめちゃくちゃ重いです。
ライブラリを普通に使ってるだけで特別なことしてないのがバレバレで恥ずかしいですが以下はコードです。重くて泣きたくなる場合は37行目のコメントアウトを外して代わりに38行目をコメントアウトしてみて下さい。
顔認識は全部ここに突っ込んだ
package { import flash.display.Sprite; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Graphics; import flash.geom.Matrix; import flash.geom.Rectangle; // import flash.events.Event; // import flash.media.Camera; import flash.media.Video; import flash.events.ActivityEvent; // import jp.maaash.ObjectDetection.ObjectDetector; import jp.maaash.ObjectDetection.ObjectDetectorOptions; import jp.maaash.ObjectDetection.ObjectDetectorEvent; public class Main extends Sprite { private const VIDEO_SCALE:Number = .8; private const DEFAULT_FACE_RECT:Number = 50; private var camera:Camera; private var video:Video; private var detector:ObjectDetector; private var options:ObjectDetectorOptions; private var raku:Raku; function Main():void { init(); initDetector(); } private function init():void { camera = Camera.getCamera(); if (camera != null) { video = new Video(stage.stageWidth, stage.stageHeight); video.attachCamera(camera); //camera.addEventListener(ActivityEvent.ACTIVITY, onCameraActivityHandler); addEventListener(Event.ENTER_FRAME, onEnterFrameHandler); addChild(video); } var target:Sprite = new Sprite(); var g:Graphics = target.graphics; g.beginFill(0x000000, 0); g.drawRect(0, 0, stage.stageHeight*2, stage.stageWidth*2) g.endFill(); addChild(target) raku = new Raku(target); addChild(raku); } private function initDetector():void { detector = new ObjectDetector; detector.options = getDetectorOptions(); detector.addEventListener(ObjectDetectorEvent.DETECTION_COMPLETE, onDetectorCompleteHandler); detector.loadHaarCascades( '/samples/kao/face.zip' ); } private function onCameraActivityHandler(e:ActivityEvent):void { if (e.activating) { addEventListener(Event.ENTER_FRAME, onEnterFrameHandler); } else { removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler); } } private function onEnterFrameHandler(e:Event):void { var bitmap:Bitmap = new Bitmap(new BitmapData(video.width, video.height, false)); var matrix:Matrix = new Matrix(); matrix.scale(VIDEO_SCALE, VIDEO_SCALE); bitmap.bitmapData.draw(video,matrix); detector.detect(bitmap); } private function onDetectorCompleteHandler(e:ObjectDetectorEvent):void { if ( e.rects ) { e.rects.forEach( function( r :Rectangle, idx :int, arr :Array ) :void { raku.moveRaku( r.x/VIDEO_SCALE, r.y/VIDEO_SCALE, r.width/VIDEO_SCALE, r.height/VIDEO_SCALE ); }); } } private function getDetectorOptions():ObjectDetectorOptions { options = new ObjectDetectorOptions; options.min_size = 50; options.startx = ObjectDetectorOptions.INVALID_POS; options.starty = ObjectDetectorOptions.INVALID_POS; options.endx = ObjectDetectorOptions.INVALID_POS; options.endy = ObjectDetectorOptions.INVALID_POS; return options; } } }
顔認識で得た矩形に合わせて拡大縮小してるだけ
package { import flash.display.Sprite; import flash.display.Graphics; import flash.events.MouseEvent; import flash.events.Event; public class Raku extends Sprite { private const DEFAULT_FACE_WIDTH:Number = 50; private const DEFAULT_FACE_HEIGHT:Number = 50; private var this_scale_x:Number = 1; private var this_scale_y:Number = 1; private var g:Graphics; private var target:Sprite; function Raku(mc:Sprite):void { target = mc; init(); } private function init():void { target.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler); Sprite(target).stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler); g = graphics; g.lineStyle(2, 0x000000); } private function onMouseDownHandler(e:MouseEvent):void { target.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveHandler); g.moveTo((e.stageX-x)/this_scale_x, (e.stageY-y)/this_scale_y); } private function onMouseUpHandler(e:MouseEvent):void { target.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMoveHandler); } private function onMouseMoveHandler(e:MouseEvent):void { g.lineTo((e.stageX-x)/this_scale_x, (e.stageY-y)/this_scale_y); } public function moveRaku(_x:Number, _y:Number, _width:Number, _height:Number):void{ this.x = _x; this.y = _y; this_scale_x = _width/DEFAULT_FACE_WIDTH; this_scale_y = _height/DEFAULT_FACE_HEIGHT; this.scaleX = this_scale_x this.scaleY = this_scale_y } } }
※10/12追記
Adobe AIR 電子証明書の補足
結論から言いますと、
ExternalInterface.call Internet explorerでnullが返ってくる件 | _quality こちらを参考にしてなんとか解決しました。
他のバージョンは分からないですが、SWFAddress2.1だと
SWFAddress.getValue();
でURLを取得できないのです。
何をどうやってもダメでして、サンプルとかWEBのチュートリアルとかではいとも簡単にSWFAddressを動かせてるのにオレはだめだめのだめ子さんだったわけですが、リンク先を試してみたところ動くようになりました!
それにしてもリンク先のeknさんはよく気がついたですね…。
この記事がなかったらと思うとぞっとします。
FlashのAS3でのガベージコレクションについて、ちょっと腑に落ちない点があったので実験してみた。
たぶんFLASH-JP - フォーラム:AS3.0 ガベージコレクションの対象についてと同じ事なんだと思うけど、実際にやってみないと理解が出来ないので。
var stgH:Number =stage.stageHeight; var stgHH:Number = stgH/2; var stgW:Number = stage.stageWidth; function init():void { var timer:Timer = new Timer(10); timer.addEventListener(TimerEvent.TIMER, xOnTimer); timer.start(); } function xOnTimer(e:TimerEvent):void { var sy:Number = Math.sin(Math.PI/180 * e.target.currentCount)*stgHH; sy += stgHH; var sprite:Sprite = new Sprite(); var r:uint = Math.floor(Math.random()*255); var g:uint = Math.floor(Math.random()*255); var b:uint = Math.floor(Math.random()*255); var col:uint = r<<16 | g<<8 | b; sprite.graphics.lineStyle(0, col, 1); sprite.graphics.drawCircle(0,0,10); sprite.addEventListener(Event.ENTER_FRAME, xOnEnterFrame); sprite.x = 1; sprite.y = sy; stage.addChild(sprite); } function xOnEnterFrame(e:Event):void { e.target.x += Math.floor(Math.random()*50); if (e.target.x > stgW) { e.target.removeEventListener(Event.ENTER_FRAME, xOnEnterFrame); e.target.stage.removeChild(e.target as Sprite); //Object(e.target) = null } } init();
これをそのままFlashにコピペすれば動きます。たぶん。FlexやFlexSDKは知らない(たぶん動かん)。
兎に角めちゃくちゃ速く、100分の1秒くらいの間隔でアホみたいにxOnTimer関数を実行しなさいよ!
とにかく丸い輪っかを書きなさいよ!
丸い輪っかは兎に角右に移動しなさいよ!
画面はしまで移動したら用済みなんでとにかく消えてしまいなさいよ!
というようなことを書いちょるわけです。
ここで調べたいことは、29行目コメントアウトしたように丸い輪っか(Sprite)の参照は消さなくても大丈夫なん?って事。
モチのロン、ここのコメントアウトを外すと怒られるわけで、怒られるのは嫌だからコメントアウトしてるわけで、「そしたらSpriteの参照は画面からはremoveChildしてるけどメモリには残ったままなんじゃない?」と思って不安でたまらないわけです。
xOnTimer関数の中でSpriteの参照をグローバルなものにしてやってもいいんだけど、え~それってAS2より酷くないか?メモリ管理したいからグローバルな参照にメモリを割り当てるって、何か本末転倒っぽくて気持ちが悪い。
ということで何とかしてxOnEnterFrame関数の中だけでSpriteの参照が消せないか、シコシコとコードを試してみたんですが、結果
ここは参照そのままに残しててもあとで必要に応じてガベージコレクタが消してくれるっぽい。
ず~っと立ち上げててもメモリの使用量はある一定の量からは使わなくなったもん。よくできてますな。
というわけで無駄な悩みで一日つぶしたというお話しでした。ギャフン