スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--.--.-- | | スポンサー広告

だんだんぼやける残像

前回のエントリと似たようなカンジですが、今度は残像にブラーをかけてみました。




クリックすると、前回っぽい残像になります。

前回はonEnterFrameでムービークリップの_alphaを変化させていましたが、今回はBlurFilterを使用してonEnterFrameでかけるブラーの強さを調整しています。

ソレ以外に前回と変わってる部分としては、

  • 本体(残像ではないムービークリップ)を表示するようにしている
  • 毎フレーム新しい残像を作らずに間を抜くようにした
  • 残像を削除するかどうかの判断にカウンタ変数を使うようにした
あたりデス。

そんでActionScriptは以下のようなカンジです。
import flash.filters.BlurFilter;
// 加速度
var k:Number = 0.4;
// 減衰係数
var a:Number = 0.5;
// 拡大率
var s:Number = 1.05;
// 残像フレーム数
var aiLimit:Number = 8;
// 残像インターバル
var aiInterval:Number = 1;
// 透過率
var ar:Number = 0.8;
// ブラー係数
var b:Number = 3;
// マウスカーソル非表示
Mouse.hide();

// 本体は非表示
jien_mc._visible = false;

// マウスカーソルを追跡するムービークリップ
var depth = _root.getNextHighestDepth();
var chaser_mc:MovieClip
= jien_mc.duplicateMovieClip("chaser_" + depth, depth);
// スピード
chaser_mc.speedX = 0;
chaser_mc.speedY = 0;
// 残像インターバルカウンタ
chaser_mc.intervalCnt = 0;
// アルファ値を変化させる残像か?
chaser_mc.alphaAfterImage = false;
// フレーム毎の処理
chaser_mc.onEnterFrame = function() {
if (this.intervalCnt >= aiInterval) {
// 残像
var afterImage_mc:MovieClip
= createAfterImage(this.alphaAfterImage);
this.swapDepths(afterImage_mc);
// カウンタを初期化
this.intervalCnt = 0;
} else {
this.intervalCnt += 1;
}
// 移動
this.speedX = k * (_xmouse - chaser_mc._x) + a * this.speedX;
this.speedY = k * (_ymouse - chaser_mc._y) + a * this.speedY;
this._x += this.speedX;
this._y += this.speedY;
}
// クリックしたら残像の種類を変更する
chaser_mc.onRelease = function() {
this.alphaAfterImage = !this.alphaAfterImage;
}
// 残像を作成します。
function createAfterImage(alphaAfterImage:Boolean):MovieClip {
// 本体をコピーする
var depth:Number = _root.getNextHighestDepth();
var afterImage_mc:MovieClip
= chaser_mc.duplicateMovieClip("afterImage_" + depth, depth);
afterImage_mc.cnt = 0;
// alphaAfterImageがtrueならアルファ値を変化させる。
// そうでなければブラー
if (alphaAfterImage) {
afterImage_mc.effect = function () {
this._alpha *= ar;
}
} else {
afterImage_mc.blur = b;
afterImage_mc.effect = function () {
this._width *= s;
this._height *= s;
var filter:BlurFilter
= new BlurFilter(this.blur, this.blur, 1);
this.filters = [filter];
this.blur += b;
}
}
// フレーム毎の処理
afterImage_mc.onEnterFrame = function () {
this.effect();
this.cnt += 1;
// 指定フレーム数に達したら消滅
if (this.cnt > aiLimit) {
this.removeMovieClip();
}
}
afterImage_mc.effect();
return afterImage_mc;
}
jien_mcはオーサリングで作ったムービークリップです。
chaser_mcはjien_mcのコピーで、ばねの動きでマウスカーソルを追跡します。
残像は、前回と同じようにduplicateMovieCilpを使って作成しますが、本体を常に再前面に表示したいのでswapDepthsを使って、本体と作成した残像の深度を入れ替えています。

aiIntervalは残像を表示しないフレーム数で、ここでしたフレーム間隔で残像を表示します。
aiLimitは残像を再生するフレーム数で、コレを超えるフレーム表示した残像は消滅します。

スポンサーサイト

テーマ:Flash - ジャンル:コンピュータ

2007.03.30 | | Comments(0) | Trackback(0) | Flash/ActionScript

残像を表示する

移動するムービークリップの残像を表示してみました。




ステージ内でマウスを動かすと残像を残しながら物体が移動します。
やってるコトは単純で、onEnterFrameでだんだん透明になるムービークリップを作ってるダケです。

ムービークリップ本体は、ばねっぽくイージングしてマウスカーソル(非表示ですが)を追いかけます。が非表示です。
onEnterFrameで、本体をduplicateMovieClipして残像を作り、ソイツのonEnterFrameでアルファ値を変化させてます。そんで、ある程度以上透明になったら残像をremoveMovieClipしてマス。

ActionScriptはこんなカンジです。

// 加速度
var k:Number = 0.4;
// 減衰係数
var a:Number = 0.5;
// 透過係数
var t:Number = 0.6;
// 透過限界
var aLimit:Number = 10;
// スピード
jien_mc.speedX = 0;
jien_mc.speedY = 0;

// 本体は非表示
jien_mc._visible = false;

// マウスカーソル非表示
Mouse.hide();

// フレーム毎の処理
jien_mc.onEnterFrame = function() {
// 移動
this.speedX = k * (_xmouse - jien_mc._x) + a * this.speedX;
this.speedY = k * (_ymouse - jien_mc._y) + a * this.speedY;
this._x += this.speedX;
this._y += this.speedY;
// 残像
createAfterImage();
}

// 残像を作成します。
function createAfterImage() {
// 本体をコピーする
var depth:Number = _root.getNextHighestDepth();
var afterImage_mc:MovieClip
= jien_mc.duplicateMovieClip("afterImage_" + depth, depth);
// フレーム毎にアルファ値を低くする
afterImage_mc.onEnterFrame = function () {
this._alpha *= t;
// アルファ値が透過限界以下になったら消滅
if (this._alpha <= aLimit) {
this.removeMovieClip();
}
}
}
jien_mcがマウスカーソルを追いかけるムービークリップ(ただし非表示)で、createAfterImageで本体をduplicateMovieClipして残像を作ってます。

テーマ:Flash - ジャンル:コンピュータ

2007.03.29 | | Comments(2) | Trackback(0) | Flash/ActionScript

Apolloでレンズ

[Z]ZAPAブロ~グ2.0さんのはじめてのApolloプログラミングを見て、オレもオレもというカンジでやってみました。

とは言ってもActionScriptはFlex2でレンズのをそのまんま使うことにして、

amxmlc -default-size 400 300 -default-frame-rate=12 -default-background-color=0xFFFFFF LensSample.as
でswfを作成しました。

