Forked from: takion's 降り注ぐ雪 diff:2 forked from: 降り注ぐ雪 papervision3Dのparticleで雪を表現 kojiikeda forked:0favorite:1lines:345license : All rights reserved modified : 2009-03-06 15:45:15 Embed Tweet // forked from takion's 降り注ぐ雪 //papervision3Dのparticleで雪を表現 package { import caurina.transitions.Tweener; import flash.display.*; import flash.events.*; import flash.net.*; import flash.system.LoaderContext; import flash.text.TextField; import flash.text.TextFormat; import flash.ui.Keyboard; import flash.utils.getTimer; import org.papervision3d.cameras.Camera3D; import org.papervision3d.core.clipping.FrustumClipping; import org.papervision3d.core.geom.renderables.Particle; import org.papervision3d.lights.PointLight3D; import org.papervision3d.materials.*; import org.papervision3d.materials.special.ParticleMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.*; import org.papervision3d.objects.special.ParticleField; import org.papervision3d.render.BasicRenderEngine; import org.papervision3d.scenes.Scene3D; import org.papervision3d.view.Viewport3D; [SWF(backgroundColor=0x000000)] public class SnowPouring 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 = 13; //camera private var exCamera : Array; private var cameraStatus : int = 0; // 0: ground, 1:during change, 2:bird-eyes, 3:Look-up private var maxFar : int = 1000; private var bmpSheet : BitmapData; private var particleMat : ParticleMaterial; private var particleField : ParticleField; private var pFieldHeight : int; private var numParticles : int; private var theta : Number = 0; private var windOffset : Array; //ground field private var fieldObj : DisplayObject3D; private var fieldSize : int = 2000; private var fieldSegment : int = 5; private var fieldMat : BitmapMaterial; 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 shiftKey : Boolean = false; private var charaHeight : int = 50; private var onJump : Boolean = false; private var deltaJump : int = 0; private var powerJump : int = 12; private var deltaRot : int = 2; private var deltaMove : int = 7; public function SnowPouring( ):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 bmpSheet = new BitmapData( 40, 40, false, 0 ); bmpSheet.perlinNoise(20,20,3,7,true,true,2,false); bmpSheet.lock(); for( var i:int = 0; i < 40; i++ ) { for( var j:int = 0; j < 40; j++ ) { if( bmpSheet.getPixel( i, j ) > 0x007700 ) { bmpSheet.setPixel( i, j, bmpSheet.getPixel( i, j ) + 0xFF00FF ); } } } bmpSheet.unlock(); fieldMat = new BitmapMaterial( bmpSheet ); fieldObj = new Plane( fieldMat, fieldSize, fieldSize, fieldSegment, fieldSegment ); fieldObj.rotationX = 90; rootNode.addChild( fieldObj ); /* create particles */ pFieldHeight = 250; numParticles = 1000; particleMat = new ParticleMaterial( 0xFFFFFF, 1, ParticleMaterial.SHAPE_CIRCLE ); particleField = new ParticleField( particleMat, numParticles, 8, fieldSize, pFieldHeight, fieldSize); for( i = 0; i < numParticles; i++ ) { Particle(particleField.particles[i]).size = Math.random() * 10 + 1; } particleField.y = pFieldHeight / 2; rootNode.addChild( particleField ); windOffset = new Array( 3 ); //wind offset windOffset[0] = 3; windOffset[1] = 5; windOffset[2] = 0; //camera setting camera = new Camera3D(90, 10, maxFar, true); camera.x = 0; camera.y = charaHeight; camera.z = 0; camera.focus = 10; camera.zoom = 50; camera.rotationY = 210 ; 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 imageLoad( bmpMat:BitmapMaterial, URLs:String ):void { var loaderContext:LoaderContext = new LoaderContext (); loaderContext.checkPolicyFile = true; var imageLoader:Loader = new Loader(); imageLoader.contentLoaderInfo.addEventListener( Event.COMPLETE, function( e:Event ):void { var loadedBmp:Bitmap = e.target.content as Bitmap; var bmp : BitmapData = loadedBmp.bitmapData; bmpMat.texture = bmp; } ); imageLoader.load( new URLRequest( URLs ), loaderContext ); } 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 Keyboard.SPACE: spaceKey = true; break; case Keyboard.SHIFT: shiftKey = 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 Keyboard.SPACE: spaceKey = false; break; case Keyboard.SHIFT: shiftKey = false; break; default: break; } } private function loop( event:Event ):void { pouringParticles(); controlCamera(); displayDebug(); renderer.renderScene( scene, camera, viewport ); } //雪の動き private function pouringParticles():void { theta += Math.PI * 2 / 100; for( var iString:String in particleField.geometry.vertices ) { var i:int = int( iString ); particleField.particles[i].y -= ( Particle( particleField.particles[ i ] ).size / 1.5 + windOffset[2] ); particleField.particles[i].x += ( Math.sin( theta + i ) * 3 + windOffset[0] ); particleField.particles[i].z += ( Math.cos( theta + i ) * 3 + windOffset[1] ); if( particleField.particles[i].y < - pFieldHeight / 2 ) { particleField.particles[i].y = pFieldHeight; } particleField.particles[i].x = (particleField.particles[i].x + fieldSize/2 ) % fieldSize - fieldSize/2; particleField.particles[i].z = (particleField.particles[i].z + fieldSize/2 ) % fieldSize - fieldSize/2; } } private function controlCamera():void { if( spaceKey == true ) { if( cameraStatus == 0 ) // on normal mode { camera.far = 2500; renderer.clipping = new FrustumClipping(FrustumClipping.NEAR); cameraStatus = 1; // on changing modes 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 ) // on birds-eye mode { camera.far = maxFar; 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( 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 ) { if( cameraStatus == 0 ) { cameraStatus = 1; exCamera[0] = camera.rotationX; exCamera[1] = camera.rotationY; exCamera[2] = camera.rotationZ; Tweener.addTween( camera, {rotationX: -40, time:1, onComplete: function():void { cameraStatus = 3; //renderer.clipping = new FrustumClipping(FrustumClipping.BOTTOM); }} ); } else if( cameraStatus == 3 ) { cameraStatus = 1; Tweener.addTween( camera, {rotationX: exCamera[0], time:1, onComplete: function():void { cameraStatus = 0; //renderer.clipping = new FrustumClipping(FrustumClipping.BOTTOM); }} ); exCamera.length = 0; } } //avoid camera going out of the field if( camera.x > fieldLimit - deltaMove ) { camera.x = fieldLimit - deltaMove; } else if( camera.x < - fieldLimit + deltaMove) { camera.x = - fieldLimit + deltaMove; } else if( camera.z > fieldLimit - deltaMove ) { camera.z = fieldLimit - deltaMove; } else if( camera.z < - fieldLimit + deltaMove ) { camera.z = - fieldLimit + deltaMove; } } 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 = "Move : ↑↓"; debugText[ 2 ].text = "Turn : →←"; debugText[ 3 ].text = "Bird-eyes: Space"; debugText[ 4 ].text = "Loop-up : Shift" ; } } } Code Fullscreen Preview Fullscreen hacker_1qtsm.. : pv3dsnow pv3d snow particles fps shiftKey rotationY clipping FrustumClipping far scene viewport FrustumClipping.BOTTOM Tweener.addTween Particle Keyboard.SHIFT LoaderContext Keyboard.SPACE time rotationZ Boolean Keyboard.DOWN Keyboard.UP