スポンサーサイト

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

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

針金をはじいたような動き

壁にささった針金を指ではじいたような。というかそんなカンジのサンプルです。円の部分をマウスでつまんでテキトーに動かしてボタンを離すと、バネっぽく振動します。





やってることは、バネの動きをする円スプライトとステージ左端から円の中心までの曲線を描画してるだけデス。円スプライトは、画面左端の線の根元を中心とする円周を動きマス。バネっぽい動きの計算は、初期位置を0度としての角度に対してやってマス。

円スプライトの最初のx位置は、ステージ幅の2/3の位置(=半径)デス。曲線のほーは、ステージ左端を始点、ステージ幅の1/3の位置をコントールポイント、円スプライトの中心を終点としてGraphics#curveToで描画しています。

今回のサンプルでは、円と曲線の2つのスプライトをActionScriptで作成/操作しています。
円のほーは、Spriteを継承したBallクラスを定義して使ってマス。

package {
import flash.display.Sprite;
import flash.display.Graphics;
/**
* 塗りつぶした円のスプライト。
*/
public class Ball extends Sprite {
/**
* コンストラクタ。
* @param radius 半径
* @param color 色
* @param alpha 透過度
*/
public function Ball(radius:Number = 10,
color:uint = 0x000000,
alpha:Number = 1.0) {
var g:Graphics = this.graphics;
g.beginFill(color, alpha);
g.drawCircle(0, 0, radius);
g.endFill();
}
}
}
コイツは単に半径や色を指定してnewすると指定した通りの円が描画されるだけで、あとはSpriteと同等なクラスです。

曲線用のスプライトは、フレームアクションに記述してます。フレームアクションはこんなカンジです。
// ボールの色
var ballColor:Number = 0x9999FF;
// ボールの大きさ
var ballSize:Number = 10;
// 線の色
var lineColor:Number = 0x3333FF;
// ボールの初期x座標
var ballX:Number = stage.stageWidth * 2 / 3;
// ボールの初期y座標
var ballY:Number = stage.stageHeight / 2;
// コントロールポイントのx座標
var controlX:Number = stage.stageWidth / 3;
// ばね定数
var k:Number = 0.9;
// 減衰係数
var a:Number = 0.8;
// 最大角度
var range:Number = 30 * Math.PI / 180;

// フィルタ
var filterArray:Array = [new DropShadowFilter()];

// 線描画領域
var canvas:Sprite = new Sprite();
canvas.filters = filterArray;
addChild(canvas);

// ボールを配置
var ball:Ball = new Ball(ballSize, ballColor);
ball.filters = filterArray;
ball.x = ballX;
ball.y = ballY;
addChild(ball);

// かかっている力
var p:Number = 0;
// ボールの角度
var r:Number = 0;

// ボールをつかめるようにする
ball.addEventListener(MouseEvent.MOUSE_DOWN,
function (e:Event):void {
// つかめるようにするためボール移動イベントリスナを登録
stage.addEventListener(MouseEvent.MOUSE_MOVE, onBallMouseMove);
// 振動させるためボールフレームイベントリスナを解除
stage.removeEventListener(Event.ENTER_FRAME, onBallEnterFrame);
});
stage.addEventListener(MouseEvent.MOUSE_UP,
function (e:Event):void {
// ボール移動イベントリスナを解除
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onBallMouseMove);
// フレームイベントリスナを登録
stage.addEventListener(Event.ENTER_FRAME, onBallEnterFrame);
});
// ボールのマウス移動イベントハンドラ
function onBallMouseMove(e:Event):void {
// マウスのy座標から角度を求めてボールのx,y座標を決定
r = Math.asin((mouseY - ballY) / ballX);
if (r < -range) {
r = -range;
} else if (r > range) {
r = range;
}
}

// ボールのフレームイベントハンドラ
function onBallEnterFrame(e:Event):void {
// かかっている力
p = p * a - r * k;
r += p;
if (r < -range) {
r = -range;
} else if (r > range) {
r = range;
}
}

// フレームイベントハンドラ
addEventListener(Event.ENTER_FRAME,
function (e:Event):void {
ball.x = ballX * Math.cos(r);
ball.y = ballX * Math.sin(r) + ballY;
var g:Graphics = canvas.graphics;
g.clear();
g.lineStyle(1, lineColor);
g.moveTo(0, ballY);
g.curveTo(controlX, ballY, ball.x, ball.y);
});
まずボールのほーですが、ballというのがBallクラスのインスタンスです。ballをつまんで動かせるようにするために(あと離したときに振動するように)、ballにMouseEvent.MOUSE_DOWNイベントリスナを、stageにMouseEvent.MOUSE_UPイベントリスナを登録してます。

ボールをつまんで動かしてる間は、ボールの位置はマウスカーソルの位置になります。そんで、ボタンを離すと振動します。コレをするために2種類のイベントリスナをボタンを押したときと離したときに切り替えています。

ボタンを押したときに有効にしてるイベントリスナは、MouseEvent.MOUSE_MOVEデス。イベントハンドラのonBallMouseMoveメソッドでは、マウスカーソルのy座標を元に角度を計算してballのx,y座標を求めています。また、角度が指定した範囲に収まるように調整してます(このサンプルでは-30度~30度です)。

