// 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; } } } } } Butterfly watching