※このページの内容は、何故かうまくいかないは禁止。うまくいかない理由を推測して解決しようと考える人が対象
ちょっと詳しくAS

 
ちょっと難しいこと
パスと変数について
functionについて
デバッガを使う
CGIにアクセス
外部ファイルの読み込み
特殊な計算
TextFieldオブジェクト
dateオブジェクト
XML リスナー
知らないとはまる罠
テクニック、知識
AS小ネタ

   
ちょっと難しいこと
 
パスと変数について
 
functionについてあれこれ
 
デバッガを使う
 
CGIにアクセス
 
外部ファイルの読み込み
 
特殊な計算
 
TextFieldオブジェクト
 
dateオブジェクト
 
XML
 
リスナー
 
知らないとはまる罠
 
テクニック、知識
 
AS小ネタ
 
ちょっと難しいこと
   
Flashサイトを作りたいのですが…>>作るな(理由)
  • ASを学ぶなりして勝手にどうぞ
    on(Press)
    getUrl("対象URL","ターゲット(_blankとかフレーム名のmainなど)");
    MC.gotoAndPlay();
    MC.gotoAndStop();
    あたりが理解できれば作れるんじゃないの?

  • Flashサイト(Flashインターフェイス、フルFlashサイト)が嫌われる理由
    • ローディングが長くてストレスがたまる
    • 動作が重くてストレスがたまる
    • カーソルを合わせるたびに何か出て、ストレスがたまる
    • クリックする場所がわからなくてストレスがたまる
    • クリックできる場所が小さくてストレスがたまる
    • ページ移動にアニメやフェードアウトが入ってストレスがたまる
    • ブラウザの戻るボタン押すと、トップページまでいきなり戻ってストレスがたまる

    • Flashサイト制作者の問題
      • 内容がないから、外見でごまかそうとする
      • Flashでサイトを作ることが目的になっている。実験として(見せなければ、リンクを貼らなければ問題は無い)
      • 更新に手間がかかり、途中で飽きて放置する
      • 制作者の自己満足。見る人のことを考えていない

  • Flashサイトの欠点
    • 訪問者の環境によっては、サイトが見られないことがある
      閲覧者のPC性能が低くて動作が重く見づらい、回線が低速でロードに時間がかかるといった理由で途中で見るのをやめてしまう
      Flashを見ない設定にしている人、Flashが見られないブラウザ(携帯端末でアクセスなど)を使っている人は、サイト自体を見られない

    • 動作が重たい。ファイルサイズも大きくなる
      フォントを埋め込むと、とりわけサイズが大きくなる
      フォントの埋め込みをしないと、文字のサイズの違いからデザインが崩れることがある

    • 検索にかからない
      webで少しでも情報を提供するサイトであるならばFlashで作ってはいけない
      また、音声によって閲覧している視覚障害者のような人を切り捨てることになる

    • ページにブックマークができない
      戻るボタンで前のページに強制的に戻されてしまう
      (JavaScriptで新規ウィンドウを開いて表示するような工夫が必要)
      (ただし、JavaScriptを許可していない、使えないブラウザのユーザーは見ることができなくなる)
      FlashMXから名前付きアンカーとJavaScriptで、擬似的にページに飛ばせるようになった。ただし、対応しているブラウザのみ

    • 更新に手間がかかる。製作の途中で飽きて、放棄されるものが多い
      Flashサイトを作る労力で、コンテンツとしての価値があるFlashムービーを、ひとつかふたつ作れたんじゃないのかと

    • HTMLでできるリンクをFlashでわざわざする必要はない
      見た目の良いサイト、ムービーの提供以外では、ゲーム、スクロールや拡大のできる地図、ホテルや飛行機の予約(日にちと空きが一目で分かる)、アクティブなグラフの作成など、Flashだからできることをするべき。Flashを使う必要があることに使うべき。
      Flashに関する本を書いている人の多くが、HTMLでサイトを構築していて、バナー程度の目的でしかFlashを利用していない
      Flashサイトを作ることが、Webページの表現としては、あまり利益にならないことを、Flash制作者のトップが良く理解している。

  • Flashサイト作りの工夫
    • HTMLとFlashの両方の入り口を作る
      最初に来た人はFlashのサイトを見てくれる可能性があるが、二度目以降はほとんどの人がHTMLを選択する
      FlashとHTMLの両方を更新するため、手間がかかる

    • Flashとは別に、HTMLのメニューをフレームで用意しておく
      各ページそれぞれをFlashで作る

    • 更新しやすいように、外部読み込みテキストを使ったり、CGIと連動させて、製作する
      更新のたびにいちいちパブリッシュしてたのでは、手間がかかり、途中で投げ出しがち。

    • メニューなどのレイアウトに余裕を持たせる
      画面の幅を全て使った、きつきつのメニューでは、サイトの拡張が難しくなる
      新コンテンツ追加をする時に、場合によってはメニュー画面を作り直さなければならないことがある。
      またサイトの構造が複雑になり、管理が大変になる

      なんにせよ、HTMLだけで作ってコンテンツそのものに力を注ぐ、日記だけならばblogを利用するなど、Flashサイトにしないほうが賢い選択

  • FlashのWebでの利用方法(Flashサイトの妥協案
    • 見栄えのいいバナーとして利用する
      • トップページに使うのであれば、HTMLでスキップできるようにしておく。
      • 負荷のかかる表現は避け、ページのスクロールが遅くなったりするのを防ぐ。
      • 50kb程度にサイズを抑え、すぐに読み込みが終わるようにする。

    • サイトのナビゲーション(メニュー)としてFlashを利用する
      それでも、Flashが見れない環境の人は、サイトのナビゲーションが表示されないので、実質、サイトの内容が見られなくなる。
      参考:Flashの表示できないブラウザ、設定に対して代替イメージを提供する

    • サイトそのものをFlash作品にする
      クリックして先に進んでムービーを見ることを目的にした、サイトを探検するゲームのような要素を持たせる

  • まとめ
    ダメなFlashサイトが増殖すればするほど、Flashサイトというだけで嫌悪する人が増えるので、適当な気分で作らない。
    作るならば、5年前くらいの低スペックPCで、低速回線で、自分のサイトを見て、ちゃんとテストをするような努力をする。

    Flashムービーやゲームの提供、内容の面白さ、価値のある情報で、コンテンツの内容でしっかりと勝負する。

    Flashだから出来ることか、Flashを使う意味があるかをよく考えて作る。

    更新を快適にできる設計にしておき、途中まで作ったけど飽きたので放置、のようなことがないようにする。
    飽きるのはしょうがないが、生き恥を晒さずにちゃんと消す。飽きるような作り方をしたことを反省する。

    苦労してFlashサイトを作っても割りに合わないことが多い。
    それでも作りたければ、覚悟をしてしっかり作るように。

 
 
newがよく分からない/setRGBとか、Soundを使いたい
  • 基本
    newというのは、オブジェクトの生成

    myColor = new Color(_root.hoge);
    myColor.setRgb(0xFF0055);

    mySound = new Sound();
    mySound.attachSound("bgm1");
    mySound.setVolume(80);
    mySound.start();

    myArray = new Array();
    myArray[0] = "test";

    こんな感じで使う。

    なぜ、オブジェクトの生成をしなければならないのかというと、
    そういう決まりだから。慣れるしかない。

    青色の文字の部分が、新たに生成したオブジェクトの名前。
    これらは、色なら、色。音なら音のことをやってくれる。

  • 例えるなら
    sound()という音の専門家の控え室があって、
    mySoundさん、という(名前をつけた)専門家を、Sound();という部屋から呼び出しているのが、
    mySound = new Sound();
    という一文。
    あとは、mySoundさんは音の専門家なので、
    mySound.attachSound("bgm1");
    とやれば、mySoundさん、bgm1を用意してくれとなるし、
    mySound.setVolume(80);
    と書けば、mySoundさん、ボリューム80に落としてくださいというお願いになる。 ただし、mySoundさんは、音のこと以外は興味がないので他のことは一切できないし、
    画面に出てきたりはしない。あくまで裏方で一つの音の制御だけをする。

  • newで呼び出す(オブジェクトを作成する)理由
    本当は、全ての変数などは、オブジェクトとして生成して定義しなければならない。
    ただ、FlashのASの場合は自動的にやってくれるので、省略できていた。

    flag = true;
    countNumber = 0;

    というような場合、他の多くのプログラム言語では

    flag = new Boolean(true);
    countNumber = new Number(0);

    と書かなければならないところを自動的に省略してくれている。

    colorやsoundも初めから、省略してくれればいいのにと思うかもしれないが、
    そうすると、color1からcolor100までしか用意してもらえずに、
    100以上使いたいときに、困ったことになったり、
    または、色を変えたり、音の大きさを調整する命令(メソッド)を
    全てのオブジェクトが持つことになり、
    色を変えたり、音を調整する必要が無いものまで、
    いちいち、色の状態やら、音の大きさのデータを持つことになって、動作が重くなる。

    必要になったときに名前をつけて用意して、それぞれのことを専用に、その名前で呼び出して使うということ。

 
thisって省略していいの?
  • 省略していても、大抵は問題がない。
    thisをちゃんとつけておけば、非常に低い確率で遭遇する、thisがないから動かなかったという事故で悩まなくて済むかもしれない。
    最初は常につけておいて、thisが何を指しているのか、なぜ省略できるのかがよく分かってきたら取るようにしたほうがいい。

  • thisを削除したり、追加すると、問題がある場合
    • AS4.0と混同される
      • play()やstop()なども、thisをつけていないと、AS4.0の用法で使われる。
        ただし、効果が全く同じなので、thisがなくても問題がなかっただけ。

      • gotoAndPlay()とgotoAndStop()でラベル指定をするとき
        thisを付け忘れると、gotoAndPlay("シーン","ラベル")として扱われて、エラーが出る

      • startDrag()を使うとき
        thisをつけていないと、startDrag(対象)の古い書き方を要求するエラーが出る。
        おまけで対になるstopDrag()も、thisがないと気持ち悪いからthisをつけておくべき。

    • MC.onClipEvent = function()などの、イベントハンドラで記述している場合。
      _root上に記述した場合、

      mc.onPress = function(){
      this.stop();
      }

      この場合は、mcのタイムラインが止まる
      大抵の場合、thisを省略していない、こっちが正常な動作を行う。

      thisを省略した場合

      mc.onPress = function(){
      stop();
      }

      thisを省略すると、_root.stop();という意味になり、_rootのタイムラインが止まる

      _root上のmc.イベントハンドラ内に、this.hoge = 0;と書けば、_root.mc.hoge = 0;になる。
      hoge = 0;とthisを省略して書くと、_root.hoge = 0;という意味になる。
      イベントハンドラメソッドの内部では、thisは省略してはいけない。
      イベントハンドラは、匿名関数と呼ばれる。その実験
      this._name>>mcの名前
      _name>>何も表示されない

    • function内でローカル変数を使っているとき
      とりあえず、実験から。
      _root上に記述。

      function hoge(a){
      trace(this.a);
      }
      hoge("ローカル変数の値");

      実行してみると
      undefinedが表示される。
      この場合の、this.aは、function外の_root.aを指定している。
      ローカル変数にアクセスしたければ、trace(a)と書かなければならない。

      ローカル変数には、thisをつけてはいけない。

    • with(){}を使うとき
      withは同じパスを何度も書く場合に、見やすくなるのだが、thisを使うと、そのASが書かれている場所を指定してしまう。
      例えば、_rootに書かれたASが以下のような場合、

      with(_root.oya.ko.mago){
      _rotation += 30;
      _xscale += 10;
      _yscale += 10;
      }

      thisは、ASの書かれている_rootを指定していて、
      this._rotation += 30;と書くと、
      _root._rotatiton += 30;という意味になってしまう。
      この場合は、対象のMCではなく、画面全体に効果が出てしまう。
      withの中では、thisは使わないように
      そもそも、無理に長いパスを使って、外のオブジェクトを勝手に操作することが問題であり、そのMCの中にfunctionとして定義しておけば済むことなので、withは基本的に不要という考え方もある。

    • _gloabalで同名の変数を定義しているとき
      直接問題が発生するわけではないが、thisと_globalをつけて、明確に区別して変数を扱えばミスが減る。
 
undefinedとnullの違いは?
  • 動作はほぼ同じ。
    何も実行されていない、未定義のものは、undefinedとして、
    一度使い、必要がなくなったものは、からっぽという意味でnullを代入するように、Macromeidaは推奨している。
 
this.onEnterFrameやthis.onPressって、
onClipEvent(enterFrame)や、on(Press)とどう違うの?
  • this.onEnterFrameは、イベントハンドラメソッド
    主に、タイムラインに書く
    MX以降の書式。

  • onClipEvent()やon()は、ボタン/クリップ(シンボル)アクション
    MCやボタンを選択して書く

    ムービークリップにクリップアクションとして書いてある、フレーム毎に回転をするAS

    onClipEvent(enterFrame){
    this._rotation += 5;
    };

    を、MCという名前をつけて、
    以下のように、タイムラインに書くことで代用できる。

    MC.onEnterFrame = function(){
    this._rotation += 5;
    }

    意味は同じ。
    ・この場合のthisは、MC自体を指している。
    ・このfucntionは名前を持たないために、匿名関数という

    使い方、使う理由
    ムービークリップの中のタイムラインに、

    this.onEnterFrame = function(){
    this._rotation += 5;
    }

    と書けば、MCを複製するだけで、全てのMCを回転させることができる。
    いちいち、全ての複製したMCに、onClipEvent〜を書くよりは簡単

    ボタンのASを、ボタン名.onPressのように、タイムラインまとめて書くことができるので、見やすくなる。
    タイムラインにまとめて書いておけば、MCをクリックして、どこに何が書いてあったかな?と探さなくていいので、分かりやすい。

    必要に応じて、動作を後から追加、変更、削除できる。
    例えば、アラートが出ているときに背景のボタン操作をして欲しくない場合に、一時的にボタンの機能を使えなくするなど
    タイムラインのASが長くなったり、ボタンに名前をつけたりする必要があるので、無理に使う必要は無い。
    ただし、こういう書き方があり、使い分けることで、より見やすい、デバッグしやすいコーディングができるということだけは覚えておくこと

     参考:ASを書く場所


 
 
パスと変数について
 
パスについて少し詳しく
     
  • 準備
    まず以下のような構造のMCがあるとする。
    • _root(gikoを左右に動かしている)
      • giko(中にギコが踊っている画像。sippoも入っている)
        • sippo(シッポを左右に振っている画像)
    それぞれのMCは別のアニメーションをしている
    _rootのタイムラインで、左右に移動していて、
    gikoのタイムラインで、踊っていて、
    sippoのタイムラインでシッポが左右に動いている

    それぞれの実験は、準備の状態から始めて、それぞれ独立して行う
    (前に書いたASは、次のテストには残さないということ)

  • _rootについて
    メインのタイムライン(_root)上で、
    this.stop();とすると、_rootのタイムラインが止まる。
    • _root(停止)
      • giko(中にギコが踊っている画像。sippoも入っている)
        • sippo(シッポを左右に振っている画像)
    _rootで行っている、gikoの左右の移動が止まる。
    (中のMCは関係なく動いている)

    this.stop();を、_root.stop();と書き変えても効果は同じ。

    _root上では、thisも_rootも一緒。
    _rootのthisは、_root。当たり前。

    gikoや、sippoの中で、_rootのタイムラインを止めるときは、
    _root.stop();と書かなければならない。(理由は後述)

  • gikoとsippoを止める
    _root上で、
    gikoやsippoを止めるには、以下のように書く
    _root.giko.stop();
    • _root(gikoを左右に動かしている)
      • giko(停止)
        • sippo(シッポを左右に振っている画像)
    _root.giko.sippo.stop();
    • _root(gikoを左右に動かしている)
      • giko(中にギコが踊っている画像。sippoも入っている)
        • sippo(停止)

    とにかくパスがよく分からず、なぜ、うまく動かせないのか分からないときは、フルパス(_rootで始まるパス)で書いてみるとうまくいく
     
  • this
    そのMCのある場所のこと。

    gikoというMCの中での、thisは、_root.giko
    sippoというMCの中での、thisは、_root.giko.sippo

    それぞれのタイムイラインの中でtrace(this);してみると、よく分かる
    _level0は、_rootと同じような意味

    • _root(gikoを左右に動かしている)
      • giko(中にギコが踊っている画像。sippoも入っている)
        trace(this);>>_level0.giko
        • sippo(シッポを左右に振っている画像)
          trace(this);>>_level0.giko.sippo

    gikoの中のタイムラインで、this.stop();すると、gikoが停止する

    • _root(gikoを左右に動かしている)
      • giko(停止)
        this.stop();
        • sippo(シッポを左右に振っている画像)
    踊っているgikoが止まる。

    sippoの中のタイムラインで、this.stop();すると、sippoが停止する

    • _root(gikoを左右に動かしている)
      • giko(中にギコが踊っている画像。sippoも入っている)
        • sippo(停止)
          this.stop();
    振っているシッポが止まる。

    _root.giko.stop();
    _root.giko.sippo.stop();
    で、それぞれ、同じことができる。

     

  • _parent
    一つ上の階層。
    gikoの中で、_parent.stop();すれば、_rootの再生が止まる
    • _root(停止)
      • giko(中にギコが踊っている画像。sippoも入っている)
        _parent.stop();
        • sippo(シッポを左右に振っている画像)
    _rootのgikoの左右移動が止まる。

    sippoの中で、_parent.stop();すれば、gikoの再生が止まる

    • _root(gikoを左右に動かしている)
      • giko(停止)
        • sippo(シッポを左右に振っている画像)
          _parent.stop();

    ちなみに、sippoの中で、_rootを止めるには、_parent._parent.stop();となる。

    • _root(停止)
      • giko(中にギコが踊っている画像。sippoも入っている)
        • sippo(シッポを左右に振っている画像)
          _parent._parent.stop();

    実際に_parentを使うのは、loadMoiveなどを使って読み込まれていて_rootからのフルパスで階層を指定することが出来ない場合や、duplicateMoviclipで増殖したときに親に指令を出すときなどである。正直、最初はよく分からなくてもいい

 
パスについて2
     
  • テキストエリアのパス
    • _root(無名のテキストエリアがある)
      • 無名のテキストエリア
        (ダイナミックテキストになっていて、
        変数名が、messageとなっている)
    _root.message = "ダイナミックテキストを出力しました";
    これだけ。messageに代入する値を変えれば、表示する内容も変わる。
    要するに、微妙に別のMCのようにも見えるが、ボタンと同様で、
    テキストフィールドの置いてあるMCの変数として利用すればいいというだけのこと

    TextFieldオブジェクトでアクセスする

    • _root(dtxtNameというインスタンス名のテキストフィールド)
      • dtxtName
        (名前だけつける。変数名は書かなくてもよい)
    _root上で、
    this.dtxtName.text = "textプロパティを使って表示してみる"


     
  • MCと変数のパス
    • _root上のタイムラインで、変数「hoge」を定義。アクセス
      • _root
        hoge = 0;
        • oya
          • ko
      _rootのMC(タイムライン)中でのみ、hogeという変数を使える。
      _rootの上での、this.hogeは、_root.hogeになる。
      意味は一緒

      oyaやkoは、hogeという変数を持っていないので、
      oyaやkoのMC中でtrace(hoge)をしても、undefinedしか返ってこない。
      oyaやkoで、_rootのhogeを使いたければ、_root.hogeと書く必要がある。
      または、下記のように_parentでアクセスする。

    • _root.hogeに_parentでアクセスする方法
      • _root
        hoge = 0;
        • oya
          trace(_parent.hoge);
          • ko
      oyaにとっては一つ上なので、_parent.hoge。

      • _root
        hoge = 0;
        • oya
          • ko
            trace(_parent._parent.hoge);
      koにとっては、二つ上なので、_parent._parent.hoge。

    • oyaに「hoge」を定義した場合。
      • _root
        • oya
          hoge = 0;
          • ko
      oyaのhogeなので、oyaのMC中でのみ、hogeが利用できる。
      また、oyaのMC中でのみ、this.hogeとしてアクセスできる。

      この場合は、_rootやkoは「hoge」を持っていない。
      _rootとkoで、trace(hoge)すると、undefinedが返ってくる。

      _root上で、oyaの「hoge」にアクセスするには、oya.hoge。

      • _root
        trace(oya.hoge);
        • oya
          hoge = 0;
          • ko
      また_rootならば、this.oya.hogeでもアクセスできる。
      _rootにとってのthisは、_rootである。

      フルパスである、_root.oya.hogeを使えば、どこからでもアクセスできる。

      koからアクセスするには、一つ上なので_parent.hogeになる。

    • koにhogeを定義した場合
      • _root
        • oya
          • ko
            hoge = 0;
      koのMC中でのみ、this.hoge、hogeが利用できる。
      _rootやoyaは「hoge」を持っていない。

      とりあえず、フルパスである、_root.oya.ko.hogeならばどこからでもアクセスできる。

      _rootにとってのko.hoge

      • _root
        trace( oya.ko.hoge );
        • oya
          • ko
            hoge = 0;
      _rootからアクセスするには、oya.ko.hoge、または、_root.oya.ko.hoge、this.oya.ko.hoge。

      oyaにとってのko.hoge。

      • _root
        • oya
          trace( ko.hoge );
          • ko
            hoge = 0;
      oyaからアクセスするには、ko.hoge。
      this.ko.hogeでもよい。

      フルパスである_root.oya.ko.hogeでもよい。
      ただし、この場合のthisは、_root.oyaになっている。

     

  • クリップアクションの変数のパス
    • _root
      • onClipEvent(load){
        hoge = 0;
        }

        giko
    gikoのhogeにアクセスするには、_root.giko.hoge。
    また、giko内のタイムラインのthis.hogeと同じ変数。

    • _root
      • giko
        this.hoge = 0;

     参考:知らないとはまる罠


 
変数のルール
  • 変数などの名前のルール
    • 予約語を使わない
      switchやcolorなど、プログラムに必要な予約語は変数や名前に使わない。
      予約語を使っても正常に動くことがあるが、予期せぬときに何故か動かない問題に遭遇する可能性が高い。
      予約語を入力すると色が変わるので、予約語を入力してしまったら何かに変更する。
      例:×color = 0xFFFFFF;→○playerColor = 0xFFFFFF;
      例:×date = myDate.getDate();→○niti = myDate.getDate();

    • 数字で始まる変数名は使えない
      例:×2ch = url;→○nich = url;

    • 日本語(2byte文字)は使えない
      変数としては使えないのは当然だが、フレームラベルなどにも、使わないようにする。

  • 予約語
    • 5
      break, continue, delete, else, for, function, if, in, new, return, this, typeof, var, void, while, with

    • MX(6)

    • MX2004(7)
 
_globalについて
  • _global
    MX以降から
    グローバルオブジェクトであることを宣言
    _global.hoge = 0;
    のように宣言すれば、hogeという変数を、どこでも使えるようになる。
    そのMCの中で、別にhogeという変数を定義していた場合は、そのMCのhogeが優先される。この場合は、アクセスするのに_globalが必要になる

    また、_global.Neko = new Object();
    と書けば、Nekoというグローバルオブジェクトが作成される。
    MathやKey、Mouseなどのオブジェクトと同様に、いつでも、アクセスできるようになる


 
ボタンのthisについて
  • ボタンのthisは、省略しても、明示しても、ボタンのあるタイムラインを示す。
    • _root(インスタンス名のないボタンが置いてある)
      • インスタンス名のないボタン(にクリップアクションとして記述)
        on( Press) {
        trace( this );
        }
        >>_level0(つまりは_root)が返ってくる。
    何も気にせずに、on(Press){gotoAndPlay(1);}などと書けたのは、そういうボタンの特殊な性質によるものだった。

    なので、自分を押すと自分が回転するボタンを作ろうと、以下のように書いても。

    on( Press) {
    this._rotation += 30;
    }
    thisは_rootであり、ボタンではなく、_rootが回転してしまう。
    実際にやってみるとよく分かるが、画面全体を回すボタンになってしまう。

    ボタンを回転させるには、ボタンに名前を付けて、以下のように書かなければならない。(MX以降)

    • _root(kaitenBtnが置いてある)
      • kaitenBtn(にクリップアクションとして記述)
        on( Press) {
        kaitenBtn._rotation += 30;
        }

 
ボタンの中のthis._parentについて
  • oya.ko.btnという構造のときに、
    btnから、oyaを明確に指定している。

    イベントハンドラメソッドで利用している場合は、
    this._parentと書かないと予定通りの動作が行えない。

    oya.ko.btn.onPress=function(){
    _parent._alpha = 50;
    }

    この場合、ボタンを押すとkoのアルファを50にしたくても、出来ない。
    this._parentと書く必要がある。
 
 
 
functionについてあれこれ
 
functionの使い方/使う理由
  • 一連のスクリプトをまとめて使いやすくする

    function ransu(maxNum){
    var rndNum = Math.random()*maxNum;
    rndNum = Math.floor(rndNum)+1;
    return rndNum;
    }

    answer=ransu(10);
    trace(answer);

    とすると、1から10の整数が得られる。

    この程度ならば、

    rndNum = Math.random()*10;
    answer = Math.floor(rndNum)+1;
    trace(answer);

    で、同じことができるが、数値を変えて何度も使うならば、functionを使った方が便利。

  • メソッドとして利用する

    function hidari(num){
    this._x -= num;
    if(this._x < 0){
    this._x = 0;
    }
    }

    ※MCの中に記述しておく。
    giko.hidari(10);
    のように、動く数値を入れて利用する。
    画面外に出そうになったときの処理は、
    hidari()の中で自分でやらせる。

    例えば、カーソルの左が押されたら、
    giko.hidari(10);
    と書いておき、後は、hidari()にまかせてしまう。

  • メソッドとして利用する利点
    余計なfunctionを作るのは面倒だ、
    カーソルが押されたら、その場で全部やってしまうほうがシンプルでよいと
    最初は考えがちだが、

    実際に製作するようになると、
    gikoはkabeにぶつかると進めない、
    monaにぶつかるとダメージを受ける、
    オプション画面を開いているときは、カーソル入力で移動しないというような
    複雑なルールを設定する必要が出てくる。

    カーソルはカーソルで、
    オプション画面が開いていれば、オプション画面の操作にキー入力を送る。
    開いていなければgikoが移動するように、指令を出す。

    gikoはgikoで、
    移動先を調べる。
    その際も、if(_parent.kabe.butukari(x,y))のように、
    kabe.butukari()に、壁があるかどうかを任せる。

    mona.butukari()で衝突を判定して、ぶつかっていたら、
    giko.damage()でダメージを専門で処理する。

    こうしておくと、何か問題があったときに、
    誰が、どういうメソッドで何をしているかがはっきりしているので、
    問題の個所の修正がしやすくなる。

    monaにぶつかると、ぶつかった演出はあるが、ダメージを受けないのであれば、
    gikoのダメージの処理を行っている部分、giko.damage()内を修正すればいいことがすぐに分かる。

    また、床でダメージを受けたときの処理があれば、giko.damage()に全て任せる。
    勝手に、床がgikoの体力を削って、体力がゼロなら〜のようなことをしていると、
    後でダメージの処理に修正を加えたときに、床とgiko.damage()の二箇所を修正しなければならなくなる。
    こういうことを繰り返していると、後々、どこが問題なのか分からないので総当りで調べることしかできず、デバッグが難しいという問題に突き当たる。

    たとえ、1行の処理でも、全く同じ事をするならば別のfunctionにする。
    そうしておくと、どんなときの修正も一箇所で済むことになる。


 
グローバル変数とローカル変数の話
varをつける理由は?
  • 意味
    グローバルとは、外から見える(アクセスできる)ということ。
    ローカルとは、外から見えないということ。

  • 実験しながら見ていく
    あるMCに、xy座標を送るとそのMCとの距離を返すfunctionを定義する。

    function xyKyori(x,y){
    yoko = Math.abs(this._x - x);//x方向の距離
    tate = Math.abs(this._y - y);//y方向の距離
    answer = Math.sqrt(yoko*yoko + tate*tate);//二乗して平方根(距離)
    return answer;
    }

    yokoとtateという変数をfunction内で使っている。
    もしも、同じMCでyokoとtateという変数を利用していたら、
    xyKyoriを使うと、yokoとtateの値がおかしくなってしまう。

    その実験。

    function xyKyori(x,y){
    yoko = Math.abs(this._x - x);//x方向の距離
    tate = Math.abs(this._y - y);//y方向の距離
    answer = Math.sqrt(yoko*yoko + tate*tate);//二乗して平方根(距離)
    return answer;
    }
     
    yoko = 100;
    tate = 200;//大事なグローバル変数と仮定
     
    test = xyKyori(15,28);//functionを実行
    trace (yoko);
    trace (tate);

    結果は、
    15
    28

    functionで計算が行われると、
    yokoとtateの値が書き換えられてしまう。
    もしも、yokoとtateがfunction外で使っている変数ならば、
    予想外の動作をしてしまい、重大なバグに繋がる。

    ここで、yokoとtateにvarをつけてみる。

    function xyKyori(x,y){
    var yoko = Math.abs(this._x - x);//x方向の距離
    var tate = Math.abs(this._y - y);//y方向の距離
    answer = Math.sqrt(yoko*yoko + tate*tate);//二乗して平方根(距離)
    return answer;
    }
     
    yoko = 100;
    tate = 200;//大事な変数と仮定
     
    test = xyKyori(15,28);//functionを実行
    trace (yoko);
    trace (tate);

    結果は
    100
    200
    こうすると、yokoとtateの値をfunction内で弄っても、
    functionの外の同名の変数は影響を受けない。

    function内の変数に「var」をつけると、ローカル変数になり、
    functionの中だけで使う変数になる。
    また、ローカル変数には、thisをつけてはいけない。


    よく分からなくても、functionの中だけで使い、functionを抜けるといらなくなる変数には、varをつけて定義して、thisはつけないでアクセスすると覚えておけばよい

    ちなみに、xyKyori(x,y)内の、xとy(これを「引数(ひきすう)」という)はローカル変数になっているので、varはつけなくても良い。

  • ローカル変数を利用する理由
    functionを抜けると、ローカル変数は削除され、メモリーの節約ができる。
    変数名が一致しないように、変数を増やしたり、長い名前にしなくて済む。
    グローバル変数で使っている書式と変数名を、そのままfunction内でも使え、見やすい。

 
匿名関数とは?
test = function(){〜}; とfunction test(){〜}の違いは?
  • 匿名関数 test = function(){

    MC.myMcFunc = function () {〜}
    のように、他のMCの関数を定義することができる。
    また、既に定義している関数の再定義もできる。

  • 名前付きの関数 function test(){

    普段はこっちを利用すればよい。

 
this.onEnterFrame = myFunction()が一回しか実行されないのは何故?
  • myFunction()として、()をつけると、関数が実行される
    this.onEnterFrame = myFunction();
    は、返り値が渡るだけなので、一度しか実行されない
    関数myFunction()の実行された結果を、onEnterFrameに代入を、一度だけ行っている。

  • myFunctionとして、()をつけない場合、関数名のみのときは、関数への参照。
    this.onEnterFrame = myFunction;
    は、参照が渡り、毎フレーム実行される。
    onEnterFrameという変数に、myFunctionの参照を代入し、
    それを自動でonEnterFrame() として呼び出して実行してくれる。

    厳密には、functionというのは、Function型というオブジェクト

 
 
デバッガを使う
 
とりあえず使ってみる
  • なんでデバッガを使うのか?難しくて面倒そうじゃない?
    100行以上の複雑なASを書くようになると、どうして思い通りに動かないのかが全く分からないという状態になることがある。
    動作の怪しい変数全てにtraceを書いていってもいいけど、非効率。
    そこで、デバッガを使うことになる

    また、ASが内部でどのように動いているのかが見えるので、使っているだけで自然とMCやパス、プロパティなどについての理解が深まる。
    要するに、デバッガを使えない奴はダメなFlashプログラマー。
    デバッガを使える人はよく訓練されたFlashプログラマーってことだ。

  • デバッガの起動の仕方
    • メニューの「制御」から、「ムービーのデバッグ」
    • または、ショートカットで、「Ctrl+Shift+Enter」

  • 起動後
    デバッガを起動すると、停止した状態で始まるので、続行(緑色の再生ボタン)を押す。
    (ブレークポイントはMX以降の機能)

 
変数のウォッチ
  1. まず、デバッガを起動。再生

  2. MCの構造で、level0から、目的の変数のある場所を探す

  3. 変数タブから、動作が怪しげな変数を探して右クリック。ウォッチ

  4. ウォッチタブを見ながら、ムービーを動かしてみる。

  5. 何か操作をして、変数が予定外の数値を指したらそこが間違い。
    探して修正する。

  6. その変数の動作が問題なければ、別の変数を調べてみる。

 
ブレークポイントの挿入
  • 何かをすると、挙動がおかしい場所がわかっているときに利用

    1. 例えば、あるifが何故か場合によっては動作しないことがある。
      問題の場所は分かっているが、どういうときに問題が起るのか分からない。といったとき

    2. まず、問題の場所で、AS上で右クリックから、「ブレークポイントの挿入」
      これで、この問題の行のASが実行される前にムービーが一度停止するようになる。

    3. デバッガで再生してみて、停止したら、ローカル変数などを見てみる。
      数値のつもりが、文字列が代入されていたなどの問題点が分かる。

    4. 問題がない部分だったら、「続行」を押して次に停止するまで待つ。


  • ブレークポイントは複数設定できる
  • デバッグ実行中に新たにブレークポイントを追加できる
    (ただし、このブレークポイントはデバッグが終了すると消える)
 
細かくステップで実行する
  • 問題のある場所がよく分からないときに利用

    1. なんとなく問題のありそうな付近にブレークポイントを挿入

    2. 停止したら、ステップオーバー、ステップイン、ステップアウトのボタンを使い分けて、一行づつ実行しながら変数の挙動などを見つつ、問題の個所を探す

      • ステップイン
        一行づつ実行。
        ただし、functionは無視する。

      • ステップオーバー
        一行づつ実行。
        functionの中にも入っていって細かく調べる

      • ステップアウト
        functionの中から一気に脱出する

 
 
 
CGIにアクセス
 
CGIにアクセスする方法
  • ブラウザで受け取るgetURL()
    同一のウィンドウを使って、highscore.cgi(別に用意する必要がある)をGETメソッドで開く。

    score.getURL("../cgi-bin/highscore.cgi", "_self", "GET");

    参考:Google検索の入力欄を作る(getURL)

  • ムービーで受け取るloadVariable(),loadVariablesNum()
    counter.cgi(別に用意する必要がある)から、変数を受け止る。
    カウンターなので、毎回+1した結果が返ってくるCGI

    this.loadVariable("../cgi-bin/counter.cgi");

    POSTメソッドでthis内の変数データを送信して、変数データを受け取る

    this.loadVariable("../cgi-bin/highScore.cgi", "POST");

  • swfを受け取るloadMovie(),loadMovieNum()
    同一のMC(this)に、swfをPOSTメソッドで読み込む

    this.loadMovie("../cgi-bin/nextSwf.cgi","POST");

    CGIからswfファイルが返ってくる必要がある。

  • Numのあるなしの違い
    MC.loadMovie("URL")は、MCに読み込む。
    loadMovieNum("URL", 階層)は、指定した階層(レベル)に読み込む。

  • GETメソッドとPOSTメソッドの違い
    GETは、URL(URI)中にアドレスとしてデータを含める送信方法。Googleなどの検索結果など。
    POSTは掲示板などの書き込みのように、formから送信する方法

    発展:知らないとはまる罠、ドメイン間のセキュリティについて

 
Google検索の入力欄を作る(getURL)

  • まず「テキスト入力」とボタンを作り。
    両方選択したまま、MC化する。そのMC内の全ての変数が送信されるため、一つのMCにまとめておく
    テキスト入力の変数を「q」にする。「q=入力された変数の値」が送信される

    on(press){
    getURL("http://www.google.co.jp/search", "_blank", "GET");
    }

    以上。
    flashといれてボタンを押すと、
    getURL以下のアドレスに、q=flashが付け足され、
    http://www.google.co.jp/search?q=flash」で新しいウィンドウが開く。
    複数のローカル変数があれば、「&」で繋がれて送信される。
    hl="ja";があるならば、〜?hl=ja&q=flashのようになる

 
getURL("index.html#hoge")の、「#」以下が無視される
  • 「#」を「%23」に置き換える

    getURL("index.html%23hoge")

 
チェックボックスを作る
  • コンポーネントパネルのCheckBoxを利用(MX以降)
    コンポーネントパネルからドロップ。
    プロパティから設定。
    labelラベル名
    Initial Value最初からチェックが入っているか
    Label Placementラベルの位置。右か左
    Change Handler触ったときに反応するファンクション(未定義でも可)
    チェックボックス名.getValue()でアクセス

    cb1と名前を付けたチェックボックスのChange Handlerに、cb1Changedと記入
    cb1に触るたびに結果がtraceされる。

    function cb1Changed(){
    trace(cb1.getValue())
    }

 
ラジオボタンを作る
  • コンポーネントパネルのRadioButtonを利用(MX以降)
    コンポーネントパネルからドロップ。
    プロパティから設定。
    labelラベル名
    Initial State最初からチェックが入っているか
    Group Nameグループ。同一グループでチェックが複数入らないようにする
    Data返されるデータ。getValue()で取得できる
    Label Placementラベルの位置。右か左
    Change Handler触ったときに反応するファンクション(未定義でも可)
    Group Nameが、group1だったら、
    決定ボタンが押されたときなどに、(投稿用のデータ格納)MC.data1 = group1.getValue();のようにしてDataの値を取得して利用する
 
コンポーネントのデザインを変更する
  • ライブラリを開き、「Flash UI Components」の中からそれらしきものを探して改造する。
  • 〜Skinsというフォルダ内にある画像を入れ替えれば、思い通りのデザインに変更できる。
  • labelの部分の色を変えるには
 
クリップパラメータ(コンポーネント)の定義
  • Flash5は、チェックボタンやラジオボタンを作成するには、ライブラリ上でMCを右クリックから、「クリップパラメータの定義」で。
  • クリップパラメータを設定すれば、ライブラリから配置してすぐにコンポーネントとして利用できる。
 
 
 
外部ファイルの読み込み
 
とりあえず使ってみる
  • テスト
    about.txtというテキストファイルを作成
    テキストの中身は以下のようにする。

    test=外部ファイル読み込み成功&hoge=ボケステ&

    次に以下のASを記入

    System.useCodepage = true;//文字コードをShift-JISに
    this.createEmptyMovieClip("dummyMC", 1);//読み込み用のMCを作成
    dummyMC.onData = function() {//dummyMCが読み込まれたら…
        traceAbout();
    };
    dummyMC.loadVariables("about.txt");//dummyMCにabout.txtを読み込む
    function traceAbout(){//読み込み後の処理
        trace(dummyMC.test);
        trace(dummyMC.hoge);
    }

  • 説明
    createEmptyMovieClip()でdummyMCを深度1で作成している。dummyMCは読み込みのために作っている。
    読み込むためのMCがタイムラインに配置されていれば省略してもよい。
    dataMCがあれば、いきなりdataMC.loadVariables("about.txt");のようになる。

    onDataは、読み込みが終わったらtraceAbout()を実行をする。
    これを忘れると、読み込みが終わる前に処理が実行がされて、何も表示されないといった問題が発生する可能性がある。
    また、onDataは、読み込む前に定義しておくこと。>>理由

    読み込まれるテキストの内容は、&でつなぐことで、複数の変数を読み込ませることができる。

    読み込まれた値は、MC.変数名で取得する。
    この際、読み込まれた値は、文字列になっているので、数値として扱いたければ、Number(hoge)のように変換する必要がある。

  • 実際に使うには…
    ムービーが開始したとき、ボタンが押されてページ切り替えのときなどに、loadVariables()でデータを読み込んだりするような使い方をする。
    ただし、ボタンの中でloadVariales()やonDataは使わないほうがよい

    読み込みが終了したら、テキストエリアなどで表示すればよい。
    また読み込んだ変数をうまく利用すれば、、パブリッシュしなおさずに、表示されるメッセージや写真、背景色などを外部から簡単に変更することができる。

    データを「,」で繋いでおき、split()で配列にすると、データが扱いやすくなる。

 
読み込みテキストのトラブル
     
  • 外部の読み込みファイルの更新をしても変化がない
    以前のキャッシュが残っているため

    ブラウザの更新ボタンを押す

    HTMLにF5ボタンを押して再読み込みしてくださいとか書いておく
    かなり無責任なやり方だが

  • 確実に読み込むには、
    読み込みファイルの後ろにランダムな文字列を入れておく

    this.loadVariables("about.txt" + "?" + Math.floor(Math.random() * 65536) );

    ただし低い確率で同じファイルが読み込まれない可能性がある

  • 日付と時刻を追加してより確実に

    onClipEvent (load) {
    System.useCodepage=true;

    var nowdate =new Date();
    var y = nowdate.getFullYear();
    var m = nowdate.getMonth() +1;
    var d = nowdate.getDate();
    var h = nowdate.getHours();
    var min = nowdate.getMinutes();
    var s = nowdate.getSeconds();
    now = String(y) + String(m) + String(d) + String(h) + String(min) + String(s);

    this.loadVariables("about.txt" +"?" + now);
    }

    about.txt?2004115320 のように、その時の日付と時間をファイル名のあとに付加するので、
    時計をいじって意図的にしないかぎりキャッシュから読むことはない。  
  • 読み込んだテキストが文字化けする
    FlashMXから、読み込むファイルの形式がUnicode(UTF-8)になったことが原因

    • System.useCodepage = true;
      と読み込む前に書いておく

    • Unicode(EUC、UTF-8)で保存できるテキストエディタで保存する

    • Flash5形式でパブリッシュしてしまう
      ※他の部分で動かなくなることがあるので、あまりお勧めできないやり方
     
  • 外部ファイルが読み込めない(ローカルでは動作するがアップすると…)
    読み込むURLの制限にかかっていないか?
     参考:知らないとはまる罠

    • 相対パスで、swfのあるフォルダか、その下のフォルダを指定する。
      http://〜のように、フルパスで書くと読み込めないことがある
      ../のように、上のフォルダを指定すると読み込めない
     
  • 改行をうまく利用できない
    外部テキストの改行は、「\r\n」のようになっている。(改行コードによって変わる)
    dataArr=mc.hoge.split("\r\n")のような処理を行うと、改行で分解して、配列として利用することが可能。

     


  • その他外部テキストのトラブル例
    • 改行があるとうまくいかない
      myData=hoge1.swf&
      とテキストの中身の最後に&を付けておくと少し安心

    • 「=」の後にスペースがあるとうまくいかない
      ×myData = hoge1.swf&

    • 外部テキストの中に「&」、が入ってる
      &の後から別変数として認識される。

      LoadVarsやXMLなどの別の方法で読み込むか、
      もしくは「&」を「@」などに置き換えて
      split("@").join("&"); をする

      同様に、「+」、「%」も読み込めない。
      うまく置き換えるか、そもそもの読み込み方を変える。

    • なんかよく分からないけどうまくいかない
      知らねぇ。
      デバッガ使うなりして自力で解決汁
 
外部テキストをLoadVarsで直接読む
  • 「=」や「&」を含まないテキストファイルをLoadVarsで読むと
    最初のプロパティ名がテキストファイルの中身そのものになる。

    System.useCodepage = true;
    var myLoadVars = new LoadVars();
    myLoadVars.onLoad = function() {
        for (var propName in this) {
            trace(propName);
            break;
        }
    };
    myLoadVars.load("test.txt");

    test.txtの内容

    外部テキストです(照れ)

    ただし、仕様外のやり方なので今後の動作の保証はない
 
外部の画像を読み込む(loadMovie)
     
  • とにかく画像を読み込む
    (MX以降)

    photo1.loadMovie("01.jpg");

    これで、photo1というMCに、01.jpgが読み込まれる。
    photo1の中心点は(データから数値入力して)左上にしておくこと
    プログレッシブ形式のJPEG画像は表示されない

     

  • 読み込む画像ファイルを、外部テキストで指定する
    上記の、外部ファイルの読み込み、外部の画像ファイルを読み込むを参考にして、
    gaibu.txtというテキストファイルを作成
    テキストの中身

    txt=写真の説明&url=01.jpg&

    ASの内容

    System.useCodepage = true;
    photoArea.loadVariables("gaibu.txt");
    photoArea.onData = function() {
        photoArea.showPhoto();
    };
    photoArea.showPhoto = function(){
        this.message = this.txt;
        this.photo.loadMovie(this.url);
    }

    photoAreaというMCを配置し、MCの中にメッセージを表示するテキストエリア(変数message)と、写真を読み込むためのphotoというMCを配置しておく。

 
外部のSWFファイルを読み込む
  • screen.loadMovie("story1.swf");

    これで、screenにstory1.swfが読み込まれる
    screenの中心点は(データから数値入力して)左上にしておくこと

     参考:loadMovieの注意点

 
外部読み込みファイルにローディングバーをつける
  • 簡単なやり方
    全部をSWFの中に入れておき、読み込まれるSWFにローディングバーをつけておく
    写真が一枚だったとしても、中に写真が入っていて、ローディングバーがついている、ひとつのSWFとして用意する。

  • enterFrameで取得する例
    ローディングバーとなるMCを作り、barという名前をつけて、以下のASを記述。
    進行状況(プログレス)バーをつけるの「2」の手順の、x座標を0にするのを忘れずに

    onClipEvent (load) {
        this._visible = false;//最初は画面から消しておく
        function kaisi(mcPass) {//kaisiというメソッドを定義
            this._xscale = 0;//実行されたらリサイズして
            this._visible = true;//表示
            this.onEnterFrame = function() {
                var loadedSize = mcPass.getBytesLoaded();
                var totalSize = mcPass.getBytesTotal();
                var parcent = loadedSize / totalSize * 100;
                this._xscale = parcent;//パーセントに応じて横幅を変更
                if (parcent>=100 && totalSize > 100) {//読み込み完了したら
                    delete this.onEnterFrame;
                    this._visible = false;//enterFrameを削除。不可視に
                }
            };
        }
    }

    ボタンが押されたときなどに、

        _root.screen.loadMovie("story1.swf");
        _root.bar.kaisi(_root.screen);//_root.screenのロードの監視を開始

    ※if評価式の「totalSize > 100」、の部分はMCのファイルサイズがあまりにも小さかったら、読み込みが始まってなく、元々のMCのサイズを返しているので無視するようにしている。
    心配ならば、読み込む対象のMC(この場合screen)に、trace (this.getBytesTotal());を書いて、初期のMCのファイルのサイズを測っておき、適当に設定する(12だったら、20のように)。
    100バイト以下のファイルを読み込むことはほとんどないから大丈夫だとは思うが

    totalSize != undefined && loadedSize != undefinedのほうが格好いいかな?個人的にはこの書き方は不安定な希ガス

    パブリッシュプレビューでは、外部のファイルのロードは一瞬で終わってしまい、表示されない。(MX2004からは表示されるようになった)
    MXでのテストでは、実際にアップロードしてから実験をする。
    また、一度読み込むとキャッシュとして残るので、読み込みテストには、1M以上のダミーファイルを作っておき、キャッシュは1M以下に設定して、テストのたびにキャッシュが消えるよう、ブラウザ再起動などの工夫を
    読み込む側のSWFのキャッシュが残っていて、修正してテストしたがうまく動かないというときは、読み込む側のファイル名を変えてみるなどの工夫を

    素人にはお勧めできない。

 
loadMovieの注意点
     
  • 読み込んだSWFのパスについて
    _root.yukaに外部からa.swfを読み込み。
    a.swfは、_root.oya.koという構造になっているとする。

    a.swfを読み込むと、_root.yuka.oya.koというパスになる。

    _root.yuka.play();と書けば、a.swf(の_rootだったもの)を再生することができる。

    a.swfで、_rootを使っている場合。
    oyaに_root.oya.ko.play();のように書いているときに問題が発生する。

    _root.oya.koの構造のときに(読み込んでいないときは)、
    _root.oya.ko.play();は正常に動作するが、
    読み込みを行うと、_root.oya.koというパスは存在しなくなり、再生されなくなる。

    _parentを使い、oya内で_parent.play();と記述しておけば、a.swf単体でも、読み込んでからでも正常に動作するようになる。
    要するに、読み込まれるswfファイルには、_rootを使わずに、相対パスで記述するように
    _root.play()のように、読み込み側の操作として明確な意味があるならば別

     

  • 読み込んだSWFのfpsについて
    読み込むほうのfpsが優先される。
    60fpsのムービーに、30fpsのa.swfを読み込むと、
    a.swfは2倍速で再生される。
    同じfps速度で作っておかなければならない。
    setIntervalを駆使すれば、後から再生速度を無理矢理変えることは可能だが

     

  • loadMovie()で読み込めるファイルとバージョン
    5から
    SWFのみ

    MXから
    MP3、JPEG
    ただし、特殊なビットレートのMP3や、プログレッシブ形式のJPEGは読み込めない。またサイズが大きすぎると読み込めないことがある。

 
外部MP3の読み込み
     
  • とにかく鳴らす
    外部のSWFファイルを読み込むを使って、
    SWFファイルを画面外のMCに読み込むなどして、鳴らす。

     参考:ボタンでサウンドをオンオフする

     

  • loadSound()で鳴らす
    サウンドをASで制御するを参考に

    this.createEmptyMovieClip("sound_mc", 1);
    mySound = new Sound(sound_mc);//サウンドの読み込み
    mySound.loadSound("bgm.mp3", false);
    mySound.start();

    loadSound("mp3のURL", false);
    パラメータのfalseは、ストリーミングしないということ。
    読み込みが終了したら再生が開始される。

     

  • ストリーミングで外部のmp3を再生する

    mySound = new Sound();
    mySound.loadSound("bgm.mp3", true);

    途中まで読み込みが行われたらストリーミングで再生される。

     

  • サウンドの再生が終わったら再び再生する
    上記の方法(またはSoundオブジェクトとして)で音を鳴らした後に、
    (タイムライン上のサウンドには使えない)

    mySound.onSoundComplete = function(){
    funcSoundEnd();//サウンド終了時に実行
    }

    サウンド終了時にもう一度鳴らすには、(この場合はfunction funcSoundEnd())
    mySound.start();//非ストリミーングで再生している場合
    mySound.loadSound("bgm.mp3", true);//ストリーミングで再生している場合

     

  • 読み込みサウンドにローディングバーをつける
    上記の外部読み込みファイルにローディングバーをつけるを参考に、 mySound.getBytesLoaded()と
    mySound.getBytesTotal()で取得して変更。

     

  • サウンドを再生している位置を取得する

    parcent = mySound.position/mySound.duration * 100 /1000;

    positionは現在の再生位置、durationはサウンドの長さ(1000ミリ秒)
    プロパティなので「()」はつかない
     

  • 曲を再生中に次の曲を読み込む、再生が終わったら次の曲を再生する

  • サウンド関係のメソッド/プロパティ
     >>サウンド関係のメソッド/プロパティ
 
 
 
特殊な計算
 
n進数を使う
  •   とにかく16進数を使う

    a=0x10;
    trace(a);

    結果は16。
    0xFFFFFFのように、16進数は、頭に「0x」を付ければよい。
    ASで利用する際は、常に10進数で計算しておき、何かに使うとき、出力するときに、変換すればよい。
    「0x」を付けても、trace()すると、10進数で表示される。0xFFと255は等価。
     
  • 10進数を、16進数にして表示する

    num = 4095;//0xFFF
    ans = num.toString(16);
    ans = ans.toUpperCase();
    trace(ans);

    0xFFFが表示される。
     
  • n進数の文字列を10進数にする
    (parseIntを使う)

    • 16進数の文字列を、10進数にする

      str = "ffffff";
      trace("16進数は "+str);
      ans =parseInt(str,16);
      trace("10進数は "+ans);

      テキスト入力から、色を設定するような場合に

    • 2進数の文字列を10進数にする

      str = "1111";
      trace("2進数は "+str);
      ans =parseInt(str,2);
      trace("10進数は "+ans);

     
  • n進数にする
    (toString()を使う)

    • 16進数にする例

      num = 15;
      ans = num.toString(16);
      trace(ans);

      fが得られる

    • 2進数にする例

      num = 15;
      ans = num.toString(2);
      trace(ans);

      1111が得られる

      2-35進数まで表現可能。

 
Mathオブジェクト(数値計算関係)のメソッド/プロパティ
  • メソッド
    Math.abs()
    Math.round()
    Math.floor()
    Math.ceil()
    Math.sin()
    Math.cos()
    Math.tan()
    Math.asin()
    Math.acos()
    Math.atan()
    Math.atan2()
    Math.pow()
    Math.sqrt()
    Math.log()
    Math.exp()
    Math.max()
    Math.min()
    Math.random()

  • プロパティ
    Math.PI
    Math.SQRT1_2
    Math.SQRT2
    Math.E
    Math.LN2
    Math.LN10
    Math.LOG2E
    Math.LOG10E
 
Numberオブジェクト関係のメソッド/プロパティ
  • メソッド
    Number()
    Number.toString()
    Number.valueOf()

  • プロパティ(演算に使う定数)
    Number.MAX_VALUE
    Number.MIN_VALUE
    Number.POSITIVE_INFINITY
    Number.NEGATIVE_INFINITY
    Number.Nan
 
ビット演算
  • とにかく使ってみる

    r = 0xFF << 4*4;
    g = 0xAA << 4*2;
    b = 0x11 << 4*0;
    rgb = r+g+b;
    ans = rgb.toString(16);
    trace(ans);

    r、g、bの変数があり、
    rgbを0xFFAA11のようにして利用する場合、
    普通のやり方では、
    r*65536 + g*256 + b
    または、
    r*0x10000 + g*0x100 + b
    と書かなければならない。

    それを、0xFF << 4*4と書くと、
    0xFFを2進数で、4ビット(16進数で一桁)、4桁、(計16ビット)
    左に移動することができる。
    0xFF 1111 1111
    0xFF0000 1111 1111 0000 0000 0000 0000

    同様に、gも4ビット、2桁移動させる。
    最後に合計すれば、rgbが目的の値になる。

    反対に、右シフトをすれば、16進数で、桁の数を減らしたりもできる。

    rgb = 0xFFAA11;
    r = rgb >> 4 * 4;
    r = r.toString(16);
    trace(r);

    右シフトで4桁移動したので、FFが得られる

  • ビット演算を使う理由
    ASでは特にない。
    計算速度も遅いし、プログラマの自己満足程度
    暗号化などのレベルに達すれば利用する(らしい)
    (他のプログラム言語では、2進数でプリミティブな計算ができ、非常に高速になるので、テクニックの一つではある。ASでは(擬似的に実現しているため?)遅くなる)

  • ビット演算子
    &
    |
    ^
    ~
    <<
    >>
    >>>
    &=や<<=などの代入演算子もある
 
その他、特殊な計算、関連
 
 
 
TextFieldオブジェクト
 
とにかく表示する
  • TextFieldオブジェクトでアクセスする
    (MX以降から)
    • _root(dTxtというインスタンス名のテキストフィールド)
      • dTxt
        (ダイナミックテキストに名前だけつける。変数名は書いてはいけない)
    _root上(のタイムライン)で、
    this.dTxt.text = "textプロパティを使って表示してみる"

    trace("dTxtの内容は : " + this.dTxt.text);

 
テキストの表示スタイルを変更(TextFormat)
  • プロパティを変更する例

    dTxt.text = "hoge";
    myTF = new TextFormat();
    myTF.font = "_明朝";
    myTF.color = 0x0000FF;
    myTF.size = 50;
    myTF.bold = true;
    dTxt.setTextFormat(myTF);

  • 後からプロパティを変更する例

    dTxt.text = "hoge\nhage";
    myTF = new TextFormat();
    myTF.color = 0x0000FF;
    myTF.size = 50;
    dTxt.setTextFormat(myTF);

    btn.onPress = function (){
        myNewTF = new TextFormat();
        myNewTF.color = 0xFF0000;
        myNewTF.size = 90;
        _root.dTxt.setTextFormat(5,9,myNewTF);
    }

    setTextFormat(0,10,TFobjName)
    で、0+1文字目から、10文字目までを、TFobjNameで適用
    setTextFormat(TFobjName)
    で全部に適用。
    setTextFormat(2,TFobjName)
    で、2+1文字目だけに適用

  • setNewTextFormat()を使う
    setTextFormat()は、変更をするだけのメソッド。
    ダイナミックテキストの内容を後から変更すると、設定したフォーマット(プロパティの色など)は全て無効になる。もう一度実行しなければならない。
    そこで、setNewTextFormat()を実行しておくと、(そのテキストフィールドの)デフォルトのフォーマットとして利用できる。

  • TextFormatオブジェクトのプロパティ
    fontフォント
    sizeフォントの大きさ
    colorフォントの色
    bold太字
    italic斜体
    underline下線
    urlリンク先のURL
    targetリンクのターゲット
    align行揃え("left","right","center")
    leading行間(pt)
    leftMargin左の隙間
    rightMargin右の隙間
    bulletリスト表か(true/false)
    indentインデント
    blockIndent段落インデント
    tabStopsタブの幅(\tを使ったときの幅)
 
リスナーの設定(TextFieldの変更を感知する)
  • 変更されたら実行

    dTxt.onChanged = function(){
    trace(this.text);//変更時の処理
    }

    イベントハンドラメソッド内は、thisの扱いが難しいので注意
    自身が置いてある親のMCに操作を行いたかったら、this._parentになる

  • フォーカスが与えられたら実行

    dTxt.onSetFocus = function () {
    trace(this._name + "setFocus ");
    };
    dTxt.onKillFocus = function () {
    trace(this._name + "killFocus ");
    };

  • リスナーが必要なくなったら消す
    dTxt.onChanged = undefined;

     参考:リスナーを設定する

 
ASでTextFieldを作る
  • とにかく作成

    this.createTextField("newTF",1,10,20,200,300);
    newTF.border = true;
    newTF.text = "テキストフィールドを\nASで作ってみるテスト"


    newTFという名前で、深度1、座標10,20に、200*300の大きさで作成している

  • 消す

    newTF.removeTextField()

     参考:カレンダー(最後でテキストフィールドを利用している)

 
TextFleildのメソッド/プロパティ
  • メソッド
    addListener()
    removeListener()
    setTextFormat()
    getTextFormat()
    setNewTextFormat()
    getNewTextFormat()
    replaceSel()
    removeTextField()
    getDepth()

  • プロパティ
    text
    htmlText
    variable
    type
    html
    password
    slectable
    multiline
    wordWarp
    embedFonts
    length
    maxChars
    restrict
    textColor
    background
    backgorundColor
    border
    borderColor
    autoSize
    textWidth
    textHeight
    scroll
    hscroll
    maxscroll
    maxhscroll
    bottomScroll

    _xや、_widthなども使える

  • イベント
    onChanged
    onScroll
    onSetForcus
    onKillForcus
 
 
 
dateオブジェクト
 
時間を表示する
  • とりあえず使ってみる

    function imaNannniti() {
        var nowDate = new Date();
        var year = nowDate.getFullYear();
        var month = nowDate.getMonth()+1;
        var datee = nowDate.getDate();
        var day = nowDate.getDay();
        var dayArr = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
        var weekDay = dayArr[day];
        var hour = nowDate.getHours();
        var minutes = nowDate.getMinutes();
        var second = nowDate.getSeconds();
        var myDay = year+" / "+month+" / "+datee+" ("+weekDay+")";
        return myDay;
    }
    trace(imaNannniti());

    dateは予約語なので、使わないように。
    ここではdateeにしている。

    年/月/日(曜日)が表示される。

    必要に応じて、myDayの値を変更して使う

  • デジタル時計の例

    onClipEvent (load) {
        function zeroTuke(num) {
            if (num<10) {
                num = "0"+num;
            }
            return num;
        }
    }
    onClipEvent (enterFrame) {
        nowDate = new Date();
        hour = nowDate.getHours();
        minutes = nowDate.getMinutes();
        second = nowDate.getSeconds();
        nowTime = zeroTuke(hour)+" : "+zeroTuke(minutes)+" : "+zeroTuke(second);
    }

    MCに書く
    nowTimeという変数を持つダイナミックテキストを、MCの中に入れておく。

  • アナログ時計の例

    onClipEvent (enterFrame) {
        nowDate = new Date();
        hour = nowDate.getHours();
        minutes = nowDate.getMinutes();
        second = nowDate.getSeconds();
        byousin._rotation = second/60*360;
        tyousin._rotation = minutes/60*360+second/60/60*360;
        tansin._rotation = hour/12*360+minutes/60/60*360+second/60/60/60*360;
    }

    MCに書く。
    byousin,tyousin,tansinというMCをそれぞれ作り、中に配置する。
    それぞれのMCの中心点は、画面(時計)の中央に、回転させていない状態(_rotationが0のとき)に、針が上を向くようにしておく。
 
あと何日を表示する
  • 指定した日まであと何日か示す例

    function simekiri(mYear, mMonth, mDate) {
        var nowDate = new Date();
        var year = nowDate.getFullYear();
        var month = nowDate.getMonth()+1;
        var datee = nowDate.getDate();
        var ima = Date.UTC(year, month, datee);
        var kijitu = Date.UTC(mYear, mMonth, mDate);
        var remainTime = (kijitu-ima)/1000/60/60/24;
        return remainTime;
    }

    trace("〆切まであと、" + simekiri(2005,1,10) +"日");

    Date.UTC()は1970年から引数で指定した年月までのミリ秒数を出す。
    目標の時間-現在の時間で、残り時間が算定できる。

    Date.UTC()の引数には、年、月、日が必須。
    オプションで、ミリ秒まで指定可能。

    テストは、PCの時計を変更して行う。

  • 秒単位までカウントダウンする例

    function simekiri(mYear, mMonth, mDate, mHour, mMin, mSec) {
        var nowDate = new Date();
        var year = nowDate.getFullYear();
        var month = nowDate.getMonth()+1;
        var datee = nowDate.getDate();
        var hour = nowDate.getHours();
        var minutes = nowDate.getMinutes();
        var second = nowDate.getSeconds();
        var ima = Date.UTC(year, month, datee, hour, minutes, second);
        var kijitu = Date.UTC(mYear, mMonth, mDate, mHour, mMin, mSec);
        var remainTime = (kijitu-ima)/1000;    //秒
        if (remainTime<=0) {
            //時間が来たときの処理。実際にはムービー再生させるなど
            remainTime *= -1;
            var answer = "〆切経過時間 : ";
            answer += Math.floor(remainTime/60/60/24)+"日 ";
            answer += Math.floor(remainTime/60/60%24)+"時間 ";
            answer += Math.floor(remainTime/60%60)+"分 ";
            answer += Math.floor(remainTime%60)+"秒 ";
            return answer;
        } else {
            var answer = "〆切まであと、";
            answer += Math.floor(remainTime/60/60/24)+"日 ";
            answer += Math.floor(remainTime/60/60%24)+"時間 ";
            answer += Math.floor(remainTime/60%60)+"分 ";
            answer += Math.floor(remainTime%60)+"秒 ";
            return answer;
        }
    }

    this.onEnterFrame = function() {
        txt = simekiri(2005, 1, 8, 3, 33, 0);
    };

    この例では、時間が過ぎたら、経過時間を表示している。

    値をifで分岐させるようにすることで、
    開催まであと何日、
    時間が来たら、開催中、
    開催時間が終わったら、終了、と表示を変えることができる。

 
タイマー
  • ボタンを押している時間を計測する例

    on (press) {
        startTime = getTimer();
    }
    on (release) {
        totalTime = getTimer()-startTime;
        trace(totalTime);
    }

    単位は1000ミリ秒
    getTimer()は、ムービー開始からの合計時間。
    今の時間-計測開始の時間で、必要な時間を求める。

    ただし、ムービーの負荷とCPUの処理能力によっては、
    僅かに誤差が出ることがある。
    厳密に測るならば、Dataオブジェクトを使ってPCの時計で測ったほうがよい。

 
曜日で表示される内容を変える
  • 曜日によって内容を変える例

    function imaNanyou() {
        var nowDate = new Date();
        var day = nowDate.getDay();
        var dayArr = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
        var weekDay = dayArr[day];
        return weekDay;
    }
    gotoAndStop(imaNanyou);

    タイムラインに、SUN、MONといったラベルをつけておき、そのラベルのあるフレームに、それぞれ表示したい内容をMCにして入れておく。
 
カレンダー
  • 今月のカレンダー

    nowDate = new Date();
    year = nowDate.getFullYear();
    month = nowDate.getMonth()+1;
    datee = nowDate.getDate();
    dayArr = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
    day = dayArr[nowDate.getDay()];
    trace("ToDay : "+year+" / "+month+" / "+datee+" ("+day+")\n");
    makeCalender(Year, Month);
    function makeCalender(year, month) {
        var myDate = new Date(year, month-1, 1);//年月日を指定してオブジェクト作成
        var firstWeek = myDate.getDay();//初日の曜日を取得
        var nextMDate = new Date(year, month, 1-1);//翌月の前日(今月の最終日)
        var lastDay = nextMDate.getDate();//最終日を取得
        showCalender(myDate, firstWeek, lastDay);
    }
    function showCalender(myDate, firstWeek, lastDay) {
        var year = myDate.getFullYear();
        var month = myDate.getMonth()+1;
        trace(year+" / "+month+"\n");//表示する年と月
        var youbi;
        for (var i = 0; i<=7; i++) {
            youbi += dayArr[i]+"\t";
        }
        trace(youbi);//曜日を表示
        var hi;//日を表示用の変数
        for (var i = 0; i<firstWeek; i++) {//最初の曜日まで空白を挿入
            hi += "\t";
        }
        for (var i = 1; i<=lastDay; i++) {//最終日まで繰り返し
            hi += i+"\t";
            if ((i+firstWeek)%7 == 0 || i == lastDay) {//土曜日までhiに代入したら表示して改行
                trace(hi+"\n");
                hi = "";
            }
        }
    }

    makeCalender(年、月)で作成。

  • 来月/先月に切り替えるボタン

    nextMonth.onPress = function() {
        month++;
        if (month>12) {
            month = 1;
            year++;
        }
        makeCalender(year, month);
    };
    lastMonth.onPress = function() {
        month--;
        if (month<0) {
            month = 12;
            year--;
        }
        makeCalender(year, month);
    };

  • traceではなくて、実際にムービーに表示する

    nowDate = new Date();
    year = nowDate.getFullYear();
    month = nowDate.getMonth()+1;
    datee = nowDate.getDate();
    dayArr = ["SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"];
    day = dayArr[nowDate.getDay()];
    today_hyouji = "ToDay : "+year+" / "+month+" / "+datee+" ("+day+")\n";
    calenderWaku();
    makeCalender(Year, Month);
    function makeCalender(year, month) {
        var myDate = new Date(year, month-1, 1);
        var firstWeek = myDate.getDay();
        var nextMDate = new Date(year, month, 1-1);
        var lastDay = nextMDate.getDate();
        showCalender(myDate, firstWeek, lastDay);
    }
    function showCalender(myDate, firstWeek, lastDay) {
        var year = myDate.getFullYear();
        var month = myDate.getMonth()+1;
        hyouji = year+" / "+month+"\n";
        var i =0;
        for (i = 0; i<firstWeek; i++) {
            eval("ddate"+i).text = "";
        }
        var count = 1;
        for (i = firstWeek; i<=lastDay+firstWeek; i++) {
            eval("ddate"+i).text = count++;
        }
        for (var i = lastDay+firstWeek; i<=37; i++) {
            eval("ddate"+i).text = "";
        }
    }
    nextMonth.onPress = function() {
        month++;
        if (month>12) {
            month = 1;
            year++;
        }
        makeCalender(year, month);
    };
    lastMonth.onPress = function() {
        month--;
        if (month<0) {
            month = 12;
            year--;
        }
        makeCalender(year, month);
    };
    function calenderWaku() {
        TFBlue = new TextFormat();
        TFRed = new TextFormat();
        TFBlue.color = 0x0000FF;
        TFRed.color = 0xFF0000;
        for (var i = 0; i<7; i++) {
            this.createTextField("dday"+i, depth++, 0, 0, 100, 50);
            var targetMC = eval("dday"+i);
            targetMC._x = 50*i+20;
            targetMC._y = 50;
            if (i == 0) {
                targetMC.setNewTextFormat(TFRed);
            }
            if (i == 6) {
                targetMC.setNewTextFormat(TFBlue);
            }
            targetMC.text = dayArr[i];
        }
        for (var i = 0; i<37; i++) {
            this.createTextField("ddate"+i, depth++, 0, 0, 50, 50);
            var targetMC = eval("ddate"+i);
            targetMC._x = 50*(i%7)+30;
            targetMC._y = 70+Math.floor(i/7)*40+20;
            if (i%7 == 0) {
                targetMC.setNewTextFormat(TFRed);
            }
            if (i%7 == 6) {
                targetMC.setNewTextFormat(TFBlue);
            }
           
            targetMC.text = "";
           
        }
    }

    calenderWaku()で、dday0〜6と
    ddate0〜37をテキストフィールドとして作成している。
    同時に、曜日を代入し、色も設定している。
    サイズや、位置などを変更したければ、ここを弄る。

    Flash5の場合は、dday0〜6と、ddate0〜37という変数を持つダイナミックテキストを配置しておくことで表示するように改造すれば表示できる。
 
その他、Dateオブジェクト関係、参考
 
項目3
 
 
 
XML
 
XMLファイルの利用
  • とにかく読み込む

    myXML = new XML();
    myXML.ignoreWhite = true;
    myXML.onLoad = yomikomi;
    myXML.load("2005Jan05.xml");
    function yomikomi() {
        trace(myXML);
    }

    2005Jan05.xmlの内容の例

    <nikki syurui="普通の日記">
        <midasi>XML読み込みの実験してますた</midasi>
        <naiyou>外部ファイル関係は(中略)死ねる</naiyou>
    </nikki>

    ignoreWhiteは、改行、tab、スペースを無視する

  • とにかくXMLを解析する

    myXML = new XML();
    myXML.ignoreWhite = true;
    myXML.onLoad = yomikomi;
    myXML.load("2005Jan05.xml");
    function yomikomi() {
        oyaNode = myXML.firstChild;
        childNodes = oyaNode.childNodes;
        for(var pName in childNodes){
            trace(pName + " \t "+ childNodes[pName]);
        }
    }

    結果は
    1     <naiyou>外部ファイル関係は(中略)死ねる</naiyou>
    0     <midasi>XML読み込みの実験してますた</midasi>

  • タグ名と、その内容を取得する

    function yomikomi() {
        oyaNode = myXML.firstChild;
        childNodes = oyaNode.childNodes;
        for(var pName in ChildNodes){
            theChildNode = childNodes[pName];
            trace( theChildNode.nodeName);
            trace( theChildNode.firstChild.nodeValue);
        }
    }

    結果は、
    naiyou    外部ファイル関係は(中略)死ねる
    midasi    XML読み込みの実験してますた

  • 親ノードのタグ名を表示する

    function yomikomi() {
        oyaNode = myXML.firstChild;
        trace(oyaNode.nodeName);
    }

  • 属性を取得する

    function yomikomi() {
        oyaNode = myXML.firstChild;
        oyaNodeAttr = oyaNode.attribute;
        for (var pName in oyaNodeAttr) {
            trace(pName+" \t "+oyaNodeAttr[pName]);
        }
    }

  • 新しいXMLを自分で作る

    myXML = new XML("<nikki syurui="普通の日記"><midasi>XML読み込みの実験してますた</midasi><naiyou>外部ファイル関係は(中略)死ねる</naiyou></nikki>")

    Stringの文字列なので改行は入れないように


  • XMLのまとめ

    <nikki syurui="普通の日記">
        <midasi>XML読み込みの実験してますた</midasi>
        <naiyou>外部ファイル関係は(中略)死ねる</naiyou>
    </nikki>

    という、XMLを読み込む場合。

    XML.firstChild(プロパティ)を使い、ノードを取り出す
    このノードは親ノードとなる。
    oyaNode = myXML.firstChild;という部分
    この時点では、oyaNodeの内容は以下のようになっている。

    <nikki syurui="普通の日記"><midasi>XML読み込みの実験してますた</midasi><naiyou>外部ファイル関係は(中略)死ねる</naiyou></nikki>

    次に、
    親ノード.childNodes(プロパティ)を使って、
    子ノードを取り出す。
    childNodes = oyaNode.childNodes;という部分
    これで、やっと、childNodesが以下のようになる。

    <midasi>XML読み込みの実験してますた</midasi>

    最後に、nodeNameと、nodeValueでタグ名と値を取り出せる
    trace( theChildNode.nodeName);
    trace( theChildNode.firstChild.nodeValue);という部分。

    要するに、
    myXML.firstChild.nodeName="nikki"
    myXML.firstChild.attributes["syurui"]="普通の日記"
    myXML.firstChild.childNodes[0]="<midasi>XML読み込みの実験してますた</midasi>"
    myXML.firstChild.childNodes[1]="<naiyou>外部ファイル関係は(中略)死ねる</naiyou>"
    のように、配列に代入が行われている(と考えると分かりやすい)


    参考:文字コードについて(知らないとはまる罠)
    参考リンク:(XMLについて学べるサイト)

 
XML関係のメソッド/プロパティ
  • メソッド
    XML.createElement()
    XML.createTextNode()
    XML.cloneNode()
    XML.appendChild()
    XML.insertBefore()
    XML.removeNode()
    XML.hasChildNode()
    XML.load()
    XML.onLoad()
    XML.send()
    XML.sendAndLoad()
    XML.parseXML()
    XML.toString()
  • プロパティ
    XML.docTypeDecl
    XML.xmlDecl
    XML.childNodes
    XML.parentNode
    XML.firstChild
    XML.lastChild
    XML.nextSibling
    XML.previousSibling
    XML.attributes
    XML.nodeType
    XML.nodeName
    XML.nodeValue
    XML.loaded
    XML.status
 
XMLソケットオブジェクトのメソッド/プロパティ
  • メソッド
    XMLSocket.connect()
    XMLSocket.onConnect()
    XMLSocket.close()
    XMLSocket.onClose()
    XMLSocket.onXML()
    XMLSocket.send()

 
XMLで更新しやすいコンテンツ
 
XMLの解析をして、構造を再現
  • XMLの構造を表示する例

    myXML = new XML("<tukue><hikidasi><kureyon><iro>赤</iro><iro>青</iro></kureyon></hikidasi><ue>ノート</ue></tukue>");
    kodomoWake(myXML, new Array());
    function kodomoWake(oya, kouzou) {
        kouzou.push(oya.nodeName);
        for (var i = 0; i<oya.childNodes.length; i++) {
            var theChildNode = oya.childNodes[i];
            if (theChildNode.nodeType != 3) {
                kodomoWake(theChildNode, kouzou);
            } else {
                var childNodeValue = theChildNode.nodeValue;
                trace(kouzou.join("\t")+" \t "+childNodeValue);
            }
        }
        kouzou.pop();
    }

 
 
 
リスナー
 
とりあえず使う
     
  • リスナーの設定
    (リスナーはMX以降から)

    • dTextというTextFieldオブジェクを監視する例

      dtext.onChanged = function () {
          trace(dText.text);}
      };

    • リスナー用のオブジェクトを設定して変更を監視する例

      myListener = new Object();
      myListener.onChanged = function (){
          trace(dText.text);
          //処理
          };
      dText.addListener(myListener);

    • 使い終わったリスナーを削除

      dText.removeListener(myListener);

    • koumokuとkazuというテキスト入力を監視する例

      myListener = new Object();
      myListener.onChanged = function () {
          trace(koumoku.text +" "+kazu.text);
          //処理の内容
          };
      koumoku.addListener (myListener);
      kazu.addListener (myListener);

      複数のリスナーを(myListenerで)一つの処理に回している

    • addListenerで直接リスナーを設定する例

      dText.addListener(trace(dText););

      addListenerを使うと、一つのリスナーに複数のイベントを設定できる

    • 値の変化とスクロールのリスナーをまとめて設定する例

      dText.addListener({onChanged:function () {
          trace("changed : "+dText.text);
      }, onScroller:function () {
          trace("scroller : "+dText.scroll);
      }});

     
  • リスナーのイベント
    • TextFieldオブジェクト
      onSetFocusフォーカスがあたったら
      onKillFocusフォーカスがはずれたら
      onChanged値が変化したら
      onScrollerスクロールされたら

    • MovieClipオブジェクト
      onSetFocusフォーカスがあたったら(Tabキーなど)
      onKillFocusフォーカスが外れたら

    • Keyオブジェクト
      onKeyDownキーが押されたら
      onKeyUpキーが放されたら

    • Stageオブジェクト
      onResizeサイズが変わったら

  • リスナーを設定する理由
    一括して管理できるので、一つ一つのMCで変数などの変更を監視して通知するよりも、作りやすい。
    それぞれのMCがenterFrameなどを使う必要がないので動作が軽くなる
    後々の変更や修正が一箇所で済むので、快適に作れるようになる。
 
Enterを押したら反応
  • Key.addListener(dText);
    dText.onKeyDown = function() {
        if (Key.getCode() == Key.ENTER) {
            //処理の内容
            trace(dText.text);
            dText.text = "";
        }
    };

 
画面サイズに合わせて表示サイズを変える
  • 真ん中に同一サイズで固定する例

    Stage.scaleMode = "noScale";

  • 左上に同一サイズで固定する例

    Stage.scaleMode = "noScale";
    Stage.align = "TL";

  • Stage.scaleMode
    noScale拡大なし
    noBorder縦横比維持したまま拡大
    showAll縦横比維持したまま拡大(デフォルト)
    exactFit上下の余白なしで拡大

  • Stage.align
    TLTTR
    L空白(.align="")R
    BLBBR

  • 画面サイズに関わらず、右端に常に表示する
    _rootのタイムラインに記述。
    barという右端に置きたいMCを作成。
    スクロールバーなどの機能をMCに入れておく

    Stage.scaleMode = "noScale";
    Stage.align = "TL";
    //リスナ
    myListener = new Object();
    myListener.onResize = function() {
        setBar();
    };
    Stage.addListener(myListener);
    //初期化
    setBar();

    //barの位置変更
    function setBar(){
        bar._x = Stage.width - bar._width;
        bar._y = 0;
        bar._height = Stage.height;
    }

    画面サイズが変更されるたびに、
    setBar()が呼び出され、位置が変更される。

  • 画面サイズを取得する
    上記のsetBar部分に記述。

    w.text = Stage.width;
    h.text = Stage.height;

    w,hというテキストフィールドに、画面のサイズを表示できる。
 
 
 
知らないとはまる罠
 
ASが実行される順番、タイミング
  • クリップアクション>フレームアクション
    MCに書かれたクリップアクションが先に実行される。

    フレーム1が1面、2が2面のようなゲームの場合、
    フレーム1に初期化用のメソッドやデータがあっても、
    クリップアクションが先に実行されてしまい、なぜか動かないという罠にはまる

  • クリップアクションの順序
    loadは登場したフレーム、
    enterFrameはloadの後の毎フレーム、
    unloadはMCが消えた次のフレームで実行される。
    enterFrameは、登場した次のフレームから実行される

  • 階層化したMCのタイミング
    かなり複雑。
    確実に動かすならば、前もって画面外に読ませておくとよい。

    duplicateMovieClipで複製したMCのfunctionは
    直後には実行できないケースがあるので、
    AS記述専用の空のムービークリップにスクリプトいれて、まとめておくほうが安定する

  • 読み込み速度の問題
    ストリーミングの仕様上、MCの読み込みが終わる前に再生が始まってしまうことがある。
    プリローダーをつけて、確実に読み込まれるまで待つ。

  • まとめ
    実行の順番は、慣れるしかない。
    うまく行かないときに、いろいろと書く場所を変えているうちに分かってくる。

    _rootの変数を、MCから無闇に変更させないようにする、自分自身の変数だけを管理して、メソッドでやり取りをするような、OOPを心がける。

 
同じキーフレームに飛ばしても実行されない
  • フレームアクションは同じキーフレームに飛ばしても実行されない
    this.gotoAndPlay(_currentFrame)としても、
    ループはせずに次のフレームに行く。
    前に1フレームの余裕を取って、this.gotoAndPlay(_currentFrame-1)のようにするとよい。
    この仕様のおかげで、フレーム1しかないムービーにはstop()を書かなくても延々と初期化が繰り返されたりしない
 
配列のコピーがうまくいかない(arrayA = arrayB)
  • 配列の直接代入
    (Arrayオブジェクトを格納した)配列の変数をそのまま代入しても、
    参照しているだけで、片方を操作すると、両方が影響を受ける。

    arrayA = new Array();
    arrayB = new Array();

    arrayA = ["A","A","A"];
    arrayB = arrayA;
    trace("arrayA : " + arrayA);
    trace("arrayB : " + arrayB);

    arrayA = ["x","x","x"];//arrayAのみ操作

    trace("arrayA : " + arrayA);
    trace("arrayB : " + arrayB);

    arrayBの値が、arrayAを操作すると一緒に変化してしまう。
    arrayBはarrayAの値を見ている(参照)だけ。

  • 対策
    concat()や、forなどで完全に別の配列として代入しないといけない。

     参考:配列(構造体)の完全コピー

 
MCの座標は整数ではない
  • 座標は、たいてい整数以外の数値を返してくる。
    スライドバーで0〜100を取得しようとすると、
    92.8のような数値が返される。
    Math.round()で四捨五入、Math.floor()で切り捨てをするなどの工夫を

  • 直接関係はないが、
    hoge/0というような式もエラーになるので、MCの座標などから数値を取って割る場合は、その前にifで評価するとよい。
    大抵は0.02などの数値が入っているので問題ないが、ごく稀に0になったときだけ実行されないという問題で困らないために。

  • swf直で再生したときの問題。
    画面サイズが、予定していたサイズと異なることがある。
    画面外の余白が見えているような状態で再生すると、本来は入らない値が入力される可能性がある。
 
初めから配置してあるMCはremoveMovieClip()できない
  • swapDepthes()すれば消せるようになるが、仕様外の裏技。
    今後どうなるかは不明。
 
ドメイン間のセキュリティ/アップすると外部ファイルが読み込めない
  • ローカルでは問題がないのに、アップロードすると読み込みが行われない場合
    セキュリティの仕様上、同じドメインの上でしか、XMLやCGIなどにアクセスできないようになっている。
    http://hoge.com/flash/で再生している場合、
    http://hoge.com内のファイルにしかアクセスできない。
    ローカルでの再生中は、この制限はない

    MX2004(FP7)からは、http://hoge.com/flash/以下のフォルダにしかアクセスできなくなった

  • System.security.allowDomain()を使う
    MX以降から
    読み込まれる側のswfファイルに、
    System.security.allowDomain("hoge.com")を記入する
    hoge.comにあるswfからの読み込みを許可できる?
    ☆状況再現できないので、様子見

  • ポリシーファイルを用意する
    MX2004から
    crossdomain.xmlというファイルを作り、読み込まれるCGIなどのあるフォルダに置いておく。
    xmlの内容は、

    <?xml version="1.0"?>
    <!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
    <!-- kyoka from hoge-->
    <cross-domain-policy>
    <allow-access-from domain="hoge.com/flash" />
    <allow-access-from domain="*.hoge.com/flash" />
    </cross-domain-policy>

    この場合、hoge.com/flashというアドレスのswfからの、読み込みを許可している。
    また、<allow-access-from domain="*" />とワイルドカード(「*」のこと)で指定すれば、あらゆるところからの読み込みを許可できる。
    要するに、外部読み込みファイルのあるフォルダに(ポリシーファイルがアップロードできる=持ち主である)証明書であるcrossdomain.xmlを置けばよい
    基本的に、使う必要のあるフォルダのみに置くように。
     
     参照元/参考リンク(公式):Macromedia Flash Player 7 におけるセキュリティの変更について ページ3
 
onLoadが実行されない
  • onLoadは読み込みが完了したときに実行されるが、
    既にキャッシュに読み込まれているときには実行されない場合がある。
    onloadを定義してから読み込みを開始するとよい。

    先に書類を渡しておきながら、(ファイルの読み込み)
    次に書類を受け取ったらサインしてねとお願いしている。(onLoadを定義)
    噛み砕くとこんな状態。
    こんな簡単なこともできないのかと怒るのではなく、指示の仕方を振り返る。

    まずonLoadを定義して、読み込んだら〜してとお願いしておけば、
    次に読み込みが行われて、確実に実行できる。

  • また、

    hoge.onLoad = function(success){
        if(success){
            //読み込み時の処理
        }else{
            //読み込み失敗時の処理
        }
    }

    と書くことで、読み込み失敗時の処理を行うこともできる。
    エラーメッセージを出すなり、次の処理を行わないなど。
 
MX2004(AS2.0)は大文字小文字の変数を区別する
  • hogeと、Hogeは別の変数として扱われる
    MX(6)形式ではうまくいくのに、MX2004(7)でパブリッシュすると実行できないASがある。
    変数の名前を厳密に区別する必要がある。

     参考:変数のコツ
     参考:AS2について

 
 
 
テクニック、知識
 
AS(プログラミング)テクニック
  • while(true)ループ

    while(true){

    /-
    処理
    -/
    if(条件式){break;}
    }

    whileでループをする。
    ループの条件式が複雑で長くなるような場合でも見やすい

  • 必殺for break

    for(var i=0; i<10; i++){

    //処理
    if(条件式){break;}
    }

    もうforの処理が必要なくなったら、breakで脱出してしまう。
    while(true)ループと同様

  • 必殺if return

    function hoge(){
    if( !条件式 ){return;}//処理をせずにさっさと戻る

    /-
    処理
    -/
    }

    最初のifの括弧を後に残さないで、見やすくする。
    この場合、条件式がfalseのとき、要するにfunctionの処理が必要ないときは、さっさとreturnさせてしまう。

  • undefined初期化チェック

    if(init==undefined){
    init=true;
    //以下初期値データ
    }

    変数が未定義(undefined)ならば、初期化を実行する。
 
重たくなるAS
  • onEnterFrame
    onClipEvent(enterFrame)は便利だが多用しない

    カスタムマウスや、ドラッグの機能であれば、マウスが止まっているときは実行されないようにmouseMoveを利用する。
    マウスの移動がカクカクするのを防げる

    onClipEvent (mouseMove) {
    /-
    処理の内容
    -/
    updateAfterEvent();
    }

  • Stirng系の操作
    とにかく重くなる。
    辞書や文章の検索などは、致命的に重たい。
    実用的なスピードを得るには、CGIと組み合わせるような工夫が必須

  • 少数点以下の計算
    コンピュータは少数点以下の値は、擬似値で計算を行っている。
    なるべく整数にして計算を行ったほうがよい。
    また、擬似値で計算しているため、0.5+0.5が0.9になるようなことが稀にあるので、あまり信頼できない。

  • 使い終わった変数を残さない
    とにかく、delete。
    無駄な変数を作らなければ、ミスが減るので生産性も高くなる。

    初期化のメソッドを作り、初期化以外では、勝手に変数は作らないようにする。
    しっかりと初期化が出来れば、二度目の再生で前のデータが残っていて問題が発生することはなくなる。

    また、ローカル変数を利用して、必要のない変数がいつまでも残らないようにする。

    enterFrameやsetInteval()も、使い終わった後に、ifで何もしないようにするのではなく、ちゃんと自分で消えるようにしておく。

  • 無駄なアクセス回数を増やさない
    for(var i = 0; i < arr.length; i++)
    を、
    var nagasa = arr.length;
    for(var i = 0; i < nagasa; i++)
    と書く。
    forループ中、arr.lengthに毎回アクセスしないようにする。
 
変数のコツ
  • a、b、c、a1、a2のような適当な名前を使わない
    10行で終わるプログラムならば、それでもいいが、
    全体でアクセスする可能性のある変数は、デバッグを容易にするためにも、
    多少長くても、なんらかの意味のある言葉を使うように。

  • hoge1、hoge2のように連番にしない
    Array()を使うべき。
    ※配列が使えないインスンス名は、tama1のようにしてもよい。
    ただし、tamaMaxNum、tamaJyoutai[i]といった現在の数を管理する変数を用意しておく。

  • 誰が何をするのように、複数の言葉を組み合わせる。
    種類と型など、言葉のつなぎ方のルールを決めておく。

    gScore
    bActive
    msgString
    ufoNum
    f_hoge
    s_message

  • 最初の言葉は小文字にして、次の言葉は大文字で始める。
    可読性を高めるので必須。
    hentaiKamenSanjyou

    MX2004以降は大文字小文字の違いで変数を分けるのでより重要に。
    hogeとHogeは別の変数になった。

  • 予約語を含む名前は使わないようにする
    例:newColor→new と colorは予約語であり、
    new Colorという書き方もあるので、混同する恐れがある。
    例:hogePlay()→hoge.play()と見間違えたりタイプミスすることがある。
    hogeUgoke()などのように、絶対に間違えない変数を使う。
 
ASと合わせて使えるもの
  • CGI
    • Perl
    • PHP
    • C(++)

  • JavaScript

  • FCS
 
ASの苦手なこと
  • お絵かき
    MCとして線が多くなると重たくなる上に、別形式の画像で保存する機能がない

  • 3D(ゲーム)
    ビデオカードの3Dが使えないのと、計算そのものが遅いので不向き。
    Directorなどの別の方法を検討すべき。

  • 多くのMCが出てくるもの(弾幕STGゲームなど)
    描画能力が高くない、処理が遅くなりがち。
    環境によってプレイできない人が発生しやすい。hitTest()が重たい

  • 複雑な計算、時間のかかる計算
    単純に速度が遅いのと、あまりにもループ回数が多いと途中で勝手に中止される。
    フレームをまたいだ計算など、非常にトリッキーなプログラミングを要求される。

  • サーバーと同期をとるもの(ネット対戦ゲームなど)
    ウェブページのCGIゲーム程度なら可能だが、リアルタイムで情報の取得は確実性に欠ける
    FCSの利用を検討してみる。


  • AS(Flash)以外の方法
    ※ASと関係ないので、目的に合わせて選択し、調べて、利用する
    • web(ブラウザ)で実行
      • Director(ShockWave)
        Flashと似た操作感覚
        ビデオカードの3Dが使える。

      • Javaアプレット
        計算が速い(ブラウザで使うにしては)
        ※WindowsXPでは、インストールの手間があるので、PC初心者やJavaアプレットが嫌いな人には見てもらえない欠点がある。

      • Matrix Engine
        ビデオカードの3Dが使える

    • 実行プログラム
      C++
      C#
      VC
      Java
      などなど

 
スクリプトエディターを使う
 
特殊キーコード
  • Key.isDown(num)で取得
    再生環境に依存するので、多用はしないほうがよさそう
    あくまで、補助に使う程度で

  • マウス関連
    1左クリック
    2右クリック
    4ミドル
    5ボタン4
    6ボタン5

  • Windows限定IME関連
    245IMEがオン
    246IMEがオフ
    243全角がオフ
    244 全角がオン
    242ひらがなモード
    241カタカナモード
    240英数字モード
 
 
 
AS小ネタ
 
文字のサイズを測る
  • 新規のflaファイルで、

    ! "#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

    を使いたいフォントでテキストフィールドに入れ、ダイナミックテキストに直してから分解を1回かける
    画面からはみ出ても、すべて1行に書くこと

    以下のASをタイムラインに書いてプレビューすれば、自動で調べて書き出せる。

    var charX = new Array();
    for (var i in this) {
        var x = this[i]._x;
        if (x) {
            charX[this[i].text.charCodeAt(0)] = x;
        }
    }
    for (var i = 32; i<charX.length-1; i++) {
        trace(String.fromCharCode(i)+" : letterWidth["+i+"] = "+(charX[i+1]-charX[i]));
    }

 
奇数/偶数を判定
  • a%2

    1-a%2

  • a & 1

    ~a & 1

 
(操作するたびに)aの値を…
  • 0と1を切り替える

    a = Math.abs(a-1);

    a = 1-a;

    a ^= 1;

    a = Number(!a);

  • aがtrueだったら、1、falseだったら-1

    a = a*2 -1;

    a = [-1, 1][Number(a)];

  • 0と1と-1を切り替える

    a = 0;
    t = [];
    t[0] = 1;
    t[1] = -1;
    t[-1] = 0;

    a = t[a];

    a = (a+2) % 3 -1;

    a = ((a>>1)-a<<1) + (~(a>>1)&1);

  • 0, 1, 2, ... ,n - 1, n, 0, 1, 2, ... ,n - 1, n, 0, ...

    a = (a + 1) % (n + 1)

    a = ((a^n) + 0x7FFFFFFF >> 31) & a+1;

 
スロット風のカウント表示
  • 準備
    スロットの数字部分を作る。
    MCにマスクとモーショントゥイーンを駆使して、
    フレーム1から10で、0から1を表示
    フレーム11から20で、1から2を表示…
    フレーム91から100で、9から0を表示となるようにする。
    (フレーム数が10の時は、表示される数字には、1が来るようにする。)

  • スロットの文字のMCにクリップアクション

    onClipEvent (load) {
        num = 0;
        function setNum(num) {
            this.num = num;
        }
    }
    onClipEvent (enterFrame) {
        if (num == 0) {
            num = 10;
        }
        if (_currentframe<num*10 || num*10<_currentframe-5) {
            this.play();
        } else {
            this.gotoAndStop(num*10);
        }
    }

    ASを書いた後に、
    コピーして、配置。インスタンス名をs4,s3,s2,s1とつける。
    (s4〜s1全てに同じASが書かれているようにする)
    s4は4桁目(n000)、s3は3桁目(0n00)になる。

  • _rootに変数inputを持つテキスト入力を作成
    (ここに数値を入れることでカウンターの数値を変化させられる。)
    _rootに記述

    this.onEnterFrame = function() {
        setSlotNum(input);
    };
    function setSlotNum(input) {
        var arr = new Array();
        arr = input.toString().split("").reverse();
        nagasa = 4;
        for (var i = 0; i<nagasa; i++) {
            var mc = this["s"+(i+1)];
            var num = Number(arr[i]);
            if(typeof(num) != "number"){num = 0;}
            mc.setNum(num);
        }
    }

  • 説明
    スロットの文字部分は、
    s3.setNum(5)とすれば、s3が5まで動くようになっている

    引数が、0のときは10にするようにする。(つまり0まで再生)
    ifの条件式は、目標の数字になったら(+5フレーム以内ならば)停止させている。
    (+5フレーム以内という条件は、目標の数字が6で、現在の表示が5のときに、いきなり、6に表示がいかないようにしている。)

    _root上のASは、
    inputという変数の値を毎フレームsetSlotNum()に送っている。
    setSlotNum()では、まずは、string文字列にしてから、配列に入れて分解し、
    配列をひっくり返し(後ろからs1、s2のため)、
    カウンターの桁数のnagasaだけ、ループさせて、setNum()を実行している。

    ただし、setNum()に送る数値がNumberではないときは、0を指定している。
    0012のような場合に、00の部分が勝手にループしないように止めることが出来る。

 
 
 
大項目
 
★項目1
 
項目2
 
項目3
 
関係のメソッド/プロパティ
  • メソッド

  • プロパティ
 
 
 
大項目
 
★項目1
 
項目2
 
項目3
 
関係のメソッド/プロパティ
  • メソッド

  • プロパティ