Hatena::ブログ(Diary)

三等兵

2010-03-11

はじめてActionScript3.0にさわりスパゲッティーができた

別にやりたくないのにー!というかやったことがない!大変心外だ。ASごっつ難しいやん。コンポーネントごっつあるやん。そういうのいややん。最初でくじけた。


とりあえず環境はこれで。

http://clockmaker.jp/blog/2009/07/tutorial-install-flashdevelop-flex-sdk/

FlashDevelopはなんとなく適当なものをうつしてみたところ、補完便利。


学習サイト


リファレンスは便利そう。



とりあえずASのルールを把握。

http://clockmaker.jp/blog/2009/07/tutorial-install-flashdevelop-flex-sdk/ここのサンプル。

package {
	import flash.display.Sprite;
	public class Main extends Sprite {
		public function Main():void {
			var sp:Sprite = new Sprite();
			sp.graphics.beginFill(0xFF0000);
			sp.graphics.drawCircle(100, 100, 100);
			addChild(sp);
		}
	}
}

package?なんでも入るものでしょうか。クラス思いっきり入ってるし。importはコンポーネントを利用するのに使うんだろう。ASではなんていうんだろ?クラス?どっちでもいいか。

それで継承して、コンストラクタで定義。変数はちょっとまだよくわからんなあ。型は宣言する必要がありそうだけど。ああ、そうなるとかなり型がありそう。クラスむちゃくちゃあったよなあ…。うつだ。

あとMainクラスそのものはインスタンス化しないの?じゃあコンパイルんときに、ってあれえ?appChildって何に対してやっているの?ああ、これクラスそのものがコンパイルされたらオブジェクトになるのかな。



よし、なんとなく判った気になろう。

今度は例の、

http://wonderfl.net/

でみてみる。とりあえずアカウントは昨日作っといた。ここで昨日はAS挫折したんだけど…。それにしてもウェブで作れるんですね。すごい時代になったものです。


勉強タグで一番上にあったもの。すごいなぁ。こういうことできるんだ。コード拝借。

http://wonderfl.net/code/57b6cd7eaee06e66f57c28edfa5272e90550d020

// write as3 code here..

package
{    
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.filters.*;

    // なぜかクリックしないと描画されない>< 
    // -> 別のマシンだと動いた

    [SWF(frameRate="24", backgroundColor="#000000")]

     /** 
      *  
      * @author ll_koba_ll (RAWHIDE.)
      */  
    public class Rotationlight extends Sprite
    {
        private var blur:BlurFilter;
        private var container:Sprite;
        private var source:Sprite;
        private var bmpd:BitmapData;

        public function Rotationlight()
        {

            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.quality = StageQuality.LOW;            
            init();            
            addEventListener(Event.ENTER_FRAME, update);
        }

        private function init():void
        {
            trace(stage.stageWidth)
            blur = new BlurFilter(4,4);            
            bmpd = new BitmapData(500, 500, true, 0x00FFFFFF);
            container = new Sprite();
            source = new Sprite();

            addChild(new Bitmap(bmpd));
            container.addChild(source);

            with(source.graphics)
            {
                beginFill(0x00bbff);
                drawCircle(0,0,20);
                endFill();
            }
            
        }

        private function update(e:Event = null):void
        {
            bmpd.draw(container, null, null, BlendMode.ADD);
            bmpd.applyFilter(bmpd, bmpd.rect, new Point(), blur);
            source.x = mouseX;
            source.y = mouseY;
        }
         
    }
}

packageはやっぱり使うんだね。名前空間っぽい。それからimport文。アスタリスクはワイルドカードか。たくさんありすぎてわからないからこれ利用しよう。

んでクラスのメンバ変数は、なんじゃこれ。ああ、型だよね。なんか型の位置が慣れない。ちょっと戸惑う。それでコンストラクタには…stageてなんじゃあ。いきなり出てこられてもなぁ。このあたりは知らないからスルーで。

あとはメソッドとイベントだね。よし、なんとなくルールは分かった気になってこれから違うものを作る。


簡易Flash音楽プレイヤー

