サイトトップ

Director Flash 書籍 業務内容 プロフィール
オブジェクト指向で考えるActionScript − Flash MXでより進んだWebデザイン作成 −
>>>補足および正誤表
モーショングラフィックスで学ぶActionScript モーショングラフィックスで学ぶActionScript − Flash MX −
>>>補足および正誤表
Flash OOP FLASH OOP − ActionScriptによるオブジェクト指向プログラミング
>>>補足および正誤表
JaGra PROFESSIONAL SCHOOL公開講座
Flash MX 2004 ActionScript中級
オブジェクト指向で考えるFlash ActionScript上級テクニック
Flash ActionScript 2.0初級
Flash ActionScript 2.0中級

JaGra PROFESSIONAL SCHOOL Seminar

Flash 8特別セミナー「新機能とスクリプティング」

Date: 2005年12月6日 Product: Flash

Platform: All
Viersion: 8.0

1. ぼかしとドロップシャドウフィルタ
スクリプトによるフィルタの基本的な使い方について、詳しくは「スクリプトでフィルタを使う − BlurFilter」を参照してほしい。

サンプル001■DropShadowFilterとBlurFilter(SWFのみ[*1])
DropShadowFilterとBlurFilter

フィルタを適用するには、第1にフィルタインスタンスを、new演算子で作成。フィルタクラス名は、フルネームで指定する。BlurFilterクラスのフルネームは、flash.filters.BlurFilter。「ActionScript 2.0リファレンスガイド」(図001)で確認する。

図001■BlurFilterクラス

import宣言すれば、そのスクリプトペイン(ウィンドウ)内は、クラス名だけでアクセスできる。

   // importでBachのフルネームを宣言
   import johann.sebastian.Bach;
   // 以下Bach
   var myMusician:Bach = new Bach();

第2に、作成したフィルタインスタンスを配列に入れて、その配列をMovieClip.filtersプロパティに適用する。つぎのフレームアクション(スクリプト001)は、スクリプトを記述したMovieClipインスタンスに、BlurFilterを適用。関数BlurFilter()に引数を指定していないので、デフォルト値として水平・垂直のぼかし量にはともに4が設定される。

スクリプト001■MovieClipにBlurFilterを適用

import flash.filters.BlurFilter;
var myBlur:BlurFilter = new BlurFilter();
this.filters = [myBlur];


BlurFilter(水平方向ぼかし, 垂直方向ぼかし, クォリティ)
指定した設定でBlurFilterインスタンスを生成する。クォリティは整数で、通常1から3までの値を使う(数値が大きいほどぼけ幅も大きい。0はぼかしなし)。デフォルト値(引数省略時の値)はぼかし量が4、クォリティは1。

サンプル002は、楕円軌道を回転するMovieClipに対してBlurFilter()を適用し、ぼかし量0から4までの数値で、Y座標が上(マイナス方向)になるほど高い値を指定している。

サンプル002■3DRotation
3DRotation

サンプル001のスクリプトはつぎのとおり(スクリプト002)。楕円軌道を回転する3D風のアニメーションについては、F-siteセミナー「はじめの一歩のアクションスクリプト」レジュメの「4. Mathクラスを使う」の項を参照。

スクリプト002■3D風に楕円軌道を回転するMovieClipにBlurFilterを適用

// タイムライン: _root
// [ライブラリ]にリンケージ識別子"Pen"を設定したMovieClipが格納
// 第1フレームアクション
var nAmount:Number = 6;
var menus_array:Array = new Array();
var oInitObject:Object = new Object();
oInitObject.nRadiusX = 100;
oInitObject.nRadiusY = 20;
oInitObject.nCenterX = Stage.width/2;
oInitObject.nCenterY = Stage.height/2;
for (var i:Number = 0; i<nAmount; ++i) {
  var target_mc:MovieClip = this.attachMovie("Pen", "my"+i+"_mc", i, oInitObject);
  target_mc.nRadian = i*360/nAmount/180*Math.PI;
  menus_array.push(target_mc);
}
this.onEnterFrame = function():Void {
  xRotateAll(2/180*Math.PI);
};
function xRotateAll(nRadian:Number):Void {
  var nLength:Number = menus_array.length;
  for (var i:Number = 0; i<nLength; ++i) {
    menus_array[i].xRotate(nRadian);
  }
}