あとは、LensSample.xmlを
<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://ns.adobe.com/apollo/application/1.0.M3"
appId="com.fc2.blog96.100th.LensSample" version="1.0">

<properties>
<name>LensSample</name>
<publisher>HundredthMonkey</publisher>
<description>apollo lens sample</description>
<copyright>HundredthMonkey</copyright>
</properties>

<rootContent
systemChrome="standard"
transparent ="false"
visible ="false">LensSample.swf</rootContent>

<icon>
<image16x16>icons/ApolloApp_16.png</image16x16>
<image32x32>icons/ApolloApp_32.png</image32x32>
<image48x48>icons/ApolloApp_48.png</image48x48>
<image128x128>icons/ApolloApp_128.png</image128x128>
</icon>
</application>
なカンジで書いて
adt -package LensSample.air LensSample.xml LensSample.swf icons
でairファイルを作成できました。

airファイルをインストール/実行すると、

こんなカンジでブジ実行できました。

とりあえずやってみただけでFlex2のとまったく同じなのがアレですケド。

テーマ:プログラミング - ジャンル:コンピュータ

2007.03.26 | | Comments(0) | Trackback(0) | Apollo

Flex2でレンズ

以前Flashで作ったレンズで部分拡大をFlex2(というかActionScript3.0)でも作ってみました。




基本的にやってることはFlash版と同じデス。

ActionScriptはこんなカンジです。