JSで読み込みと再生を制御できれば問題ない。objectタグやembedタグはブラウザや環境によって微妙だったので、じゃあFlashしかないかなと既存のものを探したら、無いのでもう自分で作ることに。

機能整理。

  • 見た目は再生ボタンだけ
    • 画像じゃなくてもASだけできそう
    • 再生中のバーはできそうだったらつける
  • 読み込みと再生をJSで制御
    • これ必須
  • ボタンの再生と停止のイベントはもちろん

終わり。できそうだね。よーしやろう。はっはっはーとりあえずどのクラス使えば良いのかわからん!できん!挫折だ!人生初の挫折!エリート街道3丁目の住人のこのわたしがあああ。ええいめんどくさいがちょっとリファレンスみてくる。みてきた。わけわかめ。とりあえずこれだけで。細かいクラスはわからんのでワイルドカード。textは念のため。

package{
  import flash.display.*;
  import flash.media.*;
  import flash.events.*;
  import flash.text.*;

  public class Mp3 extends Sprite {
  
  }
}

これからメンバ変数定義していく。あ、その前にサイズを調整したい。setSizeみたいなのあるかな。みてくるみてきた。http://actionscript.g.hatena.ne.jp/d4-1977/20080812/1218565872

package{
  import flash.display.*;
  import flash.media.*;
  import flash.events.*;
  import flash.text.*;

  [SWF(width="200", height="50")]
  
  public class Mp3 extends Sprite {
  
  }
}

こんな感じ?


次にメンバ変数。containerみたいなのあるかな?あとパネルとかボタンとか。わからん見てくる。みてきた。パネルはいらんそう?コンストラクタ部分に子のパネル?というかスプライトが作れるみたい。

package{
  import flash.display.*;
  import flash.media.*;
  import flash.events.*;
  import flash.text.*;

  [SWF(width="200", height="50")]

  public class Mp3 extends Sprite {
    private var btn:SimpleButton;
    private var btnText:TextField;
    private var sound:Sound;
    private var soundCannel:SoundChannel;

    public function Mp3() {

    }
  }
}

とりあえずこれだけ。次にボタン配置したいんだけど。そこにイベントも組み込みたいが。うーん、ちょっと調べてくる調べてきた。っていうかそれっぽい参考になりそうなのが。

http://hkpr.info/flash/game/sample.php


どうやらSpriteでボタンを実装すればいいらしい。buttonオブジェクトがあるわけじゃないんだね。とりあえず真似しよう。


四角なボタンができました。それにしてもメソッドの「:Sprite」って何だろ?これないとダメらしい。(後から気づいたけどどうも返り値の型かなと。voidだとreturnがなくてもいいってことじゃない?)

package{
  import flash.display.*;
  import flash.media.*;
  import flash.events.*;
  import flash.text.*;

  [SWF(width="200", height="50")]

  public class Mp3 extends Sprite {
    private var btn:SimpleButton;
    private var btnText:TextField;
    private var sound:Sound;
    private var soundCannel:SoundChannel;

    public function Mp3() {
      btn = new SimpleButton();
      btn.upState = Makebtn(0xDDDDDD, 45, 45, 1);
      btn.x = 5;
      btn.y = 2.5;
      addChild(btn);
    }

    //引数: 色、幅、高さ、丸み
    private function Makebtn(color:uint, width:int, height:int, round:int):Sprite {
      var btnBoard:Sprite = new Sprite();
      btnBoard.graphics.lineStyle(3);
      btnBoard.graphics.beginFill(color);
      btnBoard.graphics.drawRoundRect(0, 0, width, height, round);
      btnBoard.alpha = 0.2;
      return btnBoard;
    }
  }
}

テキストはいらなさそうだからはずして、全部こっちで実装しよう。再生と停止は横▲のやつと、■を作れば良い。ここからボタンをクリックしたら横▲と■に切り替わるようにする。横▲はデフォルトでいいかな。あとは■を作るメソッド。


まずは。横▲ってどうやって作れば良いのか…。図形描写嫌いなんだよなぁ。探してくる探してきた。グラフィックスのメソッド。http://livedocs.adobe.com/flash/9.0_jp/ActionScriptLangRefV3/flash/display/Graphics.html


