メイン | 2005年04月 »

スクリプトの種類と設定する場所

ActionScriptスクリプトは、フレームに設定するフレームアクション、インスタンスに設定するオブジェクトアクション(ムービークリップアクション、ボタンアクション)、そして外部ファイルのActionScriptファイル(ASファイル)に分けることができます。これらの違いはムービーの構造や目的によって使い分けますが、いずれの場合もスクリプトはアクションパネルを開いて書き込みます。(スクリプトの種類→p.??)

・アクションパネル
アクションパネルはウインドウメニュー>開発パネル>アクションを選択して開きます。プロパティウインドウを表示している場合には、パネルの右端に[このオブジェクトのActionScriptの編集]ボタンをクリックして選択しているオブジェクトのアクションパネルを表示することもできます。

note:
Flash MX 2004からはノーマルモード/エキスパートモードの切替はなくなりました。

図2-1-1 アクションパネルを開く。

ActionScriptのメソッド名や演算子などのエレメントはアクションパネル上部のツールバーに並んでいる[スクリプトに新規アイテムを追加...]メニューから選んで入力できます。または、パネルの左の欄のツリーでダブルクリックして入力することもできます。

図2-1-2 ActionScriptのエレメントはメニューや左の欄のツリーから選んで入力できます。

・ActionScriptファイル
ActionScriptファイル(ASファイル)はActionScriptを書いた外部ファイルです。ASファイルには、コンパイル時に#includeアクションでスクリプトに読み込む単純な外部ファイルとしての役割とActionScript2.0のクラス定義で利用するASファイルという2つの役割があります。
ASファイルは拡張子に.asを付けて保存したテキストファイルですが、Flash MX 2004 Professional版ではASファイルを新規作成でき、アクションパネルを使ってコード入力やエラーチェックができます。ASファイルは一般のテキストエディタで作っても問題ありません。

・スクリプトの書き出しと#includeアクション
アクションパネルでスクリプトを選択して反転させ、アクションパネルの右肩にあるポップアップメニューから[スクリプトの書き出し...]コマンドを実行すれば、選択しておいたスクリプトがASファイルとして書き出されます。
 逆に、test.asファイルとして書き出しておいたASファイルならば、

#include "test.as"

と書けば、この位置にスクリプトが読み込まれます。行末に;を書かない点に注意してください。この位置に読み込むASファイルの最終行は改行するか;を付けます。長いスクリプトや汎用性のあるスクリプトはASファイルとして書き出しておくと流用などが効率よく行えます。

note:
ActionScript2.0のクラス定義ファイルはクラスパスで参照するので、#includeアクションで読み込む必要はありません。

投稿者 oshige : 11:55 | コメント (0) | トラックバック

コードヒント

ビルトインクラスの名前をタイプするとコードヒントが表示されます。コードヒントは、そのオブジェクトで利用できるメソッド名やプロパティ名のリストになっています。候補リストの中からメソッドやプロパティを選びたい場合には、アルファベットを続けてタイプして名前を選択します。選択されたところでreturnキーを押せば確定します。上下の矢印キーで候補を選ぶこともできます。コードヒントが表示されるタイミングは、Math.やArray.のようにクラス名に続いてドットをタイプしたときです。

図2-1-3 クラス名に続いてドットをタイプするとコードヒントが表示されます。

・コードヒントを閉じる・表示する
 コードヒントを閉じるにはコードヒント以外の位置をクリックするかESCキーを押します。カッコが必要なエレメントのコードヒントでは)をタイプします。消えたコードヒントを再び表示するには、スクリプトパネルにある[コードヒントの表示]ボタンをクリックします。ctrl+スペースバーでも表示できます。

・オブジェクトの厳密な型指定によるコードヒント表示
ActionScript2.0ではオブジェクトのデータ型を厳密に指定できます。ビルトインクラスのデータ型を指定すると、変数名をタイプした場合にコードヒントが表示されます。データ型指定を行う式を記述する際にも変数名に続いて:をタイプした時点でコードヒントが出ます。(厳密な型指定→p.??)

図2-1-4 厳密な型指定を行うとコードヒントが表示されるようになります。


・接尾辞によるコードヒント表示
変数のデータ型を厳密に指定しなくても、ビルトインクラスについてはmy_array、my_mc、my_btnのようにオブジェクト名の接尾辞を次のものにすればクラスに応じたコードヒントが表示されます。

ビルトインクラス   接尾辞
Array        _array
Button        _btn
Camera        _cam
Color         _color
ContextMenu     _cm
ContextMenuItem   _cmi
Date         _date
Error         _err
LoadVars       _lv
LocalConnection    _lc
Microphone      _mic
MovieClip       _mc
MovieClipLoader   _mcl
PrintJob       _pj
NetConnection    _nc
NetStream      _ns
SharedObject     _so
Sound        _sound
String         _str
TextField       _txt
TextFormat      _fmt
Video         _video
XML          _xml
XMLNode       _xmlnode
XMLSocket      _xmlsocket


図2-1-5 接尾辞を利用したコードヒント。

