スポンサーサイト

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

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

パースのついた回転

y軸を中心に画像がグルグル回転するサンプルです。





マウスカーソルの位置によって、回転の向き/速度が変わります。

基本的な考え方は、画像をスライスして変形させる円筒っぽい画像表示エントリと同様に、画像を細かく刻んでソレゾレを移動/変形するモノです。

今回のサンプルでは、2枚の画像を幅1ピクセルで切り刻んでソイツラに3次元座標をもたせて透視変換して表示というカンジです。

スクリプトは、切り刻んだ画像を保持するSpriteの継承クラスを用意して、フレームアクションでそのクラスのインスタンスを生成という格好にしました。

スクリプトのソースは、こんなカンジです。

package {
import flash.display.*;
import flash.geom.*;
/**
* 表示オブジェクトを水平回転するためのクラス。
*/
public class HorizontalRotater extends Sprite {
/** スクリーンまでの距離 */
private var _distance:Number;
/** 元になる表示オブジェクト */
private var _src:DisplayObject;
/** スライスした画像 */
private var _slice_array:Array;
/**
* コンストラクタ。
* @param src 元になる表示オブジェクト
* @param distance スクリーンまでの距離
*/
public function HorizontalRotater(src:DisplayObject,
distance:Number) {
this._src = src;
this._distance = distance;
_slice_array = createSliceArray();
rotate(0);
this.x = src.x + src.width / 2;
this.y = src.y + src.height / 2;
}
/**
* スライス画像を生成し、戻します。
*/
private function createSliceArray():Array {
var ary:Array = new Array();
// z座標
var oz:Number = _src.width / 2;
// 縮小率
var s:Number = _distance / (_distance + oz);
// 縮小前のサイズ
var sw:Number = _src.width / s;
var sh:Number = _src.height / s;
// 切り出し用マトリックス
var mtx:Matrix = new Matrix();
mtx.scale(1 / s, 1 / s);
var ct:ColorTransform = new ColorTransform();
var rect:Rectangle = new Rectangle(0, 0, 1, sh);
// 幅1ピクセルにスライスする
for (var i:int = 0; i < sw; i++) {
// BitmapData切り出し
var bd:BitmapData = new BitmapData(1, _src.height / s);
mtx.tx = -i;
bd.draw(_src, mtx, ct, BlendMode.NORMAL, rect, false);
// ビットマップを生成し、配列に保存
var bitmap:Bitmap = new Bitmap(bd);
bitmap.x = i - sw / 2;
bitmap.y = - bitmap.height / 2;
bitmap.visible = _src.visible;
addChild(bitmap);
ary.push({bitmap:bitmap,
orgx:bitmap.x,
orgy:bitmap.y,
orgheight:bitmap.height,
oz:oz});
}
return ary;
}
/**
* 指定した角度に画像を回転します。
* @param angle 角度
*/
public function rotate(angle):void {
var cos:Number = Math.cos(angle * Math.PI / 180);
var sin:Number = Math.sin(angle * Math.PI / 180);
var d:Number = _distance;
for each (var item:Object in _slice_array) {
var bitmap:Bitmap = item.bitmap;
var orgx:Number = item.orgx;
var orgy:Number = item.orgy;
// 角度から、x座標/z座標を求める
var x:Number = orgx * cos;
var z:Number = item.oz - orgx * sin;
// 縮小率
var s:Number = d / (d + z);
// 位置/高さを設定
bitmap.x = Math.round(x * s);
bitmap.height = item.orgheight * s;
bitmap.y = Math.round(orgy * s);
}
}
}
}
ファイル名はHorizontalRotater.asになります。回転させたい画像と仮想スクリーンまでの距離を指定してインスタンスを生成して、角度を指定してrotateメソッドを実行すると、指定した角度で画像が表示されマス。

createSliceArrayは画像を幅1ピクセルずつ切り出すメソッドで、コンストラクタから実行します。初期のz座標もここで指定してるのですが、その値は0ではなく画像の幅の半分です。これは画像を回転させてもz座標がマイナスにならないようにするためデス。

z座標が0ではないので、そのまま透視変換して表示すると表示サイズが元のものより小さくなってしまいます。元と同じ大きさで表示するために画像切り出し時にMatrix#scaleを使って拡大して切り出しています。

rotateメソッドは角度をつけて表示するためのメソッドで、まず指定された角度からx座標とz座標を算出します(回転してもy座標はかわらない)。その後ソレゾレのz座標の値を元に透視変換後の位置/高さを設定しています。

で、フレームアクションからこのクラスを使っています。
var front:HorizontalRotater
= new HorizontalRotater(obj_mc, 350);
addChild(front);
obj_mc.visible = false;
var back:HorizontalRotater
= new HorizontalRotater(onion_mc, 350);
addChild(back);
onion_mc.visible = false;
back.visible = false;
var ox:Number = front.x;
var rate:Number = 0.05;
var angle:Number = 0;
addEventListener(Event.ENTER_FRAME,
function(e:Event) {
if (angle < 0) {
angle += 360;
}
angle = (angle + (stage.mouseX - ox) * rate)
% 360;
if (angle > 90 && angle <= 270) {
front.visible = false;
back.visible = true;
back.rotate((angle + 180) % 360);
} else {
front.visible = true;
back.visible = false;
front.rotate(angle);
}
});
obj_mc/onion_mcは画像をムービークリップシンボル化したものデス。それぞれのHorizontalRotaterインスタンスを生成して、それをaddChildしています。

ENTER_FRAMEイベントで、マウスカーソルの位置から角度を変化させてrotateメソッドを実行しています。角度によってどちらのHorizontalRotaterインスタンスを表示するかを切り替えています。
スポンサーサイト

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

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

コメント

コメントの投稿


秘密にする

«  | HOME |  »

プロフィール

HundredthMonkey

Author:HundredthMonkey
プログラマ。

ブロとも申請フォーム

この人とブロともになる

メールフォーム

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

ブログ内検索


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