// MovieClip: リンケージ識別子"Pen"
// 第1フレームアクション
import flash.filters.BlurFilter;
var nMyDepth:Number = this.getDepth();
this.xRotate(0);
function xRotate(nTheta:Number):Void {
  nRadian += nTheta;
  var nUnitX:Number = Math.cos(nRadian);
  var nUnitY:Number = Math.sin(nRadian); // -1 ≦ nUnitY ≦ 1
  _x = nRadiusX*nUnitX+nCenterX;
  _y = nRadiusY*nUnitY+nCenterY;
  _xscale = 100*nUnitY;
  // _alpha = 50*(nUnitY+1)/2+50;
  var nBlur:Number = 4*(-nUnitY+1)/2; // 0 ≦ nUnitY ≦ 4
  // BlurFilterインスタンス生成
  var myBlur:BlurFilter = new BlurFilter(nBlur, nBlur/2);
  // MovieClip.filtersプロパティ設定
  this.filters = [myBlur];
  var nDepth = (nUnitY>0 ? nMyDepth+100 : nMyDepth);
  this.swapDepths(nDepth);
}


[*1] ベースにした.flaファイルは、[Flash 8アプリケーション]/Samples and Tutrials/Samples/ActionScript/Filters/Filters.fla。

2. ビットマップデータをディゾルブする
BitmapData.loadBitmap()およびMovieClip.attchBitmap()メソッドを使うと、[ライブラリ]からビットマップをダイナミックにMovieClipとして配置できる。つぎのサンプルは、[ライブラリ]にあるリンケージ識別子"Pen"を設定したビットマップ(図002)をロードして、ダイナミックに作成したMovieClipに配置する(スクリプト003)。

図002■[ライブラリ]のビットマップにリンケージ識別子を設定
ライブラリ

スクリプト003■[ライブラリ]からビットマップをダイナミックに配置

import flash.display.BitmapData;
var myBitmapData:BitmapData = BitmapData.loadBitmap("Pen");
var _mc:MovieClip = this.createEmptyMovieClip("mc", this.getNextHighestDepth());
_mc.attachBitmap(myBitmapData, _mc.getNextHighestDepth());


BitmapData.loadBitmap(リンケージ識別子)
リンケージ識別子が設定されたビットマップをロードして、新しいBitmapDataインスタンスを作成する。

MovieClip.attachBitmap(BitmapDataインスタンス, 深度)
指定されたBitmapDataインスタンスのイメージを、MovieClipに設定する。

サンプル003■PixelDissolve

サンプル003は、画像をクリックすると、ディゾルブによりホワイトアウトする(スクリプト004)。Bitmap.pixelDissolve()メソッドには、毎回異なったランダム値を引数として渡す必要がある。そのようなランダム値は、メソッドの戻り値になっているので、それを受取って次回の呼出し時に用いる。

スクリプト004■画像をクリックでディゾルブ

import flash.display.BitmapData;
import flash.geom.Point;
var myBitmapData:BitmapData = BitmapData.loadBitmap("Pen");
var _mc:MovieClip = this.createEmptyMovieClip("mc", this.getNextHighestDepth());
_mc.attachBitmap(myBitmapData, _mc.getNextHighestDepth());
var nRandom:Number;
_mc.onPress = function() {
  nRandom = Math.floor(Math.random()*10);
  this.onEnterFrame = xDissolve;
};
var nTotalDissolved:Number = 0;
var nTotalPixels:Number = myBitmapData.width*myBitmapData.height;
var nDissolving:Number = 30;
var zeroPoint:Point = new Point(0, 0);
function xDissolve() {
  nRandom = myBitmapData.pixelDissolve(myBitmapData, myBitmapData.rectangle, zeroPoint, nRandom, nDissolving, 0x00FFFFFF);
  nTotalDissolved += nDissolving;
  if (nTotalDissolved>=nTotalPixels) {
    delete this.onEnterFrame;
  }
  nDissolving = Math.floor(nDissolving*1.1);
}


BitmapData.pixelDissolve(ソースBitmapData, ソース矩形領域, 左上隅Point, ランダム値, ピクセル数, カラー値)
ソースイメージを、指定したカラー値でディゾルブする。ターゲットのBitmapDataと異なるソースイメージを指定すれば、ターゲットからソースへのディゾルブも可能。

