静岡理工科大学 菅沼ホーム ActionScript目次 索引

描画とイベント処理

      1. オブジェクトの階層
      2. 基本的な例
        1. 表示階層
        2. 透明度とマスク
        3. アニメーション
      3. 演習問題の解答
      4. お絵かき

  1. オブジェクトの階層

      ActionScript で構築された各アプリケーションには," 表示リスト " と呼ばれる表示されるオブジェクトの階層があります.表示リストには,アプリケーション内で表示されるエレメントがすべて含まれます.表示エレメントは,ステージ( Stage )オブジェクト表示オブジェクト,及び,表示オブジェクトコンテナから構成されます.

      ステージオブジェクトは,表示オブジェクトの基本コンテナです.各アプリケーションには必ず 1 つの Stage オブジェクトがあり,その中に表示オブジェクト及び表示オブジェクトコンテナがすべて含まれます.各 SWF ファイルに対して,対応する ActionScript クラスをその SWF ファイルのメインクラスと呼びます.HTML ページに埋め込まれた SWF ファイルを開くと,メインクラスによって生成されるインスタンス(表示オブジェクトコンテナ)が Stage オブジェクトの子として追加されます.このとき,SWF ファイルのメインクラスは,常に Sprite クラスを継承します.

      ActionScript では,アプリケーション内で画面上に表示されるすべてのエレメントのタイプは表示オブジェクトであり,次の図に示すように,DisplayObject クラスのサブクラスです.表示オブジェクトコンテナ( DisplayObjectContainer クラス)は,特殊な型の表示オブジェクトであり,他の表示オブジェクトをその子として含むこともできます.なお,DisplayObjectContainer クラスは,DisplayObject クラスのサブクラスです.

      Shape,Sprite,および,MovieClip の各オブジェクトには,Graphics クラスのインスタンスである graphics プロパティを持っています.Graphics クラスには,線,塗り,および,シェイプを描画するためのプロパティおよびメソッドがあり,様々な図形を描くことが可能です.

      表示オブジェクトをコンテンツを描画するキャンバスとしてのみ使用する場合は,Shape クラスを使用します.Shape クラスには,Sprite クラスや MovieClip クラスにある追加機能によるオーバーヘッドがないため,描画の性能が優れています.表示オブジェクト上に他の表示オブジェクトも含めたい場合は,Sprite クラスを使用します.

      以下に,コア表示オブジェクトクラスの関係と,各クラスの概要を述べます.これらのほとんどのクラスは,flash.display パッケージに含まれています.

    クラス名 概要 インスタンス生成
    DisplayObject すべての表示オブジェクトクラスの最上位クラスである 不可能
    AVM1Movie ActionScript 1.0 または 2.0 でオーサリングされたロード済み SWF ファイルを表現する 不可能
    Bitmap 外部ファイルからロードされたビットマップオブジェクト,または,ActionScript でレンダリングされたビットマップオブジェクトを定義する.また,Loader クラスを使用して外部ファイルからビットマップをロードできる(ロードできるのは,GIF,JPG,PNG ファイル). 可能
    InteractiveObject マウスとキーボードの操作に使用されるすべてのオブジェクトの基本クラスである 不可能
    MorphShape Flash オーサリングツールでシェイプトゥイーンを作成したときに作成される 不可能
    Shape ベクターグラフィック ( 矩形,線,円など) を作成する 可能
    StaticText インスタンスをコードで作成することはできない.Adobe Flash CS3 Professional だけで作成できる. 不可能
    Video ビデオファイルの表示に使用される 可能
    DisplayObjectContainer Loader,Stage,Sprite,MovieClip の親クラスである 不可能
    SimpleButton Flash ボタンシンボルの ActionScript 表現である 可能
    TextField テキストの表示と入力用の表示オブジェクトである 可能
    Loader 外部アセット( SWF ファイルまたはグラフィック)をロードする 可能
    Sprite 独自のグラフィックを格納でき,かつ,子表示オブジェクトを格納することもできる 可能
    Stage アプリケーションには Stage インスタンスが 1 つあり,表示リスト階層の最上位にある 不可能
    MovieClip タイムラインがあること以外,Sprite オブジェクトと似ている 可能

  2. 基本的な例

    1. 表示階層

        この例において,その表示オブジェクトの親子関係は最初右図のようになっています.つまり,円オブジェクト( ball )は左の四角形オブジェクト( rect1 )の子供となっています.しかし,この関係は必ずしも固定されたものではありません.円をクリックすることによって,親とするオブジェクトが移動していきます.以下に示すのは,表示を行う HTML ファイル struct.htm と,ActionScript のソースプログラム Struct.as です.

        なお,この例を実行すると,円をクリックする毎に以下に示すような結果(各四角形の子供の数)が表示されます(見易いように,TextField を下の方へドラッグして下さい).
      0 1 0
      0 0 1
      1 0 0
      ・・・
      				

      struct.htm

      <!DOCTYPE HTML>
      <HTML>
      <HEAD>
      	<TITLE>表示階層</TITLE>
      	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=utf-8">
      	<LINK REL="stylesheet" TYPE="text/css" HREF="../../../../master.css">
      </HEAD>
      <BODY CLASS="white">
      	<H1 CLASS="center">表示階層</H1>
      	<P CLASS="center">
      		<object type="application/x-shockwave-flash" width="400" height="300" data="Struct.swf">
      			<param name="movie" value="Struct.swf">
      			<param name="quality" value="high">
      			<param name="bgcolor" value="#eeffee">
      		</object>
      	</P>
      </BODY>
      </HTML>
      				

      Struct.as

      01	package {   // パッケージ名は省略
      02		import flash.display.Sprite;
      03		import flash.events.MouseEvent;
      04	
      05		[SWF(backgroundColor="0xeeffee", width="400", height="300", frameRate="30")]
      06	
      07		public class Struct extends Sprite {
      08			private var rect1 : Sprite;
      09			private var rect2 : Sprite;
      10			private var rect3 : Sprite;
      11			private var ball : Sprite;
      12			private var sw : int = 1;
      13			public var msg : Message;
      14	
      15			public function Struct() {
      16				msg = new Message(300, 100);
      17				addChild(msg);
      18				rect1 = new Sprite();
      19				addChild(rect1);
      20				rect1.graphics.lineStyle(1, 0);
      21				rect1.graphics.drawRect(-50, -50, 100, 100);
      22				rect1.x = 70;
      23				rect1.y = 65;
      24				
      25				rect2 = new Sprite();
      26				addChild(rect2);
      27				rect2.graphics.lineStyle(1, 0);
      28				rect2.graphics.drawRect(-50, -50, 100, 100);
      29				rect2.x = 200;
      30				rect2.y = 65;
      31				
      32				rect3 = new Sprite();
      33				addChild(rect3);
      34				rect3.graphics.lineStyle(1, 0);
      35				rect3.graphics.drawRect(-50, -50, 100, 100);
      36				rect3.x = 330;
      37				rect3.y = 65;
      38				
      39				ball = new Sprite();
      40				rect1.addChild(ball);
      41				ball.graphics.beginFill(0x00ff00);
      42				ball.graphics.drawCircle(0, 0, 40);
      43				ball.graphics.endFill();
      44				ball.addEventListener(MouseEvent.CLICK, onBallClick);
      45			}
      46			
      47			public function onBallClick(event:MouseEvent):void
      48			{
      49				if (sw == 1) {
      50					sw = 2;
      51					rect2.addChild(ball);
      52				}
      53				else if (sw == 2) {
      54					sw = 3;
      55					rect3.addChild(ball);
      56				}
      57				else {
      58					sw = 1;
      59					rect1.addChild(ball);
      60				}
      61				msg.tx.appendText(rect1.numChildren + " " + rect2.numChildren + " " + rect3.numChildren + "\n");
      62			}
      63		}
      64	}
      				
      02 行目

        システムの「 flash.display 」パッケージにある Sprite クラスを読み込んでる.

      03 行目

        マウスクリックに対するイベント処理を行うため,システムの「 flash.events 」パッケージにある MouseEvent クラスを読み込んでる.

      05 行目

        背景色,画面のサイズ,及び,描画間隔の定義である.背景色は,HTML ファイルで指定した色が優先され,その記述がない場合は,ここで指定した色になる.画面は HTML ファイルで指定した大きさになり,ここで指定したサイズと異なっていた場合は,HTML ファイルで指定した大きさになるように拡大または縮小の処理が行われる.また,frameRate ( 1 秒間に表示するフレーム数)は,定期的に画面を再描画したいような場合の描画間隔に相当する.

      07 行目

        ステージに貼り付けられる Struct クラス(メインクラス)の定義の始まりである(その内容は,07 行目~ 63 行目).

      15 行目~ 45 行目

        Struct クラスのコンストラクタである.コンストラクタは,クラス名と同じ名前を持つメソッドであり,クラスのインスタンスが生成されたとき,最初に実行される.つまり,オブジェクトの初期化を行うメソッドである.

      16 行目~ 17 行目

        メインクラスに,メッセージを出力するために,Message クラスのオブジェクトを追加している.

      18 行目~ 23 行目

        メインクラスの指定した位置 ( 70, 65 ) に,Sprite クラスのオブジェクト rect1 を追加し,矩形を描いている.

      25 行目~ 30 行目

        メインクラスの指定した位置 ( 200, 65 ) に,Sprite クラスのオブジェクト rect2 を追加し,矩形を描いている.

      32 行目~ 37 行目

        メインクラスの指定した位置 ( 330, 65 ) に,Sprite クラスのオブジェクト rect3 を追加し,矩形を描いている.

      39 行目~ 43 行目

        rect1 に,Sprite クラスのオブジェクト ball を追加し,緑色で塗りつぶした円を描いている.ball の上には,子表示オブジェクトを格納しないので Shape クラスでも良いように思える.しかし,Shape クラスは,InteractiveObject クラスを継承しないため,マウスイベントやキーボードイベントをサポートしない.

      44 行目

        ball をマウスでクリックした際のイベント処理を行うため,イベントリスナを追加( addEventListener,Sprite クラスの親である EventDispatcher クラスのメソッド)している.この結果,ball をクリックすると,メソッド onBallClick (このメソッド名は任意)が実行される.

      47 行目~ 62 行目

        ball をマウスでクリックした際に実行されるメソッドである.変数 sw の値が 1 であるときは ball を rect2 に,2 であるときは ball を rect3 に,また,3 であるときは ball を rect1 に移動している.また,62 行目では,rect1,rect2,及び,rect3 の子供の数を Message クラスのテキストフィールドに出力している.

        Message クラスは,「コンパイルと実行」で使用したクラスであり,下に示す Message クラスを定義したファイル Message.as を上のプログラムと同じフォルダにコピーし,出力したいクラスの中に,
      var msg : Message = new Message();
      addChild(msg);
      				
      の 2 行を追加すれば( 16,17 行目),61 行目のように,中間結果を出力したいようなときに利用できます.なお,TextField は,ドラッグすることによって任意の位置に移動可能です.

      Message.as

      package
      {
      	import flash.display.Sprite;
      	import flash.text.TextField;
      	import flash.text.TextFieldType;
      	import flash.text.TextFormat;
      	import flash.text.TextFormatAlign;
      	import flash.events.MouseEvent;
      
      	public class Message extends Sprite
      	{
      		public var tx : TextField;
      		public function Message(w : int, h : int)
      		{
      			tx = new TextField();
      			tx.width = w;
      			tx.height = h;
      			tx.x = 0;
      			tx.y = 0;
      			tx.type = TextFieldType.DYNAMIC;
      			tx.background = true;
      			tx.backgroundColor = 0xffffff;
      			tx.border = true;
      			tx.borderColor = 0x00ff00;
      			tx.multiline = true;
      			var tf : TextFormat = new TextFormat();
      			tf.size = 20;
      			tx.defaultTextFormat = tf;
      			addChild(tx);
      			addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      		}
      
      		private function onMouseDown(event:MouseEvent):void
      		{
      			startDrag();
      			addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
      			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
      		}
      
      		private function onMouseMove(event:MouseEvent):void
      		{
      			event.updateAfterEvent();
      		}
      
      		private function onMouseUp(event:MouseEvent):void
      		{
      			stopDrag();
      			removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
      			stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
      		}
      	}
      }
      				
    2. 透明度とマスク

        透明度の変更例においては,内側の円をクリックすると徐々に透明度が増し,最終的には完全に透明になってしまいます.以下に示すのは,そのプログラム Color_e.as です.このプログラムにおいて,ball1 は単に描くだけですので Shape クラスを利用しています.

      Color_e.as

      01	package {
      02		import flash.display.Sprite;
      03		import flash.display.Shape;
      04		import flash.events.MouseEvent;
      05	
      06		[SWF(backgroundColor="0xeeffee", width="130", height="130", frameRate="30")]
      07	
      08		public class Color_e extends Sprite {
      09			private var ball1 : Shape;
      10			private var ball2 : Sprite;
      11	
      12			public function Color_e() {
      13				init();
      14			}
      15	
      16			private function init():void {
      17				ball1 = new Shape();
      18				addChild(ball1);
      19				ball1.graphics.beginFill(0xff0000);
      20				ball1.graphics.drawCircle(65, 65, 50);
      21				ball1.graphics.endFill();
      22	
      23				ball2 = new Sprite();
      24				addChild(ball2);
      25				ball2.graphics.beginFill(0x0000ff);
      26				ball2.graphics.drawCircle(65, 65, 30);
      27				ball2.graphics.endFill();
      28				ball2.addEventListener(MouseEvent.CLICK, onBallClick);
      29			}
      30			
      31			public function onBallClick(event:MouseEvent):void
      32			{
      33				if (ball2.alpha > 0)
      34					ball2.alpha -= 0.1;
      35			}
      36		}
      37	}
      				
      12 行目~ 14 行目

        クラス Color_e のコンストラクタである.ここでは,単に,メソッド init を呼んでいるだけである.

      16 行目

        メソッド init の定義の始まりである(その内容は,16 行目~ 29 行目).

      17 行目~ 21 行目

        メインクラスに,Shape クラスのオブジェクト ball1 を追加し,半径 50 ピクセルの赤色で塗りつぶした円を描いている.この例では,ball1 の子供として他のオブジェクトを追加していないので,Shape クラスを利用している.

      23 行目~ 27 行目

        メインクラスに,Sprite クラスのオブジェクト ball2 を追加し,半径 30 ピクセルの青色で塗りつぶした円を描いている.

      31 行目~ 35 行目

        ball2 をマウスでクリックした際に実行されるメソッドである.継承している DisplayObject クラスのプロパティ alpha を使用して,透明度を 0.1 ずつ変化させている.

        また,マスクの例においては,内側の円が外側の円に対するマスクとして働き,内側の円をクリックすると,外側の円の内,内側の円で覆われた部分だけが表示されます.以下に示すのは,そのプログラムです.

      Mask_e.as

      01	package {
      02		import flash.display.Sprite;
      03		import flash.display.Shape;
      04		import flash.events.MouseEvent;
      05	
      06		[SWF(backgroundColor="0xeeffee", width="130", height="130", frameRate="30")]
      07	
      08		public class Mask_e extends Sprite {
      09			private var ball1 : Shape;
      10			private var ball2 : Sprite;
      11	
      12			public function Mask_e() {
      13				init();
      14			}
      15	
      16			private function init():void {
      17				ball1 = new Shape();
      18				addChild(ball1);
      19				ball1.graphics.beginFill(0xff0000);
      20				ball1.graphics.drawCircle(65, 65, 50);
      21				ball1.graphics.endFill();
      22	
      23				ball2 = new Sprite();
      24				addChild(ball2);
      25				ball2.graphics.beginFill(0xffffff);
      26				ball2.graphics.drawCircle(65, 65, 30);
      27				ball2.graphics.endFill();
      28				ball2.addEventListener(MouseEvent.CLICK, onBallClick);
      29			}
      30			
      31			public function onBallClick(event:MouseEvent):void
      32			{
      33				ball1.mask = ball2;
      34			}
      35		}
      36	}
      				
      12 行目~ 14 行目

        クラス Mask_e のコンストラクタである.ここでは,単に,メソッド init を呼んでいるだけである.

      16 行目

        メソッド init の定義の始まりである(その内容は,16 行目~ 29 行目).

      17 行目~ 21 行目

        メインクラスに,Shape クラスのオブジェクト ball1 を追加し,半径 50 ピクセルの赤色で塗りつぶした円を描いている.この例では,ball1 の子供として他のオブジェクトを追加していないので,Shape クラスを利用している.

      23 行目~ 27 行目

        メインクラスに,Sprite クラスのオブジェクト ball2 を追加し,半径 30 ピクセルの白色で塗りつぶした円を描いている.

      31 行目~ 34 行目

        ball2 をマウスでクリックした際に実行されるメソッドである.継承している DisplayObject クラスのプロパティ mask を使用して,ball1 に ball2 のマスクをかけている.

    3. アニメーション

        以下に示すのは,ボールの落下(ボールをクッリクすると停止し,もう一度クリックすると再び動き出します)に対するプログラム Ball.as です.enterFrame イベントは,ActionScript の実行が完了し次のフレームのレンダリングを開始する準備が整ったとき,または,フレームレート( 1 秒間に表示するフレーム数を表す)で定められた時間が経過したときに発生します.ただし,フレームレートで定められた時間が経過しても,ActionScript の実行が完了していない場合は,その完了まで最大 15 秒待ちます.

        この例を実行すると,Message クラスの TextField に以下に示すような結果が表示されます.すべてのデータが表示されないと思いますが,TextField をクリックした後,矢印キーを使用すればすべてのデータを見ることができます.
      position 1.5 0
      position 3 0.15000000000000002
      position 4.5 0.4
      position 6 0.75
      position 7.5 1.2000000000000002
      position 9 1.75
      position 10.5 2.4000000000000004
      position 12 3.1
      	・・・・・
      			

      Ball.as

      01	package {
      02		import flash.display.Sprite;
      03		import flash.events.Event;
      04		import flash.events.MouseEvent;
      05	
      06		[SWF(backgroundColor="0xeeffee", width="600", height="400", frameRate="30")]
      07	
      08		public class Ball extends Sprite {
      09			private var ball : Sprite;
      10			private var g : Number = 9.8;   // y 軸方向の加速度
      11			private var v0 : Number = 0;   // y 軸方向の初期速度
      12			private var v : Number = 0;   // y 軸方向の現在速度
      13			private var t : Number = 0;   // 時間の初期値
      14			private var h0 : Number = stage.stageHeight;   // ボールの初期位置の y 座標(上が正,初期高さ)
      15			private var sw : Number = 1;   // ボールの状態( 0:停止している,1:動いている)
      16			public var msg : Message;
      17	
      18			public function Ball() {
      19				msg = new Message(300, 100);
      20				addChild(msg);
      21				ball = new Sprite();
      22				addChild(ball);
      23				ball.graphics.beginFill(0x00ff00);
      24				ball.graphics.drawCircle(0, 0, 40);
      25				ball.graphics.endFill();
      26				ball.x = 0;
      27				ball.y = 0;
      28				addEventListener(Event.ENTER_FRAME, onEnterFrame);
      29				ball.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      30			}
      31	
      32			private function onEnterFrame(event:Event):void {
      33				if (ball.x < stage.stageWidth + 40 && sw > 0) {
      34					ball.x += 1.5;
      35					t      += 0.1;
      36					v       = -g * t + v0;
      37					ball.y  = stage.stageHeight - (-0.5 * g * t * t + v0 * t + h0);
      38					if (ball.y >= stage.stageHeight - 40 && v < 0) {
      39						ball.y = stage.stageHeight - 40;
      40						v0     = -0.8 * v;
      41						h0     = 40;
      42						t      = 0;
      43					}
      44					msg.tx.appendText("position " + ball.x + " " + ball.y + "\n");
      45				}
      46			}
      47	
      48			private function onMouseDown(event:MouseEvent):void {
      49				if (sw == 0)
      50					sw = 1;
      51				else
      52					sw = 0;
      53			}
      54		}
      55	}
      				
      03,04 行目

        ENTER_FRAME イベントに対応するため,Event クラス,また,マウスイベントに対応するため,MouseEvent クラスを読み込んでる.

      06 行目

        frameRate によって,1 秒間に表示するフレーム数(約 33 ms 毎に表示)を指定している.

      21 行目~ 27 行目

        メインクラスに,Sprite クラスのオブジェクト ball を追加し,緑色で塗りつぶした半径 40 ピクセルの円を描いている.

      28 行目

        ENTER_FRAME イベントに対する処理を行うため,イベントリスナを追加している.この結果,ENTER_FRAME イベントが発生すると(約 33 ms 毎に発生),メソッド onEnterFrame が実行される.

      29 行目

        ball をマウスでクリックした際の処理を行うため,イベントリスナを追加している.この結果,ball をクリックすると,メソッド onMouseDown が実行される.

      32 行目~ 46 行目

        ENTER_FRAME イベントが発生した際に実行されるメソッドである.以下の処理は,ボールが動いており( sw > 0 ),かつ,画面内に存在したとき実行される.
      • 34 行目: ボールの x 座標の変更( 1.5 ピクセル / 33 ms )
      • 35 行目: 時間の変更( 0.1 秒 / 33 ms )
      • 36 行目: ボールの速度の変更
      • 37 行目: ボールの y 座標の変更.画面座標に合うように座標変換も行っている.
      • 38 行目~ 43 行目: ボールが地面に落ちたときの跳ね返り処理を行っている.その際,速度が 0.8 倍される.
      • 44 行目: ボールの位置を Message クラスのテキストフィールドに出力している.

      48 行目~ 53 行目

        ball をマウスでクリックした際に実行されるメソッドである.ボールが動いている場合は停止,停止している場合は再び動かしている.

        アニメーションを実現するあと一つの方法は,Timer クラスを利用する方法です.以下に示すのは,ボールの落下( Timer クラスを利用)に対するプログラム Ball.as です.

      Ball.as

      01	package {
      02		import flash.display.Sprite;
      03		import flash.events.MouseEvent;
      04		import flash.events.TimerEvent;
      05		import flash.utils.Timer;
      06	
      07		[SWF(backgroundColor="0xeeffee", width="600", height="400", frameRate="30")]
      08	
      09		public class Ball extends Sprite {
      10			private var ball : Sprite;
      11			private var g : Number = 9.8;   // y 軸方向の加速度
      12			private var v0 : Number = 0;   // y 軸方向の初期速度
      13			private var v : Number = 0;   // y 軸方向の現在速度
      14			private var t : Number = 0;   // 時間の初期値
      15			private var h0 : Number = stage.stageHeight;   // ボールの初期位置の y 座標(上が正,初期高さ)
      16			private var sw : Number = 1;   // ボールの状態( 0:停止している,1:動いている)
      17			public var msg : Message;
      18	
      19			public function Ball() {
      20				msg = new Message(300, 100);
      21				addChild(msg);
      22				var tt : Timer = new Timer(33, 100);
      23				ball = new Sprite();
      24				addChild(ball);
      25				ball.graphics.beginFill(0x00ff00);
      26				ball.graphics.drawCircle(0, 0, 40);
      27				ball.graphics.endFill();
      28				ball.x = 0;
      29				ball.y = 0;
      30				ball.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      31				tt.addEventListener(TimerEvent.TIMER, next);
      32				tt.addEventListener(TimerEvent.TIMER_COMPLETE, stop);
      33				tt.start();
      34			}
      35	
      36			private function next(event:TimerEvent):void {
      37				if (ball.x < stage.stageWidth + 40 && sw > 0) {
      38					ball.x += 1.5;
      39					t      += 0.1;
      40					v       = -g * t + v0;
      41					ball.y  = stage.stageHeight - (-0.5 * g * t * t + v0 * t + h0);
      42					if (ball.y >= stage.stageHeight - 40 && v < 0) {
      43						ball.y = stage.stageHeight - 40;
      44						v0     = -0.8 * v;
      45						h0     = 40;
      46						t      = 0;
      47					}
      48					msg.tx.appendText("position " + ball.x + " " + ball.y + "\n");
      49				}
      50			}
      51	
      52			private function stop(event:TimerEvent):void {
      53				msg.tx.appendText("End of Timer\n");
      54			}
      55	
      56			private function onMouseDown(event:MouseEvent):void {
      57				if (sw == 0)
      58					sw = 1;
      59				else
      60					sw = 0;
      61			}
      62		}
      63	}
      				
      04 行目

        TimerEvent に対応するため,TimerEvent クラスを読み込んでる.

      05 行目

        Timer を使用するため,Timer クラスを読み込んでる.

      22 行目

        Timer クラスのオブジェクトを生成している.この結果,TimerEvent が 33 ms 毎に発生し,100 回発生した時点で停止することになる.

      31 行目

        TimerEvent に対する処理を行うため,イベントリスナを追加している.この結果,TimerEvent が発生すると,メソッド next が実行される.

      32 行目

        TimerEvent が終了した際に実行する処理を行うため,イベントリスナを追加している.この結果,TimerEvent が終了すると,メソッド stop が実行される.

      33 行目

        Timer をスタートさせている.

      36 行目~ 50 行目

        TimerEvent が発生した際に実行されるメソッドである.以下の処理は,ボールが動いており( sw > 0 ),かつ,画面内に存在したとき実行される.
      • 38 行目: ボールの x 座標の変更( 1.5 ピクセル / 33 ms )
      • 39 行目: 時間の変更( 0.1 秒 / 33 ms )
      • 40 行目: ボールの速度の変更
      • 41 行目: ボールの y 座標の変更.画面座標に合うように座標変換も行っている.
      • 42 行目~ 47 行目: ボールが地面に落ちたときの跳ね返り処理を行っている.その際,速度が 0.8 倍される.
      • 48 行目: ボールの位置を Message クラスのテキストフィールドに出力している.

      52 行目~ 54 行目

        Timer が終了した際に実行されるメソッドである.終了メッセージを,Message クラスのテキストフィールドに出力している.

        この例は,先の例とほとんど同じような動きをしますが,
      var tt : Timer = new Timer(33, 100);
      				
      によって,33 ミリ秒ごとにタイマーイベントを生成し,100 回の生成で終了している点が異なっています.また,終了時には,メッセージを出力しています.2 番目の値を大きくするか,または,2 番目の引数を省略(または 0.無限に続く)すれば,先の例とほとんど同じになります.

        参考のため,上述の例を Java Appret として作成した場合,そのプログラム Ball.java は以下のようになります.

      import java.awt.*;
      import java.awt.event.*;
      import java.applet.*;
      
      public class Ball extends Applet implements Runnable
      {
      	private boolean state = true;
      	private double g = 9.8;
      	private double v0 = 0;
      	private double v = 0;
      	private double t = 0;
      	private double h0, x, y;
      	private int sw = 1;
      	private Dimension d;
      	private Thread th;
      
      	public void init() {
      					// 背景色
      		setBackground(new Color(238, 255, 238));
      					// 初期設定
      		d  = getSize();
      		h0 = d.height + 40;
      		x  = -40;
      		y  = -40;
      		addMouseListener(new Mouse());
      					// スレッドの生成
      		th = new Thread(this);
      		th.start();
      	}
      
      	public Insets getInsets()
      	{
      		return new Insets(0, 0, 0, 0);
      	}
      
      	public void stop()
      	{
      		state = false;
      	}
      
      	public void run()
      	{
      		while (state) {
      			try {
      				th.sleep(33);
      			}
      			catch (InterruptedException e) {}
      			if (x < d.width + 80 && sw > 0) {
      				x += 1.5;
      				t += 0.1;
      				v  = -g * t + v0;
      				y  = d.height - (-0.5 * g * t * t + v0 * t + h0);
      				if (y >= d.height - 80 && v < 0) {
      					y  = d.height - 80;
      					v0 = -0.8 * v;
      					h0 = 80;
      					t  = 0;
      				}
      				System.out.println("position " + x + " " + y);
      				repaint();
      			}
      		}
      	}
      
      	public void paint (Graphics g)
      	{
      		g.setColor(Color.green);
      		g.fillOval((int)x, (int)y, 80, 80);
      	}
      
      	class Mouse extends MouseAdapter {
      		public void mouseClicked(MouseEvent e)
      		{
      			int mx, my;
      			double x1, y1, r;
      
      			mx = e.getX();
      			my = e.getY();
      			x1 = x + 40 - mx;
      			y1 = y + 40 - my;
      			r  = Math.sqrt(x1 * x1 + y1 * y1);
      			if (r < 40) {
      				if (sw > 0)
      					sw = 0;
      				else
      					sw = 1;
      			}
      		}
      	}
      }
      				

        以上示した例からも明らかなように,ActionScript のプログラムは,Java のアプレットプログラムと非常に似ています.Java において,main となるプログラムが必ず Applet クラスを継承しなければならないように,ActionScript では,Sprite クラスを継承する必要があります.イベント処理に対して,リスナーとイベントハンドラーを使用する点は,形式は異なりますが,Java と同様です.

        ただし,円や直線を描くグラフィックスの部分で大きく異なります.Java においては,上の例で示したアニメーションのように,定期的に円を描き直しています.しかし,ActionScript では,最初に描いた図の位置を定期的に変更しているだけです.つまり,ActionScript においては,グラフィックスは Sprite オブジェクトや Shape オブジェクトに描いた模様のようなものであり,一度描いたものが消えることはありません.このため,グラフィックス自身が一つの表示オブジェクトのように取り扱われます.たとえば,Sprite オブジェクトに円を描き,そのオブジェクトにマウスイベントに対するリスナーを付加した場合,塗りつぶさない円の場合は,円周を表す線分に対してだけリスナーが働きますが,塗りつぶした円の場合は,円内のどこでマウスをクリックしても有効となります.

        Java においては,グラフィックスは単なる図形であり,図形自身にリスナーを付加することはできません.そのため,上述のプログラム例のように,円の部分をクリックしたか否かの判定のために,円の中心からの距離を計算しなければならず,ActionScript の場合に比べ面倒になっています.Java においても,小さなパネルに円を描き,そのパネルにリスナーを付加し,かつ,そのパネルを移動させるようにすれば,似たような処理を実現できますが,多少面倒なものになります.

        一般的に述べれば,言語としての機能は Java の方が ActionScript より上です.基本的に,ActionScript で可能なことは Java でも可能です.しかし,今までの例ではあまり示すことができませんでしたが,マルチメディア素材,たとえば画像などを取り扱う場合,ActionScript の方が簡単に取り扱えます.たとえば,画像にフィルタをかける,画像の一部の色を変更するなどの操作を,ActionScript では組み込まれたメソッドを利用して簡単に実行することができますが,Java においては,プログラムで記述してやらなければならないことが多くあります.従って,アニメーションなどを作成する目的のためには,ActionScript の方が向いているのかもしれません.

  3. 演習問題の解答

      以下,描画とイベント処理の例をいくつか挙げていきます.まず最初に,Java の演習問題の解答の項で示したアプレットと同様の機能を持つ ActionScript のプログラムは,例えば,以下のようになります.

    Test.as

    001	package
    002	{
    003		import flash.display.Sprite;
    004		import flash.text.TextField;
    005		import flash.text.TextFieldType;
    006		import flash.text.TextFormat;
    007		import flash.events.MouseEvent;
    008		import flash.filters.DropShadowFilter;
    009	
    010		[SWF(backgroundColor="0xe1ffe1", width="400", height="180", frameRate="30")]
    011	
    012		public class Test extends Sprite
    013		{
    014			private var a : int = 3;
    015			private var b : int = 4;
    016			private var c : TextField;
    017			private var q : TextField;
    018			private var q_t1 : TextField;
    019			private var q_t2 : TextField;
    020			private var na : TextField;
    021			private var tf : TextFormat;
    022			private var err : Sprite;
    023			private var trans : sButton;
    024	
    025			public function Test()
    026			{
    027				init();
    028			}
    029			
    030			private function init():void
    031			{
    032				tf = new TextFormat();
    033				tf.size = 20;
    034				tf.bold = true;
    035						// メッセージ
    036				q_t1 = new TextField();
    037				q_t1.text = "次の問題の答えは?";
    038				q_t1.width = 350;
    039				q_t1.height = 25;
    040				q_t1.x = 50;
    041				q_t1.y = 10;
    042				q_t1.type = TextFieldType.DYNAMIC;
    043				q_t1.setTextFormat(tf);
    044				addChild(q_t1);
    045	
    046				q_t2 = new TextField();
    047				q_t2.text = "";
    048				q_t2.width = 300;
    049				q_t2.height = 25;
    050				q_t2.x = 20;
    051				q_t2.y = 55;
    052				q_t2.type = TextFieldType.DYNAMIC;
    053				q_t2.setTextFormat(tf);
    054				addChild(q_t2);
    055						// 問題
    056				q = new TextField();
    057				q.text = "3  +  4  =  ";
    058				q.width = 100;
    059				q.height = 25;
    060				q.x = 50;
    061				q.y = 105;
    062				q.type = TextFieldType.DYNAMIC;
    063				q.setTextFormat(tf);
    064				addChild(q);
    065	
    066				c = new TextField();
    067				c.width = 200;
    068				c.height = 25;
    069				c.background = true;
    070				c.backgroundColor = 0xffffffff;
    071				c.x = 170;
    072				c.y = 105;
    073				c.type = TextFieldType.INPUT;
    074				c.defaultTextFormat = tf;
    075				c.filters = [new DropShadowFilter(4, 45, 0xaaaaaa, 1, 2, 2, 1, 1, true)];
    076				addChild(c);
    077						// 名前の入力
    078				var na_t : TextField = new TextField();
    079				na_t.text = "名前:";
    080				na_t.width = 70;
    081				na_t.height = 25;
    082				na_t.x = 20;
    083				na_t.y = 140;
    084				na_t.type = TextFieldType.DYNAMIC;
    085				na_t.setTextFormat(tf);
    086				addChild(na_t);
    087	
    088				na = new TextField();
    089				na.width = 150;
    090				na.height = 25;
    091				na.background = true;
    092				na.backgroundColor = 0xffffffff;
    093				na.x = 110;
    094				na.y = 140;
    095				na.type = TextFieldType.INPUT;
    096				na.defaultTextFormat = tf;
    097				na.filters = [new DropShadowFilter(4, 45, 0xaaaaaa, 1, 2, 2, 1, 1, true)];
    098				addChild(na);
    099						// 送信ボタン
    100				trans = new sButton("送信", 20);
    101				trans.x = 300;
    102				trans.y = 140;
    103				addChild(trans);
    104				trans.addEventListener(MouseEvent.CLICK, onClick);
    105			}
    106						// 送信ボタンが押されたときの処理
    107			private function onClick(event:MouseEvent):void {
    108								// 答えや問題が入力されなかった場合
    109				if (c.text.length <= 0 || na.text.length <= 0) {
    110					err = new Sprite();
    111					err.graphics.beginFill(0xffffff);
    112					err.graphics.drawRect(20, 20, 300, 80);
    113					err.graphics.endFill();
    114					err.graphics.lineStyle(3, 0xffff0000);
    115					err.graphics.drawRect(20, 20, 300, 80);
    116					addChild(err);
    117					var txt : TextField = new TextField();
    118					txt.width = 200;
    119					txt.height = 25;
    120					txt.x = 30;
    121					txt.y = 30;
    122					txt.type = TextFieldType.DYNAMIC;
    123					err.addChild(txt);
    124					var ok : sButton = new sButton("OK", 20);
    125					ok.x = 140;
    126					ok.y = 60;
    127					err.addChild(ok);
    128					ok.addEventListener(MouseEvent.CLICK, onClick_err);
    129					if (c.text.length <= 0) {
    130						txt.text = "答えを入力して下さい!";
    131						txt.setTextFormat(tf);
    132					}
    133					else {
    134						txt.text = "名前を入力して下さい!";
    135						txt.setTextFormat(tf);
    136					}
    137					trans.removeEventListener(MouseEvent.CLICK, onClick);
    138				}
    139								// 答えのチェック
    140				else {
    141					var cv : int = parseInt(c.text);
    142					if (cv == a+b) {
    143						q_t1.text = na.text + " さん,正解です\n";
    144						q_t1.setTextFormat(tf);
    145						q_t2.text = "続いて,次の問題の答えは?";
    146						q_t2.setTextFormat(tf);
    147						a = int(100 * Math.random());
    148						b = int(100 * Math.random());
    149						q.text = a + " + " + b + "  =  ";
    150						c.text = "";
    151						q.setTextFormat(tf);
    152					}
    153					else {
    154						q_t1.text = na.text + " さん,間違っています\n";
    155						q_t1.setTextFormat(tf);
    156						q_t2.text = "もう一度計算してみて下さい";
    157						q_t2.setTextFormat(tf);
    158					}
    159				}
    160			}
    161						// 警告メッセージを確認したときの処理
    162			private function onClick_err(event:MouseEvent):void {
    163				removeChild(err);
    164				trans.addEventListener(MouseEvent.CLICK, onClick);
    165			}
    166		}
    167	}
    			
    032 行目~ 034 行目

      TextFormat クラスを利用して,文字のフォーマットを設定している.

    036 行目~ 044 行目

      TextField クラスのオブジェクトを,指定された大きさで,指定された位置に追加している.042 行目においては,TextFieldType クラスのプロパティ DYNAMIC を指定し,編集不可能に設定している.

    046 行目~ 054 行目

      TextField クラスのオブジェクトを,指定された大きさで,指定された位置に追加している.ただし,初期状態においては,何も表示されない.

    056 行目~ 064 行目

      TextField クラスのオブジェクトを,指定された大きさで,指定された位置に追加している.問題を表示する領域である.

    066 行目~ 076 行目

      TextField クラスのオブジェクトを,指定された大きさで,指定された位置に追加している.073 行目においては,TextFieldType クラスのプロパティ INPUT を指定し,編集可能に設定している.また,075 行目においては,フィルタ( DropShadowFilter クラス)を適用している.

    078 行目~ 086 行目

      TextField クラスのオブジェクトを,指定された大きさで,指定された位置に追加している.

    088 行目~ 098 行目

      TextField クラスのオブジェクトを,指定された大きさで,指定された位置に追加している.名前を入力する領域である.

    100 行目~ 104 行目

      「送信」ボタン( sButton クラスのオブジェクト)を追加し,そこに,マウスクリックに対するイベント処理を行うため,イベントリスナ(MouseEvent クラス)を追加している.この結果,このボタンがクリックされると,onClick メソッドが実行される.

    107 行目~ 160 行目

      「送信」ボタンがクリックされたときの処理である.
    • 109 行目~ 138 行目: 答え,または,名前が入力されていない場合は,対応する警告メッセージを表示する Window (実体は,TextField クラスのオブジェクト)を生成している.この Window の「 OK 」ボタンをクリックしない限り,「送信」ボタンは無効となる( 137 行目)
    • 142 行目~ 152 行目: 答えが正しかった場合の処理であり,メッセージと次の問題を q_t1,q_t2,及び,q に設定している.
    • 153 行目~ 158 行目: 答えが間違っていた場合の処理であり,メッセージを q_t1,及び,q_t2 に設定している.

    162 行目~ 165 行目

      警告メッセージを表示する Window ( TextField )に設定された「 OK 」ボタンがクリックされたときの処理である.エラーを表示した Window を消去し,「送信」ボタンを有効にしている.

      sButton クラスは,ボタンを表示するための汎用クラスです.今後の例においても,しばしば,使用していきます.

    sButton.as

    /*******************************************************************/
    /* ボタン                                                          */
    /*      title : タイトル                                           */
    /*      size : フォントサイズ                                      */
    /*      up_c : マウスカーソルがボタンの外にあるときの色            */
    /*      over_c : マウスカーソルがボタンの上にあるときの色          */
    /*      down_c : マウスがクリックされたときの色                    */
    /*      grow_up : マウスカーソルがボタンの外にあるときのグロー色   */
    /*      grow_over : マウスカーソルがボタンの上にあるときのグロー色 */
    /*      grow_down : マウスがクリックされたときのグロー色           */
    /*******************************************************************/
    package
    {
    	import flash.display.Sprite;
    	import flash.display.SimpleButton;
    	import flash.text.TextField;
    	import flash.text.TextFormat;
    	import flash.text.TextFormatAlign;
    	import flash.text.TextLineMetrics;
    	import flash.filters.GlowFilter;
    
    	public class sButton extends SimpleButton
    	{
    		public function sButton(title:String="Button", size:int=15, up_c:uint=0xffffff00, over_c:uint=0xffadff2f, down_c:uint=0xff00ff00, grow_up:uint=0xdddddd, grow_over:uint=0xdddddd, grow_down:uint=0xdddddd)
    		{
    					// ボタンの外
    			var msg1 : TextField = new TextField();
    			msg1.text = title;
    			var tf : TextFormat = new TextFormat();
    			tf.size = size;
    			tf.align = TextFormatAlign.CENTER;
    			msg1.setTextFormat(tf);
    			var ms : TextLineMetrics = msg1.getLineMetrics(0);
    			msg1.width = ms.width + 10;
    			msg1.height = ms.height;
    			msg1.x = 10;
    			msg1.y = 5;
    			var er : Number = 0.8 * msg1.height;
    			var gr : Number = 0.3 * msg1.height;
    
    			var r1 : Sprite = new Sprite();
    			var a1 : Number = (up_c >>> 24) / 255;
    			up_c = up_c & 0x00ffffff;
    			r1.graphics.beginFill(up_c, a1);
    			r1.graphics.drawRoundRect(0, 0, msg1.width+20, msg1.height+10, er, er);
    			r1.graphics.endFill();
    			r1.filters = [new GlowFilter(grow_up, a1, gr, gr, 3, 3, true)];
    			r1.addChild(msg1);
    					// ボタンの上
    			var msg2 : TextField = new TextField();
    			msg2.text = title;
    			msg2.setTextFormat(tf);
    			msg2.width = ms.width + 10;
    			msg2.height = ms.height;
    			msg2.x = 10;
    			msg2.y = 5;
    
    			var r2 : Sprite = new Sprite();
    			var a2 : Number = (over_c >>> 24) / 255;
    			over_c = over_c & 0x00ffffff;
    			r2.graphics.beginFill(over_c, a2);
    			r2.graphics.drawRoundRect(0, 0, msg2.width+20, msg2.height+10, er, er);
    			r2.graphics.endFill();
    			r2.filters = [new GlowFilter(grow_over, a2, gr, gr, 3, 3, true)];
    			r2.addChild(msg2);
    					// ボタンをクリック
    			var msg3 : TextField = new TextField();
    			msg3.text = title;
    			msg3.setTextFormat(tf);
    			msg3.width = ms.width + 10;
    			msg3.height = ms.height;
    			msg3.x = 10;
    			msg3.y = 5;
    
    			var r3 : Sprite = new Sprite();
    			var a3 : Number = (down_c >>> 24) / 255;
    			down_c = down_c & 0x00ffffff;
    			r3.graphics.beginFill(down_c, a3);
    			r3.graphics.drawRoundRect(0, 0, msg3.width+20, msg3.height+10, er, er);
    			r3.graphics.endFill();
    			r3.filters = [new GlowFilter(grow_down, a3, gr, gr, 3, 3, true)];
    			r3.addChild(msg3);
    
    			useHandCursor = true;
    			upState = r1;
    			overState = r2;
    			downState = r3;
    			hitTestState = r3;
    		}
    	}
    }
    			

      ActionScript においても,サーバ側とデータをやりとりしたいような場合は,フォームにおける CGI に相当するプログラムが必要になります.以下に示す例では,上で述べた例に対して,正誤のチェックだけをサーバで行うようにしています.

      また,Java の場合と同様,正誤の判定結果をテキストフィールドに表示するようにしています.このように,ActionScript の場合においても,新しいページを開くことなく,同じページ内で何回もサーバとの交信を繰り返すことが可能です.

    001	package
    002	{
    003		import flash.display.Sprite;
    004		import flash.text.TextField;
    005		import flash.text.TextFieldType;
    006		import flash.text.TextFormat;
    007		import flash.net.URLLoader;
    008		import flash.net.URLRequest;
    009		import flash.net.URLVariables;
    010		import flash.net.URLRequestMethod;
    011		import flash.events.Event;
    012		import flash.events.MouseEvent;
    013		import flash.filters.DropShadowFilter;
    014	
    015		[SWF(backgroundColor="0xe1ffe1", width="400", height="250", frameRate="30")]
    016	
    017		public class Problem extends Sprite
    018		{
    019			private var a : int = 3;
    020			private var b : int = 4;
    021			private var c : TextField;
    022			private var q : TextField;
    023			private var na : TextField;
    024			private var msg : TextField;
    025			private var ld : URLLoader;
    026			private var tf : TextFormat;
    027	
    028			public function Problem()
    029			{
    030				init();
    031			}
    032			
    033			private function init():void
    034			{
    035				tf = new TextFormat();
    036				tf.size = 20;
    037				tf.bold = true;
    038	
    039				var q_t : TextField = new TextField();
    040				q_t.text = "次の問題の答えは?";
    041				q_t.width = 190;
    042				q_t.height = 25;
    043				q_t.x = 105;
    044				q_t.y = 10;
    045				q_t.type = TextFieldType.DYNAMIC;
    046				q_t.setTextFormat(tf);
    047				addChild(q_t);
    048	
    049				q = new TextField();
    050				q.text = "3  +  4  =  ";
    051				q.width = 100;
    052				q.height = 25;
    053				q.x = 50;
    054				q.y = 45;
    055				q.type = TextFieldType.DYNAMIC;
    056				q.setTextFormat(tf);
    057				addChild(q);
    058	
    059				c = new TextField();
    060				c.width = 200;
    061				c.height = 25;
    062				c.background = true;
    063				c.backgroundColor = 0xffffffff;
    064				c.x = 170;
    065				c.y = 45;
    066				c.type = TextFieldType.INPUT;
    067				c.defaultTextFormat = tf;
    068				c.filters = [new DropShadowFilter(4, 45, 0xaaaaaa, 1, 2, 2, 1, 1, true)];
    069				addChild(c);
    070	
    071				var na_t : TextField = new TextField();
    072				na_t.text = "名前:";
    073				na_t.width = 70;
    074				na_t.height = 25;
    075				na_t.x = 20;
    076				na_t.y = 84;
    077				na_t.type = TextFieldType.DYNAMIC;
    078				na_t.setTextFormat(tf);
    079				addChild(na_t);
    080	
    081				na = new TextField();
    082				na.width = 150;
    083				na.height = 25;
    084				na.background = true;
    085				na.backgroundColor = 0xffffffff;
    086				na.x = 110;
    087				na.y = 84;
    088				na.type = TextFieldType.INPUT;
    089				na.defaultTextFormat = tf;
    090				na.filters = [new DropShadowFilter(4, 45, 0xaaaaaa, 1, 2, 2, 1, 1, true)];
    091				addChild(na);
    092	
    093				var trans : sButton = new sButton("送信", 20);
    094				trans.x = 300;
    095				trans.y = 80;
    096				addChild(trans);
    097	
    098				msg  = new TextField();
    099				msg.width = 380;
    100				msg.height = 120;
    101				msg.background = true;
    102				msg.backgroundColor = 0xffffffff;
    103				msg.x = 10;
    104				msg.y = 120;
    105				msg.type = TextFieldType.INPUT;
    106				msg.multiline = true;
    107				msg.defaultTextFormat = tf;
    108				msg.filters = [new DropShadowFilter(4, 45, 0xaaaaaa, 1, 2, 2, 1, 1, true)];
    109				addChild(msg);
    110	
    111				ld = new URLLoader();
    112				ld.addEventListener(Event.COMPLETE, onComplete);
    113				trans.addEventListener(MouseEvent.CLICK, onClick);
    114			}
    115	
    116			private function onClick(event:MouseEvent):void {
    117				var uv : URLVariables = new URLVariables();
    118				uv.a = a;
    119				uv.b = b;
    120				uv.c = c.text;
    121				var rq : URLRequest = new URLRequest("check.php");
    122				rq.method = URLRequestMethod.POST;
    123				rq.data = uv;
    124				ld.load(rq);
    125			}
    126	
    127			private function onComplete(event:Event):void {
    128				if (int(event.target.data) > 0) {
    129					msg.textColor = 0x000000;
    130					msg.text = na.text + "さん,正解です\n";
    131					msg.appendText("続いて,次の問題の答えは?");
    132					a = int(100 * Math.random());
    133					b = int(100 * Math.random());
    134					q.text = a + " + " + b + "  =  ";
    135					q.setTextFormat(tf);
    136				}
    137				else {
    138					msg.textColor = 0xff0000;
    139					msg.text = na.text + "さん,間違っています\n";
    140					msg.appendText("もう一度計算してみて下さい");
    141				}
    142			}
    143		}
    144	}
    			
    039 行目~ 047 行目

      TextField クラスのオブジェクトを,指定された大きさで,指定された位置に追加している.045 行目においては,TextFieldType クラスのプロパティ DYNAMIC を指定し,編集不可能に設定している.

    049 行目~ 057 行目

      TextField クラスのオブジェクトを,指定された大きさで,指定された位置に追加している.問題を表示する領域である.

    059 行目~ 069 行目

      TextField クラスのオブジェクトを,指定された大きさで,指定された位置に追加している.066 行目においては,TextFieldType クラスのプロパティ INPUT を指定し,編集可能に設定している.また,068 行目においては,フィルタ( DropShadowFilter クラス)を適用している.

    071 行目~ 079 行目

      TextField クラスのオブジェクトを,指定された大きさで,指定された位置に追加している.

    081 行目~ 091 行目

      TextField クラスのオブジェクト q を,指定された大きさで,指定された位置に追加している.名前を入力する領域である.

    093 行目~ 096 行目

      「送信」ボタン( sButton クラスのオブジェクト)を追加している.

    098 行目~ 109 行目

      メッセージを表示するため,複数行表示可能な( 106 行目),TextField クラスのオブジェクト msg を追加している.

    111 行目~ 112 行目

      URLLoader クラスのオブジェクトを生成し,そこに,COMPLETE イベント( COMPLETE は,Event クラスの定数であり,受信の終了を示す)に対する処理を行うため,イベントリスナを追加している.この結果,サーバからのデータの受信を終えると,onComplete メソッド( 127 行目~ 142 行目)が実行される.

    113 行目

      マウスで「送信」ボタンがクリックされたときの処理を行うため,「送信」ボタンにイベントリスナを追加している.この結果,「送信」ボタンがクリックされると,onClick メソッド( 116 行目~ 125 行目)が実行される.

    116 行目~ 125 行目

      「送信」ボタンがクリックされたときの処理である.URLVariables クラスのオブジェクトに問題と答えを設定し( 117 行目~ 120 行目),URLRequest クラスを利用して送信している( 121 行目~ 123 行目).次に,URLLoader クラスのオブジェクトによって,サーバからのデータを受け取っている.受信を終了すると,onComplete メソッド( 127 行目~ 142 行目)が実行される.

    128 行目~ 136 行目

      答えが正しかった場合の処理であり,TextField クラスのオブジェクト msg にメッセージを表示すると共に,TextField クラスのオブジェクト q に,新しい問題を提示している.

    137 行目~ 142 行目

      答えが間違っていた場合の処理であり,TextField クラスのオブジェクト msg にメッセージを表示している.

      以下に示すのは,サーバ側のプログラム( CGI ) check.php のソースです.なお,PHP に関しては,「 PHP 」を参照して下さい.

    <?php
    	$a = intval($_POST['a']);   // 送られてくるデータは a=3&b=4&c=7
    	$b = intval($_POST['b']);
    	$c = intval($_POST['c']);
    	if (($a + $b) == $c)
    		printf("1\n");
    	else
    		printf("0\n");
    ?>
    			

  4. お絵かき

      この例は,Java の場合と同様,マウスのドラッグを利用した簡単なお絵かきツールです.

    Draw.as

    01	package {
    02		import flash.display.Sprite;
    03		import flash.text.TextField;
    04		import flash.text.TextFieldType;
    05		import flash.text.TextFormat;
    06		import flash.events.MouseEvent;
    07	
    08		[SWF(backgroundColor="0xe1ffe1", width="250", height="200", frameRate="30")]
    09	
    10		public class Draw extends Sprite {
    11	
    12			private var canvas:Sprite;
    13			private var sw : Boolean = false;
    14	
    15			public function Draw() {
    16						// タイトル
    17				var tf : TextFormat = new TextFormat();
    18				tf.size = 20;
    19				tf.bold = true;
    20				var title : TextField = new TextField();
    21				title.text = "マウスで絵を描こう!";
    22				title.width = 200;
    23				title.height = 25;
    24				title.x = 25;
    25				title.y = 10;
    26				title.type = TextFieldType.DYNAMIC;
    27				title.setTextFormat(tf);
    28				addChild(title);
    29						// 描画領域
    30				canvas = new Sprite();
    31				canvas.graphics.beginFill(0xFFFFFF);
    32				canvas.graphics.drawRect(10, 50, 230, 140);
    33				canvas.graphics.endFill();
    34				canvas.graphics.lineStyle(3, 0x00FFFF);
    35				addChild(canvas);
    36						// 描画領域へイベントリスナの追加
    37				canvas.addEventListener(MouseEvent.MOUSE_DOWN, start);
    38				canvas.addEventListener(MouseEvent.MOUSE_MOVE, move);
    39				canvas.addEventListener(MouseEvent.MOUSE_UP, stop);
    40			}
    41	
    42			private function start(e:MouseEvent):void {
    43				sw = true;
    44				canvas.graphics.moveTo(canvas.mouseX, canvas.mouseY);
    45			}
    46		    
    47			private function move(e:MouseEvent):void {
    48				if(sw)
    49					canvas.graphics.lineTo(canvas.mouseX, canvas.mouseY);
    50			}
    51	
    52			private function stop(e:MouseEvent):void {
    53				sw = false;
    54			}
    55		}
    56	}
    			
    17 行目~ 28 行目

      タイトルを表示するため,TextField クラスのオブジェクトを追加している.

    30 行目~ 35 行目

      描画領域として白い矩形を追加すると共に,34 行目において,直線の色を 0x00FFFF,太さを 3 ピクセルに設定している.

    37 行目~ 39 行目

      マウスボタンが押されたとき,マウスが移動したとき,及び,マウスボタンが離されたときのイベントに対応するため,イベントリスナ(MouseEvent クラス)を追加している.この結果,それぞれの場合に,メソッド start,move,及び,stop が実行される.

    42 行目~ 45 行目

      マウスボタンが押されたときの処理である.押された状態であることを示す変数 sw を true に設定し,現在のマウス位置に移動している.

    47 行目~ 50 行目

      マウスが移動しているときの処理であり,マウスボタンが押されている場合は,マウスの前回の位置と今回の位置を直線で結んでいる.

    52 行目~ 54 行目

      マウスボタンが離されたときの処理であり,押された状態であることを示す変数 sw を false に設定している.

      以下に示す例は,上で示した例にメニューを付加し,多少お絵かきソフトらしく修正したものです.始点と終点をクリックすることによって直線を描くことができます.また,線の太さや色の変更も可能です.

    Draw.as

    001	package {
    002		import flash.display.Sprite;
    003		import flash.display.Shape;
    004		import flash.text.TextField;
    005		import flash.text.TextFieldType;
    006		import flash.text.TextFormat;
    007		import flash.events.MouseEvent;
    008	
    009		[SWF(backgroundColor="0xffffff", width="500", height="300", frameRate="30")]
    010	
    011		public class Draw extends Sprite
    012		{
    013	
    014			public var canvas : Sprite;
    015			public var mark : Shape;
    016			public var type : int = 0;   // 図形の種類(0:自由曲線,1:直線)
    017			public var color : int = 0xff0000;   // 線の色
    018			public var wid : int = 10;   // 線の太さ
    019			private var sw : Boolean = false;   // マウスボタンが押されているか否か,描画中か否か
    020				// コンストラクタ
    021			public function Draw() {
    022						// 描画領域
    023				canvas = new Sprite();
    024				canvas.graphics.beginFill(0xFFFFFF);
    025				canvas.graphics.drawRect(144, 0, 500, 300);
    026				canvas.graphics.endFill();
    027				addChild(canvas);
    028						// 制御領域領域
    029				var ctr : Control = new Control(this);
    030				ctr.graphics.beginFill(0xEEFFEE);
    031				ctr.graphics.drawRect(0, 0, 144, 300);
    032				ctr.graphics.endFill();
    033				addChild(ctr);
    034						// 描画領域へイベントリスナの追加
    035				canvas.addEventListener(MouseEvent.MOUSE_DOWN, start);
    036				canvas.addEventListener(MouseEvent.MOUSE_MOVE, move);
    037				canvas.addEventListener(MouseEvent.MOUSE_UP, stop);
    038			}
    039				// イベント処理
    040			private function start(e:MouseEvent):void {
    041						// 自由曲線
    042				if (type == 0) {
    043					sw = true;
    044					canvas.graphics.moveTo(canvas.mouseX, canvas.mouseY);
    045				}
    046						// 直線
    047				else {
    048					if (!sw) {   // 始点
    049						sw = true;
    050						mark = new Shape();
    051						canvas.addChild(mark);
    052						mark.graphics.lineStyle(1, 0x000000);
    053						mark.graphics.moveTo(canvas.mouseX-10, canvas.mouseY);
    054						mark.graphics.lineTo(canvas.mouseX+10, canvas.mouseY);
    055						mark.graphics.moveTo(canvas.mouseX, canvas.mouseY-10);
    056						mark.graphics.lineTo(canvas.mouseX, canvas.mouseY+10);
    057						canvas.graphics.moveTo(canvas.mouseX, canvas.mouseY);
    058					}
    059					else {   // 終点
    060						sw = false;
    061						canvas.graphics.lineStyle(wid, color);
    062						canvas.graphics.lineTo(canvas.mouseX, canvas.mouseY);
    063						canvas.removeChild(mark);
    064					}
    065				}
    066			}
    067		    
    068			private function move(e:MouseEvent):void {
    069				if (type == 0) {
    070					if(sw) {
    071						canvas.graphics.lineStyle(wid, color);
    072						canvas.graphics.lineTo(canvas.mouseX, canvas.mouseY);
    073					}
    074				}
    075			}
    076	
    077			private function stop(e:MouseEvent):void {
    078				if (type == 0)
    079					sw = false;
    080			}
    081		}
    082	}
    083	
    084	/****************************/
    085	/* Control クラス           */
    086	/*      coded by Y.Suganuma */
    087	/****************************/
    088	import flash.display.Sprite;
    089	import flash.events.MouseEvent;
    090	
    091	class Control extends Sprite
    092	{
    093		private var dr : Draw;   // Draw クラス
    094		private var type0 : sButton;
    095		private var type1 : sButton;
    096		private var color0 : sButton;
    097		private var color1 : sButton;
    098		private var line0 : sButton;
    099		private var line1 : sButton;
    100						// コンストラクタ
    101		function Control(dr : Draw)
    102		{
    103			this.dr = dr;
    104								// ボタンの配置
    105			type0 = new sButton("曲線", 20, 0xffffffff);
    106			type0.x = 2;
    107			type0.y = 10;
    108			type0.name = "curve";
    109			addChild(type0);
    110			type0.addEventListener(MouseEvent.CLICK, onClick);
    111	
    112			type1 = new sButton("直線", 20, 0xffffffff);
    113			type1.x = 70;
    114			type1.y = 10;
    115			type1.name = "line";
    116			addChild(type1);
    117			type1.addEventListener(MouseEvent.CLICK, onClick);
    118	
    119			color0 = new sButton(" 赤 ", 20, 0xffff0000);
    120			color0.x = 8;
    121			color0.y = 45;
    122			color0.name = "red";
    123			addChild(color0);
    124			color0.addEventListener(MouseEvent.CLICK, onClick);
    125	
    126			color1 = new sButton(" 緑 ", 20, 0xff00ff00);
    127			color1.x = 78;
    128			color1.y = 45;
    129			color1.name = "green";
    130			addChild(color1);
    131			color1.addEventListener(MouseEvent.CLICK, onClick);
    132	
    133			line0 = new sButton("細い", 20, 0xffffffff);
    134			line0.x = 2;
    135			line0.y = 80;
    136			line0.name = "thin";
    137			addChild(line0);
    138			line0.addEventListener(MouseEvent.CLICK, onClick);
    139	
    140			line1 = new sButton("太い", 20, 0xffffffff);
    141			line1.x = 70;
    142			line1.y = 80;
    143			line1.name = "thick";
    144			addChild(line1);
    145			line1.addEventListener(MouseEvent.CLICK, onClick);
    146		}
    147						// ボタンが押されたときの処理
    148		private function onClick(e:MouseEvent):void {
    149			if (e.target.name == "curve")
    150				dr.type = 0;
    151			else if (e.target.name == "line")
    152				dr.type = 1;
    153			else if (e.target.name == "red")
    154				dr.color = 0xff0000;
    155			else if (e.target.name == "green")
    156				dr.color = 0x00ff00;
    157			else if (e.target.name == "thin")
    158				dr.wid = 2;
    159			else if (e.target.name == "thick")
    160				dr.wid = 10;
    161		}
    162	}
    			
    023 行目~ 027 行目

      描画領域として,背景色白の矩形を領域の右側に追加している.

    029 行目~ 033 行目

      制御用ボタンを配置するために,背景色 0xeeffee の矩形を領域の左側に配置している,

    035 行目~ 037 行目

      マウスボタンが押されたとき,マウスが移動したとき,及び,マウスボタンが離されたときのイベントに対応するため,イベントリスナ(MouseEvent クラス)を追加している.この結果,それぞれの場合に,メソッド start,move,及び,stop が実行される.

    040 行目~ 066 行目

      マウスボタンが押されたときの処理である.自由曲線を描くモードのときは,押された状態であることを示す変数 sw を true に設定し,現在のマウス位置に移動している( 042 行目~ 045 行目).直線を描くモードのときは,始点をクリックした場合と終点をクリックした場合とでは処理が異なる.変数 sw が false の場合( 048 行目~ 058 行目)は,変数 sw を true にし,始点のマーク(十字)を表示させるために,Shape クラスのオブジェクト mark を追加している.その後,canvas 上のマウスがクリックされた位置に移動している.また,変数 sw が true の場合( 059 行目~ 064 行目)は,変数 sw を false にし,始点から現在のマウス位置までを結ぶ直線を描くと共に,始点のマーク( mark )を削除している.

    068 行目~ 075 行目

      マウスが移動しているときの処理である.自由曲線を描くモードで,かつ,マウスボタンが押されている場合は,マウスの前回の位置と今回の位置を直線で結んでいる.

    077 行目~ 080 行目

      マウスボタンが離されたときの処理である.自由曲線を描くモードである場合は,マウスボタンが押された状態であることを示す変数 sw を false に設定している.

    105 行目~ 145 行目

      制御用のボタンを追加し,各ボタンにはその名前,及び,イベントリスナを追加している.

    148 行目~ 161 行目

      ボタンがクリックされたときの処理であり,クリックされたボタンに対応した処理を行っている.

静岡理工科大学 菅沼ホーム ActionScript目次 索引