Virtual Aquarium with MotionTrack
せっかくカメラ使ってるのでモーショントラッキングも入れてみました。
画面からちょっと離れた方がいい感じで動きます。
/**
* Copyright mousepancyo ( http://wonderfl.net/user/mousepancyo )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/4F99
*/
// forked from mousepancyo's Virtual Aquarium
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Vector3D;
import flash.geom.Point;
import flash.media.Camera;
import flash.media.Video;
import flash.net.URLRequest;
import flash.system.Security;
import flash.system.LoaderContext;
import jp.progression.commands.*;
import jp.progression.commands.lists.*;
import jp.progression.commands.lists.LoaderList;
import jp.progression.commands.net.*;
import jp.progression.data.*;
import jp.progression.events.*;
[SWF(width="465", height="465", frameRate="30", backgroundColor="0xFFFFFF")]
public class Main extends Sprite
{
private const WIDTH:Number = 465;
private const HEIGHT:Number = 465;
private const NUM_FISH:int = 7;
private const DEFAULT_URL:String = "http://www.digifie.jp/assets/images/111005/";
private const NUM_MATERIAL:int = 10;
private var _cam:Camera;
public var video:Video;
private var _imgList:Array /*BitmapData*/ = [];
private var container3D:Sprite;
// Fish
private var _fishList:Array = [];
private var _motionValList:Array = [4, 3, 2, 5, 2, 3, 4];
// Bubble & Weed
private var _bubble1:Bubble;
private var _bubble2:Bubble;
private var _weed1:PolyImage;
private var _weed2:PolyImage;
private var _weed3:PolyImage;
private var _px:Number = WIDTH * .5;
private var _py:Number = HEIGHT * .5;
// Tracker
private var _tracker:Tracker;
public function Main()
{
root.transform.perspectiveProjection.fieldOfView = 50;
root.transform.perspectiveProjection.projectionCenter = new Point(WIDTH * .5, HEIGHT * .5);
addChild(new Bitmap(new BitmapData(WIDTH, HEIGHT, false, 0x001432)));
container3D = new Sprite();
container3D.x = WIDTH * .5; container3D.y = HEIGHT * .5; container3D.z = -10;
addChild(container3D);
//
bmdMultyLoad();
}
// Setup
private function setup():void
{
// Bubbles
_bubble1 = new Bubble(); _bubble1.x = -200; _bubble1.y = 470; _bubble1.z = 10;
_bubble2 = new Bubble(); _bubble2.x = 150; _bubble2.y = 470; _bubble2.z = 0;
_bubble1.blendMode = _bubble2.blendMode = "add";
container3D.addChild(_bubble1); container3D.addChild(_bubble2);
_bubble1.mouseChildren = _bubble2.mouseChildren = _bubble1.mouseEnabled = _bubble2.mouseEnabled = false;
// Fish
for(var i:int = 0; i<7; i++)
{
var n:int = (Math.random() * 7) | 0;
var speed:Number = Math.random() * 3 + 1;
var fish:Fish = new Fish(_imgList[i], 3, 2, .3 + (speed | 0) * .1, _motionValList[n]);
fish.id = i; fish.scaleX = -1; fish.speed = speed;
if(Math.random() < .5)
{
fish.isTurn = true;
}
else
{
fish.rotationY = 180; fish.isTurn = false;
}
_fishList.push(fish);
fish.x = (Math.random() * WIDTH * 2 - WIDTH) | 0; fish.y = (Math.random() * HEIGHT - HEIGHT * .5) | 0;
fish.z = - 10 * i; container3D.addChild(fish);
}
_weed1 = new Weed(_imgList[7], 2, 4, .3, 8); _weed1.x = -300; _weed1.y = -50; _weed1.z = -90;
_weed2 = new Weed(_imgList[8], 2, 4, .2, 7); _weed2.x = -100; _weed2.y = 0; _weed2.z = 20;
_weed3 = new Weed(_imgList[9], 2, 4, .2, 9); _weed3.x = 80; _weed3.y = -200; _weed3.z = -120;
container3D.addChild(_weed1); container3D.addChildAt(_weed2, 1); container3D.addChild(_weed3);
addChild(new Water());
//
addEventListener(Event.ENTER_FRAME, update);
}
// ------------ Camera & Video ------------------------------------------------------------------/
private function setupCamera():void
{
_cam = Camera.getCamera();
_cam.setMode(640, 480, 30);
video = new Video(_cam.width, _cam.height);
video.attachCamera(_cam);
video.scaleX = -1;
video.x = 640 * .5; video.y = -480 * .5; video.z = 50;
container3D.addChildAt(video, 0);
//
_tracker = new Tracker(WIDTH, HEIGHT, video);
//addChild(_tracker);
//
setup();
}
// ------------ Multy Loader ------------------------------------------------------------------/
private function bmdMultyLoad():void{
var context:LoaderContext = new LoaderContext;
context.checkPolicyFile = true;
var loadList:LoaderList = new LoaderList();
//
for ( var i:int = 1; i < NUM_MATERIAL + 1; i++ )
{
loadList.addCommand(
new LoadBitmapData(new URLRequest(DEFAULT_URL + i + ".png"),
{cacheAsResource:true, context:context, resGroup:"image", resId:i}
)
)
}
// Start
loadList.onStart = function():void {
trace( "start multy loader." );
}
// Progress
loadList.onProgress = function():void {
//trace( this.percent,"%" );
}
// Complete
loadList.onComplete = function():void{
trace( " files load complete." );
//
for( i = 1; i < NUM_MATERIAL + 1; i++ )
{
var bmd:BitmapData = getResourceById(i.toString()).data;
//addChild(new Bitmap(bmd));
_imgList.push(bmd);
}
//
setupCamera();
};
// Exec
loadList.execute();
}
// ------------ Update ------------------------------------------------------------------/
private function update(e:Event):void
{
_bubble1.update(); _bubble2.update();
_weed1.update(); _weed2.update(); _weed3.update();
//
for(var i:int = 0; i<NUM_FISH; i++)
{
_fishList[i].update();
movedFish(_fishList[i], _fishList[i].speed);
}
//
if(_tracker.isMotion)
{
_px += (_tracker.trackPoint.x - _px) * .1;
_py += (_tracker.trackPoint.y - _py) * .1;
}
else
{
_px += ((465 * .5) - _px) * .05;
_py += ((465 * .5) - _py) * .05;
}
container3D.rotationY = -(_px - WIDTH * .5) * .25;
container3D.rotationX = (_py - HEIGHT * .5) * .25;
}
// ------------ Moved Fish ------------------------------------------------------------------/
private function movedFish(target:PolyImage, speed:Number):void
{
if(target.isTurn)
{
target.x += speed;
if(target.x > WIDTH)
{
target.addEventListener(Event.ENTER_FRAME, target.turn);
}
}
else
{
target.x -= speed;
if(target.x < -WIDTH)
{
target.addEventListener(Event.ENTER_FRAME, target.turn);
}
}
}
}
}
// ------------ Water ------------------------------------------------------------------/
import flash.display.Sprite;
internal class Water extends Sprite
{
public function Water()
{
this.graphics.beginFill(0x65BCD1, .4);
this.graphics.drawRect(0, 0, 465, 465);
}
}
// ------------ PolyImage ------------------------------------------------------------------/
//package
//{
import flash.display.Sprite;
import flash.display.Shape;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.events.Event;
import flash.geom.Point;
internal class PolyImage extends Sprite
{
protected var _vertices:Vector.<Number> = new Vector.<Number>();
protected var _indices:Vector.<int> = new Vector.<int>();
protected var _uvData:Vector.<Number> = new Vector.<Number>();
protected var _pX:Vector.<Number> = new Vector.<Number>();
protected var _pY:Vector.<Number> = new Vector.<Number>();
protected var _pointList:Vector.<Point> = new Vector.<Point>();
protected var _bmd:BitmapData;
protected var _bm:Bitmap;
protected var _shape:Shape = new Shape();
protected var _isRev:Boolean; // 反転用フラグ
protected var _ofset:Number = 0; // ポイントのオフセット値
protected var _acc:Number = 0.9;
protected var _xLen:int;
protected var _yLen:int;
//
public var isTurn:Boolean;
public var isJump:Boolean;
public var transformAccel:Number;
public var maxDeformation:Number;
public var id:int;
public var speed:Number = 1;
public function PolyImage(bmd:BitmapData, xlen:int, ylen:int)
{
_bmd = bmd;
_xLen = xlen;
_yLen = ylen;
setup();
}
// ---------- Setup & CreateObject -------------------------------------/
protected function setup():void
{
addChild(_shape);
_shape.x = -50;
//
for (var i:int=0; i < _yLen; i++) {
for (var j:int=0; j < _xLen; j++) {
_uvData.push(j / (_xLen-1), i / (_yLen-1));
_vertices.push(_bmd.width * j / (_xLen-1), _bmd.height * i / (_yLen-1));
_pX.push(_bmd.width * j / (_xLen-1));
_pY.push(_bmd.height * i / (_yLen-1));
if (i != (_yLen - 1) && j != (_xLen - 1)) {
_indices.push(_xLen * i + j, _xLen * i + j + 1, _xLen * (i + 1) + j);
_indices.push(_xLen * i + j + 1, _xLen * (i + 1) + j, _xLen * (i + 1) + j + 1);
}
}
}
for (i=0; i < _xLen * _yLen; i++) {
var p:Point = new Point();
p.x = _pX[i];
p.y = _pY[i];
_pointList.push(p);
//
/*var dot:Dot = new Dot(i)
dot.x = _pX[i]
dot.y = _pY[i]
addChild(dot);*/
}
createTriangles(_vertices, _indices, _uvData);
}
// ---------- Motion Update -------------------------------------/
public function update():void
{
doMotion();
}
// ---------- Do Motion (Overrideeble) -------------------------------------/
protected function doMotion():void
{
// override
}
// ---------- Create Triangles (UV Mapping) -------------------------------------/
internal function createTriangles(ver:Vector.<Number>, ind:Vector.<int>, uv:Vector.<Number>, cull:String = "none"):void
{
_shape.graphics.clear();
//_shape.graphics.lineStyle(1, 0xFF0000, 0.5)
_shape.graphics.beginBitmapFill(_bmd, null, true, true);
_shape.graphics.drawTriangles(ver, ind, uv, cull);
_shape.graphics.endFill();
}
// ---------- Turn -------------------------------------/
public function turn(e:Event = null):void
{
if(isTurn){
if(this.rotationY < 180){
this.rotationY += (30 + speed);
}else{
isTurn = false;
this.rotationY = 180;
this.removeEventListener(Event.ENTER_FRAME, turn);
}
}else{
if(this.rotationY > 0){
this.rotationY -= (30 + speed);
}else{
isTurn = true;
this.rotationY = 0;
this.removeEventListener(Event.ENTER_FRAME, turn);
}
}
}
}
//}
import flash.display.Sprite;
import flash.display.Shape;
import flash.text.TextField;
class Dot extends Sprite{
public function Dot(n:int){
var shape:Shape = new Shape();
addChild(shape);
shape.graphics.beginFill(0xFF0000, 0.5);
shape.graphics.drawCircle(0,0,5);
shape.graphics.endFill();
//
var tx:TextField = new TextField();
addChild(tx);
tx.text = n.toString();
}
}
// ------------ Weed ------------------------------------------------------------------/
//package
//{
import flash.display.BitmapData;
internal class Weed extends PolyImage {
public var accel:Number = 3;
//public var transformAccel:Number = 2;
public function Weed(bmd:BitmapData, xlen:int = 2, ylen:int = 3, accel:Number = .5, maxDef:Number = 10)
{
super(bmd, xlen, ylen);
transformAccel = accel;
maxDeformation = maxDef;
}
protected override function doMotion():void
{
var nX:int = 0;
var nY:int = 0;
if(_isRev){
_ofset += transformAccel;
if(_ofset > maxDeformation){
_ofset = maxDeformation;
_isRev = false;
}
}else{
_ofset -= transformAccel;
if(_ofset < -maxDeformation){
_ofset = -maxDeformation;
_isRev = true;
}
}
for (var i:int=0; i < _vertices.length; i++) {
if (i % 2 != 1) {
if (nX < _pointList.length) {
var ofsetX:Number;
if(nX %2 == 0){
ofsetX = _ofset * nX * maxDeformation * .075;
}else{
ofsetX = _ofset * -nX * maxDeformation * .075;
}
//
if(nX >= _xLen) ofsetX *= -1;
//
_vertices[i] = _pointList[nX].x + ofsetX;
nX++;
}
} else {
if (nY < _pointList.length) {
var ofsetY:Number;
if(nY %4 == 0){
ofsetY = _ofset * -2;
}else if(nY %3 == 0){
ofsetY = _ofset;
}else if(nY %2 == 0){
ofsetY = _ofset * -1;
}else{
ofsetY = _ofset * 2;
}
//
if(nY >= _xLen) ofsetY *= -1;
//
_vertices[i] = _pointList[nY].y + ofsetY;
nY++;
}
}
}
createTriangles(_vertices, _indices, _uvData);
}
}
//}
// ------------ Fish ------------------------------------------------------------------/
//package
//{
import flash.display.BitmapData;
internal class Fish extends PolyImage {
public var accel:Number = 3;
//public var isTurn:Boolean;
public function Fish(bmd:BitmapData, xlen:int = 3, ylen:int = 2, accel:Number = 1, maxDef:Number = 8)
{
super(bmd, xlen, ylen);
transformAccel = accel;
maxDeformation = maxDef;
}
protected override function doMotion():void
{
var nX:int = 0;
var nY:int = 0;
if(_isRev){
_ofset += transformAccel;
if(_ofset > maxDeformation){
_ofset = maxDeformation;
_isRev = false;
}
}else{
_ofset -= transformAccel;
if(_ofset < -maxDeformation){
_ofset = -maxDeformation;
_isRev = true;
}
}
for (var i:int=0; i < _vertices.length; i++) {
if (i % 2 != 1) {
if (nX < _pointList.length) {
var ofsetX:Number;
if(nX %2 == 0){
ofsetX = _ofset * nX * .5;
}else{
ofsetX = _ofset * -nX * .5;
}
//
if(nX >= _xLen) ofsetX *= -1;
//
_vertices[i] = _pointList[nX].x + ofsetX;
nX++;
}
} else {
if (nY < _pointList.length) {
var ofsetY:Number;
if(nY %2 == 0){
ofsetY = _ofset;
}else{
ofsetY = _ofset * -1;
}
//
if(nY >= _xLen) ofsetY *= -1;
//
_vertices[i] = _pointList[nY].y + ofsetY;
nY++;
}
}
}
createTriangles(_vertices, _indices, _uvData);
}
//
}
//}
// ------------ Bubble ------------------------------------------------------------------/
//package
//{
import flash.display.Sprite;
import flash.display.Shape;
internal class Bubble extends Sprite
{
private var _bubles:Array = [];
private var _particles:Array = [];
private var _startX:Number;
private var _startY:Number;
public function Bubble()
{
this.mouseEnabled = false;
}
private function createParticle():void
{
var p:Particle = new Particle();
var radius:Number = Math.random() * Math.sqrt(Math.random()) * 3.5;
var angle:Number = Math.random() * (Math.PI) * 2;
//
p.vx = Math.cos(angle) * radius;
p.vy = Math.sin(angle) * radius;
p.scale = Math.random() * .1;
_particles.push(p);
//
var bubble:BubbleMaterial = new BubbleMaterial();
addChild(bubble);
_bubles.push(bubble);
}
private function emitte():void
{
var n:int = Math.random() * 1 + .2;
_startX = 0;
_startY = 0;
while (n--) createParticle();
}
public function update():void
{
var n:int = _particles.length;
while (n--) {
var v:Number = Math.random() * 0.15 + 0.85;
var p:Particle = _particles[n];
var ranx:Number = Math.random() * 2 - 1;
var rany:Number = Math.random() * - 1;
p.vx += ranx;
p.vy += rany;
p.vx *= v;
p.vy *= v;
p.x += p.vx;
p.y += p.vy;
//
_bubles[n].x = p.x; _bubles[n].y = p.y;
//
if(p.scale <= .6) p.scale += .01
if (p.y < -768){
_particles.splice(n, 1);
removeChild(_bubles[n]);
_bubles.splice(n, 1);
}
}
//
emitte();
}
//
public function removed():void
{
var l:int = _bubles.length;
for(var i:int; i<l; i++)
{
removeChild(_bubles[i]);
}
_bubles = [];
_particles = [];
}
}
//}
//
import flash.display.Sprite;
import flash.display.Shape;
internal class BubbleMaterial extends Sprite
{
public function BubbleMaterial()
{
var n:int = Math.random() * 10 | 0;
var sp:Shape = new Shape();
//
sp.graphics.beginFill(0xFFFFFF, .25);
sp.graphics.drawCircle(-n * .3, -n * .3, n * .5);
sp.graphics.endFill();
sp.graphics.lineStyle(1.5, 0xFFFFFF, .35);
sp.graphics.drawCircle(0, 0, n);
sp.rotation = Math.random() * 180 | 0;
//
addChild(sp);
}
}
//
import flash.geom.Point;
internal class Particle extends Point
{
public var vx:Number = 0
public var vy:Number = 0
public var scale:Number = 0;
public var c:uint = 0xFFFFFF;
}
//package
//{
import flash.display.BlendMode;
import flash.filters.BlurFilter;
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.media.Video;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.events.TimerEvent;
import flash.utils.Timer;
internal class Tracker extends Sprite
{
private var _w:Number;
private var _h:Number;
public var trackPoint:Point = new Point();
public var _previous:BitmapData;
public var _current:BitmapData;
private var _px:Number;
private var _py:Number;
private var _blur:BlurFilter = new BlurFilter(64,64);
private var _vid:Video;
private var _mirror:Matrix;
private var _point:Point = new Point();
private var _area:Rectangle;
public var isMotion:Boolean = false;
public function Tracker(w:Number, h:Number, vid:Video)
{
_w = w;
_h = h;
_vid = vid;
_mirror = new Matrix();
_mirror.scale( -1, 1);
var ofsetX:Number = _vid.width - (vid.width - 465) * .5
_mirror.translate(ofsetX, 0);
_current = new BitmapData(465, 465, false, 0x000000);
_previous = _current.clone();
addChild(new Bitmap(_previous));
//
var timer:Timer = new Timer(200);
timer.addEventListener(TimerEvent.TIMER, trackerUpdate);
timer.start();
}
private function trackerUpdate(e:TimerEvent):void
{
track();
trackPoint.x = _px;
trackPoint.y = _py;
}
private function track():void
{
_current.draw(_vid, _mirror);
_current.draw(_previous, null, null, BlendMode.DIFFERENCE);
_current.applyFilter(_current, _current.rect, _point, _blur);
_current.threshold(_current, _current.rect, _point, ">", 0xFF333333, 0xFFFFFFFF);
_previous.draw(_vid, _mirror);
_area = _current.getColorBoundsRect(0xFFFFFFFF,0xFFFFFFFF,true);
isMotion = ( _area.width > ( _current.width / 100) * 5 || _area.height > (_current.height / 100) * 5 );
if (isMotion)
{
_px = _area.x + _area.width * .5;
_py = _area.y + _area.height * .5;
}
/*graphics.clear();
graphics.lineStyle(1, 0xFF0000, .5);
graphics.drawRect(_area.x, _area.y, _area.width, _area.height);*/
}
}
//}