ユニークなランダム値が返されるので、連続したディゾルブには、その値をつぎの呼出し時に引数として渡す。

3. コンボリューション行列
ConvolutionFilterは、コンボリューション行列を用い、ピクセル単位で周囲のピクセル情報をもとにイメージ処理を行う。その結果、エンボスや輪郭検出、ぼかし、シャープなど、さまざまな効果が適用できる(サンプル004)。行列に指定する値とその効果については、「コンボリューション行列」の解説が詳しい。

サンプル004■Convolution − いくつかの効果

エンボスを5×5のコンボリューション行列で指定すると、つぎのようになる(表001)。

表001■エンボスのコンボリューション行列

0

0

0

0

0

0

1

1

0

0

0

1

0

-1

0

0

0

-1

-1

0

0

0

0

0

0

除数   1

バイアス   128


ConvolutionFilter(列数, 行数, コンボリューション行列, 除数, バイアス)
コンボリューション行列を適用してピクセル単位のイメージ処理を行う。

つぎのサンプル005は、画像をクリックすると、コンボリューション行列を使ってエンボスの効果を適用する(スクリプト005)。

サンプル005■ConvolutionEmboss

スクリプト005■ConvolutionFilterでエンボスを設定

// MovieClip this;
import flash.filters.ConvolutionFilter;
import flash.display.BitmapData;
var _mc:MovieClip = this.createEmptyMovieClip("image_mc", this.getNextHighestDepth());
_mc.attachBitmap(BitmapData.loadBitmap("Pen"), _mc.getNextHighestDepth());
// ConvolutionFilter引数設定
var nMatrixX:Number = 5;   // 列数
var nMatrixY:Number = 5;   // 行数
// コンボリューション行列を配列として作成
var matrix_array:Array = new Array();
// 最終的に作成される25エレメントの配列[*2]
// [0,0,0,0,0,0,1,1,0,0,0,1,0,-1,0,0,0,-1,-1,0,0,0,0,0,0]
matrix_array = matrix_array.concat([0, 0, 0, 0, 0]);
matrix_array = matrix_array.concat([0, 1, 1, 0, 0]);
matrix_array = matrix_array.concat([0, 1, 0, -1, 0]);
matrix_array = matrix_array.concat([0, 0, -1, -1, 0]);
matrix_array = matrix_array.concat([0, 0, 0, 0, 0]);
var nDivisor:Number = 1;   // 除数
var nBias:Number = 128;   // バイアス
_mc.onPress = function():Void {
  var myConvolution:ConvolutionFilter = new ConvolutionFilter(nMatrixX, nMatrixY, matrix_array, nDivisor, nBias);
  this.filters = [myConvolution];
};


[*2] ConvolutionFilter()に指定するコンボリューション行列は行数(5)×列数(5)の総エレメント数(25)を羅列した配列なので、Array.concat()メソッドを使って、RGBA各カラー値ごとの5エレメントからなる4つの配列をひとつに連結している。

4. 変換行列
Transform.matrixプロパティは、MovieClipの拡大・縮小や回転、傾斜を決める値を格納したMatrixオブジェクト(変換行列)。3×3の変換行列のうち、a、b、c、d、tx、tyの6つのプロパティが操作できる。サンプル006は、これら6つのプロパティの操作と、回転を行った場合のa、b、c、dの値の算出を、シミュレートする。

サンプル006■変換行列の操作(SWFのみ)
ColorMatrix

変換行列をもつMatrixクラスには、直接プロパティ値を変更する方法以外に、移動や拡大・縮小、回転を行うためのメソッドが用意されている。

Matrix.translate(tx, ty)
水平方向にtxピクセル、垂直方向にtyピクセル平行移動する。

Matrix.scale(a, d)
水平方向にa倍、垂直方向にd倍の拡大・縮小を行う。

Matrix.rotate(θ)
角度θ(ラジアン)の回転を行う。変換行列のプロパティ4つの値を、a:cosθ、b:sinθ、c:-sinθ、d:cosθに設定するのと同じ結果になる。

サンプル007■Transform
グレースケール

サンプル007は、画像の3つの頂点をドラッグで移動すると、それらの座標に対応した変換行列の値を計算して、画像を平行四辺形に変形する。計算した変換行列の値は、Matrixインスタンスのプロパティに設定したうえで、そのMatrixをMovieClip.transformプロパティに設定している(スクリプト006)。

