Butterfly watching
game-like sample using Papervision 3d and Tweener
added butterfly motion using perlinNoise
inspired by http://www.25lines.com/finalists/0812/034.txt :)
// forked from takion's Papervision3D Game-like Sample
//game-like sample using Papervision 3d and Tweener
//added butterfly motion using perlinNoise
//inspired by http://www.25lines.com/finalists/0812/034.txt :)
package {
import caurina.transitions.Tweener;
import flash.display.*;
import flash.events.*;
import flash.geom.Point;
import flash.net.*;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import flash.utils.getTimer;
import flash.system.Security;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.core.clipping.FrustumClipping;
import org.papervision3d.lights.PointLight3D;
import org.papervision3d.materials.*;
import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
import org.papervision3d.materials.special.CompositeMaterial;
import org.papervision3d.materials.utils.MaterialsList;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.parsers.DAE;
import org.papervision3d.objects.primitives.*;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
[SWF(backgroundColor=0x6666FF)]
public class Pv3DSam1 extends Sprite
{
//private var container : Sprite;
private var viewport : Viewport3D;
private var scene : Scene3D;
private var camera : Camera3D;
private var rootNode : DisplayObject3D;
private var renderer : BasicRenderEngine;
private var light : PointLight3D;
//for debug
private var frameCount : Number;
private var prevTimer : Number;
private var debugText : Array;
private var numDebugItems : int = 12;
//camera information
private var exCamera : Array;
private var cameraStatus : int = 0; // 0: ground, 1:during change, 2:bird-eyes, 3:Look-at-paperPlane
//coneObject
private var coneObj : DisplayObject3D;
private var coneMat : CompositeMaterial; //FlatShadeMaterial;
//cubeObject
private var cubeObj : DisplayObject3D;
private var cubeSize : int = 50;//cubeオブジェクト1辺の長さ
private var cubeSegment : int = 1; //面の分割数
private var cubeMatList : MaterialsList;
private var cubeMat : CompositeMaterial; //FlatShadeMaterial;
private var cubeRotTheta : Number = 0;
//paperPlaneObject
private var paperPlaneObj : DisplayObject3D;
private var paperPlaneSize : int = 20;
private var paperPlaneMat : CompositeMaterial; //FlatShadeMaterial;
private var paperPlaneRotTheta : Number = 0;
//butterflyObject (dae model data)
private var butterflyObj : DisplayObject3D;
private var butBody : DAE;
private var butWingR : DAE;
private var butWingL : DAE;
private var bmpSheet : BitmapData = new BitmapData(40, 40, false, 0);
private var px1 :Number = 0;
private var perlinPoint : Point;
private var butterflyNoise : int = 10;
private var motionFlag : int = 0;
//ground field
private var fieldObj : DisplayObject3D;
private var fieldSize : int = 2000;
private var fieldSegment : int = 1;
private var fieldMat : CompositeMaterial;
private var fieldLimit : int = fieldSize / 2 - 20;
private var rightKey :Boolean = false;
private var leftKey :Boolean = false;
private var upKey :Boolean = false;
private var downKey :Boolean = false;
private var zKey :Boolean = false;
private var spaceKey :Boolean = false;
private var charaHeight : int = 50;
private var onJump : Boolean = false;
private var deltaJump : int = 0;
private var powerJump : int = 40;
private var deltaRot : int = 2;
private var deltaMove : int = 7;
public function Pv3DSam1():void
{
stage.frameRate = 30;
stage.quality = "LOW";
stage.scaleMode = "noScale";
stage.align = StageAlign.TOP_LEFT;
viewport = new Viewport3D( 0, 0, true );
renderer = new BasicRenderEngine( );
scene = new Scene3D( );
rootNode = new DisplayObject3D( );
light = new PointLight3D( );
addChild( viewport );
scene.addChild( rootNode );
renderer.clipping = new FrustumClipping(FrustumClipping.BOTTOM);
light.y = 2000;
initializeDebugger();
//create ground field
fieldMat = new CompositeMaterial();
fieldMat.addMaterial( new ColorMaterial( 0x888800, 1 ) );
fieldMat.addMaterial( new WireframeMaterial( 0x000000, 0.3 ) );
fieldMat.lineAlpha = 0.1;
fieldMat.fillAlpha = 1;
fieldObj = new Plane( fieldMat, fieldSize, fieldSize, fieldSegment, fieldSegment );
fieldObj.rotationX = 90;
rootNode.addChild( fieldObj );
//create cone
coneMat = new CompositeMaterial();
coneMat.addMaterial( new FlatShadeMaterial( light, 0xDDDDDD, 0xFF6666 ) );
coneMat.addMaterial( new WireframeMaterial( 0x000000, 0.3 ) );
coneObj = new Cone( coneMat, 50, 200, 16, 1 );
coneObj.y = 101;
rootNode.addChild( coneObj );
//create cube
cubeMat = new CompositeMaterial();
cubeMat.addMaterial( new FlatShadeMaterial(light, 0xFFFF00, 0xAAAA00) );
cubeMat.addMaterial( new WireframeMaterial( 0x000000, 0.3 ) );
cubeMat.oneSide = false;
cubeMatList = new MaterialsList( );
cubeMatList.addMaterial( cubeMat, "all" );
cubeObj = new Cube( cubeMatList, cubeSize, cubeSize, cubeSize, cubeSegment, cubeSegment, cubeSegment );
cubeObj.y = cubeSize;
rootNode.addChild( cubeObj );
//create paperPlane
paperPlaneMat = new CompositeMaterial();
paperPlaneMat.addMaterial( new FlatShadeMaterial( light, 0x88CCAA, 0x448866 ) );
paperPlaneMat.addMaterial( new WireframeMaterial( 0x000000, 0.3 ) );
paperPlaneMat.oneSide = false;
paperPlaneObj = new PaperPlane( paperPlaneMat, 0.7 );
paperPlaneObj.y = 30;
paperPlaneObj.rotationY = 180;
rootNode.addChild ( paperPlaneObj );
//create butterfly
butBody = new DAE;
butWingR = new DAE;
butWingL = new DAE;
butWingR.x = 2;
butWingR.y = 0;
butWingR.z = 10;
butWingL.x = -2;
butWingL.y = 0;
butWingL.z = 10;
butBody.x = 0;
Security.loadPolicyFile("http://takion.ps.land.to/3dmodel/crossdomain.xml");
butBody.load("http://takion.ps.land.to/3dmodel/body.dae", cubeMatList);
butWingR.load("http://takion.ps.land.to/3dmodel/wingR.dae", cubeMatList);
butWingL.load("http://takion.ps.land.to/3dmodel/wingL.dae", cubeMatList);
butterflyObj = new DisplayObject3D();
butterflyObj.addChild(butBody);
butterflyObj.addChild(butWingR);
butterflyObj.addChild(butWingL);
butterflyObj.scale = 1;
butterflyObj.y = 100;
butterflyObj.x = 100;
butterflyObj.z = 100;
butterflyObj.rotationX = -20;
rootNode.addChild( butterflyObj );
perlinPoint = new Point( 200, 200 );
//
//camera setting
camera = new Camera3D(90, 10, 2500, true);
camera.z = -cubeSize;
camera.y = charaHeight;
camera.x = 124;
camera.z = -340;
camera.focus = 10;
camera.zoom = 50;
camera.rotationY = 300 ;
exCamera = new Array();
//fps computing
frameCount = 0;
prevTimer = getTimer();
stage.addEventListener( Event.ENTER_FRAME, loop );
stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownHandler );
stage.addEventListener( KeyboardEvent.KEY_UP, keyUPHandler );
}
private function initializeDebugger():void
{
debugText = new Array();
var debugTextFormat:TextFormat = new TextFormat();
debugTextFormat.size = 11;
debugTextFormat.color = 0xFFFFFF;
debugTextFormat.font = "Courier New";
for( var i:int = 0; i < numDebugItems; i++ )
{
debugText[ i ] = new TextField();
debugText[ i ].type = "dynamic";
debugText[ i ].width = 150;
debugText[ i ].height = 20;
debugText[ i ].x = 12;
debugText[ i ].y = 8 + 15 * i;
debugText[ i ].defaultTextFormat = debugTextFormat;
debugText[ i ].text = " --------";
addChild( debugText[i] );
}
}
private function keyDownHandler( event:KeyboardEvent ):void
{
switch ( event.keyCode )
{
case Keyboard.RIGHT:
rightKey = true;
break;
case Keyboard.LEFT:
leftKey = true;
break;
case Keyboard.UP:
upKey = true;
break;
case Keyboard.DOWN:
downKey = true;
break;
case 90: // Z key
zKey = true;
break;
case Keyboard.SPACE:
spaceKey = true;
break;
default:
break;
}
}
private function keyUPHandler( event:KeyboardEvent ):void
{
switch ( event.keyCode )
{
case Keyboard.RIGHT:
rightKey = false;
break;
case Keyboard.LEFT:
leftKey = false;
break;
case Keyboard.UP:
upKey = false;
break;
case Keyboard.DOWN:
downKey = false;
break;
case 90:
zKey=false;
break;
case Keyboard.SPACE:
spaceKey = false;
break;
default:
break;
}
}
private function loop( event:Event ):void
{
controlCamera();
premitivesMotion();
butterflyMotion();
displayDebug();
renderer.renderScene( scene, camera, viewport );
}
private function displayDebug():void
{
frameCount ++;
if ( (getTimer() - prevTimer ) / 1000 >= 0.25 )
{
var fps:Number = frameCount * 1000 / ( getTimer() - prevTimer );
fps = Math.floor( fps * 10 ) / 10;
prevTimer = getTimer();
frameCount = 0;
debugText[ 0 ].text = "FPS : " + fps;
}
debugText[ 1 ].text = "CAMERA_X : " + int( camera.x );
debugText[ 2 ].text = "CAMERA_Y : " + int( camera.y );
debugText[ 3 ].text = "CAMERA_Z : " + int( camera.z );
debugText[ 4 ].text = "ROT_X : " + int( camera.rotationX );
debugText[ 5 ].text = "ROT_Y : " + int( camera.rotationY );
debugText[ 6 ].text = "ROT_Z : " + int( camera.rotationZ );
debugText[ 8 ].text = "Move : ↑↓";
debugText[ 9 ].text = "Turn : →←";
debugText[ 10 ].text = "Observe : Z";
debugText[ 11 ].text = "Bird-eyes: Space"
}
private function premitivesMotion():void
{
butterflyNoise = Math.random() * 3 + 3;
cubeObj.rotationZ += 10;
cubeRotTheta += Math.PI * 2 / 100;
cubeObj.x = Math.cos( cubeRotTheta ) * 150 - 250;
cubeObj.z = Math.sin( cubeRotTheta ) * 150 - 250;
paperPlaneObj.rotationY -= 360 / 100;
paperPlaneObj.x = - Math.cos( cubeRotTheta ) * 300 + 150;
paperPlaneObj.z = - Math.sin( cubeRotTheta ) * 300 + 150;
paperPlaneObj.y = ( Math.cos( cubeRotTheta ) ) * 100 + 110;
}
private function butterflyMotion():void
{
//field wandering by perlinNoise
bmpSheet.perlinNoise(20,20,3,6406,true,true,2|1,false,[new Point(px1+=0.3,0),new Point(-px1/2,0),new Point(0,0)]);
var exPos:Point = new Point( perlinPoint.x, perlinPoint.y );
var rgb24:uint=bmpSheet.getPixel( perlinPoint.x*0.025, perlinPoint.y*0.025);
if(rgb24>0) {
perlinPoint.x+=(128-(rgb24 >> 16))/5;
perlinPoint.y+=(128-((rgb24 ^ (rgb24 >> 16 << 16)) >> 8))/5;
}
perlinPoint.x+=(800-perlinPoint.x) / int( 40 * butterflyNoise );
perlinPoint.y+=(800-perlinPoint.y) / int( 40 * butterflyNoise );
//rotate to the progressing direction
var vecDir:Point = new Point( perlinPoint.x - exPos.x, perlinPoint.y - exPos.y );
var rotAngle:Number = Math.acos( vecDir.y / Math.sqrt( vecDir.x * vecDir.x + vecDir.y * vecDir.y ) ) * 180 / Math.PI;
if( vecDir.x < 0 ) rotAngle = 360 - rotAngle; //because of Z axis direction?
butterflyObj.x = (perlinPoint.x - 800);
butterflyObj.z = (perlinPoint.y - 800);
butterflyObj.rotationY = rotAngle;
//flap wings
motionFlag = Math.sin( cubeRotTheta * 10 ) * 3;
butWingL.rotationZ = motionFlag * 20;
butWingR.rotationZ = motionFlag *(-20);
//regular bound motion
butterflyObj.y += Math.cos( cubeRotTheta * 5 ) * butterflyNoise;
}
private function controlCamera():void
{
if( spaceKey == true )
{
if( cameraStatus == 0 )
{
renderer.clipping = new FrustumClipping(FrustumClipping.NEAR);
cameraStatus = 1;
exCamera[0] = camera.x;
exCamera[1] = camera.y;
exCamera[2] = camera.z;
exCamera[3] = camera.rotationX;
exCamera[4] = camera.rotationY;
exCamera[5] = camera.rotationZ;
Tweener.addTween( camera, {x: 0, y:2300, z:0, time:2} );
Tweener.addTween( camera, {rotationX: 90, time:3, onComplete: function():void{cameraStatus = 2} } );
}
else if( cameraStatus == 2 )
{
cameraStatus = 1;
Tweener.addTween( camera, {x: exCamera[0], y:exCamera[1], z:exCamera[2], time:3} );
Tweener.addTween( camera, {rotationX: exCamera[3], time:2, onComplete: function():void
{
cameraStatus = 0;
renderer.clipping = new FrustumClipping(FrustumClipping.BOTTOM);
}} );
exCamera.length = 0;
}
}
if( rightKey == true )
{
camera.rotationY += deltaRot;
}
else if( leftKey == true )
{
camera.rotationY -= deltaRot;
}
if( zKey == true )
{
if( cameraStatus == 0 )
{
exCamera[0] = camera.rotationX;
exCamera[1] = camera.rotationY;
exCamera[2] = camera.rotationZ;
cameraStatus = 3;
}
if( cameraStatus == 3 )
{
camera.lookAt( butterflyObj );
}
}
else
{
if( cameraStatus == 3 )
{
cameraStatus = 0;
camera.rotationX = exCamera[0];
camera.rotationY = exCamera[1];
camera.rotationZ = exCamera[2];
exCamera.length = 0;
}
}
if( cameraStatus == 0 )
{
if( camera.x > - fieldLimit && camera.x < fieldLimit && camera.z > - fieldLimit && camera.z < fieldLimit )
{
if( upKey == true )
{
camera.moveForward( deltaMove );
}
else if ( downKey == true )
{
camera.moveBackward( deltaMove );
}
}
/*
if( shiftKey == true && onJump == false)
{
onJump = true;
deltaJump = powerJump;
}
if( onJump == true )
{
camera.y += deltaJump;
if( deltaJump == -powerJump )
{
onJump = false;
deltaJump = 0;
}
else
{
deltaJump -= 2;
}
}
*/
//avoid camera going out of the field
if( camera.x > fieldLimit - 10 )
{
camera.x = fieldLimit - 10;
}
else if( camera.x < - fieldLimit + 10)
{
camera.x = - fieldLimit + 10;
}
else if( camera.z > fieldLimit - 10 )
{
camera.z = fieldLimit - 10;
}
else if( camera.z < - fieldLimit + 10 )
{
camera.z = - fieldLimit + 10;
}
}
}
}
}