package {
import flash.display.*;
import flash.events.*;
import flash.ui.Mouse;
// メインクラス
public class LensSample extends Sprite {
// 画像リソース
[Embed(source='image.png')]
private var ImageBitmap:Class;
// サイズ入力欄
private var sizeInput:LabelInput;
// 曲率半径入力欄
private var rInput:LabelInput;
// 焦点距離入力欄
private var fInput:LabelInput;
// 設定ボタン
private var settingBtn:LabelButton;
// 画像
private var imageBitmap:Bitmap;
// レンズ
private var lens:BitmapSprite;
// サイズ
private var size:Number;
// コンストラクタ
public function LensSample() {
// サイズ入力欄
sizeInput = new LabelInput("サイズ", "100");
addChild(sizeInput);
// 曲率半径入力欄
rInput = new LabelInput("曲率半径", "70");
rInput.x = 90;
addChild(rInput);
// 焦点距離入力欄
fInput = new LabelInput("焦点距離", "100");
fInput.x = 200;
addChild(fInput);
// 設定ボタン
settingBtn = new LabelButton(" 設定 ");
settingBtn.x = 300;
settingBtn.addEventListener(MouseEvent.CLICK,
onSettingBtnClick);
addChild(settingBtn);
// 画像
imageBitmap = new ImageBitmap();
imageBitmap.x = 100;
imageBitmap.y = 50;
addChild(imageBitmap);
// レンズ
lens = new BitmapSprite();
lens.visible = false;
addChild(lens);
// セットアップ
onSettingBtnClick(null);
// イベントリスナ
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
// 設定ボタンをクリックしたときの処理
private function onSettingBtnClick(evt:Event):void {
size = Number(sizeInput.inputText);
// レンズにフィルタをセット
lens.filters = [LensFilterFactory.create(size,
Number(rInput.inputText),
Number(fInput.inputText))];
}
// フレーム毎の処理
private function onEnterFrame(evt:Event):void {
// 画像上にマウスカーソルが存在したらレンズ処理
if (mouseX >= imageBitmap.x
&& mouseX <= imageBitmap.x + imageBitmap.width
&& mouseY >= imageBitmap.y
&& mouseY <= imageBitmap.y + imageBitmap.height) {
var bitmap:BitmapData
= BitmapDataUtils.clip(imageBitmap,
imageBitmap.mouseX - size / 2,
imageBitmap.mouseY - size / 2,
size,
size);
lens.x = mouseX - size / 2;
lens.y = mouseY - size / 2;
lens.bitmapData = bitmap;
Mouse.hide();
lens.visible = true;
} else {
Mouse.show();
lens.visible = false;
}
}
}
}
import flash.display.*;
import flash.text.*;
import flash.filters.DisplacementMapFilter;
import flash.geom.*;
// BitmapDataユーティリティ
class BitmapDataUtils {
// 指定したオブジェクトからクリッピングしたビットマップデータを
// 戻します。
public static function clip(src:IBitmapDrawable,
x:Number,
y:Number,
w:Number,
h:Number):BitmapData {
var dest:BitmapData = new BitmapData(w, h);
var matrix:Matrix = new Matrix();
matrix.tx = -x;
matrix.ty = -y;
dest.draw(src,
matrix,
new ColorTransform(),
"normal",
new Rectangle(0, 0, w, h),
false);
return dest;
}
}
// 内部にビットマップを持つスプライト
class BitmapSprite extends Sprite {
// 内部画像
private var src:Bitmap;
// コンストラクタ
public function BitmapSprite() {
// 画像
src = new Bitmap();
addChild(src);
}
// ビットマップデータをセット
public function set bitmapData(bitmapData:BitmapData):void {
if (src.bitmapData) {
src.bitmapData.dispose();
}
src.bitmapData = bitmapData;
}
}
// レンズフィルタファクトリ
class LensFilterFactory {
// DisplacementMapFilterを作成し、戻します。
public static function create(size:Number,
r:Number,
f:Number):DisplacementMapFilter {
var mapData:BitmapData = new BitmapData(size,
size,
false,
0xFF008080);
var o:Number = size / 2;
var o2:Number = o * o;
var r2:Number = r * r;
var y:Number;
var dY:Number;
var dY2:Number;
var x:Number;
var dX:Number;
var dR2:Number;
var l:Number;
var d:Number
// 調整値を割り出す
var maxY:Number = 0;
var maxX:Number = 0;
for (y = 0; y < size; y++) {
dY = y - o;
dY2 = dY * dY;
for (x = 0; x < size; x++) {
dX = x - o;
dR2 = dX * dX + dY2;
// ピクセルが、レンズムービークリップの内接円に
// 入っている場合のみ処理
if (dR2 < o2) {
// ずれ
l = Math.sqrt(r2 - dR2) - Math.sqrt(r2 - o2);
d = l / (f + l);
// 最大値設定
maxY = Math.max(maxY, Math.abs(dY * d));
maxX = Math.max(maxX, Math.abs(dX * d));
}
}
}
var yAdj:Number = 128 / (maxY + 1);
var xAdj:Number = 128 / (maxX + 1);
// ビットマップ生成
for (y = 0; y < size; y++) {
dY = y - o;
dY2 = dY * dY;
for (x = 0; x < size; x++) {
dX = x - o;
dR2 = dX * dX + dY2;
// ピクセルが、レンズムービークリップの内接円に
// 入っている場合のみ処理
if (dR2 < o2) {
// ずれ
l = Math.sqrt(r2 - dR2) - Math.sqrt(r2 - o2);
d = l / (f + l);
// ピクセルの色
var yC:Number = -Math.floor(dY * d * yAdj);
var xC:Number = -Math.floor(dX * d * xAdj);
var c:Number = 0xFF000000
+ (0x80 + yC) * 0x100
+ (0x80 + xC);
// ピクセルを描画する
mapData.setPixel(x, y, c);
}
}
}
// フィルタ作成
var filter:DisplacementMapFilter
= new DisplacementMapFilter(mapData,
new Point(),
4,
2,
Math.ceil(256 / xAdj),
Math.ceil(256 / yAdj));
return filter;
}
}
// ラベル付き入力フィールド
class LabelInput extends Sprite {
// ラベル
private var label:TextField;
// 入力フィールド
private var input:TextField;
// コンストラクタ
public function LabelInput(labelText:String,
inputDefault:String) {
// フォーマット
var format:TextFormat=new TextFormat();
format.font = "_等幅";
format.size = 10;
format.color = 0x000000;
// ラベル生成
label = new TextField();
label.setTextFormat(format);
label.autoSize = TextFieldAutoSize.LEFT;
label.text = labelText;
addChild(label);
// 入力欄生成
input = new TextField();
input.border = true;
input.type = TextFieldType.INPUT;
input.setTextFormat(format);
input.x = label.x + label.width;
input.width = 50;
input.height = label.height;
input.text = inputDefault;
addChild(input);
}
// 入力文字列を戻します。
public function get inputText():String {
return input.text;
}
// 入力文字列を設定します。
public function set inputText(value:String):void {
input.text = value;
}
}
// ラベル付きボタン
class LabelButton extends Sprite {
// コンストラクタ
public function LabelButton(labelText:String) {
// フォーマット
var format:TextFormat=new TextFormat();
format.font = "_等幅";
format.size = 10;
format.color = 0x000000;
// ラベル生成
var label:TextField = new TextField();
label.setTextFormat(format);
label.text = labelText;
label.autoSize = TextFieldAutoSize.CENTER;
label.border = true;
label.background = true;
label.backgroundColor = 0xdddddd;
label.selectable = false;
label.mouseEnabled = false;
addChild(label);

buttonMode = true;
}
}
で、swfの作成はFlex2SDKを使って
mxmlc -default-size 400 300 -default-frame-rate=12 -default-background-color=0xFFFFFF LensSample.as
としました。

こうして貼ってみると長いですね。
いくつかクラスを定義してますが、ソレゾレ何のクラスかというと、

LensSampleはメインのクラスで、3つの入力欄と設定ボタンと画像とレンズが配置してあります。画像はFlashではシンボルでしたが、こちらはpng画像を読み込んでいます。設定ボタンがクリックされたらレンズにDisplacementMapFilterを再設定します。onEnterFrameでは、マウスカーソルが画面上にあったらその周辺の画像をレンズに設定しています。

BitmapDataUtilsはBitmapDataを操作するためのメソッドを定義しています。clipメソッドは指定したオブジェクトから、指定した座標/幅/高さでビットマップデータを切り出すメソッドです。

BitmapSpriteは内部にBitmapを一つ持つスプライトで、レンズに使っています。

LensFilterFactoryは、レンズの動作をするDisplacementMapFilterのファクトリです。createメソッドで、指定したサイズ/曲率半径/焦点距離を持つレンズのDisplacementMapFilterオブジェクトを生成します。やってることはFlash版と同じデス。

LabelInputは、ラベルと入力フィールドを持つスプライトです。サイズ/曲率半径/焦点距離の入力欄に使用しています。

LabelButtonは、ラベルのあるボタンです。ボタンといってもSpriteのbuttonModeをtrueにしてるだけなので、見栄えはショボイです。

といったカンジで、あまりActionScript3.0の利点をいかしたというカンジではないですね。というか利点はあまりわかってないのですケド。

テーマ:プログラミング - ジャンル:コンピュータ

2007.03.25 | | Comments(0) | Trackback(0) | Flex2

画像の部分拡大

前回とはチガウやり方で、マウスカーソル周辺部を拡大表示するサンプルを作ってみました。




拡大して表示とはいうものの、今回は厳密に言うと拡大してません。

どういうコトかってーと、元々大きな画像をシンボル化して最初はソレを縮小したものを表示しています。マウス周辺部だけ元の大きさで表示してるので一見拡大してるように見えるという寸法デス。

拡大画像表示は、BitmapData#drawを使ってマス。コレのパラメータのMatrixを指定して拡大することもできるのですが、BitmapData#drawは変換がかかったシンボルをソースにしてもソレを無効にして実行されるので、今回のケースではMatrixでは拡大してません。ので、フラッシュに取り込んだサイズで切り取り/表示されます。

スクリプトは、以下のようになってマス。

import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.geom.Rectangle;
// 元画像のサイズ
var orgWidth:Number = 1024;
var orgHeight:Number = 768;
// 元画像と表示画像の比
var wRatio:Number = orgWidth / image_mc._width;
var hRatio:Number = orgHeight / image_mc._height;

// 切り取りサイズ
var windowWidth:Number;
var windowHeight:Number;

// 切り取り窓
var depth:Number = _root.getNextHighestDepth();
var window_mc:MovieClip = _root.createEmptyMovieClip("window_" + depth, depth);
// 設定ボタン
test_btn.onRelease = setup;

setup();

// セットアップ
function setup() {
windowWidth = Number(width_txt.text);
windowHeight = Number(height_txt.text);
}

// フレーム毎の処理
function onEnterFrame() {
if (_xmouse < image_mc._x
|| _xmouse > (image_mc._x + image_mc._width)
|| _ymouse < image_mc._y
|| _ymouse > (image_mc._y + image_mc._height)) {
// 画像範囲外なら切り取り窓は表示しない
window_mc._visible = false;
// マウスカーソル表示
Mouse.show();
} else {
// 切り取り窓位置調整
window_mc._x = _xmouse - windowWidth / 2;
window_mc._y = _ymouse - windowHeight / 2;
// 切り取った画像を保持するビットマップデータ
var bitmap:BitmapData = new BitmapData(windowWidth,
windowHeight);
// 切り取る矩形
var rect:Rectangle = new Rectangle(0,
0,
windowWidth,
windowHeight);
// 切り取り時変換
var matrix:Matrix = new Matrix();
matrix.tx = -(_xmouse - image_mc._x) * wRatio
+ windowWidth / 2;
matrix.ty = -(_ymouse - image_mc._y) * hRatio
+ windowHeight / 2;
// 切り取り
bitmap.draw(image_mc,
matrix,
new ColorTransform(),
"normal",
rect,
false);
window_mc.attachBitmap(bitmap, 1);
// マウスカーソル非表示
Mouse.hide();
// 切り取り窓表示
window_mc._visible = true;
}
}
image_mcは表示画像デス。実際は1024×768の画像を256×192で表示しています。
切り取り時の変換でMatrix.tx, Matrix.tyでゴチャゴチャとセットしてますが、コレはBitmapData#draw時には画像が元のサイズで扱われてしまうため、元のサイズでのオフセット位置を算出しています。

テーマ:Flash - ジャンル:コンピュータ

2007.03.23 | | Comments(0) | Trackback(0) | Flash/ActionScript

レンズで部分拡大

DisplacementMapFilterで、レンズを通したように画像を拡大してみました。マウスを左側の画像の上に持っていくとその周辺がレンズで拡大されたように変形するハズです(うまくいかないときは一回クリックしてみてクダサイ)。




このフラッシュでは、入力したサイズ/曲率半径/焦点距離からマップ画像と表示用ムービークリップを生成し、サイズにしたがって元画像をクリッピングしたものにDisplacementMapFilterをかけてマス。
サイズで指定した値がレンズの直径なので、曲率半径はサイズの1/2以上の必要がありマス。

マップ画像ですが、下図のようなレンズを想定して算出しました。
レンズ
水色に塗ってある部分がレンズで、oがレンズの半径(サイズの1/2)、rが曲率半径、fが焦点距離デス。

マップ画像を作りたいので、ココから表示ピクセルと元ピクセルの位置のずれを算出していきます。
レンズの中心からyの距離での元画像とのずれy'は、

  x' / (f + x') = y' / y