スクリプト006■MovieClipの3頂点の座標を指定して変形

// タイムライン: _root
// 第1フレームアクション
// 変形するMovieClip: _root.my_mc
import flash.geom.Matrix;
import flash.geom.Point;
// Pointインスタンスで指定された3頂点に合わせてMovieClipを変形する
// MovieClip.transform.matrixのプロパティ値を計算して設定
function xTransformMovieClipPoints(_mc:MovieClip, point0:Point, point1:Point, point2:Point):Void {
  var myMatrix:Matrix = _mc.transform.matrix;
  var contents_mc:MovieClip = _mc.contents;
  var nWidth:Number = contents_mc._width;
  var nHeight:Number = contents_mc._height;
  var point1_0:Point = point0.subtract(point1);
  var point1_2:Point = point2.subtract(point1);
  myMatrix.tx = point1.x;
  myMatrix.ty = point1.y;
  myMatrix.a = (point1_0.x)/nWidth;
  myMatrix.b = (point1_0.y)/nWidth;
  myMatrix.c = (point1_2.x)/nHeight;
  myMatrix.d = (point1_2.y)/nHeight;
  _mc.transform.matrix = myMatrix;
}
// 3頂点の座標を取得してxTransformMovieClipPoints()に渡す
// ドラッグした頂点のMovieClipから呼出される
function xTransform() {
  var point0:Point = new Point(point0_mc._x, point0_mc._y);
  var point1:Point = new Point(point1_mc._x, point1_mc._y);
  var point2:Point = new Point(point2_mc._x, point2_mc._y);
  xTransformMovieClipPoints(my_mc, point0, point1, point2);
}

// MovieClip: ドラッグする頂点
// 第1フレームアクション
function onPress():Void {
  this.startDrag();
}
function onRelease():Void {
  xOnRelease();
}
function onReleaseOutside():Void {
  xOnRelease();
}
function xOnRelease():Void {
  this.stopDrag();
  _root.xTransform()
}

変換行列は、画像の3Dマッピングに応用できる。サンプル008は、立方体の3D空間における仮想の頂点座標を回転し[*3]、2Dに透視変換した座標に対して6つの画像を変形して、3次元の回転を表現している。応用事例として、サンプル中のスクリプトに簡単なコメントを加えた。

サンプル008■3D_Box − 変換行列の応用
グレースケール

[*3] 3Dの座標を扱うクラスは、Flash 8にも存在しない。したがって、座標の管理はスクリプトで行い、3次元での回転も独自に計算する必要がある。3Dの座標の扱いについては、以下のURLが参考になる。

3D基礎知識」「3D座標変換」「Affine変換とAffine行列の関係」「ベクトルと行列」「Javaソース付き 3Dプログラミング入門

なお、書籍としては、郡山 彬/原 正雄/峯崎 俊哉『CGのための線形代数』がコンパクトにまとまっている。

5. setTimeout()とclearTimeout()関数
Flash 8から、setTimeout()clearTimeout()関数が実装された。ヘルプに記載はないものの、公式にサポートされる。詳しくは「setTimeout()関数」と「clearTimeout()関数」を参照してほしい。

6. 参考URL
Flash 8の技術情報に関わる参考サイト。

Flash 8 LiveDocs英語版 / Flash 8 LiveDocs日本語版
ヘルプと同内容のドキュメント。ユーザーやMacromediaの人たちが、修正・補足の情報をコメントとして追加できる。Flash 8から日本語版がアップされた。

Flash 8ヘルプ勝手に正誤表
野中が独自の判断により、一方的に作成。LiveDocsにもコメントを入れて、リンクしている。Macromedia側の確認を経て、採用されたものもある。

mixi: [ActionScript Lounge]コミュニティ
野中の主催するmixiのコミュニティ。ActionScriptのマニアックな話題を掲載する。Flash 8のバグ情報も適宜追加中。

A. おまけ
Flash 8には、MXからあるゲーム以外に、イースターエッグがもうひとつ加わった。

図003■クリックするとEaster Eggsが
Easter Eggs

開発チームといえるか、疑問な顔ぶれも...
Flash 8 Team

_____

作成者: 野中文雄
作成日: 2005年12月16日
(ドラフト作成: 2005年12月15日)


Copyright © 2001-2006 Fumio Nonaka.  All rights reserved.