あれ?なんか頂点の数決めて描写できるやつないのか。じゃあこのlineToとmoveToってのを使ってやってみる。あと色は、0x000000ってのは16進数。じゃあ適当に変えてみる。

package {
  import flash.display.*;
  import flash.media.*;
  import flash.events.*;

  [SWF(width="150", height="50")]
  
  public class Mp3 extends Sprite {
    private var btn:SimpleButton;
    private var sound:Sound;
    private var soundCannel:SoundChannel;

    public function Mp3() {
      btn = new SimpleButton();
      btn.upState = makebtn(0xFF3399, 45, 45, 1);
      btn.x = 5;
      btn.y = 2.5;
      addChild(btn);
    }

    //引数: 色、幅、高さ、丸み
    private function makebtn(color:uint, width:int, height:int, round:int):Sprite {
      var btnBoard:Sprite = new Sprite();
      btnBoard.graphics.lineStyle(3);
      btnBoard.graphics.beginFill(color);
      btnBoard.graphics.drawRoundRect(0, 0, width, height, round);
      btnBoard.graphics.endFill();
      btnBoard.addChild(MakeTriangle());
      return btnBoard;
    }

    //横▲
    private function MakeTriangle():Sprite {
      var tri:Sprite = new Sprite();
      tri.graphics.lineStyle(1, 0x000000);
      tri.graphics.beginFill(0x000000);
      tri.graphics.moveTo(10, 5);
      tri.graphics.lineTo(40, 22.5);
      tri.graphics.lineTo(10, 40);
      tri.graphics.lineTo(10, 5);
      tri.graphics.endFill();
      return tri;
    }
  }
}

よーしうまくいったよー!ここでalphaチャンネルやめたのと、色を適当に変更。きれいに黒とピンクのボタンができました。今度はクリックしたら音楽がとまり、■の形になるようにしたい。音楽はおいといて、■ですね。それから、このままのコードだと▲と四角を切り替えるタイミングがだめなので変更。

package {
  import flash.display.*;
  import flash.media.*;
  import flash.events.*;

  [SWF(width="150", height="50")]

  public class Mp3 extends Sprite {
    private var btn:SimpleButton;
    private var sound:Sound;
    private var soundCannel:SoundChannel;

    public function Mp3() {
      btn = new SimpleButton();
      btn.upState = makeBase(/* make:Triangle or Square*/);
      btn.x = 5;
      btn.y = 2.5;
      addChild(btn);
    }

    //btnBase, param:makeTriangle(color) or makeSquare(color)
    private function makeBase(shape:Sprite):Sprite {
      var btnBoard:Sprite = new Sprite();
      btnBoard.graphics.lineStyle(3);
      btnBoard.graphics.beginFill(0xFF3399);
      btnBoard.graphics.drawRoundRect(0, 0, 45, 45, 1);
      btnBoard.graphics.endFill();
      btnBoard.addChild(shape);
      return btnBoard;
    }

    //▲
    private function makeTriangle(color:uint):Sprite {
      var tri:Sprite = new Sprite();
      tri.graphics.lineStyle(1, color);
      tri.graphics.beginFill(color);
      tri.graphics.moveTo(7.5, 5);
      tri.graphics.lineTo(39, 22.5);
      tri.graphics.lineTo(7.5, 40);
      tri.graphics.lineTo(7.5, 5);
      tri.graphics.endFill();
      return tri;
    }

    //■
    private function makeSquare(color:uint):Sprite {
      var square:Sprite = new Sprite();
      square.graphics.lineStyle(1, color);
      square.graphics.beginFill(color);
      square.graphics.drawRoundRect(7.5, 7.5, 30, 30, 1);
      square.graphics.endFill();
      return square;
    }
  }
}

makeBaseメソッドで▲と■の2つを生成できるようになりました。まあ、入れ替える方法の方がいいとは思うのですが、今のところわからないので。