なので、
  y' = y x' / (f + x')
となるハズです。
そんでx'は
  x' = sqrt(r^2 - y^2) - sqrt(r^2 - o^2)
のハズです。
なので元画像のピクセルは、表示位置からレンズの中心向かって
  y(sqrt(r^2 - y^2) - sqrt(r^2 - o^2)) / (f + sqrt(r^2 - y^2) - sqrt(r^2 - o^2))
ずれた位置にあるハズです。
上記のずれをd、表示ピクセルの座標を(x, y)、レンズの中心座標を(o, o)とすると、x方向、y方向のずれはx0, y0は、
  y0 = d(y - o)
x0 = d(x - o)
デス。たぶん。

コレを元に作成したマップ画像が、右側の画像デス。
あとは、onEnterFrameでマウスカーソルの位置から元画像を指定したサイズで切り取ってattachBitmapしてるダケです。

ActionScript自体は、
import flash.display.BitmapData;
import flash.filters.DisplacementMapFilter;
import flash.geom.Matrix;
// 位置、サイズ
var l:Number = test_mc._x;
var t:Number = test_mc._y;
var w:Number = test_mc._width;
var h:Number = test_mc._height;

// レンズの大きさ
var size:Number;
// 曲率半径
var r:Number;
// 焦点距離
var f:Number;

// マップ画像オフセット
var mapOffsetX:Number = w + 10;
var mapOffsetY:Number = 0;

// スケール調整値
var yAdj:Number = 1;
var xAdj:Number = 1;

// レンズムービークリップ
var lens_mc:MovieClip;

// マップムービークリップ
var map_mc:MovieClip;

// 設定ボタン
test_btn.onRelease = setupLens;

setupLens();

// レンズのセットアップ
function setupLens() {
size = Number(size_txt.text);
r = Number(r_txt.text);
f = Number(f_txt.text);
// マップ画像
var mapBitmap:BitmapData = createMapBitmap();

// マップ画像表示
if (map_mc) {
map_mc.removeMovieClip();
}
var depth:Number = _root.getNextHighestDepth();
map_mc = _root.createEmptyMovieClip("mask_" + depth, depth);
map_mc.attachBitmap(mapBitmap, 1);
map_mc._x = l + mapOffsetX;
map_mc._y = t + mapOffsetY;

// レンズムービークリップ
if (lens_mc) {
lens_mc.removeMovieClip();
}
depth = _root.getNextHighestDepth();
lens_mc = _root.createEmptyMovieClip("lens_" + depth, depth);

// フィルタ設定
var filter:DisplacementMapFilter
= new DisplacementMapFilter(mapBitmap,
new Point(),
4,
2,
Math.ceil(256 / xAdj),
Math.ceil(256 / yAdj));
lens_mc.filters = [filter];
}


// フレーム毎の処理
function onEnterFrame() {
// 対象ムービークリップ上にマウスカーソルがない場合は
// レンズは表示しない
if (_root._xmouse < test_mc._x
|| _root._xmouse > test_mc._x + test_mc._width
|| _root._ymouse < test_mc._y
|| _root._ymouse > test_mc._y + test_mc._height) {
lens_mc._visible = false;
Mouse.show();
return;
}
lens_mc._visible = true;
// レンズを動かす
lens_mc._x = _root._xmouse - size / 2;
lens_mc._y = _root._ymouse - size / 2;
// マウスカーソルの位置を中心にレンズ効果
var src:BitmapData = new BitmapData(size, size);
var matrix:Matrix = new Matrix();
matrix.tx = -(test_mc._xmouse - size / 2);
matrix.ty = -(test_mc._ymouse - size / 2);
src.draw(test_mc, matrix, new ColorTransform(),
"normal", new Rectangle(0, 0, size, size), false);
lens_mc.attachBitmap(src, 1);
Mouse.hide();
}


// DisplacementMapFilter用のビットマップを生成する
function createMapBitmap():BitmapData {
var bitmap:BitmapData
= new BitmapData(size, size, false, 0xFF008080);
var o:Number = size / 2;
var o2:Number = o * o;
var r2:Number = r * r;
// 調整値の設定
var maxY:Number = 0;
var maxX:Number = 0;
for (var y:Number = 0; y < size; y++) {
var dY:Number = y - o;
var dY2:Number = dY * dY;
for (var x:Number = 0; x < size; x++) {
var dX:Number = x - o;
var dR2:Number = dX * dX + dY2;
// ピクセルが、レンズムービークリップの内接円に
// 入っている場合のみ処理
if (dR2 < o2) {
// ずれ
var l:Number = Math.sqrt(r2 - dR2) - Math.sqrt(r2 - o2);
var d:Number = l / (f + l);
// 最大値設定
maxY = Math.max(maxY, Math.abs(dY * d));
maxX = Math.max(maxX, Math.abs(dX * d));
}
}
}
yAdj = 128 / (maxY + 1);
xAdj = 128 / (maxX + 1);
// ビットマップ生成
for (var y:Number = 0; y < size; y++) {
var dY:Number = y - o;
var dY2:Number = dY * dY;
for (var x:Number = 0; x < size; x++) {
var dX:Number = x - o;
var dR2:Number = dX * dX + dY2;
// ピクセルが、レンズムービークリップの内接円に
// 入っている場合のみ処理
if (dR2 < o2) {
// ずれ
var l:Number = Math.sqrt(r2 - dR2) - Math.sqrt(r2 - o2);
var d:Number = l / (f + l);
// ピクセルの色
var yC:Number = -Math.floor(dY * d * yAdj);
var xC:Number = -Math.floor(dX * d * xAdj);
var c:Number = 0xFF000000
+ (0x80 + yC) * 0x100
+ (0x80 + xC);
// ピクセルを描画する
bitmap.setPixel(x, y, c);
}
}
}
return bitmap;
}
こんなカンジです。

test_mcは、変形元画像のムービークリップです。
x、y方向のずれは0x80を中心に0x00~0xFFの範囲しか指定できないので、createMapBitmap()の最初のループで算出されるずれの最大値を探して、範囲内に収まるように調整してマス。

結果をみるとどうやらちゃんと表示されてるような気がしますが、計算があってるかは自信アリマセン。

2007/7/5このエントリのソースコードはFlash8用デス。Flash CS3で同じことするバージョンがFlash CS3でレンズにあります。

テーマ:Flash - ジャンル:コンピュータ

2007.03.20 | | Comments(0) | Trackback(0) | Flash/ActionScript

ばねでイージング

イージングにバネっぽい動きを使ってみました。




「ばね」はバネの強さで、数字が大きいほどひっぱる力が強いデス。
「減衰」は収束する速さで、小さいほど収束するのが早いデス。1でまったく減衰しないデス。

「位置」は'_x'プロパティ、「大きさ」は'_width','_height'プロパティ、角度は'_rotation'プロパティ、「ブラー」はBlurFilterのブラーの強さをフレーム毎に変化させています。

変化量は、変化量をp'、直前の変化量をp、「ばね」をk、「減衰」をa、バネの伸びをlとすると

  p' = p * a + l * k
といったカンジで算出しています。

ActionScriptは以下のようなカンジです。
import flash.filters.BlurFilter;
// ばね定数
var k:Number;
// 減衰定数
var a:Number;
// 初期情報の保存
jien_mc.orgX = jien_mc._x;
jien_mc.orgY = jien_mc._y;
jien_mc.orgW = jien_mc._width;
jien_mc.orgH = jien_mc._height;
jien_mc.orgR = jien_mc._rotation;

// 再生フレーム数
var max:Number = 30 * 10;

// ムービークリップの初期化
function initMC() {
jien_mc.filters = [];
jien_mc._x = jien_mc.orgX;
jien_mc._y = jien_mc.orgY;
jien_mc._width = jien_mc.orgW;
jien_mc._height = jien_mc.orgH;
jien_mc._rotation = jien_mc.orgR;
}

// 位置ボタン
move_btn.onRelease = function () {
initMC();
// 定数
k = Number(k_txt.text);
a = Number(a_txt.text);
// 移動初期位置
jien_mc._x = 0;
// かかっている力
jien_mc.xp = 0;
var cnt:Number = 0;
// フレーム毎に位置を変化
jien_mc.onEnterFrame = function () {
// カウンタが再生フレーム数に達したら終了
if (cnt++ > max) {
this._x = this.orgX;
delete this.onEnterFrame;
return;
}
// ばねの伸び
var lx:Number = this.orgX - this._x;
// かかっている力
this.xp = this.xp * a + lx * k;
// 移動
this._x += this.xp;
}
}

// 大きさボタン
size_btn.onRelease = function () {
initMC();
// 定数
k = Number(k_txt.text);
a = Number(a_txt.text);
// 初期サイズ
jien_mc._width /= 10;
jien_mc._height /= 10;
// かかっている力
jien_mc.xp = 0;
jien_mc.yp = 0;

var cnt:Number = 0;
// フレーム毎にサイズを変化
jien_mc.onEnterFrame = function () {
// カウンタが再生フレーム数に達したら終了
if (cnt++ > max) {
delete this.onEnterFrame;
return;
}
// ばねの伸び
var lx:Number = this.orgW - this._width;
var ly:Number = this.orgH - this._height;
// かかっている力
this.xp = this.xp * a + lx * k;
this.yp = this.yp * a + ly * k;
// サイズ変更
this._width += this.xp;
this._height += this.yp;
}
}

// 角度ボタン
rotation_btn.onRelease = function () {
initMC();
// 定数
k = Number(k_txt.text);
a = Number(a_txt.text);
// 初期角度
jien_mc.r = -360;
// かかっている力
jien_mc.rp = 0;

var cnt:Number = 0;
// フレーム毎に角度を変化
jien_mc.onEnterFrame = function () {
// カウンタが再生フレーム数に達したら終了
if (cnt++ > max) {
delete this.onEnterFrame;
return;
}
// ばねの伸び
var lr:Number = this.orgR - this.r;
// かかっている力
this.rp = this.rp * a + lr * k;
// 角度変更
this.r += this.rp;
this._rotation = this.r;
}
}

// ブラーボタン
blur_btn.onRelease = function () {
initMC();
// 定数
k = Number(k_txt.text);
a = Number(a_txt.text);
// 初期ブラー
jien_mc.b = 64;
// かかっている力
jien_mc.bp = 0;
var cnt:Number = 0;
// フレーム毎にアルファを変化
jien_mc.onEnterFrame = function () {
// カウンタが再生フレーム数に達したら終了
if (cnt++ > max) {
delete this.onEnterFrame;
return;
}
// ばねの伸び
var lb:Number = 0 - this.b;
// かかっている力
this.bp = this.bp * a + lb * k;
// ブラー変更
var absB:Number = Math.abs(this.b);
var filter:BlurFilter = new BlurFilter(absB, absB, 1);
this.filters = [filter];
this.b += this.bp;
}
}
jien_mcは、イージング対象のムービークリップです。
ムービークリップのonEnterFrameイベントハンドラで、変化量の算出とムービークリップのプロパティの変更をしています。

テーマ:Flash - ジャンル:コンピュータ

2007.03.17 | | Comments(0) | Trackback(0) | Flash/ActionScript

2つのフラッシュを連携させる

LocalConnectionを使って2つのフラッシュが連携するようにしてみました。




↑のボタンを押すと新しいウィンドウが開いて、フラッシュが表示されマス。すでにウィンドウが開いている場合はそのウィンドウで表示されマス。

どんなカンジで連携してるかというと、
1.ボタンを押すと、どのボタンが押されたかを示す文字列をパラメータとしてメニュー側から表示側へ送信します。
2.表示側は、受け取ったパラメータに応じた表示を行いマス。
3.1.で送信に失敗した場合は表示ウィンドウを開きマス。
4.表示側は再生開始時にメニュー側に準備ができたことを通知します。
5.メニュー側は、表示側の準備が完了したことを受信したときに再送信すべきパラメータがあったら送信します。
なカンジです。

それぞれでのクライアント(送信側)サーバー(受信側)がどうなってるかで書くと
1.メニュー側がクライアントとして動作
2.表示側がサーバーとして動作
4.表示側がクライアントとして動作
5.メニュー側がサーバーとして動作
というカンジで、1.2.と4.5.はそれぞれベツのローカルコネクション名で通信しています。

メニュー側のスクリプトは、

// 最新送信内容
var latestParam:String = null;
// 受信コネクション
var receiver:LocalConnection = new LocalConnection();
receiver.ready = function(param:String) {
// latestParamに値がセットされていたら再送する
if (latestParam != null) {
connect(latestParam);
latestParam = null;
}
}
receiver.connect("lc_menu");

// 送信コネクション
var sender:LocalConnection = new LocalConnection();
sender.onStatus = function(info:Object) {
switch (info.level) {
case 'status':
// 成功したので、パラメータをとっておく必要はない
latestParam = null;
break;
case 'error':
// ウィンドウを開く
_root.getURL("http://blog-imgs-11.fc2.com/1/0/0/100th/display.html",
"_blank");
break;
}
}

// Noneボタン
none_btn.onRelease = function() {
connect("none");
}
// Regularボタン
regular_btn.onRelease = function() {
connect("regular");
}
// Strongボタン
strong_btn.onRelease = function() {
connect("strong");
}
// Elasticボタン
elastic_btn.onRelease = function() {
connect("elastic");
}
// Bounceボタン
bounce_btn.onRelease = function() {
connect("bounce");
}
// Backボタン
back_btn.onRelease = function() {
connect("back");
}

// paramを送信します。
function connect(param:String) {
latestParam = param;
sender.send("lc_display", "disp", param);
}
といったカンジで、表示側のスクリプトは、
import mx.transitions.Tween;

// パラメータ
var paramMap = {none:mx.transitions.easing.None.easeOut,
regular:mx.transitions.easing.Regular.easeOut,
strong:mx.transitions.easing.Strong.easeOut,
elastic:mx.transitions.easing.Elastic.easeOut,
bounce:mx.transitions.easing.Bounce.easeOut,
back:mx.transitions.easing.Back.easeOut};

// テンプレートムービークリップを非表示
jien_mc._visible = false;

// 受信処理
var receiver:LocalConnection = new LocalConnection();
receiver.disp = function(param:String) {
var mc:MovieClip = createMovieClip();
var tween:Tween = new Tween(mc,
"_x",
paramMap[param],
50,
400,
2,
true);
tween.onMotionFinished = function() {
mc.removeMovieClip();
}
}
receiver.connect("lc_display");

// 新しいムービークリップを作成し、戻します。
function createMovieClip():MovieClip {
var depth:Number = getNextHighestDepth();
var mc:MovieClip = jien_mc.duplicateMovieClip("jien_" + depth,
depth);
return mc;
}

// 受信が可能であることを送信する
var sender:LocalConnection = new LocalConnection();
sender.send("lc_menu", "ready", "test");
という風になっています。
jien_mcというのは表示の元ネタになるムービークリップで、コレをduplicateMovieClipしたものをそれぞれのアクションで使ってマス。
paramMapは、パラメータ文字列とTweenに渡すメソッドのマップです。

1.2.に対応するのが、lc_displayという名前のコネクションで表示側が待ちうけてます。
4.5.に対応するのが、lc_menuという名前のコネクションでメニュー側が待ちうけデス。

テーマ:Flash - ジャンル:コンピュータ

2007.03.15 | | Comments(0) | Trackback(0) | Flash/ActionScript

アフィン変換

ワリとよく見かけるサンプルですが、オレもオレもというワケでやってみました。
affine




DisplacementMapFilterを使った場合はムービークリップの形状は変わらず中身が変形されてましたが、MovieClip.transform.matrixを使うとムービークリップ自体が変形されマス。

ムービークリップmcの幅をw、高さをhとして、コレを左上の座標が(x0, y0)、右上の座標が(x1, y1)、左下の座標が(x2, y2)となるよーな変換は、

  mc.transform.matrix = new Matrix(
(x1 - x0) / w, (y1 - y0) / w,
(x2 - x0) / h, (y2 - y0) / h,
x0, y0);
ってカンジです。

ソースコードは以下なカンジです。
import flash.geom.Matrix;

// 初期サイズ
var w:Number = image_mc._width;
var h:Number = image_mc._height;

// ドラッグしているムービークリップ
var dragging:MovieClip = null;

// ボタンイベントをバインドする
topLeft_btn.onPress = doPress;
topLeft_btn.onRelease = doRelease;
topLeft_btn.onReleaseOutside = doRelease;
topRight_btn.onPress = doPress;
topRight_btn.onRelease = doRelease;
topRight_btn.onReleaseOutside = doRelease;
bottomLeft_btn.onPress = doPress;
bottomLeft_btn.onRelease = doRelease;
bottomLeft_btn.onReleaseOutside = doRelease;

function onEnterFrame() {
// マウスドラッグしてなければなにもしない。
if (dragging == null ){
return;
}
dragging._x = _xmouse;
dragging._y = _ymouse;
// 変換行列
var mtx:Matrix
= new Matrix((topRight_btn._x - topLeft_btn._x) / w,
(topRight_btn._y - topLeft_btn._y) / w,
(bottomLeft_btn._x - topLeft_btn._x) / h,
(bottomLeft_btn._y - topLeft_btn._y) / h,
topLeft_btn._x,
topLeft_btn._y);
// 変換
image_mc.transform.matrix = mtx;
}

function doPress() {
dragging = this;
}

function doRelease() {
dragging = null;
}

image_mcは変形対象のムービークリップ、topLeft_btn、topRight_btn、bottomLeft_btnはドラッグできるポイントを示すムービークリップです。
2007/7/19このエントリのサンプルコードはFlash8用に書かれたモノです。Flash CS3で同様のことをするサンプルはFlash CS3でアフィン変換エントリです。

テーマ:Flash - ジャンル:コンピュータ

2007.03.13 | | Comments(0) | Trackback(0) | Flash/ActionScript

DisplacementMapFilterで遠近法っぽい変換

前回のDisplacementMapFilterを使った拡大/縮小を改造して、遠近法っぽく画像を変換するようにしてみました。
遠近法っぽくとはいっても透視変換等の3次元の処理はまったくしておらず、各ピクセルのy座標値によって拡大率を変化させてそれっぽくしてるだけデス。




前回は横方向/縦方向の拡大率を入力してマップ画像を生成してましたが、今回は各ピクセルのy座標値に対しての拡大量入力するようにしました。
例によって左側が変換後の画像、右側が変換に使用しているマップ画像デス。
各ピクセルでの拡大率ですが、y軸方向の場合ならy座標値をy、基準点のy座標値をoY(サンプルでは0です)、入力値をsYとしたときの各ピクセルの拡大率を

  (y - oY)sY + 1
として算出しています。
x軸方向も同じようなカンジです。
ソースコードは以下のようなカンジですが、前回のとほとんど同じデス。
import flash.display.BitmapData;
import flash.filters.DisplacementMapFilter;
// 位置、サイズ
var l:Number = test_mc._x;
var t:Number = test_mc._y;
var w:Number = test_mc._width;
var h:Number = test_mc._height;

// 原点
var oX:Number = w / 2;
var oY:Number = 0;

// マスク画像オフセット
var maskOffsetX:Number = w + 10;
var maskOffsetY:Number = 0;

// 表示ボタン
test_btn.onRelease = doTrans;

// マスク画像
var mask_mc:MovieClip;

// スケール調整値
var yAdj:Number = 1;
var xAdj:Number = 1;

// 初期表示
doTrans();

function doTrans() {
// 倍率
var sX:Number = Number(sx_txt.text);
var sY:Number = Number(sy_txt.text);

if (mask_mc) {
mask_mc.removeMovieClip();
}
// マスク画像
var mask:BitmapData = createMask(sX, sY, oX, oY);

// マスク画像表示
var depth:Number = _root.getNextHighestDepth();
mask_mc = _root.createEmptyMovieClip("mask_" + depth, depth);
mask_mc.attachBitmap(mask, 1);
mask_mc._x = l + maskOffsetX;
mask_mc._y = t + maskOffsetY;

// フィルタ設定
var filter:DisplacementMapFilter
= new DisplacementMapFilter(mask,
new Point(),
4,
2,
Math.ceil(256 / xAdj),
Math.ceil(256 / yAdj));
test_mc.filters = [filter];
}


// マスク画像を作成し、戻す。
function createMask(sX:Number, sY:Number, oX:Number, oY:Number)
:BitmapData {
// 差が128以内に収まるように調整値を設定する
var maxY:Number = 0;
var maxX:Number = 0;
for (var y:Number = 0; y < h; y++) {
maxY = Math.max(maxY,
Math.abs(getYC(y, (y - oY) * sY + 1, oY)));
for (var x:Number = 0; x < w; x++) {
maxX = Math.max(maxX,
Math.abs(getXC(x, (y - oY) * sX + 1, oX)));
}
}
yAdj = 128 / (maxY + 1);
xAdj = 128 / (maxX + 1);
// ビットマップ生成
var bitmap:BitmapData = new BitmapData(w, h);
for (var y:Number = 0; y < h; y++) {
// yに対する色の明るさを求める
var yC = Math.floor(getYC(y,
(y - oY) * sY + 1,
oY) * yAdj);
for (var x:Number = 0; x < w; x++) {
// xに対する色の明るさを求める
var xC = Math.floor(getXC(x,
(y - oY) * sX + 1,
oX) * xAdj);
// このピクセルの色を算出
var c:Number = 0xFF000000 +
(0x80 + yC) * 0x100 +
xC + 0x80;
// ピクセルを描画する
bitmap.setPixel(x, y, c);
}
}
return bitmap;
}

// 指定したy座標で用いる色の明るさ(0x80との差)を戻します。
function getYC(y:Number, sY:Number, oY:Number):Number {
return -Math.round((y - oY) * (sY - 1) / sY);
}

// 指定したx座標で用いる色の明るさ(0x80との差)を戻します。
function getXC(x:Number, sX:Number, oX:Number):Number {
return -Math.round((x - oX) * (sX - 1) / sX);
}

2007/7/1このエントリのソースコードはFlash8でのものデス。Flash CS3でこんなようなコトをしてるのはDisplacementMapFilterでパースをつけてみるエントリです。

テーマ:Flash - ジャンル:コンピュータ

2007.03.12 | | Comments(0) | Trackback(1) | Flash/ActionScript

DisplacementMapFilterを使った画像の拡大/縮小

DisplacementMapFilterを使って、画像を拡大/縮小するサンプルを作ってみました。
横と縦のテキスト入力欄に数値を入力して表示ボタンを押すと、ムービークリップの中心を基準に、入力した数値で画像を拡大/縮小します。
左側が拡大/縮小後の画像、右側がそのために使用したマップ画像です。




ムービークリップの拡大/縮小は、もっとラクなやり方がイロイロあるしそっちのほーがキレイにできるのでこの方法を使う必要はないのですが、DisplacementMapFilterについてもうちょっと詳しく知りたいと思ったのでこのようなサンプルを作ってみました。

どういう風にマップ画像を生成してるかってーと、DisplacementMapFilterはマップ画像の各ピクセルでそのピクセルと表示したい元の画像のピクセルの位置の差を色として設定することで画像を変形させる。ということなので、各表示ピクセルの位置と元画像のピクセルの位置の差を求める方法を考えマス。

このサンプルの場合だと指定した値だけ拡大したいので、たとえばy軸方向について考えると、基準点のy座標をoY、表示したいピクセルのy座標をy、元の画像のピクセルのy座標をy0、y軸方向の拡大率をsYとすると、

  y - oY = sY(y0 - oY)

なハズなので、y - y0をy0なしで表記すると
  y - y0 = (y - oY)(sY - 1) / sY

で、この分だけピクセルの色を変化させりゃーいいハズ。たぶん。
↓のgetYCという関数がソレにあたります。
import flash.display.BitmapData;
import flash.filters.DisplacementMapFilter;
// 位置、サイズ
var l:Number = test_mc._x;
var t:Number = test_mc._y;
var w:Number = test_mc._width;
var h:Number = test_mc._height;

// 原点
var oX:Number = w / 2;
var oY:Number = h / 2;

// マスク画像オフセット
var maskOffsetX:Number = w + 10;
var maskOffsetY:Number = 0;

// 表示ボタン
test_btn.onRelease = doTrans;

// マスク画像
var mask_mc:MovieClip;

// スケール調整値
var yAdj:Number = 1;
var xAdj:Number = 1;

// 初期表示
doTrans();

function doTrans() {
// 倍率
var sX:Number = Number(sx_txt.text);
var sY:Number = Number(sy_txt.text);

if (mask_mc) {
mask_mc.removeMovieClip();
}
// マスク画像
var mask:BitmapData = createMask(sX, sY, oX, oY);

// マスク画像表示
var depth:Number = _root.getNextHighestDepth();
mask_mc = _root.createEmptyMovieClip("mask_" + depth, depth);
mask_mc.attachBitmap(mask, 1);
mask_mc._x = l + maskOffsetX;
mask_mc._y = t + maskOffsetY;

// フィルタ設定
var filter:DisplacementMapFilter
= new DisplacementMapFilter(mask,
new Point(),
4,
2,
Math.ceil(256 / xAdj),
Math.ceil(256 / yAdj));
test_mc.filters = [filter];
}


// マスク画像を作成し、戻す。
function createMask(sX:Number, sY:Number, oX:Number, oY:Number)
:BitmapData {
// y方向の差が128以内に収まるように調整値を設定する
var max:Number = Math.max(Math.abs(getYC(0, sY, oY)),
Math.abs(getYC(h - 1, sY, oY)));
yAdj = 128 / (max + 1);
// x方向の差が128以内に収まるように調整値を設定する
max = Math.max(Math.abs(getXC(0, sX, oX)),
Math.abs(getXC(w - 1, sX, oX)));
xAdj = 128 / (max + 1);
// ビットマップ生成
var bitmap:BitmapData = new BitmapData(w, h);
for (var y:Number = 0; y < h; y++) {
// yに対する色の明るさを求める
var yC = Math.floor(getYC(y, sY, oY) * yAdj);
for (var x:Number = 0; x < w; x++) {
// xに対する色の明るさを求める
var xC = Math.floor(getXC(x, sX, oX) * xAdj);
// このピクセルの色を算出
var c:Number = 0xFF000000 +
(0x80 + yC) * 0x100 +
xC + 0x80;
// ピクセルを描画する
bitmap.setPixel(x, y, c);
}
}
return bitmap;
}

// 指定したy座標で用いる色の明るさ(0x80との差)を戻します。
function getYC(y:Number, sY:Number, oY:Number):Number {
return -Math.round((y - oY) * (sY - 1) / sY);
}

// 指定したx座標で用いる色の明るさ(0x80との差)を戻します。
function getXC(x:Number, sX:Number, oX:Number):Number {
return -Math.round((x - oX) * (sX - 1) / sX);
}

x軸方向に関してもだいたい同じよーにやってマス。

上記ソースコード中の、差が128以内に収まるように調整値を設定する。というのはどういうことかというと、ピクセルの色と0x80の差で元ピクセルの位置を指定するため、場合によっては0x00~0xFFの範囲を超えちゃうかも知れないので、その場合は色で示す変化量を範囲内に収めて、フィルターで指定するスケールで調整してマス。

テーマ:Flash - ジャンル:コンピュータ

2007.03.11 | | Comments(0) | Trackback(0) | Flash/ActionScript

DisplacementMapFilterを使った水面ぽい画像表示

DisplacementMapFilterにパーリンノイズ画像を設定するよくあるサンプルです。

速度と変化量を設定して表示ボタンを押すと、左側にフィルタを適用した画像、右側にフィルタに使用している画像が表示されます。






やってることは、まずパーリンノイズのオクターブ毎に変化スピードを決めといて、フレーム毎にオフセットをそのぶん変化させてパーリンノイズ画像を作って、DisplacementMapFilterにセットするというカンジです。
以下が上記サンプルのActionScriptのソースです。
image_mcというのがフィルタを適用する元画像(ムービークリップ)です。


import flash.display.BitmapData;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.filters.DisplacementMapFilter;

// ノイズ関数の数
var octaveCnt:Number = 3;
// 乱数シード
var rndSeed:Number = Math.floor(Math.random() * 65535);
// マスク画像オフセット
var maskOffsetX:Number = image_mc._width + 10;
var maskOffsetY:Number = 0;
// パーリンノイズのオフセット値の配列
var offsetArray:Array = new Array();
// パーリンノイズの変化量の配列
var speedArray:Array = new Array();

// 変化スピード
var speed:Number;
// ゆがみの拡大率
var scale:Number;

// フィルター画像表示用ムービークリップ
var map_mc:MovieClip;
// パーリンノイズ画像
var perlinNoiseBitmap:BitmapData = new BitmapData(image_mc._width, image_mc._height);

// 表示ボタン
test_btn.onRelease = doInit;

// 初期表示
doInit();

// 表示の初期化をします。
function doInit() {
// 速度と変化量の設定
speed = Number(speed_txt.text);
scale = Number(var_txt.text);

// マップ用ムービークリップの設定
if (map_mc) {
map_mc.removeMovieClip();
}
map_mc = _root.createEmptyMovieClip("map_mc", _root.getNextHighestDepth());
map_mc._x = image_mc._x + maskOffsetX;
map_mc._y = image_mc._y + maskOffsetY;

// 変化方向の初期化
initOffsetArray();
}

// オフセット配列を変化速度配列の初期化
function initOffsetArray() {
// 関数の数だけ必要
for (var i:Number = 0; i < octaveCnt; i++) {
offsetArray[i] = new Point(0, 0);
// 乱数で変化する向きを決定
speedArray[i] = new Point(speed * (Math.floor(Math.random() * 2) == 0 ? -1 : 1),
speed * (Math.floor(Math.random() * 2) == 0 ? -1 : 1));
}
}

function onEnterFrame() {
// オフセット位置の変更
for (var i:Number = 0; i < octaveCnt; i++) {
offsetArray[i].x += speedArray[i].x;
offsetArray[i].y += speedArray[i].y;
}
// パーリンノイズ画像生成
perlinNoiseBitmap.perlinNoise(image_mc._width,
image_mc._height,
octaveCnt,
rndSeed,
false,
true,
1,
false,
offsetArray);
// 歪みフィルターを作成
var filter:DisplacementMapFilter
= new DisplacementMapFilter(perlinNoiseBitmap,
new Point(0, 0),
1,
1,
scale,
scale);
image_mc.filters = [filter];
// パーリンノイズ表示用ムービークリップに画像をセットアップ
map_mc.attachBitmap(perlinNoiseBitmap, 1);
}


2007/6/24このエントリのソースコードはFlash8でのものです。
Flash CS3で似たような処理をするものをFlash CS3で水面ぽい画像表示にエントリしました。

テーマ:Flash - ジャンル:コンピュータ

2007.03.10 | | Comments(5) | Trackback(0) | Flash/ActionScript

«  | HOME |  »

プロフィール

HundredthMonkey

Author:HundredthMonkey
プログラマ。

ブロとも申請フォーム

この人とブロともになる

メールフォーム

名前:
メール:
件名:
本文:

ブログ内検索


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。