ボタンを離したときに有効になるイベントリスナはEvent.ENTER_FRAMEデス。イベントハンドラのonBallEnterFrameメソッドでは角度rがバネっぽい変化をするように計算しています。一応、ここでも角度が指定した範囲に収まるようにしています。

曲線の方はというと、canvasが曲線を描画する領域となるSpriteデス。Event.ENTER_FRAMEイベントハンドラで、canvasをクリアして、ステージ左端からballの中心までの曲線を描画しています。

スポンサーサイト

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

2007.12.12 | | Comments(0) | Trackback(0) | Flash CS3

スプレーで描く

スプレーを吹き付けて描画するようなカンジのサンプルです。マウスボタンを押してる間だけスプレーします。スプレーの色はそのたびに変わります。





画像はあらかじめ置いてあります。ActionScriptでは、透明なBitmapDataを用意してそこにsetPixel32メソッドを使って色をつけています。不透明なキャンバスにスプレーするならsetPixelでもイイと思いマス。

フレームアクションのソースはこんなカンジです。

// 飛沫の飛ぶ範囲係数
var size:Number = 5;
// 一回で飛ばす飛沫の数
var sprayCnt:Number = 60;
// 描画領域
var canvas:BitmapData = new BitmapData(stage.stageWidth,
stage.stageHeight,
true,
0x00000000);
var bmp:Bitmap = new Bitmap(canvas);
addChild(bmp);
// 色
var color:uint;
// 乱数ジェネレータ
var rndGene:GaussianRandom = new GaussianRandom();
// マウスボタンを押したときのイベントハンドラ
stage.addEventListener(MouseEvent.MOUSE_DOWN,
function (e:Event) {
// スプレーの色を決定
color = Math.random() * 0x1000000 + 0xFF000000;
// フレームイベントリスナを登録
addEventListener(Event.ENTER_FRAME, doEnterFrame);
});
// マウスボタンを離したときのイベントハンドラ
stage.addEventListener(MouseEvent.MOUSE_UP,
function (e:Event) {
// フレームイベントリスナを解除
removeEventListener(Event.ENTER_FRAME, doEnterFrame);
});
// フレームイベントハンドラ
function doEnterFrame(e:Event):void {
// 描画領域をロック
canvas.lock();
// 決められた数だけ飛沫を描画
for (var i:int = 0; i < sprayCnt; i++) {
// 角度
var angle:Number = Math.random() * Math.PI * 2;
// 中心からの距離
var radius:Number = rndGene.random() * size;
// 描画
canvas.setPixel32(mouseX + Math.cos(angle) * radius,
mouseY + Math.sin(angle) * radius,
color);
}
// 描画領域のロックを解除
canvas.unlock();
}
canvasというBitmapDataがスプレーの描画領域デス。Bitmapオブジェクトにセットして、Bitmapオブジェクトをステージに入れてマス。

MouseEvent.MOUSE_DOWNでスプレーの色を乱数で決めてマス。0xFF000000を足してるのは不透明にするためデス。また、フレームイベントリスナとしてdoEnterFrameを登録しています。

MouseEvent.MOUSE_UPでは、MOUSE_DOWNで登録したイベントハンドラを外してマス。これでマウスボタンを押してる間だけdoEnterFrameが実行されます。

doEnterFrameでは、sprayCntで指定した数のピクセルを塗っています(同一座標に重なることがあるので、実際に色がつくピクセルはそれより少なくなることもあります)。角度とマウスカーソルの座標からの距離を乱数で求めて、その位置をMOUSE_DOWN時に求めた色で塗っています。

角度はMath#random()で求めているのですが、距離のほうはMath#random()ではイマイチだったので、別の乱数ジェネレータ(GaussianRandom)を作ってソイツから得た乱数を使っています(でも大差なかったカモ)。

距離を求めるのに使ってるGaussianRandomクラスのコードはこんなカンジです。
package {
/**
* 正規分布乱数ジェネレータ。
*/
public class GaussianRandom {
/** 次の値があるか? */
private var hasNext:Boolean = false;
/** 次の値 */
private var next:Number = 0;
/**
* 正規分布乱数を生成し、戻します。
* @return 生成した乱数
*/
public function random():Number {
if (hasNext) {
hasNext = false;
return next;
} else {
do {
var v1:Number = Math.random() * 2 - 1;
var v2:Number = Math.random() * 2 - 1;
var s:Number = v1 * v1 + v2 * v2;
} while (s >= 1 || s == 0);
var m:Number = Math.sqrt(-2 * Math.log(s) / s);
hasNext = true;
next = v2 * m;
return v1 * m;
}

}
}
}
polar methodというアルゴリズムを使って正規分布乱数を生成しています(のつもりデス)。このアルゴリズムでは一度に二つの乱数が得られるので、一回生成したら片方はとっておいて次にrandomメソッドが呼ばれたときにソレを戻すようにしています。

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

2007.12.03 | | Comments(0) | Trackback(0) | Flash CS3

«  | HOME |  »

プロフィール

HundredthMonkey

Author:HundredthMonkey
プログラマ。

ブロとも申請フォーム

この人とブロともになる

メールフォーム

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

ブログ内検索


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