さて、今度はクリックしたら画像が切り替わるイベントなどもろもろ。ちょっとイベント入れるのでかなりコード変わりますね。それからオンマウスしたらちょっと画像変わるようにも。んー、でもクリックしたら、の判定をどうすればいいのかなあ?ちょっと調べてくる調べてきた。http://livedocs.adobe.com/flash/9.0_jp/ActionScriptLangRefV3/flash/events/MouseEvent.html

こいつやな。

package {
  import flash.display.*;
  import flash.media.*;
  import flash.events.*;

  [SWF(width="150", height="50")]

  public class Mp3 extends Sprite {
    private var btn:SimpleButton;
    private var sound:Sound;
    private var soundCannel:SoundChannel;

    public function Mp3() {
      btn = new SimpleButton();
      btn.upState = makeBase(makeTriangle(0x000000));
      btn.overState = makeBase(makeTriangle(0xffffff));
      btn.hitTestState = btn.upState;
      btn.addEventListener(MouseEvent.MOUSE_DOWN, btnDown);
      btn.x = 5;
      btn.y = 2.5;
      addChild(btn);
    }

    //click event
    private function btnDown(event:MouseEvent):void {
      if (change == false) {
        btn.upState = makeBase(makeSquare(0x000000));
        btn.overState = makeBase(makeSquare(0xffffff));
        change = true;
      } else if (change == true) {
        btn.upState = makeBase(makeTriangle(0x000000));
        btn.overState = makeBase(makeTriangle(0xffffff));
        change = false;
      }
    }

    //btnBase, param:makeTriangle(color) or makeSquare(color)
    private function makeBase(shape:Sprite):Sprite {
      var btnBoard:Sprite = new Sprite();
      btnBoard.graphics.lineStyle(3);
      btnBoard.graphics.beginFill(0xFF3399);
      btnBoard.graphics.drawRoundRect(0, 0, 45, 45, 1);
      btnBoard.graphics.endFill();
      btnBoard.addChild(shape);
      return btnBoard;
    }

    //▲
    private function makeTriangle(color:uint):Sprite {
      var tri:Sprite = new Sprite();
      tri.graphics.lineStyle(1, color);
      tri.graphics.beginFill(color);
      tri.graphics.moveTo(7.5, 5);
      tri.graphics.lineTo(39, 22.5);
      tri.graphics.lineTo(7.5, 40);
      tri.graphics.lineTo(7.5, 5);
      tri.graphics.endFill();
      return tri;
    }

    //■
    private function makeSquare(color:uint):Sprite {
      var square:Sprite = new Sprite();
      square.graphics.lineStyle(1, color);
      square.graphics.beginFill(color);
      square.graphics.drawRoundRect(7.5, 7.5, 30, 30, 1);
      square.graphics.endFill();
      return square;
    }
  }
}

詰まったここ。simpleButtonはupStateやoverStateプロパティを使用するときhitTestStateプロパティを設定しないとsimpleButtonは非アクティブになるらしい。それからイベントの切り替えに関してはboolean値で切り替えた。falseなら、trueならで。


あとは音楽を鳴らす、鳴らさないのイベントで一応の出来上がりー。こっから局所的にのっけます。

import flash.net.URLRequest;

private	var urlRequest:URLRequest;

public function Mp3() {
  btn = new SimpleButton();
  btn.upState = makeBase(makeTriangle(0x000000));
  btn.overState = makeBase(makeTriangle(0xffffff));
  btn.hitTestState = btn.upState;
  btn.addEventListener(MouseEvent.MOUSE_DOWN, btnDown);
  btn.x = 5;
  btn.y = 2.5;
  addChild(btn);

  urlRequest = new URLRequest("http://www.muzie.co.jp/download/266328/songs417/oriental.mp3");
  sound = new Sound(urlRequest);
}

おもいっきりパクってますが。どうやらimportに関してはFlashdevelopは自動で挿入されるみたいですね。便利。とりあえずこれでボタンを押せば音楽は鳴るようになりました。

でもこのままでは停止ボタンを押すとまた最初からの再生となってしまうみたいなので、停止した時間帯を記憶できるように。というわけで調べてきた。これは簡単。

private var soundPosition:Number = 0;