・エレメントのコードヒント
 if、do whileなどのカッコが必要なエレメントでは、if(のように(をタイプした時点で書式のコードヒントが表示されます。forのようにパラメータを必要とするエレメントではfor(とタイプした時点でパラメータの書式が示されます。このとき、複数のパラメータの与え方がある場合には「1 of 3」のように複数の書式が表示され、その中から矢印ボタンをクリックして選ぶことができます。矢印ボタンのクリックはctrl+→、ctrl+←でも行えます。

図2-1-6 エレメントの書式のコードヒント。

 また、Escキーに続いてifとタイプするだけでifの書式が入力されるというように、Escキーを組み合わせたショートカットがあります。アクションパネルの[表示オプション]メニューの[Escショートカットキーの表示]をチェックしておくと、どのような組み合わせが利用できるのかが表示されます。


・コメントによるコードヒント表示
コードヒント表示が行われるように、コメントを利用してオブジェクトのデータ型を指定することができます。ただし、これは勧められる方法ではありません。

図2-1-7 コードヒント表示の目的でコメントを利用してデータ型を指定する方法。

投稿者 oshige : 12:03

コメント文

スクリプトの説明などをコメント文として書き込むことができます。アクションパネルのメニューの[シンタックスに色を付ける]がチェックしてあるとき、初期設定ではコメント文は灰色で表示されます。コメント文の書き方は2通りあります。
1つは//に続けてコメント文を書く方法です。行の中の//の後に続く入力は、スクリプトではなくコメント文としてみなされて実行されません。
2つ目は/*から始まり、*/で終わる間の入力です。複数行にわたってコメント文を書きたい場合やデバッグの最中に一時的に複数行のスクリプトを実行したくない時にコメントアウトするときに便利です。


図2-1-8 コメント文。初期設定ではコメントは灰色で表示されます。

投稿者 oshige : 12:04

空行と改行、セミコロン;

スクリプトを見やすくするために、スクリプトの中に自由に空行を入れることができます。
スクリプトは改行によって区切られるのではなく、;をステートメントの区切りとします。ステートメントの最後に;があれば改行は必要ありません。行末に;がない場合にも、スクリプトの構文を判断して改行をスクリプトの区切りとして解釈してくれます。

投稿者 oshige : 12:05 | コメント (0) | トラックバック

スクリプトの固定

アクションパネルの押しピンの形をした[スクリプトの固定]ボタンをクリックすると、現在開いているスクリプトをタブに登録できます。1つのムービーで複数のスクリプトを検討したいときに便利な機能です。固定したスクリプトを閉じるには、スクリプトをタブで開き[固定したスクリプトを閉じる]ボタンをクリックします。

図2-1-9 [スクリプトの固定]ボタンをクリックすると、現在開いているスクリプトをタブに登録できます。

note:Windows版では複数のFlashファイルを開いたとき、ファイルやアクションパネルをタブで切り替えることができます。

投稿者 oshige : 12:06 | コメント (0) | トラックバック

自動フォーマットと表示オプション

アクションパネルをスクリプトの構造が見やすくなるように自動的にインデントが行われます。指定のキーワードによって自動的にインデントされる場合もありますが、途中を削除したりした場合などではインデントが正しくなりません。そのような場合にはアクションパネルの[自動フォーマット]ボタンをクリックします。このとき、スクリプトにシンタックスエラー(スペルミスや書式などの文法エラー)があるとインデントが行われません。どこがエラーなのか知りたい場合には、[シンタックスチェック]ボタンをクリックします。エラーがあれば、エラーの場所とその内容が出力パネルに表示されます。
 改行の位置や演算子の前後の空白挿入などのいくつかの設定は、アクションパネル右のメニューの[自動フォーマットオプション...]で設定を選ぶことができます。行番号は表示オプションメニューで表示するように設定できます。アクションパネルのフォントの種類やサイズは環境設定のActionScriptパネルで行います。環境設定では自動インデントやコードヒント、シンタックスの色なども設定できます。

図2-1-10 自動フォーマットの書式を選ぶことができます。

投稿者 oshige : 12:06 | コメント (0) | トラックバック

スクリプトのシンタックスチェック

スクリプトを入力するアクションパネルにはシンタックスチェック、すなわち書式の間違いをチェックする機能があります。
 アクションパネルの[シンタックスチェック]ボタンをクリックするとシンタックスのチェックが行われ、エラーが見つかった場合には、エラーが見つかった行と内容が出力パネルに表示されます。シンタックスチェックでは、#includeで読み込まれるASファイルの有無と内容のチェックも行います。
 なお、[自動フォーマット]ボタンをクリックしたときにもシンタックスのチェックが行われますが、外部ASファイルのチェックは行われません。

図2-2-1 [シンタックスチェック]ボタンをクリックするとシンタックスエラーの内容が出力パネルに表示されます。

note:
出力パネルの結果はパネル右上のメニューの[ファイルに保存...]でテキストファイルに書き出せます。

・厳密なデータ型チェック
変数や関数の戻り値にデータ型を指定しておくと、シンタックスチェックの際にデータの型もチェックされます。たとえば、次のスクリプトでは変数msgのデータ型はストリングに限定されているので、数値を入力するステートメントはエラーになります。(厳密なデータ型→ p.???)


//データ型エラーになる式
var msg:String = 123;

関数の引数にデータ型を指定することもできます。ただし、データ型のチェックはあくまでもコンパイル時に行われるので、実行時に与えた引数はチェックされません。

//引数のデータ型を指定している関数
function test1(v:Number) {
  var ans = v*2;
  return ans;
}

test1()関数の引数のデータ型をNumberと指定しているので、次の行はコンパイル時にエラーになります

test1("テスト");

関数の戻り値にデータ型を指定することもできます。関数から戻る値のデータ型を指定できることから、データ型を指定した変数への代入の際などにデータ型を比較できるようになります。

//戻り値のデータ型を指定した関数
function test2():Number {
  var ans = 123;
  return ans;
}

 test2()の戻り値のデータ型はNumberなので、次の式ではmsg変数のString型と一致せずにエラーになります。

var msg:String = test2();

投稿者 oshige : 12:51 | コメント (0) | トラックバック

trace()で出力パネルに書き出す

スクリプトの中でtrace()ステートメントを使えば、ムービープレビューの際に変数の値などを出力パネルに書き出すことができます。
たとえば、ステージにムービークリップシンボルのインスタンスを作ってtest_mcと名前を付け、メインのタイムラインのフレーム1に次のフレームアクションを書き込みます。ムービーをプレビューしてインスタンスをクリックすると、クリックするたびにインスタンスの座標が少しずつ移動します。出力パネルには水平、垂直に移動する距離が書き出されます。trace([randx, randy])のようにリストの形式でと複数の値を指定すると、値はカンマ区切りで書き出されます。

sampleファイル→trace.fla

フレームアクション:フレーム1
test_mc.onPress = function() {
  //移動量をランダムに決める
  randx = Math.ceil(Math.random()*60-30);
  randy = Math.ceil(Math.random()*60-30);
  trace([randx, randy]);
  //座標の移動
  this._x += randx;
  this._y += randy;
  trace("移動しました"); //出力→ 移動しました
};

図2-2-2 動作確認の目的で変数の値とメッセージをtrace()を使って出力パネルに書き出します。

投稿者 oshige : 12:54 | コメント (0) | トラックバック

デバッガの活用

デバッガを利用するとインスタンスのプロパティや変数の値などをムービーを実行しながら見張ることができます。デバッガを使うには、制御メニューから[ムービーのデバッグ]を選択します。するとムービーのプレビューが表示され、同時にデバッガパネルも開きます。
[ムービーのデバッグ]を実行した直後はムービーの再生が停止した状態になっています。ムービーが停止した状態でもインスタンスのプロパティなどは値を調べることができます。ムービーの再生を開始するには、デバッガパネルの[続行]ボタンをクリックします。ムービーを再開すると変数の値などの変化をリアルタイムに見ることができます。

sampleファイル→debugger.fla

図2-2-3 [ムービーのデバッグ]を実行した直後は停止した状態になっています。[続行]ボタンで再開します。

デバッガの右にはスクリプトを選んで表示できます。行番号をクリックしてブレイクポイントを打てば、ムービーの再生を一旦停止して変数の値などを確認できます。[続行]ボタンをクリックすれば再びムービーが再開します。ただし、この機能はクラス定義ファイルなどの外部ActionScriptファイルでは使えません。


図2-2-4 ブレイクポイントを打ったステップで一旦停止します。

・デバッガメニュー
また、ムービープレビューを行っている最中にはデバッガメニューが利用できます。デバッグメニューの[オブジェクトのリストアップ]、[変数のリストアップ]を選択すると、オブジェクトや変数の情報が出力パネルに書き出されます。

投稿者 oshige : 12:54 | コメント (0) | トラックバック

Errorクラス

Errorクラスはスクリプト実行時にあらかじめ設定した条件が発生したときに例外処理を行うためのもので、デバッグの目的で利用するものではありません。Flash Playerの実行時エラーのイベントを自動的に処理するというものでもありません。
少し難しいですがここでErrorクラスを利用した例を示しておきましょう。次の例では、テキストフィールドmyURLに入力されたURLをチェックして、URLが空だった場合あるいは"http:"から始まっていないときにエラー処理を行います。エラーがない場合には指定のURLをブラウザで開きます。

sampleファイル→errorurl.fla

フレームアクショント:フレーム1
//webBtnボタンを設定する
webBtn.onRelease = function() {
  try {
    errMsgfld.text = ""; //エラーフィールドのクリア
    var testURL = myURL.text; // URLを取り込む
    var theURL:String = urlcheck(testURL); // URLのチェック
    getURL(theURL, "_blank"); // Webページの移動
  } catch (e_err:Error) {
    errMsg.text = "エラー;" + e_err.message;
  }
};
//URLをチェックする
function urlcheck(url:String):String {
  if (url == "") {
    throw new Error("URLが空です。");
  } else if (url.substr(0, 5) != "http:") {
    throw new Error("URLはhttp:から書いてください。");
  }
  return url;
}

このスクリプトを試すには、ステージにボタン、入力テキスト、ダイナミックテキストを配置し、プロパティインスペクタでそれぞれにwebBtn、myURL、errMsgというインスタンス名を付けます。そして、メインのタイムラインのフレーム1にこのフレームアクションを書き込みます。入力テキストmyURLにURLを書き込んでwebBtnボタンをクリックするとURLがチェックされます。urlcheck()メソッドに渡された引数urlの値が適当な値であるかどうかはif文でチェックします。問題なければ引数urlの値をそのままreturnで戻します。

図2-2-5 URLを入力するフィールドが空のままボタンをクリックしたとき。

図2-2-6 URLが"http:"からはじまっていなかったとき。

このスクリプトで注目する箇所は、webBtnボタンのonReleaseハンドラではtry~catchのブロック、urlcheck()メソッドではthrowです。先にurlcheck()メソッドを見るとわかるように、引数のurlが不適当だった場合にはErrorクラスのインスタンスを生成してそれをthrowしています。throwされたインスタンスはurlcheck()メソッドを呼び出したonReleaseハンドラのcatchブロックが受け取りe_err変数に入いります。e_errインスタンスのmessageプロパティにはErrorクラスでインスタンスを作る際に引数にしたメッセージ文が入ってます。なお、try~catchのブロックの最後に必ず実行するfinallyブロックを付けることができます。

note:
Errorクラスを拡張したカスタムクラスのErrorインスタンスをスローすれば、複数のcatchブロックで個別に受け取れます。その場合は引数のタイプ指定でインスタンスを振り分けます。

投稿者 oshige : 12:55 | コメント (0) | トラックバック

大文字と小文字

Flash Player 7以降向けにパブリッシュされたムービーからはキーワード、、変数名、メソッド(関数)名、クラス名、プロパティ名などの大文字と小文字が区別されます。#includeで読み込む外部ファイルやクラス定義のためのActionScriptファイルでも同様です。たとえば、変数aと変数Aは区別されます。

var a = 1;
trace("a=" + a); // 変数aを調べる
trace("A=" + A); // 変数Aを調べる

出力結果
a=1
A=undefined

ムービークリップシンボルのインスタンスに付けるインスタンス名も大文字と小文字が区別されます。次の2つのインスタンスはmy_mcとMy_MCの別々のインスタンスとして認識されます。

my_mc._x = 100; // インスタンスmy_mcをx座標100の位置に移動
My_MC._y = 130; // インスタンスMy_MCをy座標130の位置に移動


ただし、古いバージョンからのアクションには大文字と小文字を区別せずに動作するものがあります。

var n = 15;
this.gotoAndPlay(n);//フレーム15へ移動
this.gotoandplay(n);//フレーム15へ移動

投稿者 oshige : 10:27 | コメント (0) | トラックバック

名前の付け方(識別子)

変数、プロパティ、メソッド(関数)、インスタンスなどに付ける名前を識別子といいます。識別子の先頭の1文字は、英字、アンダースコア、ドル記号のいずれかでなければなりません。数字やドットで始まる名前は使えません。名前の中に演算子で使っている記号を入れることはできません。すでにActionSriptが使っている予約語を識別子に使うことはできません。
なお、インスタンス名の末尾に_mcといった接尾辞を付けるとアクションパネルにスクリプトを入力する際にオブジェクト型に応じたコードヒントを表示できるようになります(コードヒント→p.??)。

予約語:
break、case、class、continue、default、delete、dynamic、else、extends、for、function、get、if、implements、import、in、instanceof、interface、intrinsic、new、private、public、return、set、static、switch、this、typeof、var、void、while、with

識別子の良い例:v、v1、v2p、usrName、my_mc
識別子の悪い例:1v、v(2p)、v-1、default、性別

投稿者 oshige : 10:32 | コメント (0) | トラックバック

演算子

ある値に対して演算を行い、新しい値を作る記号を演算子といいます。簡単なものでは加算の記号の+があります。演算子には次のようなものがあります。

note:
演算の対象となる値や変数のことをオペランド(operand)と呼びます。1+2ならば1と2がオペランドです。演算子はオペレータ(operator)です。

■算術演算子
算術演算子は数値の演算を行います。+-*/は一般的な加減乗除の計算と同じです。/の除算では、0での割り算を行ってもエラーにはならず値はInfinity(正の無限大)または-Infinity(負の無限大)になります。なお、+と-は数値の前に付けて正負を示す符号としても機能します。

算術演算子
+ 加算(足し算)
- 減算(引き算)
* 乗算(掛け算)
/ 除算(割り算)
% 剰余(割り算の余り)

例:
a = 1 + 2; // aに3が入ります。
b = 10 - 2 - 1; // bに7が入ります。
c = 4 * 3; // cに12が入ります。
d = 12 / 4; // dに3が入ります。
e = 15 % 6; //15割る6の結果は2余り3なので、eには3が入ります。

■ストリング演算子
+は加算の演算子ですが、オペランドの一方がストリング(String、文字列)のとき、ストリングの連結(文をつなげる)を行う演算子になります。

ストリング演算子
+ ストリングの結合
add ストリングの結合(使用を避ける演算子)


例:
name = "鈴木";
age = 25;
msg1 = name + "さん" // msg1に"鈴木さん"が入ります。
msg2 = "わたしは" + age + "です"; //msg2に"わたしは25です"が入ります。


■代入演算子
代入演算子は変数に値を入力したり、プロパティに値を設定する場合に使います。演算結果を代入するものを複合演算子と呼ぶこともあります。


代入演算子
= 代入・設定
+= 加算後代入
-= 減算後代入
*= 乗算後代入
/= 除算後代入
%= 剰余を代入
++ インクリメント(1足す)
-- デクリメント(1引く)

算数の計算式の「1 + 2 = 3」の=は等号ですが、ActionScriptの=は「ans = 1 + 2」のように式を書いて、=の右項の値を左項の変数やプロパティに代入あるいは設定します。ActionScriptの等号は==または===です。
また、「a = 1 * 2 + 3」のように演算子を結合して式を作れるのと同様に=も連結できます。このとき、式が右側から実行されていく点に注意してください(演算子の結合性→p.??)

例:
a = 10; // aに10を代入
b = c = 10 + 1; // bとcに11を代入

例:
d = 3;
e = 2;
x = y = (z = d + e) * 2;
trace(x); //出力→ 10
trace(y); //出力→ 10
trace(z); //出力→ 5

複合演算子は演算と代入を組み合わせたものです。値が代入される変数は先に初期化されている必要があります。

例:
// aに3足す
a = 10;
a += 3;
//a = a + 3と同じ


例:
// bから8を引く
b = 15
b -= 4 * 2; // 15- 8で7になる
//b = b - 4 * 2と同じ

例:
// cに7を掛ける
c = 3;
c *= 7;
//c = c * 7と同じ

例:
// dを3で割る
d = 15
d /= 2 + 1;
//d = d /(2+1)と同じ


// eを11で割った余りをeに入れる
e %= 11;
//e = e % 11と同じ


++と--はオペランドに1を加算または減算する演算子ですが、演算子をオペランドの前に置くか後ろに置くかで演算と代入の順が違います。++aのようにオペランドの前に演算子を置いたものをプリインクリメントと呼び、先に変数aに1を加算してから残りのステートメントを実行します。一方、a++ようにオペランドの後ろに演算子を置いたものをポストインクリメントと呼び、ステートメントを実行した後から変数aに1を加算します。--a、a--も同様でそれぞれプリディクレメント、ポストデクリメントと呼びます。

例:
//aに1を加算した後でステートメントを実行する
a = 5;
x = ++a + 3;
trace(x); // xは9になります。aは既に6になっています。
trace(a); // aは6になります。aには1加算されています。

例:
//ステートメントを実行した後でaに1を加算する
a = 5;
x = a++ + 3;
trace(x); // xは8になります。aは5のままで計算されています。
trace(a); // aは6になります。aには1加算されています。

例:
//aから1を減算した後でステートメントを実行する
a = 5;
x = --a + 3;
trace(x); // xは7になります。aは既に4になっています。
trace(a); // aは4になります。aから1減算されています。

例:
//ステートメントを実行した後でaから1を減算する
a = 5;
x = a-- + 3;
trace(x); // xは8になります。aは5のままで計算されています。
trace(a); // aは4になります。aから1減算されています。


■比較演算子
比較演算子は、左右のオペランドの大きさまたは同じものかどうかを比較します。結果は、条件を満たすときにtrue、満たさない場合にはfalseの論理値になります。比較演算子は、if、while、forといった条件によって制御を判断するステートメントで主に利用します。

note:
trueおよびfalseを論理値と呼びます。trueの否定はfalse、falseの否定はtrueです。

比較演算子
a == b 等価(aとbが等しいときにtrue、等しくないときfalse)
a != b 不等価(aとbが等しくないときtrue、等しいときfalse)
a < b より小さい(aがbより小さいときtrue、そうでないときfalse)
a <= b 以下(aがb以下のときtrue、そうでないときfalse)
a > b より大きい(aがbより大きいときtrue、そうでないときfalse)
a >= b 以上(aがb以上のときtrue、そうでないときfalse)
a === b 厳密な等価(aとbが値もデータ型も等しいときにtrue、そうでないときfalse)
a !== b 厳密な不等価(aとbが値もデータ型も等しくないときにtrue、そうでないときfalse)

==と!=の等価であるかどうかの判断はデータ型に応じて比較されます。このとき、数値と論理値を比較した場合は、trueは1、falseは0として比較します。つまり(true==1)と(false==0)はtrueになります。一方、===と!==の厳密な等価の判断では、数値と論理値は別物とみなし、(true==1)と(false==0)はfalseになります。nullとundefineの比較でも同様です。(null==undefine)はtrueですが、(null===undefine)はfalseです。

例:
//my_mcのx座標がマイナスならばmy_mcの位置をx座標300へ動かす
if (my_mc._x < 0) {
 my_mc._x = 300;
}


次のものは使用を避ける演算子に分類されているものです。

使用を避ける演算子
<> 不等価
eq 等価
ne 不等価
lt より小さい
le 以下
gt より大きい
ge 以上

■論理演算子
論理演算子は、trueまたはfalseの論理値をオペランドとして扱う演算子です。(論理値→p.??)

論理演算子
a || b 論理和 (a、bどちらか一方でもtrueならばtrue。両方ともにfalseのときfalse)
a && b 論理積 (a、bともtrueのときtrue。そうでなければfalse)
!a 否定 (aがtrueならばfalse。aがfalseならばtrue)

例:
// 変数xの値が0以下または300以上のときにdの値に-1を掛ける
if ((x <= 0) || (x >= 300)) {
 d *= -1;
}

例:
//my_mcをクリックするたびにmy_txtフィールドの表示・非表示が入れ替わります
my_mc.onPress = function() {
 var v = my_txt._visible;
 my_txt._visible = !v;
};

sampleファイル→ronri_hitei.fla


次のものは使用を避ける演算子に分類されているものです。

使用を避ける演算子
or 論理和
and 論理積
not 論理否定(単項演算子)

■ビット演算子
ビット演算子とは、値を2進数に換算して計算を行うものです。各桁(ビット)ごとに値を比較したり、桁をシフトする演算を行います。

ビット演算子
| ビット単位の論理和 (OR)
& ビット単位の論理積 (AND)
~ ビット単位の否定 (NOT)
^ ビット単位の排他的論理和 (XOR)
<< ビット単位の左シフト
>> ビット単位の右シフト
>>> ビット単位の符号なし右シフト
|= ビット単位の排他的論理和 (OR) を代入
&= ビット単位の論理積 (AND) を代入
^= ビット単位の排他的論理和 (XOR) を代入
<<= ビット単位での左シフト後代入
>>= ビット単位に右シフト後代入
>>>= ビット単位に符号なし右シフト後代入

ビット単位の論理和では値を2進数に換算して各ビットごとに比較し、どちらかが1ならば1にします。たとえば、6(2進数で110)と5(2進数で101)のビット単位の論理和は7(111)になります。同様にビット単位の論理積では両方が1のときに1にし一方が0ならば0にします。6と5のビット単位の論理積は4(100)になります。
2進数における桁のシフトは左へ1シフトすると2倍(2×1階乗)、左へ2シフトすると4倍(2×2階乗)になり、逆に右へ1シフトすると1/2倍(2×-1階乗)、右へ2シフトすると1/4倍(2×-2階乗)になるというように値が2のn階乗で変化します。


例:
a = 6 | 5;
trace(a); //出力→ 7

b = 6 & 5;
trace(b); //出力→ 4

c = ~2
trace(c) //出力→ -3

d = 4 << 2;
trace(d); //出力→ 16

■記号演算子
スクリプトでは次に示す記号を利用します。+-は算術演算子ですが、符号にも利用します。

記号演算子
+ プラス符号(単項演算子)
- マイナス符号(単項演算子)
() グループ化演算、関数のパラメータを囲む
, ステートメントの区切り
. ドット演算子(メソッド、プロパティ、変数、クラスパス、メンバーへのアクセス)
: タイプの指定
[] 配列演算子、配列アクセス(プロパティ、変数、リニアリストへのアクセス)
{} 配列オブジェクト(連想配列、プロパティリストへのアクセス)
// コメント行区切り記号
/* コメントブロック区切り記号(開始)
*/ コメントブロック区切り記号(終了)

カンマを使えば、同一行に複数のステートメントを区切って書くことができます。通常、カンマはforループステートメントの中で利用しますが、次のように使うこともできます。(forループステートメント → p.??)

例:
a = 1, b = +a;
trace(a), trace(b);

これをセミコロンを使って書くと次のようになります。どちらも同じ結果になります。

例:
a = 1; b = +a;
trace(a); trace(b);

■その他の演算子
その他の演算子として、次のようなものがあります。

その他の演算子
?:  条件演算子(三項演算)
typeof  値のデータ型を調べる(単項演算子)
instanceof インスタンスが指定のクラスかどうかチェックする
void  値を破棄しundefinedを返す(単項演算子)
new  クラスからインスタンスを生成する
delete  変数、インスタンス、プロパティを消去する


?:は「条件式 ? 値1 : 値2;」の3つのオペランドをもった演算子です。条件式がtrueならば値1、条件式がfalseならば値2を返します。

例:
//変数aの値が60以上ならば"合格"、60未満ならば"不合格"とrに代入する
r = (a >= 60) ? "合格" : "不合格";

次のように条件に応じて処理を分岐させる目的でも利用できます。次のサンプルのmy_mcインスタンスをクリックするとcntの値が1からカウントアップされ、10を越えたならば再び1に戻ります。cntの値は出力パネルに書き出されます。

sampleファイル→sankou.fla

例:
//cntが10未満なら1加算し、10以上ならば1を代入する
my_mc.onPress = function() {
 (cnt < 10) ? (++cnt) : (cnt = 1);
 trace(cnt);
};


typeofはデータ型を返す演算子です。typeof(v)のように関数のような記述を目にしますが、実際にはtypeof vのようにカッコは不要です。(データ型 → p.??)

例:
v = "test";
trace(typeof v); //出力→ string

v = new Date();
trace(typeof v); //出力→ object

投稿者 oshige : 10:34 | コメント (0) | トラックバック

演算子の優先順位と結合性

スクリプトのステートメントは、左から読んで順に実行するとは限りません。ステートメントの読み方、すなわち演算の実行の順番は、演算子の優先順位と結合性によって決まります。

■演算子の優先順位
同一ステートメントで複数の演算子を使っている場合、演算子の優先順位によって演算の順番が決まります。わかりやすい例としては次のような加減乗除の演算子を使った式があげられます。

例:
a = 8 + 2 * 3 - 10 / 5;

このステートメントでは*と/の優先順位が+と-より高いので、*と/の演算が先に実行されます。これはカッコを使った次の式と同様になります。多くの場合はカッコを使うことで演算の順番をわかりやすく示すことができます。

例:
a = 8 + (2 * 3) - (10 / 5);

■演算子の結合性
演算子の結合性とは、「a = b = c」のように同一の演算子がオペランドをはさんでつながっているときに、右から左へ実行(←)するか、左から右へ実行する(→)かを示すものです。
たとえば、「a = b = c」では=の結合性は「右から左へ」なので、まずbにcの値を代入し、次にaにbの値を代入します。結果として、a、b、cは同じ値になります。カッコを使って書くと「a = (b = c)」のように実行することになります。

例:
a = 1;
b = 2;
c = 3;
a = b = c;
// a、b、cのすべてが3になる

演算子を優先順位が高い順から並べると次のようになります。演算子の結合性は、右から左へと実行していくものを←、左から右へと実行していくものを→と記してあります。


演算子  説明    結合性
+  プラス符号    ←
-  マイナス符号    ←
~  ビット単位の論理否定 (NOT)  ←
!   論理否定 (NOT)    ←
not   論理否定 (NOT)    ←
++   ポストインクリメント    →
--   ポストデクリメント    →
( )    関数(パラメータを囲む)   →
[ ]   配列エレメント    →
.   構造体メンバー参照    →
++   プリインクリメント   ←
--  プリデクリメント   ←
new  オブジェクトの割り当て   ←
delete  オブジェクトの割り当て解除  ←
typeof  オブジェクトの種類   ←
void  未定義の値を返す   ←
*  乗算     →
/  除算     →
%  剰余     →
+  加算、 ストリングの連結  →
add  ストリングの連結   →
-  減算     →
<<  ビット単位の左シフト   →
>>  ビット単位の右シフト   →
>>>  ビット単位の右シフト (符号なし)  →
<  より小さい    →
<=  以下     →
>  より大きい    →
>=  以上     →
instanceof インスタンス    →
lt  より小さい    →
le  以下     →
gt  より大きい    →
ge  以上     →
==  等しい     →
!=  等しくない    →
eq  等しい     →
ne  等しくない    →
&  ビット単位の論理積 (AND)  →
^  ビット単位の排他的論理和 (XOR)  →
|  ビット単位の論理和 (OR)   →
&&  論理積 (AND)    →
and  論理積 (AND)    →
||  論理和 (OR)    →
or  論理和 (OR)    →
?:  三項演算    ←
=  代入     ←
*=、/=、%=、 複合代入    ←
+=、-=、&=、
|=、^=、<<=、
>>=、>>>=
,   カンマ     →

投稿者 oshige : 10:39 | コメント (0) | トラックバック

定数とエスケープ記号

定数として扱える値には次のようなものがあります

定数(プロパティを含む)
true  真(falseの逆を示すブール値)。数値コンテキストでは1と評価される
false  偽(trueの逆を示すブール値)。数値コンテキストでは0と評価される
Infinity 正の無限大
-Infinity 負の無限大
null  値がないことを示す特別な値
undefined 未定義を示す特別な値
newline  キャリッジリターン(改行コード)
Key.BACKSPACE BackSpaceキーのキーコード値 (8)
Key.CAPSLOCK CapsLockキーのキーコード値 (20)
Key.CONTROL Ctrlキーのキーコード値 (17)
Key.DELETEKEY Deleteキーのキーコード値 (46)
Key.END  End キーのキーコード値 (35)
Key.ENTER Enter キーのキーコード値 (13)
Key.ESCAPE Esc キーのキーコード値 (27)
Key.HOME Home キーのキーコード値 (36)
Key.INSERT Ins キーのキーコード値 (45)
Key.PGUP PageUpキーのキーコード値 (33)
Key.PGDN PageDownキーのキーコード値 (34)
Key.SHIFT Shiftキーのキーコード値 (16)
Key.SPACE スペースバーのキーコード値 (32)
Key.TAB  Tabキーのキーコード値 (9)
Key.RIGHT 右向き矢印キーのキーコード値 (39)
Key.LEFT 左向き矢印キーのキーコード値 (37)
Key.UP  上向き矢印キーのキーコード値 (38)
Key.DOWN 下向き矢印キーのキーコード値 (40)
Math.E  自然対数の基底e
Math.PI  円周率
Math.LN2 2の自然対数
Math.LN10 10の自然対数
Math.SQRT1_2 1/2の平方根
Math.SQRT2 2の平方根
Number.MAX_VALUE 最大の数値(約1.79E+308)
Number.MIN_VALUE 最小の数値(約5e-324)
Number.NaN  非数 (NaN)を表す値
Number.POSITIVE_INFINITY 正の無限大。Infinityと同じ
Number.NEGATIVE_INFINITY 負の無限大。-Infinityと同じ

nullとundefinedを等価演算子==で比較すると結果はtrue になります。厳密な等価演算子===で比較するとfalseになります。また、Flash Player 6以前用にパブリッシュされたファイルでは、undefined.toString()は "" (空のストリング)になりますが、 Flash Player 7以降用にパブリッシュされたファイルではundefinedになります。

note:
NaN (Not a Number:非数) は定義済みの変数という分類になります。voidは演算子の分類です。


改行コードやタブ文字など、通常では表記できない文字列を\を使ったエスケープ記号を使って記述できます。

エスケープ記号
\b バックスペース
\f 改ページ
\n 改行
\t タブ
\" "
\' '
\\ \
\000 - \377 1バイトを8進数で表記
\x00 - \xFF 1バイトを10進数で表記
\u0000 - \uFFFF ユニコード(16ビットを16進数で表記)

投稿者 oshige : 10:40 | コメント (0) | トラックバック

ムービークリップインスタンスの参照

ActionScriptでは、ムービークリップシンボルのインスタンスのプロパティの値を変更することで位置を動かしたり大きさを変えるといったアニメーションを行います。インスタンスのプロパティの値を調べたり変更するにはドット演算子(.)または配列演算子([])を使って目的のインスタンスのメソッドやプロパティを指し示します。ドット演算子の場合にはドットに続いて識別子を直接書くのに対し、配列演算子を使う場合には["識別子"]のようにストリングにします。
たとえば、メインのタイムラインにmy_mcというインスタンスがある場合には、次のようになります。

例:
ドット演算子を使ったとき
_root.my_mc
配列演算子を使ったとき
_root["my_mc"]

my_mcのプロパティ_x(水平座標)の値を150に設定する式は次のようになります。

例:
ドット演算子を使ったとき
_root.my_mc._x = 150;
配列演算子を使ったとき
_root["my_mc"]._x = 150;

配列演算子を使えばインスタンス名を変数で指定できるので、参照するインスタンスを次のように動的に指定できます。

例:
targetMC = "my_MC";
_root[targetMC]._x = 150;

これまではeval()関数を使っても同様のことができましたが、Flash 5以降では参照式にeval()関数を書くことはできなくなりました。

例:
targetMC = eval("myMC" + 1);
_root.targetMC._x = 150; // 成功

// Flash 5以降ではエラー
_root.eval("myMC" + 1)._x = 150;

note:
Flash3とFlas4ではインスタンスの参照にスラッシュシンタックスが利用されていました。スラッシュシンタックスはFlash Player 7でも動作しますが使用を推奨されていません。ActionScript2.0ではスラッシュシンタックスをサポートしていません。


■_root
ムービークリップシンボルのインスタンスを特定するために、インスタンス名、_root、this、_parent、およびlevelというキーワードを使います。まず、ムービー自身を_rootで指します。ステージに置いたムービークリップは_rootの下にあることになります。たとえば、ステージに置いたムービークリップのインスタンス名がTVならば、

_root.TV

のように指します。このとき、インスタンス名の大文字小文字を区別するので注意してください。名前がTVのときにtvでは参照できません。TVの中にscreenというインスタンス名のムービークリップが入れ子で入っている時screenは、

_root.TV.screen

になります。TVの中のeyeというインスタンス名のムービークリップは、

_root.TV.eye

のように指すことができます。このような参照方法をドットシンタックスと呼びます。ドット演算子(.)は「の」と置き換えて読むとわかりやすいでしょう。「_root.TV.screen」は「_rootのTVのscreen」です。
 これを配列演算子を使って書くと次のようになります。このほうが便利な場合もあるので合わせて覚えてください。こちらはブラケットアクセスと呼びます。

_root["TV"]["eye"]

図3-1-1 ステージにTVというインスタンス名のムービークリップがあり、その中にscreenとeyeというインスタンスが入れ子で入ってます。

なお、MovieClipLoader.loadClip()メソッドまたはloadMovie()関数でインスタンスに別のswfを読み込んで表示する場合には_root参照について注意が必要です。インスタンスにswfを読み込むと、そのswfはインスタンスと入れ替わってしまうので、swfが元々参照していた_rootとは変わってしまいます。読み込まれたswf内での_rootの参照がずれないようにするには、次のように_lockrootプロパティをtrueに設定します。(_lockrootプロパティ→p.??)

//インスタンスtvに読み込んでもswfの_root参照がずれないようにする
this._lockroot = true;


note:
クラスから生成したオブジェクトをインスタンスといいますが、ここではシンボルをステージに配置して作ったインスタンスについて書いています。_root、_parent。_levelはムービークリップシンボルの階層を示す場合にのみ使用されます。

■this(ムービークリップのインスタンスの場合)
thisは、ムービークリップアクションやフレームアクションが設定されているムービークリップのインスタンス自身を指します。「_root.TV.eye」といった参照は階層を_rootからたどった絶対位置で指し示すものですが、これに対してthisは自分を相対的に示します。
たとえば、ムービークリップシンボルのTVインスタンスに設定してあるonClipEventオブジェクトアクションの中に「this._x」とあるとき、これはTVのx座標を指します。つまり「_root.TV._x」と同じです。もし、TVインスタンスが_rootのすぐ下ではなく、別のムービークリップの中に入れ子になっていたとしても、やはりthisはTVを指します。同様にthis._xがインスタンスeyeに設定してあるオブジェクトアクションの中にあればthisが指すものはeyeであり、this._xはeyeのx座標を指します。このようにthisはまさしく「これ」です。this._xは「これのx座標」と言い換えることができます。(onClipEvent→p.??)

//thisはムービークリップアクションを設定してあるインスタンスを指す
onClipEvent (enterFrame) {
  r = (r+0.3) % (2*Math.PI);
  this._xscale = 100*Math.sin(r);
}

インスタンスのイベントハンドラやメソッドを設定するfunctionブロックの内側にあるthisもそのインスタンスを指します。次のスクリプトはメインのタイムラインのフレームアクションに書かれています。上のハンドラはchoインスタンスにonEnterFramイベントハンドラを設定しています。この中のthisはchoインスタンスを指します。下のハンドラはmushiインスタンスにonPressイベントハンドラを設定しています。この中のthisはmushiインスタンスを指します。(フレームアクション→p.??)

//自動的にchoインスタンスが回転
cho.onEnterFrame = function() {
  this._rotation += 5;
};

//mushiインスタンスをクリックすると回転
mushi.onPress = function() {
  this._rotation += 5;
};

■this(ボタンのインスタンスの場合)
ボタンのインスタンスに設定したオブジェクトアクションについては注意が必要です。ボタンに設定してあるonハンドラの中でthisが指すものはボタンのインスタンス自身ではありません。thisはボタンが置いてあるインスタンスを指します。次のスクリプトを設定してあるボタンをクリックすると、ボタンが回転するのではなく、ボタンが置いてあるムービークリップのインスタンスが回転します。(onハンドラ→p.??)

//ボタンが置かれているインスタンスが回転する
on (press) {
  this._rotation += 5;
}


ボタンもインスタンス名をつければフレームアクションからイベントハンドラを設定できます。この中で指すthisはボタンのインスタンスになります。たとえば、ボタンのインスタンス名がmy_btnであるとき、ボタンが置いてあるタイムラインのフレームアクションに次のスクリプトを書きます。この場合にはthisが指すものはボタンのインスタンスなので、ボタンをクリックするとボタン自身が回転します。

//ボタンをクリックするとボタン自身が回転する
my_btn.onPress = function(){
  this._rotation += 5;
}

ボタンをクリックして別のムービークリックインスタンスを回転させるには、thisではなく、回転させたいインスタンスを指し示すようにします。

//my_btnボタンをクリックするとmushiインスタンスが回転
my_btn.onPress = function(){
  _root.mushi._rotation += 5;
}


■_parent
_parentは相対的に1つ上の階層のインスタンスを指します。さらにその上のインスタンスならば、_parent._parentというように上の階層へたどることができます。
あるムービークリップから見た時に、それが置いてあるムービークリップは_parentになります。自分が置いてあるタイムラインのフレームアクションで定義してあるメソッドや関数にアクセスするには、_parent.mymethod()のように参照することになります。

■_level
loadMovieNum()アクションを使うことで、現在のムービーに別のswfを読み込んで重ねて表示することができます。このときのムービーの重なりを_levelで示します。通常の1つしかムービーがない状態の大元のレベルが_level0になります。この上に重ねて読み込んだムービーを、_level1、_level2、_level3...のように指します。
_rootは各レベルのタイムラインを参照しています。したがって通常は_rootと_level0は同じです。しかし、実際には複数のムービーを重ねて表示しているとき、それぞれの_levelに_rootがあります。

note:
ムービークリップに別のswfやJPEGを読み込んで差し替える場合にはMovieClipLoader.loadClip()メソッドまたはloadMovie()関数を利用します。

■指定がない場合
_root、this、_parentといった指定がない場合には、スクリプトが書かれているインスタンスを指します。メインのタイムラインのフレームアクションならば、指しているのは_rootと同じになります。ムービークリップのタイムラインのフレームアクションやオブジェクトアクションならばthisはそのムービークリップのインスタンスを指します
たとえば、次の例では_rotationが参照するのはchoインスタンスが配置されているタイムラインを指します。メインのタイムラインにchoが置いてあるならば、_root._rotationと同じになるのでステージ全体が回転します。choが別のムービークリップの中に入っているのならば、choを含んでいるインスタンスが回転します。

//choが置かれているステージ全体が回転
cho.onEnterFrame = function() {
 _rotation += 5;
};


図3-1-2 インスタンスC_mcを基準(this)にすると相対的な参照はこのようになります。

投稿者 oshige : 10:41 | コメント (0) | トラックバック

インスタンスのプロパティ

プロパティとはインスタンスごとの設定値です。座標、伸縮率、幅など、いろいろな設定値があります。ほとんどのプロパティは値を読み取るだけでなく、値を設定して変更できます。さらに、変数もまたインスタンスのプロパティと解釈できます。そこで変数へのアクセスもプロパティへのアクセスと同様に考えることができます。すでに何度か例を示していますが、プロパティの参照にはドット演算子または配列演算子を使います。

例:
// photo_mcインスタンスのx座標を100に移動します。
photo_mc._x = 100;
photo_mc["_x"] = 100;

// buyインスタンスの透明度を60%にします。
_root.shop.buy._alpha = 60;
_root["shop"]["buy"]["_alpha"] = 60;

//このインスタンスの横幅を50ピクセルにします。
this._widh = 50;
this["_widh"] = 50;

//photo_mcの変数modeの値をtrueに設定します。
photo_mc.mode = true;
photo_mc["mode"] = true;

投稿者 oshige : 10:42 | コメント (0)

スクリプトの種類

ActionScriptは大きく分けて、1.フレームアクション、2.オブジェクトアクション、3.ActionScriptファイル(ASファイル)の3種類があります。オブジェクトアクションはムービークリップのインスタンスとボタンのインスタンスに設定でき、それぞれムービークリップアクション、ボタンアクションと区別して呼ぶこともあります。


図3-2-1 スクリプトを書き込むことができる場所。

図3-2-2 フレームアクション、ムービークリップアクション、ボタンアクション

投稿者 oshige : 15:07 | コメント (0) | トラックバック

フレームアクション

フレームアクションはムービークリップのインスタンスを配置する場合と同じように、キーフレームに設定します。レイヤーはどのレイヤーを使っても構いません。すでにムービークリップなどが入っているレイヤーにフレームアクションを設定することもできますが、フレームアクション専用のレイヤーを追加して使うのがわかりやすく一般的な方法です。フレームアクションが設定されているキーフレームにはaの文字が表示されます。
フレームアクションには、単独のステートメント、イベントハンドラ、ActionScript1.0のクラス定義、メソッド定義、関数定義のスクリプトを書くことができます。後述するようにムービークリップやボタンの個々のインスタンスにオブジェクトアクションを設定することができますが、それらの設定はタイムラインのフレームアクションで使ってまとめて使って書くほう書式が統一されて間違いもなく合理的です。

note:
ActionScript2.0のクラス定義はActionScriptファイルに書きます。

図3-2-3 フレームアクションに設定できる要素。


■フレームアクションが実行されるタイミング
フレームアクションは、キーフレームが再生されたときに1度だけ実行されます。たとえば、フレーム5がキーフレームになっているフレーム5~10の区間が再生される場合は、フレーム4からフレーム5に移ったとき、あるいはほかのフレームからこの区間にジャンプしてきたときに1度だけ実行されます。もしフレーム11にフレーム8に戻るスクリプトが書いてあったとすると、フレーム8~11のループ再生を行い、フレーム8を再生するたびにキーフレームのフレームアクションが実行されることになります。

■スクリプトの実行順と有効範囲
フレームアクションは1行目から順に実行されます。フレームアクションではfunctionを使ってメソッドや関数を定義できますが、同じフレームアクションに書いてあるスクリプトはすべて読み込まれてから実行されるので、1行目のスクリプトで2行目以降に定義してあるメソッドや関数を呼び出すことができます。
ただし、まだ再生していないフレームで定義してあるメソッドや関数を呼び出すことはできません。既に再生したフレームのフレームアクションならば呼び出せます。(ActionScript1.0のメソッドと関数→p.??)
また、タイムラインが1フレームしかない場合やthis.gotoAndStop(1);やthis.stop();というように、フレームアクションが設定されているフレームに留まる場合にも最初に1回しか実行されません。したがって、1フレームしかない場合などには、変数の初期化などが繰り返し行われることはありません。

■イベントハンドラ
Flash MX(Flash Player 6)から、フレームアクションにおいてインスタンスにイベントハンドラを設定できます。これにはいくつかのメリットがあります。
1つは、ムービークリップのアクションをonClipEventイベントハンドラに頼らなくてもよくなったことで、シンボル内にイベントハンドラを書き込むことができるようになりました。これにより、同じシンボルから作られるムービークリップのインスタンスにおいて共通のイベントハンドラを使えるようになります。
ただし、先にも書いたようにフレームアクションをムービークリップシンボル自身のタイムラインに書き込んだほうが効率がよいケースと、メインのタイムラインのフレームアクションからすべてのインスタンスを制御するほうがよいケースがあります。
2つは、ボタンのイベントハンドラでしか利用できなかったonPressやonRollOverなどのイベントアクションがムービークリップのイベントアクションでも利用できるようになりました。これも大変便利な部分です。たとえば、イベントハンドラを設定するインスタンスの名前がmy_mcだったとき、次のようにイベントハンドラを書きます。

my_mc.onPress = function(){
//インスタンスmy_mcがクリックされた時に実行するステートメント
};

3つは、ムービークリップ(MovieClipクラス)、ボタン(Buttonクラス)、テキストフィールド(TextFieldクラス)だけではなく、Soundクラス、Stageクラス、MovieClipLoaderクラスなどのコアクラスと呼ばれる標準のクラスがイベントをイベントハンドラで処理する仕様になっているからです。これによりスクリプトの様式が統一されて見通しも良くなります。

■MovieClipオブジェクトが受け取るイベント
ムービークリップのインスタンスは、MovieClipクラスから作られたインスタンス(MovieClipオブジェクト)です。MovieClipオブジェクトには次のイベントハンドラを設定できます。
ただし、onKeyDownやonKeyUpのイベントは、イベントが発生してもそのままではMovieClipオブジェクトに対してはイベントメッセージが送信されません。イベントを受け取るには、focusEnabledプロパティでフォーカスが当てるか、あるいはaddListener()メソッドを使ってKeyオブジェクトのリスナーに登録する必要があります。(リスナー→p.??)


イベントハンドラ     タイミング
MovieClip.onData   ムービークリップを読み込みが終わった。
MovieClip.onDragOut このムービークリップの上でマウスダウンしたままカーソルが外へ出て再び戻った。
MovieClip.onDragOver このムービークリップの上でマウスダウンしたままカーソルが外へ出た。
MovieClip.onEnterFrame フレームが進んだ。
MovieClip.onKeyDown キーが押された。(フォーカスがあるとき)
MovieClip.onKeyUp  押されたキーが上がった。(フォーカスがあるとき)
MovieClip.onKillFocus このムービークリップからフォーカスが移動した。
MovieClip.onLoad ムービークリップが読み込まれて表示された。
MovieClip.onMouseDown マウスボタンが押された。
MovieClip.onMouseMove マウスカーソルが動いた。
MovieClip.onMouseUp  マウスボタンが上がった。
MovieClip.onPress    このムービークリップがクリックされた。(マウスダウン時)
MovieClip.onRelease   このムービークリップがクリックされた。(マウスアップ時)
MovieClip.onReleaseOutside このムービークリップがプレスされたままカーソルが外へ出てマウスアップした。
MovieClip.onRollOut このムービークリップの外へカーソルが出た。
MovieClip.onRollOver このムービークリップの中にカーソルが入った。
MovieClip.onSetFocus このムービークリップにフォーカスが移った。
MovieClip.onUnload ムービークリップがタイムラインから消えた。


図3-2-4 MovieClipクラスのイベントハンドラ。

これをスクリプトで使用するには、「MovieClip」の部分を実際のインスタンス参照にします。たとえば、次のようになります。

this.onEnterFrame
my_mc.onPress
_root.my_mc.cat_mc.onRollOver


具体的なサンプルを示すと次のような使い方があります。このサンプルでは、ステージにcat_mcインスタンスを置き、メインのタイムラインのフレーム1に次のフレームアクションを書いています。ムービーをパブリッシュするとインスタンスが回転し、クリックすると逆回転になります。

sample→cat1.fla

フレームアクション:
//初期値の設定
cat_mc.k = 1;
//回転
cat_mc.onEnterFrame = function() {
this._rotation += this.k * 10;
};
//クリックで逆回転
cat_mc.onPress = function() {
this.k *= -1;
};

同様の動作を行うスクリプトをムービークリップシンボル自身のタイムラインに書き込む場合にはcat_mcというインスタンス名をthisに置き換えるだけです。このシンボルから作られたインスタンスはすべて回転するようになります。

sample→cat2.fla

フレームアクション(シンボル自身のタイムラインに記述する場合)
this.k = 1;
//回転
this.onEnterFrame = function() {
this._rotation += this.k * 10;
};
//クリックで逆回転
this.onPress = function() {
this.k *= -1;
};


■Buttonオブジェクトが受け取るイベント
ボタンのインスタンスには後述するようにボタンアクションにおいてon (press)といったイベントハンドラを設定できますが、フレームアクションでイベントハンドラを設定することもできます。ボタンのインスタンスは、Buttonクラスから作られたインスタンス(Buttonオブジェクト)です。Buttonオブジェクトには次のイベントハンドラを設定できます。
ただし、onKeyDownやonKeyUpのイベントは、イベントが発生してもそのままではButtonオブジェクトに対してはイベントメッセージが送信されません。イベントを受け取るには、focusEnabledプロパティでフォーカスが当てるか、あるいはaddListener()メソッドを使ってKeyオブジェクトのイベントリスナーに登録する必要があります。(イベントリスナー→p.??)

イベントハンドラ     タイミング
Button.onDragOut このボタンの上でマウスダウンしたままカーソルが外へ出て再び戻った。
Button.onDragOver このボタンの上でマウスダウンしたままカーソルが外へ出た。
Button.onKeyDown キーが押された。(フォーカスがあるとき)
Button.onKeyUp  押されたキーが上がった。(フォーカスがあるとき)
Button.onKillFocus  このボタンからフォーカスが移動した。
Button.onPress    このボタンがクリックされた。(マウスダウン時)
Button.onRelease   このボタンがクリックされた。(マウスアップ時)
Button.onReleaseOutside このボタンがプレスされたままカーソルが外へ出てマウスアップした。
Button.onRollOut このボタンの外へカーソルが出た。
Button.onRollOver このボタンの中にカーソルが入った。
Button.onSetFocus このボタンにフォーカスが移った。

図3-2-5 Buttonクラスのイベントハンドラ。

■TextFiledオブジェクトが受け取るイベント
テキストフィールドのインスタンスは、TextFieldクラスから作られたインスタンス(TextFieldオブジェクト)です。TextFieldオブジェクトには次のイベントハンドラを設定できます。

イベントハンドラ     タイミング
TextField.onChanged  このテキストフィールドの内容が更新された。(フォーカスがあるとき)
TextField.onKillFocus  このテキストフィールドからフォーカスが移動した。
TextField.onScroller  このテキストフィールドのスクロールの状態が変化した。(フォーカスがあるとき)
TextField.onSetFocus  このテキストフィールドにフォーカスが移った。

図3-2-6 TextFieldクラスのイベントハンドラ。

■その他のオブジェクトが受け取るイベント
このほかにも、Soundオブジェクト、LoadVarsオブジェクト、XMLオブジェクト、XMLSocketオブジェクトなどが、それぞれに関連したイベントハンドラをもつことができます。

イベントハンドラ     タイミング
Sound.onLoad  サウンドデータが読み込まれた
Sound.onSoundComplete サウンドの再生が終わった
LoadVars.onLoad  loadまたはsendAndLoadの実行が完了した
LoadVars.onData  loadまたはsendAndLoadでデータを読み込んだ
XML.onLoad  loadまたはsendAndLoadの実行が完了した
XML.onData  loadまたはsendAndLoadでXMLデータを読み込んだ
XMLSocket.onClose  XMLSocketの接続が閉じた
XMLSocket.onConnect  XMLSocketの接続が確立した
XMLSocket.onData    XML形式のストリングデータを受信した
XMLSocket.onXML  XMLオブジェクトをサーバーから受信した


図3-2-7 その他のクラスのイベントハンドラ。

投稿者 oshige : 15:09 | コメント (0) | トラックバック

ムービークリップアクション

ムービークリップアクションは、個々のムービークリップのインスタンスに設定するスクリプトです。ムービークリップアクションを設定したいインスタンスをステージで選択し、アクションウインドウを開いてスクリプトを書きます。
ムービークリップアクションは、インスタンスが表示されたら1行目から実行されるというものではなく、何かのイベントを受けて実行されるイベントハンドラの形式になっています。ムービークリップアクションに設定できるイベントハンドラには、onClipEventイベントハンドラとonイベントハンドラの2種類があります。

note:
ムービークリップアクションにonイベントハンドラを設定できるのはFlash MX(Flash Player 6)以降です。

■onClipEventイベントハンドラ
onClipEventイベントハンドラでは、()の中に応答するイベントの種類を書きます。

onClipEvent(イベント){
//実行するステートメントをここに書きます。
}

指定できるイベントには次の9種類があります。それぞれ別々のタイミングで実行されるので、1つのムービークリップアクションに複数のonClipEventイベントハンドラを書き込むことができますが、後述のonハンドラと違って1つのonClipEventイベントハンドラで複数のイベントを指定することはできません。


イベント    タイミング
load    インスタンスが登場した直後
unload    インスタンスが消えた直後
enterFrame    再生フレームが進んだ
mouseDown    マウスボタンが押された
mouseUp    マウスボタンが上がった
mouseMove    マウスカーソルが動いた
keyDown    キーが押された
keyUp    押されたキーが上がった
data    外部データを読み込み終わった

たとえば、onClipEvent(load)イベントハンドラは、そのインスタンスが登場した時に実行されます。変数の初期化やプロパティの初期設定、ムービークリップで使うメソッドや関数をfunction定義する場所として使います。
onClipEvent(enterFrame)イベントハンドラは、ムービークリップの再生フレームが進む度に実行されます。このとき、インスタンス自身が再生中であるかどうかが問題です。インスタンスが置いてある_root(入れ子の場合は1つ上の階層のムービークリップ)がstop()で停止中でも関係ありません。
onClipEvent(mouseDown)、onClipEvent(mouseUp)のイベントハンドラは、(左の)マウスボタンが下がったとき、上がったときのタイミングでそれぞれ実行されます。このとき、インスタンスがクリックされていなくても実行されるので注意が必要です。どのインスタンスがクリックされたかを知りたい場合には、マウス座標とインスタンスの領域をhitTest()を使って比較します。次のムービークリップアクションでは、インスタンス以外の場所をクリックしてもインスタンスのサイズが1.2倍に拡大します。

ムービークリップアクション:
//クリックイベントがあるとインスタンスを拡大する
onClipEvent (mouseDown) {
 this._xscale *= 1.2;
 this._yscale *= 1.2;
}

一方、次のスクリプトではクリックされた座標とインスタンスの領域のヒットテストを行っています。こうすればアクションが設定されているインスタンスをクリックしたときにそのインスタンスが拡大します。

ムービークリップアクション:
//クリックされたインスタンスだけを拡大する
onClipEvent (mouseDown) {
 if (this.hitTest(_root._xmouse, _root._ymouse, false)) {
  this._xscale *= 1.2;
  this._yscale *= 1.2;
 }
}

onClipEvent(keyDown)、onClipEvent(keyUp)のベントハンドラは、キーボードのキーが押されて下がったとき、上がったときのタイミングでそれぞれ実行されます。どのキーが押されたかはKey.isDown()やtheKeyCodeで調べることができます。

note:
onClipEventイベントハンドラの場合には、Keyオブジェクトのリスナーにしなくてもイベントを受け取ることができます。(リスナー→p.??)

■onイベントハンドラ
onイベントハンドラでも()の中に応答するイベントの種類を書きますが、onClipEventイベントハンドラと違って1つのハンドラで同時に複数のイベントを指定できます。

on(イベント1, イベント2, ...){
//実行するステートメントをここに書きます。
}


指定できるイベントには次の8種類のイベントがあります。イベントごとに個別のイベントハンドラを作ることができますが、内容が同じ場合には1つのハンドラに複数のイベントを同時に割り当てることもできます。


イベント    タイミング
dragOut   このインスタンスの上でマウスダウンしたままカーソルが外へ出て再び戻った。
dragOver  このインスタンスの上でマウスダウンしたままカーソルが外へ出た。
keyPress    キーが押された。
press    このインスタンスがクリックされた。(マウスダウン時)
release    このインスタンスがクリックされた。(マウスアップ時)
releaseOutside    このインスタンスがプレスされたままカーソルが外へ出てマウスアップした。
rollOver    このインスタンスの外へカーソルが出た。
rollOut    このインスタンスの中にカーソルが入った。

たとえば、on (press)、on(release)のイベントハンドラは、インスタンスが(左)クリックされた時、(左の)マウスボタンが下がったとき、上がったときのタイミングでそれぞれ実行されます。onClipEvent(mouseDown)イベントハンドラと違って、クリックされたインスタンスだけがイベントを受け取ります。on (releaseOutside)イベントハンドラは、次のようにon (release)イベントハンドラと組み合わせて使うと効果的です。

on (release, releaseOutside){
// クリックされた場合にマウスアップ時に実行したいスクリプトを書きます。
}

on (keyPress "キー")イベントハンドラは、指定したキーが押された時に実行されます。キーは"a"、"b"、"c"のように英数文字で指定します。returnキー、enterキーは""、Tabキーは""、←は""、→は""、↑は""、↓は""のように指定できます。

on (keyPress "キー"){
//指定のキーが押された時に実行したいスクリプトを書きます。
}

投稿者 oshige : 15:10 | コメント (0) | トラックバック

ボタンアクション

ボタンアクションは、個々のボタンシンボルのインスタンスに設定するスクリプトです。ステージでボタンのインスタンスを選択し、アクションウインドウにスクリプトを書きます。
ムービークリップアクションと同様にボタンアクションは、インスタンスが表示されたら1行目から実行されるというものではなく、何かのイベントを受けて実行されるイベントハンドラの形式になっています。
ボタンアクションに設定できるイベントハンドラは、onイベントハンドラのみです。onイベントハンドラはムービークリップの場合と同じように動作します。イベントの種類とイベントが発生するタイミングについてはムービークリップアクションでの説明を参照してください。

ボタンアクション:
//ボタンが置いてあるタイムラインをgreenフレームラベルへ進める
on (release, releaseOutside) {
 gotoAndPlay("green");
 trace("test"); // 動作テスト。出力→ test
}

投稿者 oshige : 15:10 | コメント (0) | トラックバック

変数を使う

変数とは値を保管する容器のようなものです。x = 3の式ならば変数xに3を入れるというぐあいです。しかし、値を保管しておくという捕らえ方は変数のもつ1つの側面に過ぎません。変数のもつもっとも重要な役割は、その名前が示すように値が変わるものを扱うという部分です。x = a + bという変数を使った式こそが変数の機能を示しています。変数xの値は変数aと変数bを足し合わせた値になるという、このダイナミックな式を書くために変数が存在すると言えるでしょう。この式の変数a、変数bの使い方でもわかるように、変数は値を受け渡すための容器にもなります。ここでは数値を扱っていますが、変数にはすべてのデータ型を格納できます。さらに厳密なデータ型を指定することもできます。(データ型→p.??)

例:
a = 17;
b = 55;
x = a + b;

note:
変数に対して、17、"oshige"といった数値やストリングなどのスクリプトに直接書いた値をリテラルと呼びます。

図3-3-1変数の種類

■変数の名前
変数の名前は、先頭の1文字は、英字、アンダースコア、ドル記号のいずれかでなければなりません。つまり、識別子でなければなりません。ActionScriptのエレメントおよび予約語、リテラル(true、false、null、undefined)を使うこともできません。また、英字の大文字と小文字を区別する点にも注意が必要です。たとえば、変数Aと変数aは違う変数になります。(識別子→p.??)

投稿者 oshige : 12:28 | コメント (0) | トラックバック

変数の種類とスコープ(有効範囲)

変数にはタイムライン変数、ローカル変数、グローバル変数の3種類があります。さらに、ActionScript2.0以降の外部スクリプトで定義されたクラスでは、パブリック変数、プライベート変数、スタティック変数という3種類の変数を使い分けることができます。
変数の種類の違いはスコープの違い、すなわち、変数の有効範囲の違いと言えます。たとえば、フレームアクションにある変数aとムービークリップアクションにある変数aは名前が同じでも別の変数であるというようなぐあいです。また、変数の値がどの範囲で保持されるかというという問題もあります。

note:テキストフィールドを変数として使うこともできますが、これはFlash 5以前との互換性を保つための機能です。


■タイムライン変数
フレームアクションに直接書いた変数は、そのタイムラインの中で有効な変数です。直接書いた変数とは、たとえば次のようなフレームアクションを言います。タイムライン変数の宣言にはvarステートメントを付けますが、これは省略も可能です。

フレームアクション:フレーム1
var a = 15;
var b = 32;
var x = a + b;
trace("x=" + x); //出力→ x=47

フレームアクションは、フレームアクションが設定してあるキーフレームが再生されたときに実行されます。したがって、まだ再生していないキーフレームのフレームアクションに書いてあるタイムライン変数にはアクセスできません。そのキーフレームが1度でも再生されたならば、そこに書いてあるタイムライン変数にアクセスできるようになります。
たとえば、フレーム1に次のフレームアクションを書きます。

フレームアクション:フレーム1
trace("c=" + c);

次にフレーム10をキーフレームを挿入し、次のフレームアクションを書きます。

フレームアクション:フレーム10
var c = 555;
this.gotoAndPlay(1);

このムービーをパブリッシュするとフレーム1のフレームアクションが実行され、変数cの値を出力パネルに書き出します。結果はundefined(未定義)になります。
ムービーは再生を続けてフレーム10を再生し、フレーム10のフレームアクションを実行して再びフレーム1に戻ります。フレーム1に戻るともう1度フレーム1のフレームアクションが実行されて変数cの値を出力パネルに書き出します。すると今度は変数cに555が入っているのがわかります。これが繰り返されるので出力パネルは次のようになります。このことから、同じタイムラインで同名のタイムライン変数が使用されている場合には、後から実行されたフレームアクションによって変数の値が更新されることになります。

出力パネルの結果:
c=undefined  ←1回目の出力時には値は未定義。
c=555  ←フレーム10を実行したときに値が入った。
c=555
...(以下、c=555が繰り返す)


ほかのムービークリップのタイムライン変数を参照することもできます。その場合にはインスタンスのプロパティを参照する場合と同じようにドット演算子(.)または配列演算子([])を使って参照します。たとえば、my_mcのタイムラインで使われているタイムライン変数vには次の式で参照できます。どちらも変数vに31を入れます。

例:
_root.my_mc.v = 31;
_root.my_mc["v"] = 31;

逆にほかのムービークリップのタイムラインからメインのタイムラインの変数にアクセスするといった場合には_rootを使います。

例:
_root.w = 123
_root["w"] = 123

note:
タイムライン変数はインスタンスのプロパティという解釈もできます。メインのタイムラインならば、_rootのプロパティという位置付けです。


■ローカル変数
ローカル変数は、関数やメソッドを定義するfunctionステートメントのブロック内で宣言し、その中でのみ有効な変数です。functionブロックをいったん離れると変数は破棄され、変数の値は保持されません。たとえるなら、1度退場すると無効になる入場券のようなものです。
ローカル変数はvarステートメントで宣言しなければなりません。次のkakezan関数では、ローカル変数vを掛け算の結果を入れる変数として利用しています。
また、関数やメソッドでは引数を受け渡す際にローカル変数が使われます。これをパラメータ変数と呼ぶことがあります。例で使用している変数a、変数bがパラメータ変数です。パラメータ変数はvar宣言が不要です。

//kakezan関数の定義
function kakezan(a, b) {
 var v = a * b;
 return v;
}

では、次のようなフレームアクションを考えて見ましょう。1行目で変数vに7を入れた後で、kakezan(3, 5)を実行します。変数vの値とkakezan(3, 5)の結果をtraceで出力して調べます。

sample → kakezan.fla

フレームアクション:
var v = 7;
var ans = this.kakezan(3, 5);
trace("ans=" + ans);
trace("v=" + v);

//kakezan関数の定義
function kakezan(a, b) {
 var v = a * b;
 return v;
}

図3-3-2 フレームアクション

kakezan(3, 5)を実行するとkakezan関数の中の変数vは15になります。しかし、trace("v" + v)で出力される値は1行目で変数vに入れた7になります。つまり、kakezan関数の中のローカル変数vはタイムライン変数vの値を書き換えなかったということです。

出力パネルの結果:
ans=15
v=7

この例において、functionブロック内で変数vをvarステートメントで宣言せずに使うと変数vはタイムライン変数になってしまい、1行目の変数vの値を上書きしてしまいます。結果として、出力パネルにはどちらの値も15で書き出されます。
このことから、functionブロック内の変数をvarでローカル変数宣言するのとしないとでは、大きな違いがあることがわかります。

//kakezan関数の定義
function kakezan(a, b) {
 v = a * b; // varを付けない
 return v;
}

出力パネルの結果:varを付けなかった場合。変数vは上書きされている。
ans=15
v=15


■グローバル変数
グローバル変数は_grobalオブジェクトを利用して作る変数で、ムービーを通してどこからでもアクセスできる変数です。たとえば、グローバル変数myVを使うには次のように書きます。_grobalオブジェクトのインスタンスを作る必要はありません。

例:
_global.myV = 123; //値を代入
++_global.myV; //カウントアップ

次のように配列やArrayオブジェクトを利用するとグローバル変数の管理が簡素化されます。(配列→p.??、Arrayオブジェクト→p.??)

例:
_global.colors = ["red", "green", "blue"];
_global.usrpref = {#name:"美幸", #age:29};

値を取り出すには次のように参照します。配列は要素の並びを0から数えるので、colors[1]は2番目の要素、つまり"green"を指します。


var myColor = _global.colors[1]; // "green"
var usrName = _global.usrpref.name;
var usrAge = _global.usrpref["age"];

■テキストフィールドを使った変数
テキストフィールドをダイナミックテキストまたはテキスト入力の設定にすると変数名を入力する項目が追加されます。ここに変数名を入れれば、テキストフィールドを変数のように使うことができます。変数の値はテキストフィールドに入って表示されます。値の取り出し方も同じで、テキストフィールドに表示されているデータを変数名で取り出せます。変数名を宣言する必要はありません。
たとえば、テキストフィールドにtheDataという変数名を付けたならば、次のように参照できます。

例:
theData = "これはテキストフィールドのデータです。";
var msg = theData; //変数msgに入れる

図3-3-3 テキストフィールドに変数名を付ける

note:
変数名の入力フィールドはパネルの情報領域を展開して広げないと表示されません。

ただ、テキストフィールドを変数に利用する方法は以前のバージョンのFlashの仕様を残しているだけのものといえます。テキストフィールドに値を入れたり取り出すというだけの目的ならば、テキストフィールドのtextプロパティを利用できます。この場合は、テキストフィールドに変数名を付けるのではなくインスタンス名を付けます。たとえば、インスタンス名をdata_txtと付けたならば次のように参照します。

例:
data_txt.text = "これはテキストフィールドのデータです。";
var msg = data_txt.text; //変数msgに入れる

図3-3-4 テキストフィールドにインスタンス名を付ける

投稿者 oshige : 12:30 | コメント (0) | トラックバック

データ型の種類

データ型は、実際の値をもつプリミティブ型と値への参照だけのリファレンス型の2種類に分けることができます。さらにこの2種類に加えて、特殊なデータ型としてnull(値なし)とundefined(型未定義)があります。
プリミティブ型にはString、Number、Boolean、定数があります。

データ型    値の例
String → "test"、 "こんにちは"
Number → 123、42、0.32、21e4
Boolean → true、false

-123などのマイナスの値もNumber型ですが、+-は符号を示す演算子です。定数はMath.PIやKey.Rightなどですが、実際の値が何であるかによって型が決まります(実際のところすべてはNumber型です)。
リファレンス型にはMovieClip、objectがあります。ムービークリップのインスタンスがMovieClip型です。Object型の値には、ObjectクラスやDateクラスなどのクラスから生成したインスタンスに加えて、[1, 2, 3, 4]、{name:"chan", age:21}などの配列演算子を使って作った値があります。

Object型の値
v1 = [1, 2, 3, 4];
v2 = {name:"chan", age:21};
v3 = new Array(1, 2, 3);
v4 = new Date(2004, 6, 7);
v5 = new Object();


図3-4-1 データ型の種類

■データ型のチェック
値のデータ型をチェックするにはtypeof演算子を使います。返される値はデータによって次のようになります。

ストリング → string
ムービークリップ → movieclip
ボタン → object
テキストフィールド → object
数値 → number
ブール値 → boolean
オブジェクト(インスタンス) → object
関数 → function
null → null
未定義 → undefined


例:
trace(typeof "test"); //出力→ string
trace(typeof 123); //出力→ number
trace(typeof ([1, 2, 3, 4])); //出力→ object
usr = {name:"chan", age:21};
trace(typeof usr.name); //出力→ string
today = new Date();
trace(typeof today); //出力→ object

nullとundefinedも同様です。

例:
trace(typeof null); // null
trace(typeof x); // 変数xをいきなり使用したのでundefined


型に応じて処理を振り分けるといった場合には、"string"、"number"、"object"のようにストリングで比較します。

例:
v = "test";
if (typeof v == "string") {
 trace("vはストリング");
}

投稿者 oshige : 15:57 | コメント (0) | トラックバック

データ型の変換

文字列(String)の"123"を数値(Number)の123として計算したいというように、値のデータ型を変換したい場合があります。そのような場合に次のような変換方法があります。
ただし、元の値がどう変換されるかについては元のデータ型などによって違うので注意してください。また、Flash 6以前とFlash 7では結果が同じでないものがあります。

■文字列(String)への変換
ある値をストリングに変換するには、Number.toString()メソッド、Object.toString()メソッド、String()関数を使います。

例:
x = 12;
y = x + 3;
trace(y); // 15
x = x.toString(); // "12"
y = x + 3;
trace(y); //出力→ "123"

例:
x = 12;
y = String(x) + 3;
trace(y); //出力→ "123"

例:
a = [1,2,3];
as = a.toString(); // "1,2,3"

また、次のように値を別のストリングと連結することで全体がストリングになります。空のストリング""の連結でもかまいません。

例:
age = 18;
usr = "ゆき" + age + "才";
trace(usr);// 出力→ ゆき18才


■数値(Number)への変換
ある値を数値に変換するには、Number()、parseInt()、parseFloat()の関数を使います。parseInt()は整数に変換し、parseFloat()は浮動小数点に変換します。

例:
v = Number("123.4"); // 123.4
v = Number(true); // 1
v = Number(false); // 0
v = Number("12円"); // NaN

例:
v = parseInt("123.6"); // 123
v = parseInt(true); // NaN
v = parseInt(false); // NaN
v = parseInt("12円"); // 12
v = parseInt("車5台"); // NaN
v = parseInt("3.56e+8"); //3

例:
v = parseFloat("123.4"); // 123.4
v = parseFloat("3.56e+8"); // 356000000

また、次のように値から0を引くという方法でも値を数値に変換することができます。

例:
v = "123" - 0;
trace(v); //出力→ 123
trace(typeof v) //出力→ number

■ブール値(boolean)への変換
ある値を数値に変換するには、Boolean()関数を使います。値がtrue、falseのどちらに変換されるかは、元の値の種類で決まっています。

例:
v = Boolean(0); // false
v = Boolean(1); // true
v = Boolean(123); // true
v = Boolean("test"); // true
v = Boolean(null); // false
v = Boolean(undefined); // false


note:
スクリプトの実行の過程において、対象となる値が適切なデータ型ではなかったとき、その値は演算可能なデータ型の値に自動的に置き換えられて処理されます。

投稿者 oshige : 16:04 | コメント (0) | トラックバック

厳密な型指定

ActionScriptではデータ型は適当に解釈されるためにデータ型を指定しなくても利用できます。しかし、場合によってはこの柔軟さがエラーの原因になったり、バグの発見を遅らせる要因になります。
変数や関数の引数、関数の戻り値に厳密なデータ型を設定すれば、コンパイル時にデータ型がチェックされるようになります。
また、データ型を指定すれば名前の接尾辞をつけなくとも式をタイプする際にピリオド(.)に続いてコードヒントが表示されるようになります。(コードヒント→p.??)
ただし、データ型がチェックされるのはスクリプトのコンパイル時だけなので注意が必要です。実行時に指定した以外の型のデータが与えられてもエラーになりません。

■変数のデータ型
変数に厳密なデータ型を指定するには、変数をvarで宣言しなければなりません。そして、変数名に続いてコロン(:)を書き、それに続けてデータ型を書きます。

例:
var myV:Number;
var myName:String;
var myData:Array;

この例のように変数のデータ型を設定した場合に次のスクリプトは「代入ステートメントでタイプが一致しません。」というコンパイルエラーになります。

例:コンパイル時にエラーになる
myV = "123";
myName = 2004;
myData = "test, 123";


図3-4-2 データ型が一致しないのでコンパイルエラーになります。

ただし、次のようなスクリプトではコンパイル時にvのデータ型を特定できずにエラーになりません。

例:
var v = 12;
var s:String = v; // エラーにならない

このようなケースをコンパイルエラーにするには、次のように変数vのデータ型も厳密に指定する必要があります。

例:
var v:Number = 12;
var s:String = v; // コンパイルエラーになる

■関数の引数のデータ型
関数の引数のデータ型を指定するには引数名に続けてコロン(:)を書き、それに続けてデータ型を書きます。なお、先にも書いたようにデータ型がチェックされるのはスクリプトのコンパイルです。ムービー再生中に関数が呼ばれるたびに引数のデータ型がチェックされるわけではないので注意してください。

例:
function nefuda(genka:Number, kinsyu:String) {
var ans:String = genka * 1.2 + kinsyu;
return ans;
}

この例ではnefuda()関数の1番目の引数は数値、2番目の引数はストリングでなければコンパイルエラーになります。

例:
nefuda_txt.text = nefuda("ドル" , 25); // コンパイルエラー
nefuda_txt.text = nefuda(190 , "円"); // OK

次のスクリプトでは引数の並びが逆でデータ型が一致しないのでコンパイルエラーになるように思えますが、変数の厳密なデータ型の指定の場合と同様にエラーになりません。

例:
g = 25;
k = "ドル";
nefuda_txt.text = nefuda(k, g); // エラーにならないので注意が必要

次のように変数g、kのデータ型が厳密に設定されていればエラーになります。

例:
var g:Number = 25;
var k:String = "ドル";
nefuda_txt.text = nefuda(k, g); // コンパイルエラー

sample → nefuda.fla

■関数の戻り値のデータ型
関数の引数だけでなく、戻りの値のデータ型を設定できます。たとえば、変数xのデータ型がNumberに設定されているとき、test()関数から戻る値のデータ型がわからないと変数xへの代入が妥当かどうか判断できません。そこで関数の戻りの値にもデータ型を設定しておきます。関数の戻りのデータ型を設定するには、引数を囲む()に続いてコロン(:)を書き、それに続けてデータ型を指定します。
次の例は、先のnefuda()の戻り値のデータ型をStringに設定しています。

例:戻り値のデータ型を定義する
function nefuda(genka:Number, kinsyu:String):String {
var ans:String = genka * 1.2 + kinsyu;
return ans;
}

関数の戻り値にもデータ型を設定すれば、変数への代入する時点でのデータ型の妥当性をチェックできます。

例:戻り値のデータ型がチェックされる
var lavel:String = nefuda(500, "円");


■メソッドのデータ型
メソッ定義では値を返しません。そこで、メソッド定義のデータ型はVoidにします。

例:メソッドのデータ型はVoidにする
fucrion move(target:MovieClip, x:Number, y:Number):Void {
target._x += x;
target._y += y;
}

■インスタンスのデータ型
クラスから作ったインスタンスは、そのクラスのデータ型をもちます。たとえば、Dateクラスから作ったmyDate、XMLクラスからmyXMLはそれぞれDate、XMLというデータ型を指定できます。ユーザーが定義したカスタムクラスでも同じです。MyClassクラスのインスタンスはMyClassデータ型になります。なお、インスタンスはObject型でもあるので、データ型としてObjectを指定することもできます。

例:インスタンスはクラスのデータ型になる
var myDate:Date = new Date();
var myXML:XML = new XML();
var myObj:MyClass = new MyClass();

■オブジェクトのキャスト
キャストという手法を使うと、コンパイル時のデータチェックにおいて、オブジェクト(インスタンス)のデータ型を別のデータ型として認識させることができます。
キャストはtype(item)という形式をとります。たとえば、MyClass()というカスタムクラスがあったとき、あるデータをMyClassクラスのデータ型にキャストしたい場合にはMyClass(data)のように書きます。これはString(x)、Number(y)などと共通した書式なのでわかりやすく利用できます。

投稿者 oshige : 16:05 | コメント (0) | トラックバック

配列演算子を使う

配列を利用すれば、複数の値を1つの値としてまとめて取り扱うことができて便利です。配列は配列演算子[]を使って作ることができます。値をカンマ(,)で区切り、[]で囲みます。たとえば、次のように配列を作ります。データ型はArrayを指定します。

例:
var myValue:Array = [2, 5, 3, 10, 99];
var myColor:Array = ["red", "green", "yellow"];
var weekj:Array = ["日", "月", "火", "木","金","土"]

配列から値を取り出したり値を更新するには、配列[位置]の式で配列の並びの位置を指して参照します。このとき、位置を左から0、1、2のように0から数えるので注意してください。例を示すと次のようになります。

例:
var colorlist:Array = ["red", "green", "yellow"]
var colorA:String = colorlist[0]; // "red"が入ります。
var colorB:String = colorlist[1]; // "green"が入ります。

例:
var weekj:Array = ["日", "月", "火", "木","金","土"]
var youbi:String = weekj[3] // "木"が入ります。

note:
配列のように複数の要素をひとかたまりで扱うオブジェクトを「コレクション」と呼びます。

■多次元配列
配列の中に配列を入れた多次元配列を作ることができます。多次元配列は複雑なデータを操作する上で有効な手段となります。多次元配列から要素を取り出す例を見てください。

例:
var colorlist:Array = [["red", "pink"], ["wihte", "blue"], ["green", "black"]]
var myColor:String = colorlist [2][1]; // "black"が入ります。

この例では、まずcolorlist[2]の値を取り出します。位置を0から数えるので[2]は左から3番目の ["green", "black"]になります。したがって、続いて ["green", "black"][1]を実行することになります。その結果、myColorには"black"が入ります。

note:
trace([1,2,3])は"1,2,3"、trace([["red", "pink"], ["wihte", "blue"]])は"red,pink,wihte,blue"のように[]を取り去った値が出力されます。

■Arrayクラスを使う
配列はArrayクラスを使って作ることもできます。

例:
var idlist:Array = new Array(33, 56, 74,16, 7);
var sizelist:Array = new Array("S", "M", "L");

この2つの式は、次の式を実行するのと同じ結果です。

例:
var idlist:Array = [33, 56, 74,16, 7];
var sizelist:Array = ["S", "M", "L"];

さらに、配列の要素をArrayクラスのpush()メソッドを使って追加する方法もあります。

例:
var idlist:Array = new Array();
var sizelist:Array = new Array();
idlist.push(33, 56, 74, 16, 7);
sizelist.push("S", "M");
sizelist.push("L");

■配列の値を操作するメソッドとプロパティ
配列の値(エレメント)の個数を調べる、値を追加する、値を削除する、並びを変更するといった操作は、Arrayクラスのメソッドとプロパティを利用します。値の位置は0から数えるので注意してください。

Arrayクラスのメソッドとプロパティ
Array.concat() 配列を連結し、新しい配列として返します。
Array.join() 配列の値を指定のセパレータで結合したストリングを返します。
Array.pop() 配列の最後の値を削除し、削除した値を返します。
Array.push() 配列の最後に値を追加し、配列の値の個数を返します。
Array.reverse() 配列の並びを逆にします。
Array.shift() 配列の最初の値を削除し、削除した値を返します。
Array.slice() 配列の要素を抽出し、新しい配列として返します。
Array.sort() 配列をソートします。
Array.sortOn() 配列内のフィールドに基づいて配列をソートします。
Array.splice() 配列の指定位置に値を挿入・削除し、削除された値を返します。
Array.toString() 値に相当するストリングを返します。
Array.unshift() 値を配列の最初に追加し、配列の新しい長さを返します。
Array.length 値の個数を返します。

例:配列の結合
var aList:Array = [3, 5];
var bList:Array = [9, 8];
var cList:Array = [33, 56];
var x:Array = aList.concat(bList, cList); // [3,5,9,8,33,56]

例:配列の一部を抜き出して新しい配列を作る
var aList:Array = ["a", "b", "c", "d", "e","f","g"];
var x:Array = aList.slice(2, 5); // 3個目から5個→["c", "d", "e"]
var y:Array = aList.slice(4); // 5個目から最後まで→["e","f","g"]

例:最後の値の削除と追加
var aList:Array = ["a", "b", "c", "d"];
aList.pop(); // 最後の値を削除する→["a","b","c"]
aList.push("x"); //最後に値を追加する→["a","b","c","x"]

例:先頭の値の削除と追加
var aList:Array = ["a", "b", "c"];
aList.shift(); // 先頭の値を削除する→["b","c"]
aList.unshift("x"); //先頭に値を追加する→["x", b", c"]

例:指定位置の値の削除と置き換え
var aList:Array = ["a", "b", "c", "d", "e"];
var bList:Array = ["a", "b", "c", "d"];
aList.splice(1, 3); // 位置1から3個を削除する→["a","e"]
bList.splice(1, 2, "x", "y"); // 位置1から2個を置き換える→["a","x","y","d"]

例:値のソート
var myList:Array = [3, 6, 4, 9, 1];
myList.sort(); // 昇順に並べる→[1,3,4,6,9]
myList.sort(Array.DESCENDING); // 降順に並べる→[9,6,4,3,1]

例:値の個数
var aList:Array = ["a", "b", "c"];
var cnt = aList.length; // 3

投稿者 oshige : 22:45 | コメント (0) | トラックバック

{}を使った配列オブジェクト

{}を使った配列オブジェクトは、名前と値という組み合わせでデータを管理するいわゆる連想配列に相当する機能です。これはプロパティ名とその値という考え方で、書式は{識別子1:値1, 識別子2:値2, 識別子3:値3, ...}のようになります。データ型はObject型です。

例:配列オブジェクトを作る
var goods:Object = {id:"se24", price:1980, size:"M"};
var shoeData:Object = {color:"blue", size:23.5};

配列オブジェクトの値には、インスタンスのプロパティを参照する場合と同じく、ドット演算子(.)または配列演算子([])を使って参照します。

例:配列オブジェクトから値を取り出す
var theColor:String = shoeData.color;
var theSize:Number = shoeData["size"];

配列オブジェクトの値を変更したい場合にもドット演算子(.)または配列演算子([])を使って参照します。

例:配列オブジェクトの値を変更する
shoeData.color = "green";
shoeData["size"] = 24;

投稿者 oshige : 22:46 | コメント (0) | トラックバック

配列を走査する(for~in)

配列や配列オブジェクトのプロパティ名や値を順に調べたい(走査したい)ときにはfor~inが利用できます。変数には、配列の場合には位置が取り出され、オブジェクトの場合にはプロパティ名が取り出されます。


「配列から位置を順に取り出す」
for ( 変数 in 配列){
// 繰り返すスクリプト
}

「配列オブジェクトからプロパティ名を順に取り出す」
for ( 変数 in 配列オブジェクト){
// 繰り返すスクリプト
}


例:配列の値を調べる
var colors:Array = ["red", "blue", "green", "yellow", "pink"];
for (var pn in colors) {
trace(pn + "=" + colors[pn]);
}

出力結果:
4=pink
3=yellow
2=green
1=blue
0=red


例:配列オブジェクトのプロパティ名と値を調べる
var goods:Object = {id:"sd91", name:"fix7", price:2500, volume:1};
for (var pn in goods) {
trace(pn + "=" + goods[pn]);
}

出力結果:
id=sd91
name=fix7
price=2500
volume=1

for~inは{}演算子の配列オブジェクトだけでなく、Objectクラスのインスタンスをはじめ、コアオブジェクト、ユーザー定義のクラスのインスタンスを走査することもできます。ただし、MovieClipオブジェクトなどのコアオブジェクトでは、_x、_yといった既存のプロパティ名は列挙されません。
なお、配列の値の個数はlengthで調べることができます。配列演算子([])を使って順に取り出すスクリプトは次のようになります。このスクリプトで繰り返しのために使用しているfor文はfor~inとは違います。詳しくは次の節で説明します。

例:配列の値を順に取り出す
var colors:Array = ["red", "blue", "green", "yellow", "pink"];
for (i=0; i<colors.length; i++) {
trace(i + "=" + colors[i]);
}

出力結果:
0=red
1=blue
2=green
3=yellow
4=pink

投稿者 oshige : 22:50 | コメント (0)

条件分岐

条件分岐や繰り返し処理など、複数行で1つのまとまった処理を行う構造をもったスクリプトがあります。スクリプトは基本的には上の行から順に実行されますが、条件に応じて実行する処理を選択することができます。

■if
if文は指定の条件が満たされた時だけに実行したいスクリプトを{}で囲んだブロックにします。条件式は、結果がtrue(正しい)かfalse(間違い)のどちらかの値になる式です。

「もし~ならばAを実行」
if (条件式) {
// 条件式の結果がtrueのときに実行したいスクリプトA
}

図3-6-1 ifの流れ。

次のif文では、変数aの値が10以上ならばaの値を2で割ります。

if (a>=10) {
a = a/2 ;
}

if文を入れ子にすることもできます。次のif文では、変数bの値が10~20のときにラベル"q3"のフレームに移動します。

if (b >= 10) {
if (b<=20) {
this.gotoAndPlay("q3");
}
}

このスクリプトは論理演算を使って次のように書くこともできます。

if ((b >= 10) && (b <= 20)) {
this.gotoAndPlay("q3");
}

■else
elseを使えば、if文の条件が満たされたとき、満たされないときのそれぞれのケースで実行したいスクリプトを指定できます。

「もし~ならばAを実行、でなければBを実行」
if (条件式){
// 条件式の結果がtrueのときに実行したいスクリプトA
} else {
// 条件式の結果がfalseのときに実行したいスクリプトB
}

図3-6-2 if~elseの流れ。

次のif文では、変数aの値が正ならばインスタンスのx座標に1を加算します(インスタンスは右へ移動)。正でないならば、つまり、0か負ならばx座標から1を引きます(インスタンスは左へ移動)。

if (a>0) {
this._x += 1;
} else {
this._x -= 1;
}

■else if
else ifは、if文の条件1が満たされないときには、別の条件2を満たしていないかどうかを重ねて評価したいときに使います。else ifのブロックを連結していけば条件を連続して評価していくことができます。先頭から条件式を評価し、途中で条件を満たす式に出会ったならば残りのelse ifは評価せずにifステートメントを抜けます。
なお、最後をelseブロックにすればどの条件も満たさなかったときに実行するスクリプトを設定できます。最後までelse ifならば、どの条件も満たさなければ何も実行しないままifステートメントを終了します。

「もし~ならばAを実行。でなければもし~ならばBを実行。でなければ・・・・」
if (条件式1){
// 条件式1の結果がtrueのときに実行したいスクリプトA
} else if(条件式2){
// 条件式2の結果がtrueのときに実行したいスクリプトB
} else if(条件式3){
// 条件式3の結果がtrueのときに実行したいスクリプトC
・・・
} else {
// すべての条件が満たされないときに実行するスクリプトZ
}

図3-6-3 if~else ifの流れ。

次のif文は、インスタンスのx座標がマイナスならば200にセットし、x座標が200以上ならば0にセットします。

if (this._x < 0){
this._x = 200; // 水平座標がマイナスならば200に移動
} else if (this._x > 200){
this._x = 0; // 水平座標が200より右ならば0に移動
}

note:
条件演算子?:でもif~else ifと同じように条件によって処理する式を切り分けることができます。(?:→p.??)

■switch
swith文は値に応じてスクリプトを分岐したい場合に便利な構造になっています。次の式の部分には変数やプロパティの参照式などが入ります。式の値が値1ならば、スクリプト1を実行し、値2ならばスクリプト2を実行します。用意した値1~nではない値の場合にはdefaultの初期値スクリプトを実行します。

「式の値に応じたスクリプトを実行。該当する値がなければdefaultを実行」
switch(式){
 case 値1:
   処理1;
   break;
 case 値2:
   処理2;
   break;
 case 値3:
   処理3;
   break;
 ...
 case 値n:
   処理n;
   break;
default:
   初期値スクリプト;
}

図3-6-4 switchの流れ。

次のスクリプトでは、aの値が10ならばフレームq1へ移動、20ならフレームq2へ移動、それ以外の値ならばフレームq3へ移動します。

switch (a) {
case 10 :
this.gotoAndPlay("q1");
break;
case 20 :
this.gotoAndPlay("q2");
break;
default :
this.gotoAndPlay("q3");
}

用意したケースに当てはまらない場合にはdefaultで指定したステートメントを実行しますが、defaultの設定はなくても構いません。defaultを省略すると、用意したケースに当てはまらない場合には何も実行せずにswithブロックを抜けて次のステートメントへと移行します。

図3-6-5 switchの流れ。defaultを設定しない場合。

ところで、各caseの最後でbreakを実行しないと、そのまま次のcaseの処理が続きます。このとき、値のチェックは行われずに処理部分だけが無条件で実行される点に注意が必要です。これをうまく利用すれば論理和の処理を行うことができます。たとえば、次のswitchでは変数aの値が5、7、9のいずれからならばアタリになります。

例:
var a = 7; //アタリ
switch (a) {
case 5 :
case 7 :
case 9 :
  trace("アタリ:5、7、9のどれかでした");
  break;
default :
  trace("はずれです");
}

途中のbreak後の処理がどうなっているのかを確認するには、次のスクリプトをテストしてください。変数aの値が5のときは、「5です」、「5または7です」の2つが出力されます。

例:
var a = 5;
switch (a) {
case 5 :
  trace("5です");
case 7 :
  trace("5または7です");
  break;
case 9 :
  trace("9です");
  break;
default :
  trace("はずれです");
}

図3-6-6 breakを実行しない場合には、続くケースの処理が無条件で実行されます。


また、caseで指定する値を式で書くことで複雑な条件設定も可能になります。次の場合は式の値がtrueになるケースが実行されます。つまり、変数aの値が7の場合は「5以上10未満」と出力されます。

例:
a = 7;
switch (true) {
case (a<5) :
  trace("5未満");
  break;
case (a>=5 && a<=10) :
  trace("5以上10未満");
  break;
case (a>10) :
  trace("10以上");
  break;
}

投稿者 oshige : 11:28 | コメント (0) | トラックバック

繰り返し(ループ)

同じ処理を繰り返し実行したい時にはforやwhileを使うと便利です。ただし、繰り返し処理をしている間はほかの処理が行われないので、座標を一定距離ずつ動かすといった処理には向いてません。そのような処理はMovieClip.onEnterFrameイベントハンドラやsetInterval()関数を利用します。(setInterval()→p.??)


note:
配列やオブジェクトを走査するfor~inについては配列で説明しています。(for~in→p.??)
ループ処理を15秒以上続けるとエラーになります。

■for
for文は、まず初期化を行い、次に条件式を評価します。条件式の結果がfalseならばそこでfor文を終了し、trueならば{}のブロックを実行します。{}のブロックを実行したならば更新処理を行い、再び条件式を評価します。条件式がfalseになるまでこれを繰り返します。
簡単に言えば、後述のwhileと同じく「条件がtrueの間は繰り返す」になります。


for (初期化; 条件式; 更新処理){
// 繰り返すスクリプト
}

書式からするとさまざまな用途で利用できる構文ですが、一般的には次のようにカウンタを使った繰り返しの処理に利用します。

「カウンタが指定の値になるまで繰り返す」
for (カウンタ=初期値; カウンタの評価式; カウントアップまたはカウントダウン){
// 繰り返すスクリプト
}

具体的には次のようなスクリプトを書きます。これを実行するとカウンタの変数iが10になるまでブロックを繰り返し実行します。これをプレビューすると10回の繰り返し中のiとiの2倍の値が出力ウインドウに表示されます。

for (var i=1; i<=10; i++){
var a = i*2;
trace([i,a]);
}

出力結果:
1,2
2,4
3,6
4,8
5,10
6,12
7,14
8,16
9,18
10,20

この繰り返しを図で表すと次のようになります。

図3-6-7 forステートメントを利用した繰り返しの処理。

■while
条件式が満たされている間(trueのとき)はスクリプトを繰り返し実行したい場合にはwhileを使います。最初から条件が満たされていないときには、while内のスクリプトは1回も実行されません。条件式の値が常にtrueだと無限ループに陥ってしまうので条件設定には注意が必要です。

「条件を満たす間は繰り返す」
while (条件式){
// 繰り返すスクリプト
}

note:
意図的に無限ループを作り、ある条件を満たしたならばbreakで抜けるという手法もあります。

■do~while
do~whileはwhile文と似ていますが、条件式を判断する前に最初に1回スクリプトを実行します。後はwhile文と同じです。

「条件を満たす間は繰り返す」
do {
// 繰り返すスクリプト
} while (条件式);


■contine
for、while、do~while、for~inの中で使います。contineを実行すると、繰り返し中のスクリプトの残りをスキップして次の繰り返しに移行します。

■break
for、while、do~while、for~inの中で使います。breakを実行すると、繰り返し中のスクリプトの残りを中断して、実行中のfor、while、do~while、for~inの文を終了し、以下に続くスクリプトへと進みます。なお、breakはswitch文でも使います。

投稿者 oshige : 11:29 | コメント (0) | トラックバック

メソッドと関数の定義

functionを使えばオリジナルのメソッドと関数を定義できます。ActionScript1.0ではメソッド定義と関数定義はフレームアクションかムービークリップのオブジェクトアクションで定義します。
フレームアクションで定義したメソッドや関数は、そのムービークリップの中で自由に利用できます。ムービー全体で使えるようにするにはメインのタイムラインのフレームアクションに定義します。ただし、それを定義したキーフレームが再生されてはじめて利用可能になる点に注意が必要です。これはタイムライン変数のスコープ(有効範囲)と同じ考え方です。

note:
オブジェクト指向プログラミングではメソッドやプロパティをもつクラスを定義し、クラス名と同名の関数(コンストラクタ関数と呼ばれる)を使ってクラスのインスタンスを作ります。その考え方はActionScript1.0またはActionScript2.0であっても基本的には変わりません。ActionScript2.0では、クラス定義ファイル(ASファイル)においてクラスのメソッドや関数を定義します。

投稿者 oshige : 17:34 | コメント (0) | トラックバック

メソッド定義

メソッドはfunction文を使って定義します。引数はなくてもかまいませんが()は必要です。

function メソッド名 (引数1, 引数2, ...) {
// 実行するスクリプト
}


次のスクリプトをメインのタイムラインのフレーム1のフレームアクションに書けば、showPhoto()メソッドはタイムラインのどこからでも利用できるメソッドになります。


メインのタイムラインのフレームアクション:
//photoインスタンスで表示するフレームをラベル番号で指定する
function showPhoto(no) {
photolist = ["cat", "dog", "fish"];
if ((no >= 0) && (no < photolist.length)) {
photo = photolist[no];
trace(photo); // 選んだラベル名を出力
}
}

そして、myMCインスタンスをクリックしてshowPhoto()メソッドを実行するには次のようにします。

メインのタイムラインのフレームアクション:
myMC.onPress = function(){
showPhoto(2); //"fish"
}

メインのタイムラインではなく、ムービークリップのタイムラインからこの関数を実行するには_root.showPhoto()のようにパスを使って参照します。
なお、showPhoto()がmyMCインスタンスだけのものならば、次のように直接インスタンスに設定できます。

//インスタンスにメソッドを設定する
myMC.showPhoto = function(no){
photolist = ["cat", "dog", "fish"];
if ((no >= 0) && (no < photolist.length)) {
photo = photolist[no];
trace(photo); // 選んだラベル名を出力
}
}

この場合、showPhoto()を実行する際にはthis.showPhoto(2)またはmyMC.showPhoto(2)のように参照します。

//クリックで実行する
myMC.onPress = function(){
this.showPhoto(2);
}

投稿者 oshige : 17:39 | コメント (0) | トラックバック

関数定義

function文の中でreturnアクションを使って値を戻せば、メソッドを呼び出した位置に値を返す関数を定義することができます。引数はなくてもかまいませんが()は必要です。

function 関数名 (引数1, 引数2, ...) {
// 実行するスクリプト
return 返し値
}


次のスクリプトをメインのタイムラインのフレーム1のフレームアクションに書けば、getPrice()関数はタイムラインのどこからでも利用できる関数になります。

//指定の商品に価格を調べる
function getPrice(theName) {
goods = {pen:230, note:450, cap:1600};
price = goods[theName];
return price;
}

getPrice()を使ってnoteの価格を取り出すには次のようにします。

//noteの価格を調べる
x = getPrice("note");
trace(x);

投稿者 oshige : 17:39 | コメント (0) | トラックバック

ムービークリップのオブジェクトアクションのメソッドと関数

本書ではオブジェクトアクションは利用しない方針ですが、一応オブジェクトアクションについても簡単に説明しておきます。
インスタンスを選択した状態でアクションを設定するとインスタンスに対して設定されるオブジェクトアクションになります。オブジェクトアクションで定義したメソッドや関数は、そのオブジェクトアクションを設定したインスタンスの中でのみ利用できます。
メソッド定義は、最初に実行されるonClipEvent(load)イベントハンドラで定義します。

インスタンスのオブジェクトアクション:
//初期化する
onClipEvent (load) {
//メソッド定義
function test() {
trace("myTest"); // 出力→ myTest
}
}
//クリックで実行
onClipEvent (mouseUp) {
test();
}

投稿者 oshige : 17:39 | コメント (0) | トラックバック

Objectクラスのインスタンスにメソッドを設定する

Objectクラスを利用すればクラス定義を行わずとも手軽にインスタンスを生成できます。先ほどムービークリップのインスタンスに直接メソッドを定義したように、Objectクラスのインスタンスにもメソッドや関数を設定できます。
次のスクリプトではObjectクラスからmyObjインスタンスを作り、testFunc()メソッドを設定しています。


//myObjインスタンスを作る
myObj = new Object();
//メソッドを設定
myObj.testFunc = function() {
trace(123); // 出力→ 123
};
//メソッドをテストする
myObj.testFunc(); //123と出力される

投稿者 oshige : 17:40 | コメント (0) | トラックバック

一定時間刻みで繰り返す

アニメーションを行うといった場合には、onEnterFrameイベントハンドラを利用して繰り返しの処理を実行するのが一般的な方法です。しかし、繰り返しの処理は必ずonEnterFrameイベントハンドラから呼び出さなければならないとしたらスクリプトを書くうえで窮屈です。また、onEnterFrameイベントハンドラでは処理のタイミングがムービークリップのフレームレートに左右されてしまうという不都合もあります。
setInterval()関数を使えばonEnterFrameイベントハンドラを使わずに繰り返しの処理を行うことができ、また、時計の秒針移動のように正確なタイミングで動きを制御したい場合やフレームレートとはまったく違うタイミングの繰り返し処理を行うこともできます。
たとえば次のステートメントを実行すると、myObjオブジェクトのmyMethod()メソッドを2秒間隔で呼び出すようになります。intervalIDにはこのインターバルの設定をキャンセルするためのidが入ります。

intervalID = setInterval(myObj, "myMethod", 2000);

myMethod()メソッドの実行の際にパラメータを渡すこともできます。パラメータがv1, v2ならば次のように書きます。

intervalID = setInterval(myObj, "myMethod", 2000, v1, v2);

インターバルをキャンセルするには、clearInterval(intervalID)を実行します。intervalIDは、setInterval()を実行したときに戻ってくる値です。

clearInterval(intervalID);

note:
setInterval()には対象となるオブジェクトを省略する書式もあります。

投稿者 oshige : 11:43 | コメント (0) | トラックバック

インスタンスのメソッドを実行する

では実際にインターバルを利用した例を見てみましょう。メインのタイムラインにmyMCインスタンスを作り、フレーム1に次のフレームアクションを書き込みます。
このムービーをパブリッシュすると、myMCインスタンスのkaitenメソッドが2秒間隔で呼び出されるようになり、結果として2秒間隔で時を刻むように10度ずつ回転します。

sample→interval.fla

フレームアクション:
//実行するイベントハンドラを設定する
myMC.kaiten = function(d:Number) {
this._rotation += d;
};

//myMCインスタンスのkaitenメソッドを2秒間隔で実行
intervalID = setInterval(myMC, "kaiten", 2000, 10);


図3-8-1 2秒間隔で時を刻むように10度ずつ回転します。

setInterval()はムービークリップシンボルのインスタンスのメソッドを呼び出すのではなく、クラス定義から生成したインスタンスのメソッドや関数を呼び出すためにも利用します。

投稿者 oshige : 11:51 | コメント (0) | トラックバック

一定時間を待つ

インターバルは一定時間間隔で繰り返しの処理を行いたいときに威力を発揮する機能ですが、一定時間を待つタイマーとしても利用できます。
次のサンプルを実行すると5秒後にインターバルで設定したtimeoutイベントが発生するので、そこでインターバルの設定をクリアします。

sample→timer1.fla


フレームアクション:
//timerObjオブジェクトの設定
timerObj = new Object();
timerObj.timeout = function() {
clearInterval(timerID); // インターバルの終了
trace("タイムアウト"); // 出力→ タイムアウト
};
//計測開始(5秒でタイムアウト)
var timerID = setInterval(timerObj, "timeout", 5000);


次のサンプルでは、ステージをクリックした時点から1秒間隔でカウントダウンを行います。カウントダウンの秒数はダイナミックテキストmsgFldに表示しています。
例に示すように10秒のカウントダウンを行いたいならばmyObj.startTimer(10)のように10を引数にしてstartTimer()メソッドを実行します。インターバルは1秒間隔でtimestepイベントを実行するので、10回カウントしたならば10秒経過になるので、そこでインターバルをクリアします。

sample→timer2.fla


フレームアクション:
msgFld.text = "ステージをクリックするとカウントダウンを開始します"
myObj = new Object();
myObj.startTimer = function(sec:Number) {
this.cntdowntimer = sec;
this.timerID = setInterval(this, "timestep", 1000);// インターバルの設定
msgFld.text = this.cntdowntimer + "秒";
};
myObj.timestep = function() {
if (this.cntdowntimer > 1) {
--this.cntdowntimer;//カウントダウン
msgFld.text = this.cntdowntimer + "秒";//表示
} else {
clearInterval(this.timerID);// インターバルのクリア
msgFld.text = "タイムアウトしました";
}
};
//10秒間のカウントダウンスタート
this.onMouseDown = function() {
myObj.startTimer(10);
};

投稿者 oshige : 11:52 | コメント (0) | トラックバック

イベントリスナーへの登録

マウスクリックがあったらどうする、キー入力があったらどうするというようにイベントに応じてスクリプトを実行するには、イベントを受け止めるイベントハンドラを設定します。しかし、イベントハンドラを作ってもそれを設定したインスタンスにイベントメッセージが送られなければ意味がありません。
たとえば、ビルインクラスのMovieClipクラスはマウスクリックイベントのonMouseUpやonMouseDown、あるいはonPressといったイベントが送られるので、これを受けるイベントハンドラを設定すればマウスクリックに応じたスクリプトを実行できます。ムービークリップインスタンスのmy_mcならば、次のイベントハンドラを設定すればマウスクリックで回転します。ステージのどこをクリックしてもonMouseDownイベントがすべてのムービークリップインスタンスに送られるので、インスタンスをクリックしなくてかまいません。

sample→evetlistener1.fla

//マウスイベントを受けてインスタンスを回転させる
my_mc.onMouseDown = function(){
this._rotation += 10;
}

ところが、次のようにObjectクラスでmyObjインスタンスを作ってonMouseDownイベントハンドラを設定しても、myObjインスタンスへはマウスイベントが送信されないので応答しません。

sample→evetlistener2.fla

//ObjectクラスのmyObjインスタンスを作る
myObj = new Object();
//イベントハンドラを設定する
myObj.onMouseDown = function(){
trace("クリックがありました");
}

myObjインスタンスにマウスクリックのイベントが送信されるようにするには、addListener()メソッドを使ってMouseクラスのリスナーに登録します。リスナーへの登録は、「サブスクライブ(subscribe)」とも呼ばれます。

//myObjをMouseクラスのイベントリスナーに登録する
Mouse.addListener(myObj);

同様に、キー入力イベントに応答するようにするには、Keyクラスのイベントリスナーに登録します。

sample→evetlistener3.fla

//ObjectクラスのmyObjインスタンスを作る
myObj = new Object();
//イベントハンドラを設定する
myObj.onKeyDown = function(){
trace("キー入力がありました");
}
//myObjをMouseクラスのイベントリスナーに登録する
Key.addListener (myObj);

note:
キー入力イベントをムービープレビューでテストする際には、制御メニューの[キーボードショートカットを無効]をチェックしておく必要があります。


MovieClipクラスにもキー入力イベントは送信されません。そこで、ムービークリップのインスタンスをキー入力で操作するにはインスタンスをKeyクラスのイベントリスナーに登録します。次の例では、矢印キーを押すとキーに応じた方向にインスタンスの座標が移動します。

sample→evetlistener4.fla

フレームアクション:
//ball_mcインスタンスにキー入力のイベントハンドラを設定
ball_mc.onKeyDown = function(){
switch (Key.getCode()){
case Key.LEFT: //←キー
this._x -= 10;
break;
case Key.RIGHT: //→キー
this._x += 10;
break;
case Key.UP: //↑キー
this._y -= 10;
break;
case Key.DOWN: //↓キー
this._y += 10;
break;
}
}
//Keyクラスのイベントリスナーに登録する
Key.addListener(ball_mc);

投稿者 oshige : 19:26 | コメント (0) | トラックバック

イベントリスナーからの消去

逆にイベントリスナーの登録を消去するには、removeListener()メソッドを実行します。

//MouseクラスのイベントリスナーからmyObjを消去する
Mouse.removeListener (myObj);

//Keyクラスのイベントリスナーからball_mcを消去する
Key.removeListener(ball_mc);

投稿者 oshige : 19:30 | コメント (0) | トラックバック

イベントリスナーを設定できるクラス

このようなイベントリスナーを設定できるクラスには次のようなものがあります。それぞれのクラスによって発生するイベントは違います。

Keyクラスのリスナーが受け取るイベント
 onKeyDown キーが押された。
 onKeyUp 押されたキーが上がった。

Mouseクラスのリスナーが受け取るイベント
 onMouseDown マウスボタンが押された。
 onMouseUp 押されたマウスボタンが上がった。
 onMouseMove マウスカーソルが動いた。
 onMouseWheel マウスホイールが回転した。

MovieClipLoaderクラスのリスナーが受け取るイベント
 onLoadComplete データの読み込みが完了した。
 onLoadError データの読み込みを失敗した。
 onLoadInit 読み込んだムービークリップの先頭フレームのアクションが実行された。
 onLoadProgress データ読み込み中(ディスクへ書き込むタイミングで発生)。
 onLoadStart データ読み込みを開始した。

Selectionクラスのリスナーが受け取るイベント
 onSetFocus フォーカスが移動tした。

Stageクラスのリスナーが受け取るイベント
 onResize swfの縦横サイズ(ステージサイズ)が変更された。

TextFieldクラスのリスナーが受け取るイベント
 onChanged テキストフィールドのテキストが変更された。
 onScroller テキストフィールドがスクロールした。


note:
V2コンポーネントでもイベントリスナーを利用してイベントを処理できます。ただし、V2コンポーネントでは、addEventListener(イベント名, リスナーオブジェクト)の書式でリスナーを登録します。

listenerObject.eventName = function(evtObj){
// ここにコードを入力
};
componentInstance.addEventListener("eventName", listenerObject);

投稿者 oshige : 19:31 | コメント (0) | トラックバック

クラスとは何か?

プログラムとは一連の作業の手続きを書いたものです。そして、決まって行う手続きは1つの作業としてルーチン化してしまい名前を付けて呼ぶことにします。これは日常生活の中にも見ることができます。たとえば「コーヒーを煎れる」という行為の中には何段階かの作業がありますが、「コーヒーを煎れる」という1つの「命令」で指示することができます。このような命令がたくさんたまってくると、次からも利用できるようにまとめて整理しておこうということになります。簡単に言えば、それが「クラス」です。
逆に言えば、クラスには便利な命令が入っているので、クラスから命令を引き出して使えばよいという考え方になります。しかし、料理はレストランで注文し給油はガソリンスタンドで行うように、クラスにも専門分野があります。たくさんある命令は分類されていくつかのクラスに整理されています。それがMathクラスであったり、Dateクラスであったりするわけです。
ActionScriptで利用できるクラスは、あらかじめ用意してあるビルトインクラスとユーザーが定義して作るカスタムクラスの2つに大きく分類できます。いつでもすぐに使えるという意味ではビルトインクラスが便利ですが、効率のよいプログラミングを行うためにはカスタムクラスを作ることを避けられません。
ビルトインクラスには、ECMAScript4に準拠したコアクラスとFlash Player固有のクラス(メディアクラス、ムービークラス、クライアント・サーバークラス、オーサリングクラスなど)が含まれています。カスタムクラスは、ActionScript1でもActionScript2.0でも作ることができますが、手法が違うだけで同じように動作します。ただ、今後のためにはActionScript2.0のクラス定義の方法を学ぶほうがよいことから、本書ではActionScript1.0のクラス定義については触れません。

投稿者 oshige : 11:11 | コメント (0) | トラックバック

クラス定義とインスタンス

オブジェクト指向プログラミングやクラス定義の説明の前に「オブジェクトとは何か?」「クラス定義とは何か?」という話をしておきましょう。
次の図はredCarオブジェクトを示したものです。redCarオブジェクトにはcolorとtypeの2つのプロパティがあり、それぞれ"red"と"at"という値をもっています。さらにredCarオブジェクトにはrun()というメソッドもあります。run()が何を行うメソッドなのかはこれだけではわかりませんが、名前からするとrun()を実行するとredCarが走るメソッドだろうと想像できます。


図4-1-1 redCarオブジェクトには2つのプロパティと1つのメソッドがあります。

次の図はblueCarオブジェクトです。redCarオブジェクトと同様にcolorとtypeの2つのプロパティとrun()メソッドがあります。


図4-1-2 blueCarオブジェクトにも2つのプロパティと1つのメソッドがあります。

次のcardもオブジェクトです。カードはデータつまりプロパティだけという作りも考えられますが、カードを表示したり、urlをリンクするといった機能をcardオブジェクト自身のメソッドとして組み込むやりかたもあります。ここではプロパティとメソッドを両方持ったcardオブジェクトになっています。

図4-1-3 cardオブジェクト

このようにオブジェクトはプロパティ(属性)の値とメソッド(関数)を自分自身でもっています。これを図に示すと次にようになります。

図4-1-4 オブジェクトとは、プロパティ(属性)の値とメソッド(関数)を自分自身でもったものをいいます。


では、どうやってこのような構造を持ったオブジェクトを作るのでしょうか。先のredCarオブジェクトとblueCarオブジェクトはプロパティの値が違うだけでプロパティの項目やメソッドは同じである点に注目してください。そこで次のようにオブジェクトの仕様を定義したものを用意し、それに基づいてredCarとblueCarのオブジェクトを作れば、オブジェクトを効率よく作れることがわかります。これは車を作るにはまず車の設計図を用意し、あとはそれに基づいて車を大量生産するのに似ています。
ここで、オブジェクトの仕様を「クラス」と呼び、クラスに基づいて作られたオブジェクトを「インスタンス」と呼びます。すなわち、Carクラスを定義して、redCarオブジェクトとblueCarオブジェクトというインスタンスを作ります。

図4-1-5 Carクラスを定義して、redCarとblueCarのインスタンスを作ります。


クラス定義からインスタンスを作るという図を一般化して示すと次のようになります。用語としては、「クラスからインスタンスを作る」、「クラスからインスタンスを生成する」といった言い回しが使われています。なお、プロパティとメソッドのことをメンバーと呼びます。後述するように、メンバーにはクラスメンバーとインスタンスメンバーがあります。

図4-1-6 オブジェクトの仕様を決めた「クラス定義」を用意し、それに基づいて「インスタンス」を生成します。


note:
Flashではライブラリからシンボルをステージに配置したものもインスタンスと呼びますが、これはMovieClipクラスやButtonクラスなどからインスタンスを作る行為を手作業で行っていると言えます。

投稿者 oshige : 11:14 | コメント (0) | トラックバック

クラス定義ファイルとクラス定義の構造

ActionScript2.0のクラス定義は、外部ActionScriptファイル(ASファイル)で行います。Flash MX Professional版の場合はクラス定義ファイルの作成とアクションウインドウのスクリプト編集機能を利用できますが、スタンダード版にはその機能がありません。クラス定義ファイルは拡張子が.asのテキストファイルなので、一般のテキストエディタで作成編集ができます。
クラス定義ファイルのファイル名は、これから定義するクラスと同名でなければなりません。たとえば、MyClassというクラスを定義する場合にはMyClass.asファイルを作ります
クラス定義ファイルの構造は次のようになります。プロパティは変数で定義して値を保存しますが、次の構造にはプロパティが書いてありません。プロパティについては後述します。


クラス定義ファイルの構造:
class クラス名{
 //コンストラクタ関数
function クラス名() {
}
 //メソッド
function メソッド名() {
}
 //関数
function 関数名() {
return(戻り値);
}
}


ここでのメソッドと関数の違いはreturnで値を戻すかどうかだけの違いです。両者を区別せずにどちらもメソッドあるいは関数と呼ぶこともあります。ただし、関数の戻り値のデータ型を指定した場合には、returnを入れないとコンパイルエラーになります。
クラス名はクラス定義ファイル名と同じにします。名前の大文字小文字を区別する点に注意してください。一般的にクラス名は大文字から始めます。クラス定義の内容はすべてclassステートメントのブロック内に書きます。たとえば、MyClassクラスのクラス定義ファイルは次のようになります。このクラスにはコンストラクタ関数だけで、メソッドや関数はありません。つまり、インスタンスを作るだけで何もしないクラスです。プロパティも設定していません。

sample→ ex04-01/my1stClassフォルダ

MyClassクラスのクラス定義:MyClass.as
class MyClass {
//コンストラクタ関数 ←クラス名と同じ
function MyClass() {
}
}

投稿者 oshige : 11:14 | コメント (0) | トラックバック

コンストラクタ関数の省略

コンストラクタ(constructor;建設者)関数ではプロパティの初期化などを行いますが、先の例のMyClassクラスのように何もしないコンストラクタ関数もあります。何もしないコンストラクタ関数は省略が可能です。また、関数という呼び方をしますが、値をreturnで戻す必要はありません。つまり、もっとも単純なクラス定義のスクリプトは次のように空のclassブロックだけになります。

もっとも単純なクラス定義:MyClass.as
class MyClass {
//コンストラクタ関数は省略
}

投稿者 oshige : 11:15 | コメント (0) | トラックバック

クラス定義からインスタンスを作る

クラス定義したクラスのインスタンスを作る方法は、ビルトインクラスのインスタンスを作る場合と基本的には同じです。先のMyClassクラス定義からmyObjインスタンスを作るスクリプトは次のとおりです。myObjインスタンスのデータ型はMyClassになります。すなわち、クラス定義には新しいデータ型を定義するという側面があることも理解できます。

sample→ ex04-01/my1stClassフォルダ

//MyClassクラスのインスタンスを作る
var myObj:MyClass = new MyClass();
//myObjを調べる
trace(typeof myObj); // 出力→ object

このとき、このFlashムービーはクラス定義ファイルMyClass.asファイルと同じ階層に作ります。Flashムービーと別の階層にあるクラス定義ファイルを利用するには、クラスパスを指定しなければなりません(クラスパス→p.??)。

note:
Flashムービーをパブリッシュするとクラス定義ファイルのスクリプトはムービー内に取り込まれてしまうので、配布の際にクラス定義ファイルを添付する必要はありません。

投稿者 oshige : 11:15 | コメント (0) | トラックバック

メソッドとプロパティ

クラス定義のもう少し具体的な例として、メンバーすなわちメソッドやプロパティをもったクラスを定義してみましょう。メンバーにはクラスメンバーとインスタンスメンバーがありますが、ここではインスタンスメンバーだけを使っています。両者の違いとクラスメンバーについては改めて説明します(クラスメンバーとインスタンスメンバー→p.??)。
次のMyClass01クラス定義には、プロパティmcとcircleメソッドが定義してあります。mcは操作対象となるムービークリップインスタンスの参照でクラスからインスタンスを作る際に引数から受け取って値を入れます。スクリプトで示すようにプロパティはコンストラクタ関数より前にvarで宣言します。circleメソッドは引数で指定したxy座標を中心とする半径rの円周上を回転角度dずつインスタンスを移動させるメソッドです。インスタンスは円周に沿った座標移動と同時に円の中心点を向くように自転します。

sample→ex04-01/MyClass01フォルダ

クラス定義ファイル:MyClass01.as
//MyClass01クラス
class MyClass01 {
//プロパティ
var mc:MovieClip;
//コンストラクタ
function MyClass01(target:MovieClip) {
mc = target;
}
//常に中心(x,y)を向くように円周を回る
function circle(x:Number, y:Number, r:Number, d:Number):Void {
//d度ずつ回転
mc._rotation += d;
var rad = mc._rotation * Math.PI / 180;
//中心座標(x,y)、半径rの円のradラジアン回転した点の座標
mc._x = x + r * Math.cos(rad);
mc._y = y + r * Math.sin(rad);
}
}

次のムービーでは、このMyClass01クラスを使ってムービークリップインスタンスのアニメーションを行っています。ステージには正方形のcenter_mcと長方形のbar_mcの2つのインスタンスがあります。ムービーをパブリッシュして確認するとbar_mcを引数としてMyClass01クラスのbarObjが作られるので、barObjのmcプロパティの値がbar_mcになります。
フレームが進むたびにbar_mcインスタンスのonEnterFrameイベントハンドラが実行されるので、barObjのcircle()メソッドが実行されてcenter_mcの周りをbar_mcが回ります。

フレームアクション:methodTest2.fla
//MyClass01クラスからインスタンスbarObjを作る
var barObj:MyClass01 = new MyClass01(bar_mc);
//毎フレームに実行
bar_mc.onEnterFrame = function() {
var x = center_mc._x;
var y = center_mc._y;
var r = 100;
var d = 10;
//barObjインスタンスのcircle()メソッドを実行する
barObj.circle(x, y, r, d);
};


図4-1-7 center_mcを円の中心としてその周りをbar_mcが回ります。

さらにcenter_mcもcircle()メソッドで動くようにすると、bar_mcの動きは公転する地球の周りを月が回るような動きになります。利用するクラス定義ファイルは同じなのでフレームアクションだけを書き換えます。

フレームアクション:methodTest3.fla
//インスタンスの生成
var centerObj:MyClass01 = new MyClass01(center_mc);
var barObj:MyClass01 = new MyClass01(bar_mc);
//円を描くようにcenter_mcを動かす
center_mc.onEnterFrame = function() {
var x = Stage.width / 2;
var y = Stage.height / 2;
var r = 100;
var d = 5;
var centerObj.circle(x, y, r, d);
};
//center_mcの周りを回る
bar_mc.onEnterFrame = function() {
var x = center_mc._x;
var y = center_mc._y;
var r = 100;
var d = 10;
barObj.circle(x, y, r, d);
};

図4-1-8 円を描いて回るcenter_mcの周りをbar_mcが回ります。どちらもMyClass01()クラスのcircle()メソッドを使っています。

なお、Windows版でムービープレビューを行った場合にはcenter_mcがステージからはみだした位置で円を描きますが、ブラウザまたはFlash Playerでswfを再生すればステージの中央を中心点として円を描きます。

投稿者 oshige : 11:16 | コメント (0) | トラックバック

プロパティのインライン初期化

プロパティの初期値をコンストラクタ関数の引数で決めるのではなく、プロパティの宣言と同時に初期化することもできます。これをインライン初期化と呼びます。たとえば、先のMyClass01クラスの円の半径と回転角度をプロパティとして決定してしまうならば、クラス定義は次のようになります。

sample→ex04-01/MyClass02フォルダ

クラス定義ファイル:MyClass02.as
//MyClass02クラス
class MyClass02 {
//プロパティのインライン初期化
var r:Number = 100;//円の半径
var d:Number = 10;//回転速度
var mc:MovieClip;//対象のムービークリップインスタンス
//コンストラクタ
function MyClass02(target:MovieClip) {
mc = target;
}
//常に中心を向くように円周を回る
function circle(x:Number, y:Number):Void {
//d度ずつ回転
mc._rotation += d;
var rad = mc._rotation * Math.PI / 180;
//中心座標(x,y)、半径rの円のradラジアン回転した点の座標
mc._x = x + r * Math.cos(rad);
mc._y = y + r * Math.sin(rad);
}
}

投稿者 oshige : 11:16 | コメント (0) | トラックバック

クラスパス

クラス定義ファイルを使うには、Flashのコンパイラが探せるようにクラス定義ファイルを保存してあるディレクトリを登録しておく必要があります。このクラス定義ファイルを保存してあるディレクトリの一覧をクラスパスと呼びます。
クラスパスにはドキュメントレベルのクラスパスとグローバルなクラスパスの2つがあります。コンパイラは最初にドキュメントレベルのクラスパスを検索し、そこで見つからなければグローバルなクラスパスを検索します。ドキュメントレベルのクラスパスはパブリッシュ設定のFlashタブにある[ActionScript設定...]で設定します。

図4-1-9 ドキュメントレベルのクラスパスは、パブリッシュ設定のFlashタブにある[ActionScript設定...]で設定します。初期値は空になってます。

初期値の設定ではドキュメントレベルのクラスパスは空なので、通常はグローバルなクラスパスを検索します。グローバルなクラスパスは編集メニューの環境設定のActionScript設定にある[ActionScript2.0設定...]で設定します。初期値ではクラスパスが2つ設定してあり、その1つはドット(.)すなわち、現在のドキュメントを保存しているフォルダになっています。したがって、クラス定義ファイルとFlashムービーファイルを同じフォルダに保存すれば、クラス名だけでクラス定義ファイルを読み込むことができるわけです。


図4-1-10 グローバルなクラスパスは、環境設定のActionScript設定にある[ActionScript2.0設定...]で設定します。


もう1つのクラスパスは、Windowsでは各ユーザーのアプリケーションフォルダのMacromedia/Flash MX 2004/ja/Classesフォルダ、Mac OSXでは各ユーザーのLibrary/Application Support/Macromedia/Flash MX 2004/ja/Configurarion/Classesフォルダになっています。このクラスパスには標準のActionScript2.0のクラス定義ファイル(クラスライブラリ)があります。

投稿者 oshige : 11:16 | コメント (0) | トラックバック

パッケージの利用

クラスパスで指定してあるディレクトリよりも下ならば、クラス定義ファイルをフォルダにまとめて入れておくことができます。このときのフォルダのパス(サブディレクトリ)をパッケージと呼びます。パッケージを使う場合には、クラス定義およびインスタンスを生成する際にクラスパスからのディレクトリ階層、すなわちパッケージ名を指定します。
次の例では、現在のFlashムービーファイルpackageSample.flaの階層にpetsフォルダがあり、その中にHana.asとTaro.asの2つのクラス定義ファイルが入っています。

sample→ex-04/packageフォルダ

packageSample.fla
petsフォルダ
 ├ Hana.as
 └ Taro.as

この場合のにHanaクラスのクラス定義ファイルは次のようになります。クラス名にパッケージ名を付けた完全修飾名でクラス名を指定しなければならない点に注意してください。


クラス定義ファイル:pets/Hana.as
//パッケージ名に続けてクラス名を書く
class pets.Hana {
//コンストラクタ
function Hana() {
}
//関数
function nakigoe():String{
return "ニャー";
}
}


同様にTaroクラスのクラス定義ファイルは次のようになります。

クラス定義ファイル:pets/Taro.as
//パッケージ名に続けてクラス名を書く
class pets.Taro {
//コンストラクタ
function Taro() {
}
//関数
function nakigoe():String {
return "ワン";
}
}

この2つのクラス定義ファイルからインスタンスを作り、それぞれのクラスのnakigoe()関数をテストするスクリプトは次のようになります。インスタンスをnew演算子で作る際にもパッケージ名に続いてクラス名を指定します。インスタンスを入れる変数のデータ型にもパッケージ名とクラス名を指定しなければならない点に注意してください。

フレームアクション:packageSample.fla
//Hanaクラスのインスタンスを作る
var hanaObj:pets.Hana = new pets.Hana();
//Taroクラスのインスタンスを作る
var taroObj:pets.Taro = new pets.Taro();
//関数を実行する
var naki_hana = hanaObj.nakigoe();
var naki_taro = taroObj.nakigoe();
trace("hanaは、" + naki_hana); // 出力→ hanaは、ニャー
trace("taroは、" + naki_taro); // 出力→ taroは、ワン

投稿者 oshige : 11:17 | コメント (0) | トラックバック

importの利用

クラスを指定するたびにパッケージ名を指定するのでは、複数のクラス定義ファイルを利用したり、パッケージ名が長い時にスクリプトが読みにくくなります。
importキーワードを使えば、使用するクラス定義ファイルが入っているパッケージ全体を前もって読み込んでおくことができ、クラス定義ファイルを呼び出すときにはクラス名だけで呼び出せるようになります。
importはクラス定義ファイルの中だけでなく、フレームアクションでも利用できます。importをフレームアクションで使用した場合は、importが有効な範囲はそれを呼び出している現在のスクリプトにのみ適用されます。別のスクリプトに移った場合には再びimportを実行しなければなりません。
次の例は、あらかじめ2つのクラス定義ファイルをimportしているので、それ以降でクラス名を指すときにはパッケージ名が必要ありません。

フレームアクション:
//利用するクラスファイル定義をあらかじめimportしておく
import pets.Hana;
import pets.Taro;
//Hanaクラスのインスタンスを作る
var hanaObj:Hana = new Hana();
//Taroクラスのインスタンスを作る
var taroObj:Taro = new Taro();

同じパッケージ内にあるクラス定義ファイルを指定する場合にはワイルドカードの*が利用できます。pets.*のようにすれば、petsフォルダにあるすべてのクラス定義ファイルを読み込むことができます。この場合、実際に読み込まれるのは参照されたファイルだけなので、利用しないファイルまで読み込まれてファイルサイズが肥大化する心配はありません。

sample→ ex04-01/importフォルダ

フレームアクション:
import pets.*;
//Hanaクラスのインスタンスを作る
var hanaObj:Hana = new Hana();
//Taroクラスのインスタンスを作る
var taroObj:Taro = new Taro();

投稿者 oshige : 11:18 | コメント (0) | トラックバック

クラスメンバーとインスタンスメンバー

クラスのプロパティとメソッドをメンバーと呼びます。クラスのメンバーにはクラスメンバーとインスタンスメンバーがあります。クラスメンバーはstaticキーワードを使って作成することから静的メンバー(静的メソッドと静的プロパティ)とも呼びます。
クラスから作ったインスタンスごとにインスタンスメンバーが作られるのに対し、クラスメンバーは1回しか作られずクラス自身に割り当てられます。そこでクラスのすべてのインスタンスで共通して利用するプロパティやメソッドはクラスメンバーとして作ります。たとえば、インスタンスが何個作られているかというカウンタや共通の割引率などはクラスメンバーにするほうが合理的です。
次のTeamクラスではインスタンスの通し番号をクラスプロパティのseqNo変数でカウントアップし、同時に各インスタンスの番号をインスタンスプロパティのmyNo変数に登録していきます。

sample→ex04-02/class_memberフォルダ

クラス定義ファイル:Team.as
class Team {
//クラスメンバー
static var seqNo:Number = 0;
//インスタンスメンバー
var myNo:Number;
var myName:String;
//コンストラクタ
function Team(memname:String) {
myNo = ++seqNo;
myName = memname;
}
//自分の情報
function who():String {
var info = myNo + "-" + myName;
return info;
}
}

ではTeamクラスをテストしてみましょう。Flashムービーを作り、フレーム1のフレームアクションに次のスクリプトを書きます。名前を引数に指定してTeamクラスのインスタンスを作ります。そしてそれぞれのインスタンスのmyNoとmyNameの値をwho()関数で調べると、myNoには各インスタンスの通し番号が入っていることがわかります。


フレームアクション:teamtest.fla
var yo:Team = new Team("大重美幸");
var ty:Team = new Team("山本太郎");
trace(yo.who()); //出力→ 1-大重美幸
trace(ty.who()); //出力→ 2-山本太郎

投稿者 oshige : 11:24 | コメント (0) | トラックバック

クラスメンバーにアクセスする

クラスメンバーはビルトインクラスのMathクラスなどの使い勝手と同じように、インスタンスを作らなくともアクセスできる手軽さがあります。そこで次のようなKansanクラスを作れば、摂氏を華氏に換算するといった関数を手軽に利用できるようになります。


sample→ex04-02/class_memberフォルダ

クラス定義ファイル:Kansan.as
class Kansanki {
//摂氏を華氏に換算して返す
static function kashi(c:Number):Number {
var f = 1.8 * c + 32;
return f;
}
//華氏を摂氏に換算して返す
static function sessi(f:Number):Number {
var c = (f - 32) / 1.8;
return c;
}
//コンストラクタ
function Kansan() {
}
}


ムービーのフレームアクションに次のように書いてムービープレビューを行うと、kashi()関数の値が書き出されます。このようにクラスメンバーにはインスタンスを介さずに直接アクセスします。、


フレームアクション:classMemTest1.fla
var f = Kansan.kashi(20);
trace(f + "F"); //出力→ 68F
var c = Kansan.sessi(50);
trace(c + "C"); //出力→ 10C

note:
ビルトインクラスのMathクラスなどはインスタンスを作らなくとも利用できますが、その理由はPIやrandom()などがクラスメンバーだからです。

投稿者 oshige : 11:51 | コメント (0) | トラックバック

メンバーアクセスの制限(publicとprivate)

publicとprivateは、ほかのクラスやインスタンスからのプロパティ参照やメソッド実行にアクセスに制限を付けるためのキーワードです。デフォルトではメンバーアクセスに制限がなく自由に利用できますが、これは次の例に示すpublicキーワードが省略されている状態と言えます。

sample→ex04-02/publicフォルダ

クラス定義ファイル:MyClass01.as
class MyClass01 {
public var counter:Number = 0;
//コンストラクタ
public function MyClass01() {
}
//メソッド
public function countUp() {
counter++;
return ("counterの値は" + counter);
}
}


デフォルトでは、クラス定義されているプロパティを調べたりメソッドを実行したりすることをほかのクラスやインスタンスから自由に行えますが、これにアクセス制限を付けることができます。
次のBallPubクラスは動き回るボールを作ります。ボールは320×240の領域内で動き回り、壁に当たると跳ね返ります。

sample→ex04-02/privateフォルダ

クラス定義ファイル:BallPub.as
class BallPub {
//パブリック変数
public var mc;
public var dx;
public var dy;
//コンストラクタ
function BallPub(target:MovieClip, x:Number, y:Number) {
this.mc = target;
this.dx = x;
this.dy = y;
}
//ボールの動き
function f1() {
//壁で跳ね返る
if ((mc._x < 0) || (mc._x > 320)) {
dx *= -1;
}
if ((mc._y < 0) || (mc._y > 240)) {
dy *= -1;
}
//ボールの移動
mc._x += dx;
mc._y += dy;
}
}

BallPubクラスのmc、dx、dyはパブリック変数なので、ほかのクラスから参照して値を変更することができます。privateEx1.flaではmyBtnボタンをクリックするたびにdxとdyの値に-1を掛けて移動方向を反転してます。


フレームアクション:privateEx1.fla
var obj1:BallPub = new BallPub(ball_a, 5, 4);
//publicなメソッドにアクセスする
this.onEnterFrame = function () {
obj1.f1();
};
//publicなプロパティにアクセスする
//ボタンクリックで移動方向を反転する
myBtn.onPress = function(){
obj1.dx *= -1;
obj1.dy *= -1;
}

図4-2-1 ボタンをクリックするとボールの動く向きが反転します。


次のBallPvクラスはBallPubクラスと同じスクリプトですが、mc、dx、dyがプライベート変数になってます。このため、BallPvクラスのように外から移動速度を変更することができません。

クラス定義ファイル:BallPv.as
class BallPv {
//プライベート変数
private var mc;
private var dx;
private var dy;
//コンストラクタ
function BallPv(target:MovieClip, x:Number, y:Number) {
this.mc = target;
this.dx = x;
this.dy = y;
}
//ボールの動き
function f1() {
//壁で跳ね返る
if ((mc._x < 0) || (mc._x > 320)) {
dx *= -1;
}
if ((mc._y < 0) || (mc._y > 240)) {
dy *= -1;
}
//ボールの移動
mc._x += dx;
mc._y += dy;
}
}


次のようにインスタンスからプライベート変数のdx、dyにアクセスするとその部分がコンパイルエラーになります。

var obj1:BallPv = new BallPv(ball_a, 5, 4);
//publicなメソッドにアクセスする
this.onEnterFrame = function () {
obj1.f1();
};
//以下はプライベート変数にアクセスするのでコンパイルエラーになる
myBtn.onPress = function(){
obj1.dx *= -1;
obj1.dy *= -1;
}

note:
privateの指定はスクリプトの実行時に変数やメソッドへのアクセスを制限するというものではなく、厳密なデータ型などと同様にコンパイル時にチェックされる制限事項です。

*訂正 (2006.06.19 )
初版 p.128、p.130
初版では論理和の演算子orを使っていました。orは使用を推奨されていない演算子なので、orの代わりに||を使ってください。申し訳ないです。(う〜ん、ちょうどこれを書いている頃にLingoを使っていたのかも・・・・)

訂正前:
//壁で跳ね返る
if ((mc._x < 0) or (mc._x > 320)) {
dx *= -1;
}
if ((mc._y < 0) or (mc._y > 240)) {
dy *= -1;
}

訂正後:
//壁で跳ね返る
if ((mc._x < 0) || (mc._x > 320)) {
dx *= -1;
}
if ((mc._y < 0) || (mc._y > 240)) {
dy *= -1;
}

投稿者 oshige : 11:51 | コメント (0) | トラックバック

暗黙的なgetterメソッドとsetterメソッド

オブジェクト指向プログラミングの作法では、ほかのクラスのプロパティの値を直接書き換えたり読み出すこと良しとしない考え方があります。ではどうやって、ほかのクラスからプロパティにアクセスするかと言えば、プロパティの値を設定したり返したりする専用のメソッド、すなわち、getterメソッドとsetterメソッドをクラス内で定義しておき、それを介してのみアクセス可能にします。
しかしこれではクラスを利用するユーザーにとって手軽さを欠いたものになりかねません。そこでgetとsetのキーワードを使い、暗黙的なgetterメソッドとsetterメソッドを定義します。これであたかもプロパティに直接アクセスしているかのように見せることができます。
たとえば、次のGameクラスにはplayerNameとgamePointの2つのプロパティが使ってあります。GameクラスのインスタンスmyGameを作ったとき、2つのプロパティはプライベート変数であることから、myGame.playerName、myGame.gamePointのように簡単にアクセスすることができません。


sample→ex04-02/getsetフォルダ

クラス定義ファイル:Game.as
class Game {
//プライベート変数
private var playerName:String;
private var gamePoint:Number = 0;
//コンストラクタ
function Game(name:String) {
this.playerName = "Bomber_" + name;
}
//暗黙のgetterメソッド
function get player():String {
return this.playerName;
}
//暗黙のsetterメソッド
function set player(name:String):Void {
this.playerName = name;
}
//暗黙のgetterメソッド
function get point():Number {
return this.gamePoint;
}
//暗黙のsetterメソッド
function set point(v:Number):Void {
this.gamePoint = v;
}
}

しかし、get、setのキーワードを使ってplayerとpointのメソッドが定義してあることから、次のように外見上はオブジェクトのプロパティに直接アクセスしているかのように、2つのプロパティに気軽にアクセスすることができます。Gameクラスをブラックボックスと考えるならば、GameクラスのユーザーにとってはplayerとpointがGameクラスのプロパティとして見えます。

フレームアクション:getsetTest.fla
var myGame:Game = new Game("oshige");
myGame.point = 59;
trace(myGame.player); //出力→ Bomber_oshige
trace(myGame.point); //出力→ 59

note:
v2コンポーネントはget、setを利用することでユーザーにとってシンプルな使い勝手を実現してます。

投稿者 oshige : 11:52 | コメント (0) | トラックバック

ビルトインクラスの拡張

Dateクラス、String、Soundクラスといったビルトインクラス(Flash標準装備のクラス)をスーパークラスにすることで、ビルトインクラスを拡張したサブクラスを作ることができます。次の例ではDateクラスを拡張して今日の曜日名を漢字で返すgetYoubi()関数と”年月日(曜日)”で日付を返すgetLongDate()関数を組み込んでいます。

sample→ex04-03/yoDateフォルダ


クラス定義ファイル:YoDate.as
//Dateクラスを拡張する
class YoDate extends Date {
var youbiList:Array = ["日", "月", "火", "水", "木", "金", "土"];
var y:Number;
var m:Number;
var d:Number;
var youbi:String;
var longdate:String;
//コンストラクタ
function YoDate() {
}
//今日の曜日を返す
function getYoubi():String {
youbi = youbiList[this.getDay()];
return (youbi);
}
//長い日付を返す
function getLongDate():String {
y = this.getFullYear();
m = this.getMonth() + 1;
d = this.getDate();
youbi = this.getYoubi();
longdate = y + "." + m + "." + d + " (" + youbi + ")";
return (longdate);
}
}

では、実際にYoDateクラスを試してみましょう。YoDateクラスはDateクラスを継承しているので、YoDateクラスでインスタンスthedayを作ると今日の日付のDateオブジェクトが作られます。続いてインスタンスthedayに対してYoDateクラスで定義した2つの関数とDateクラスのsetFullYear()関数を実行してみます。この結果からYoDateクラスはDateクラスをスーパークラスとして確かに継承していることが確認できます。

フレームアクション:yodate.fla
var theday:YoDate = new YoDate();
//YoDateクラスで定義した関数
youbi = theday.getYoubi();
trace(youbi); // 出力→ 金
longdate = theday.getLongDate();
trace(longdate); // 出力→ 2005.1.14 (金)
//Dateクラスの関数
theday.setFullYear(2005, 3, 3);
longdate = theday.getLongDate();
trace(longdate); // 出力→ 2005.4.3 (日)

投稿者 oshige : 10:35 | コメント (0) | トラックバック

静的(static)クラスの拡張

次に静的(static)クラスを拡張する方法を紹介します。ActionScriptユーザーガイドには「TextField クラスや、Math、Key、Mouse などの静的クラスを拡張することはできません。」と書いてありますが、やり方によってはこれらのビルトインクラスの静的クラスも拡張できます。次の例ではMathクラスをスーパークラスとしたYoMathTestクラスを作り、数値を指定の桁数に四捨五入するyoRound()関数を追加します。スクリプトで使っているMath.pow(a,b)メソッドはaのb階乗を返す関数です。

sample→ex04-03/yoMathフォルダ

クラス定義ファイル:YoMathTest.as
//Mathクラスを拡張する
class YoMathTest extends Math {
//コンストラクタ
function YoMathTest() {
}
//指定の桁数にまるめる
function yoRound(v:Number, keta:Number) {
var tmpV = v * Math.pow(10, keta);
var ans = Math.round(tmpV) / Math.pow(10, keta);
return ans;
}
}

yoRound()関数を使って12.345を小数点以下2桁に四捨五入してみると12.35になることがわかります。

フレームアクション:yomathtest.fla
myObj = new YoMathTest();
x = myObj.yoRound(12.345,2)
trace(x); // 出力→ 12.35

しかし、Mathクラスのround()関数はMath.round()の書式で利用できます。これと同じようにyoRound()関数を利用できるようにするには、次のようにstaticキーワードでyoRound()関数をクラスメンバー(静的メンバー)に指定します。クラスのインスタンスを作らずにメンバーを利用することから、コンストラクタ関数もアクセスできないようにprivateに指定します。

クラス定義ファイル:YoMath.as
//Mathクラスを拡張する
class YoMath extends Math {
//コンストラクタ--privateにする
private function YoMath() {
}
//指定の桁数にまるめる--staticにする
static function yoRound(v:Number, keta:Number) {
var tmpV = v * Math.pow(10, keta);
var ans = Math.round(tmpV) / Math.pow(10, keta);
return ans;
}
}


YoMathクラスのyoRound()関数はインスタンスを作らなくても利用できます。

フレームアクション:yomath_1.fla
y = YoMath.yoRound(12.345,2)
trace(y) // 出力→ 12.35

ただ、これではYoMathクラスが本当にMathクラスを継承しているのかどうか判断できません。そこで、次のテストを行ってみます。次のスクリプトのYoMath.PIは、スーパークラスのMath.PIを参照します。このようにYoMathはMathクラスのメンバーを利用できることがわかります。

フレームアクション:yomath_2.fla
Math; // ←スーパークラスを参照しておく
pi = YoMath.yoRound(YoMath.PI, 2);
trace(pi); // 出力→ 3.14

このフレームアクションにおいてMathクラスを一度呼び出している理由は、タイムラインでは先にスーパークラスにアクセスした後からでないとスーパークラスのクラスメンバーの参照に失敗してしまうからです。この点に注意が必要です。
これでYoMathクラスがMathクラスを継承していることを確認できましたが、ビルトインクラスの静的クラスはいつでもどこからでも利用できることから、わざわざ継承して使う意味はあまりないかもしれません。

投稿者 oshige : 10:37 | コメント (0) | トラックバック

オーバーライド/ポリモーフィズム

ところで、YoMath.yoRound()関数を次のようにround()という名前にしてしまうとどうなるでしょうか。round()関数はスーパークラスであるMathクラスにもある関数です。このような場合はサブクラスで定義したroud()関数が優先されます。このようにスーパークラスと同じ名前のメンバーをサブクラスで再定義することを「オーバーライド(override)」するといい、このような手法は「ポリモーフィズム(polymorphism:多態性)」と呼ばれています。


sample→ex04-03/overrideフォルダ

クラス定義ファイル:YoMath.as
class YoMath extends Math {
//コンストラクタ
private function YoMath() {
}
//指定の桁数にまるめる --- Mathクラスのround()をオーバーライドする
static function round(v:Number, keta:Number) {
var tmpV = v * Math.pow(10, keta);
var ans = Math.round(tmpV) / Math.pow(10, keta);
return ans;
}
}

Mathクラスのround()関数をオーバーライドしたYoMathクラスのround()関数をテストすると次のようになります。

フレームアクション:yomath_3.fla
a = YoMath.round(23.85, 0)
trace(a) // 出力→ 24
b = YoMath.round(23.85, 1)
trace(b) // 出力→ 23.9

note:
オーバーライドと似た用語にオーバーロード(overload)があります。オーバーロードとは引数の型に応じて同名のメソッドをコンパイル時に振り分ける機能であり、ActionScriptはオーバーロードをサポートしていません。

投稿者 oshige : 10:37 | コメント (0) | トラックバック

MovieClipクラスの拡張

MovieClipクラスを拡張する場合には、リンケージプロパティでムービークリップシンボルとクラス定義ファイルとの関連付けを行うことができます。関連付けを行うと、シンボルからムービークリップインスタンスを作るだけで、そのインスタンスではアクションを書き込まずとも関連付けておいたクラスのプロパティとメソッドを利用できるようになります。この場合にもパブリッシュしたswfにクラス定義ファイルを付けて配布する必要はありません。
次のRolloverクラスには、ムービークリップインスタンスにカーソルをロールオーバーするとインスタンスの縦横サイズが150%に拡大し、ロールアウトすると元の100%のサイズに戻す2つの機能があります。extends MovieClipのようにMovieClipクラスを継承している点に注目してください。

sample→ex04-03/exMC/Rollover.as

クラス定義ファイル:Rollover.as
//MovieClipクラスの継承
class Rollover extends MovieClip {
//コンストラクタ
function Rollover(){
}
//ロールオーバーしたら150%サイズ
function onRollOver() {
_xscale = 150;
_yscale = 150;
}
//ロールアウトしたら100%サイズ
function onRollOut() {
_xscale = 100;
_yscale = 100;
}
}

このRolloverクラスをムービークリップシンボルと関連付けるには、ムービークリップシンボルをライブラリウィンドウで選択して[リンケージ...]を開きます。続いて[ActionScriptに書き出し]をチェックし[識別子]と[AS2.0クラス]を指定します。[AS2.0クラス]フィールドにはクラス名のRolloverを入力します。


図4-3-2 ムービークリップシンボルのリンケージプロパティを開き、識別子とAS2.0クラスを設定します。


ムービークリップシンボルとクラスとの関連付けが終わったならば、シンボルをステージにドロップしてインスタンスを作ります。ムービーをプレビューするとロールオーバー/ロールアウトでRolloverクラスで指定しているようにサイズが変わることがわかります。


sample→ex04-03/exMC/rollovermc.fla

図4-3-3 シンボルから作ったインスタンスはロールオーバーで拡大します。

もう1つサンプルを試してみましょう。次のRotorクラスはクリックで回転と停止を切り替える機能があります。このRotorクラスもまたMovieClipクラスを継承しています。

sample→ex04-03/exMC/RotorMC.as

クラス定義ファイル:RotorMC.as
//MovieClipクラスを継承する
//MovieClipクラスを継承する
class RotorMC extends MovieClip {
var speed:Number = 10;
//コンストラクタ
function RotorMC() {
}
//クリックでスイッチング
function onPress() {
if (typeof (onEnterFrame) == "function") {
//回転を止める
delete onEnterFrame;
} else {
//回転し続ける
onEnterFrame = function () {
_rotation += speed;
};
}
}
}

続いて、Rollクラスのときと同じようにRotorクラスをムービークリップシンボルのリンケージパネルを開いて関連付けます。


図4-3-4 ムービークリップシンボルのリンケージプロパティを開き、識別子とAS2.0クラスを設定します。

ムービークリップシンボルとクラスとの関連付けが終わったならば、シンボルをステージにドロップしてインスタンスを作ります。ムービーをプレビューしてインスタンスをクリックすると回転と停止が切り替わります。

図4-3-5 クリックで回転と停止が切り替わります。

attachMovie()メソッドを使えば、ムービークリップのインスタンスをスクリプトで作ることができます。次のスクリプトは、ムービーを再生中にリンケージシンボルstarMCからインスタンスを3個作ります。リンケージシンボルstarMCにはRotorMCクラスが関連付けてあるので、クリックで回転と停止が切り替わるインスタンスになります。


フレームアクション:attachmc.fla
this.makemc();
function makemc() {
for (i = 1; i <= 3; i++) {
var depth = this.getNextHighestDepth();
var x = 50 * i;
var y = 30 * i;
var props = {_x:x, _y:y};
var mcname = "star" + depth;
//ムービークリップシンボルのインスタンスを作る
this.attachMovie("starMC", mcname, depth, props);
}
}

図4-3-6 attachMovie()メソッドを使ってリンケージシンボルからインスタンスを作成します。

note:
ムービークリップシンボルとクラスの関連付けはObject.registerClass()を使って行うこともできますが、ActionScript2.0ではリンケージプロパティで関連付けます。

*訂正 (2006.06.19 )
初版のp.141のスクリプトに間違いがありました。
誤:
class RotorMC extends MovieClip{

正:
class Rollover extends MovieClip {


投稿者 oshige : 10:38 | コメント (0) | トラックバック

ダイナミッククラスを作る

ダイナミッククラスとは、スクリプトを実行している最中にクラスメンバーやインスタンスメンバーを追加することができるクラスです。ダイナミッククラスを作るには、クラス定義の際にdynamicキーワードを指定します。
次のMyClassクラスにはコンストラクタ以外はプロパティもメソッドも定義してありませんが、dynamicキーワードでダイナミッククラスに指定してあることからムービーの再生中にメンバーを追加することができます。

sample→ex04-04/dynamicフォルダ

クラス定義ファイル:MyClass.as
dynamic class MyClass {
//コンストラクタ
function MyClass() {
}
}

投稿者 oshige : 10:39 | コメント (0) | トラックバック

インスタンスメンバーを追加する

たとえば、次のフレームアクションをテストするとMyClassクラスで作ったインスタンスaObj、bObjのそれぞれにpriceプロパティが追加されて150と200の値が割り当てられたことがわかります。

フレームアクション:myclasstest1.fla
//インスタンスを作る
var aObj:MyClass = new MyClass();
var bObj:MyClass = new MyClass();
//インスタンスプロパティを追加する
aObj.price = 150;
bObj.price = 200;
//追加したインスタンスプロパティを確認する
trace(aObj.price); // 出力→ 150
trace(bObj.price); // 出力→ 200

続けて次のようにaObjにインスタンスメソッドurine()を追加し、試しにaObjとbObjの両方のインスタンスでurine()を実行します。

//インスタンスメソッドを追加する
aObj.urine = function() {
var v = this.price * 1.2;
return v;
};
//追加したインスタンスメソッドを試す
trace(aObj.urine());// 出力→ 180
trace(bObj.urine());// 出力→ undefined

確かにaObjインスタンスにはurine()メソッドが追加されていますが、bObjインスタンスではurine()メソッドが利用できません。インスタンスメンバーというものは、プロパティもメソッドもインスタンスごとに保有しているものであることがこれでもわかります。

投稿者 oshige : 10:43 | コメント (0) | トラックバック

クラスメンバーを追加する

ダイナミッククラスではクラスメンバーを追加することもできます。先のMyClassクラスにクラスメンバーを追加してみましょう。クラスメンバーの追加は、クラス名に対してプロパティやメソッドを直接設定します。次の例ではxプロパティとfx()メソッドを追加し、追加が成功したかどうかを続けてテストしています。


フレームアクション:myclasstest2.fla
//クラスメンバーを追加する
MyClass.x = 120;
MyClass.fx = function(v:Number) {
var ans = v * 3;
return ans;
};
//追加したクラスメンバーをテストする
trace(MyClass.x);// 出力→ 120
trace(MyClass.fx(15));// 出力→ 45

投稿者 oshige : 10:44 | コメント (0) | トラックバック

ダイナミッククラスのビルトインクラス

Objectクラスはインスタンスにプロパティやメソッドを追加するといった使い方をします。ムービークリップシンボルのインスタンスの場合も同様です。それはObjectクラスやMovieClipクラスがダイナミッククラスだからです。これらのクラスにはインスタンスメンバーだけでなくクラスに対してクラスメンバーを追加することもできます。
ビルトインクラスの中でダイナミッククラスであるものには、Array、ContextMenu、ContextMenuItem、Function、LoadVars、MoviwClip、NetConnection、Object、SharedObject、TextFieldといったクラスがあります。

投稿者 oshige : 10:44 | コメント (0) | トラックバック

インターフェイスとは

インターフェイスとは、クラス定義を行うときの約束事として、クラスが必ず実装しなければならないメソッドを指定した仕様書のようなものです。
たとえば、ロケットとその発射装置を開発するとき、「ロケットはfire信号で点火するように開発するから、発射装置はロケットにfire信号を送れるように作ってくれればよい」というような仕様の取り決めさえあれば、ロケットと発射装置の開発は互いの内部処理はまったく知らなくとも別々に進めることができます。もし、ロケットの打ち上げに失敗しても、次のロケットも同じようにfire信号で点火するように作ってあれば、同じ発射装置で飛ばすことができます。ここに
 1.ロケットの仕様
 2.発射装置の仕様
 3.インターフェイスの仕様
の3つの仕様が存在することに気付きます。そしてロケットと発射装置はインターフェイスの仕様を共有していることがわかります。

投稿者 oshige : 11:22 | コメント (0) | トラックバック

インターフェイスの定義

これをActionScriptで書くと次のようになります。インターフェイスはinterfaceキーワードで定義します。インターフェイスで指定できるのはメソッドだけで、プロパティの指定やfunctionブロックなどを書くことはできません。

sample→ex04-05/interfaceフォルダ

インターフェイス定義:RocketInterface.as
interface RocketInterface {
function fire():Void;
}

インターフェイスの取り決めを守るクラスでは、implementsキーワードでインターフェイス定義ファイルを指定し、実際にインターフェイスで指定されているメソッドを実装します。インターフェイスを指定しているにも関わらず、インターフェイスで指定されているメソッドを実装していなかったり、メソッドの引数や戻り値のデータ型が一致していないとコンパイルエラーになります。インターフェイスRocketInterfaceを使うクラスRocket1は次のようなクラス定義になります。

インターフェイスを守るクラス定義:Rocket1.as
class Rocket1 implements RocketInterface {
//コンストラクタ
function Rocket1() {
}
//インターフェイスで取り決められているメソッド
function fire():Void {
trace("ロケット点火処理");
}
/*
以下、ロケット1号機の内部処理が続く
*/
}


同様に別の開発者はインターフェイスRocketInterface.asを譲り受ければロケット2号機の開発に着手できます。

インターフェイスを守るクラス定義:Rocket2.as
class Rocket2 implements RocketInterface {
//コンストラクタ
function Rocket2() {
}
//インターフェイスで取り決められているメソッド
function fire():Void {
trace("ロケット点火処理");
}
/*
以下、ロケット2号機の内部処理が続く
*/
}

一方、Rocket1クラス、Rocket2クラスと連携する発射装置側のLauncherクラスは次のように定義することができます。

クラス定義:Launcher.as
class Launcher {
var myRocket;
//コンストラクタ
function Launcher(rocket) {
myRocket = rocket;
}
//ロケットに点火する
function startrocket():Void {
/*
準備処理
*/
//点火
myRocket.fire();
}
/*
以下、発射装置の内部処理が続く
*/
}

実際のテストはフレームアクションで次のように行うことができます。

フレームアクション:rockettest.fla
//ロケット1号機を作る
var rocket:Rocket1 = new Rocket1();
//発射台にセット
var theLauncher:Launcher = new Launcher(rocket);
//点火
theLauncher.startrocket(); // 出力→ ロケット点火処理


note:
インターフェイスは、インターフェース、インタフェースと多様な日本語表記が流通しています。サイト等の検索の際には注意してください。

投稿者 oshige : 11:23 | コメント (0) | トラックバック

複数のインターフェイスを適用する

先の例ではインターフェイスで指定しているメソッドが1つでしたが、複数個のメソッドを指定でき、メソッドの引数やデータ型なども指定できます。また、implementsでは複数のインターフェイスファイルを同時に指定できます。たとえば、RedBook、YellowBookという2つのインターフェイスを守るMainClassクラスのクラス定義は次のようになります。

sample→ex04-05/interface2フォルダ

インターフェイス定義ファイル:RedBook.as
interface RedBook {
function redMethod1():Void;
function redMethod2():Void;
}

インターフェイス定義ファイル:YellowBook.as
interface YellowBook {
function yellowMethod1():Void;
}

インターフェイスを守るクラス定義:MainClass.as
class MainClass implements RedBook, YellowBook {
//コンストラクタ
function MainClass() {
}
//インターフェイスに基づいて実装するメソッド
function redMethod1():Void {
//処理a
}
function redMethod2():Void {
//処理b
}
function yellowMethod1():Void {
//処理c
}
/*
その他の処理
*/
}

投稿者 oshige : 11:23 | コメント (0) | トラックバック

インターフェイスのクラスパス

インターフェイス定義ファイルがサブフォルダに入っている場合には、クラス定義ファイルと同じようにクラスパスを指定しなければなりません。インターフェイス定義ファイルをサブフォルダに入れてパッケージとして整理する方法もクラス定義ファイルの場合と同じです(クラスパス→p.??、パッケージ→p.??)。RedBook、YellowBookのインターフェイス定義ファイルがrulebookフォルダに入っている場合は次のようになります。


sample→ex04-05/interfacepathフォルダ

MainClass.as
rulebookフォルダ
 ├ RedBook.as
 └ YellowBook.as


インターフェイス定義ファイル:RedBook.as
interface rulebook.RedBook {
function redMethod1():Void;
function redMethod2():Void;
}


インターフェイス定義ファイル:YellowBook.as
interface rulebook.YellowBook {
function yellowMethod1():Void;
}


インターフェイスを守るクラス定義:MainClass.as
import rulebook.*;
class MainClass implements RedBook, YellowBook {
//コンストラクタ
function MainClass() {
}
//インターフェイスに基づいて実装するメソッド
function redMethod1():Void {
//処理a
}
function redMethod2():Void {
//処理b
}
function yellowMethod1():Void {
//処理c
}
/*
その他の処理
*/
}

投稿者 oshige : 11:24 | コメント (0) | トラックバック

インターフェイスの継承

インターフェイスはクラスと同様にextrendsキーワードを使ってほかのインターフェイスを継承することができます。たとえば、GreenRuleインターフェイスがWhiteRuleインターフェイスを継承しているとき、GreenRuleインターフェイスを採用しているMyClassクラスはGreenRuleインターフェイスとWhiteRuleインターフェイスの両方のメソッドを実装しなければなりません。

sample→ex04-05/extendsフォルダ

インターフェイス定義ファイル:WhiteRule.as
interface WhiteRule {
function whiteMethod(v:Number):Number;
}


インターフェイス定義ファイル:GreenRule.as
//WhiteRuleインターフェイスを継承してる
interface GreenRule extends WhiteRule {
function greenMethod(s:String):Void;
}


インターフェイスを守るクラス定義:MyClass.as
class MyClass implements GreenRule {
var myS:String;
//コンストラクタ
function MyClass() {
}
//インターフェースに基づいて実装するメソッド
function whiteMethod(v:Number):Number {
var x = v * 2;
return x;
}
function greenMethod(s:String):Void {
myS = s;
}
}

投稿者 oshige : 11:24 | コメント (0) | トラックバック

データ型としてのインターフェイス

あるクラスが指定のインターフェイスに基づいているかどうかを調べることができます。インターフェイスに基づいていれば指定のメソッドを実装していることになり、安心してメソッドを呼び出すことができます。
インターフェイスに基づいているかどうかは、RocketInterface(myRocket)のようにインターフェイス(インスタンス)のようにキャスト式を実行したときの戻り値で判定できます(キャスト→p.??)。インターフェイスを実装するインスタンスならばインスタンスがそのまま返り、実装してない場合はnullが返ってきます。


sample→ex04-05/interfacecheckフォルダ

class Launcher2 {
var myRocket;
//コンストラクタ
function Launcher2(rocket) {
myRocket = rocket;
}
//ロケットに点火する
function startrocket():Void {
//インターフェイスが実装されているならば点火する
if (RocketInterface(myRocket) != null) {
myRocket.fire();
}
}
}

投稿者 oshige : 11:25 | コメント (0) | トラックバック