private function btnDown(event:MouseEvent):void {
  if (change == false) {
    btn.upState = makeBase(makeSquare(0x000000));
    btn.overState = makeBase(makeSquare(0xffffff));
    change = true;
    soundChannel = sound.play(soundPosition);
   } else if (change == true) {
     btn.upState = makeBase(makeTriangle(0x000000));
     btn.overState = makeBase(makeTriangle(0xffffff));
     change = false;
     soundPosition = soundChannel.position;
     soundChannel.stop();
   }
}

とりあえずこれで終わっても問題ないのだが。なんとかなりそうなので、秒数のバーもつけてみるか。つける。んーどうしよう。とりあえず秒数を取得して、それを一定の長さのバーに割り当てる感じでいこう。

とりあえずバーを作る。

private var basePlayBar:Sprite;

public function Mp3() {
・
・
basePlayBar = makeBasePlayBar();
addChild(basePlayBar);
・
・
}

private function makeBasePlayBar():Sprite {
  var bar:Sprite = new Sprite();
  bar.graphics.lineStyle(1, 0x000000);
  bar.graphics.moveTo(55, 22.5);
  bar.graphics.lineTo(145, 22.5);
  return bar;
}

おけおけ。できた。これがベースで、読み込みの色は適当に色つけて秒数を示すバーは丸か何かにすると。だから、今度は読み込みに合わせて伸縮するバーをこのベースバーにかぶせたい。それからとりあえず秒数を取得たいのだが。わからん。詰まった。1時間。

うおおおどこじゃああああ!というわけで発見。http://itpro.nikkeibp.co.jp/article/COLUMN/20080926/315524/?ST=webdesign&P=3やっぱりlengthで良いのか。これは迷いすぎた。なんとか分かったぞ。それから読み込み時間に関してはprogressイベントを使えば良いらしい。

つまり、progressイベントで読み込みのバーを表示させ、lengthにて経過時間を取得し、poitisionプロパティでなんやかんやすると。かなり適当な文章(汗

2日後。えーと、作り始めたのが8日の夜でした。昨日つーのは、7日のことかな?たぶん。もうどうでもいいけど。


なんやかんやしてほぼ完成版を。いろいろ変わってます。というかスパゲッティーな具合なのでもうわからん。何で動いているのか80%ぐらいしかわからん。メソッド名もプロパティ名も適当だ。私がみてもわからん。

詰まったのはremoveEventListener(Event.ENTER_FRAME, makePlayBar);が抜けていたがために、2日ほど無駄にした。ほぼここに時間とられた。とりあえず動くということで。

180行ぐらいあるのでこっちにのっけさせてもらいました。

http://wonderfl.net/code/24b84a3061ef8868403dd2b3501eda3ec9deccc4


CPUめっちゃ食ってたので、バーの120〜136行付近のとこにgraphics.clear()いれたら軽くなった。応急処置だけどもういいや。こういうことがあるんですね。むつかし。

当初の目的と大きく外れたのでもういいや。たぶん簡単にできる。ああ、できるかな(汗

とりあえず疲れた。


AS3の感想

  • FlashDevelopがあれば手探りでなんとかやれそう
    • 補完はかなり助かる
  • リファレンス最強。
  • Flasherは何気に気を使うことが多くて大変だなと思った
    • メモリ、CPUなどなど。めんどくさい
  • JSと似ているかどうか
    • よく似ているとはいわれますが。似ているけど特別そう近いとも思わなかった。今回限りではJavaの方が近い印象はうけた
    • JSやってたからできるかといわれると、うーん。他の型の強い言語触ってると大丈夫そう。
  • 文法について
    • 型が変数の後ろってのが慣れない
    • プロパティやメソッドのアクセスはJS方式で大丈夫そう
    • thisキーワードは適当につかってるけど、JSと同じなのかな?ちょっとわからない
      • 確認したらつかってなかった。いろいろ修正したのよ
    • 演算子は一通り使った気がするけど、特にひっかからなかったかな
  • 眠たさについて
    • かなり眠い


ちょっとASの本を買いたくなってしまった。面白い。