パーティクルシステム その3

by hankuro
「初めてのActionScript3.0」(O'REILLY)の7章モーションにパーティクルシステムがあり、
これが2Dで実現されていたので、これをpapervision3dを使用し3Dに変えてみました。
♥0 | Line 250 | Modified 2009-10-05 17:45:23 | MIT License
play

ActionScript3 source code

/**
 * Copyright hankuro ( http://wonderfl.net/user/hankuro )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/5XDA
 */

package {

	import flash.display.Sprite;
	import flash.events.*;
		
	[SWF(width = 540, height = 560, backgroundColor = 0x000000)]
	
	/*
	 * 「初めてのActionScript3.0」(O'REILLY)の7章モーションにパーティクルシステムがあり、
	 * これが2Dで実現されていたので、これをpapervision3dを使用し3Dに変えてみました。 
	 */

	public class Main extends Sprite{

		public var num:Number = 0;
		public var ballnum:Number = 5;
		public var scr:Sprite = new Sprite();

		public function Main() {
			Const_data.mousex = mouseX;
			Const_data.mousey = mouseY;
			var pl:Part_plane = new Part_plane();			
			addChild(pl);
			stage.addEventListener(Event.ENTER_FRAME, onLoop, false, 0, true);
			for (var i:Number = 0; i < ballnum;i++){
				var p:Part = new Part(Math.random() * 0xFFFFFF);			
				addChild(p);
			}
			scr.graphics.beginFill(0xFFFFFF, 0);
			scr.graphics.drawRect(0, 0, 540, 560);
			scr.graphics.endFill();
			scr.buttonMode = true;
			addChild(scr);
			scr.addEventListener(MouseEvent.CLICK, onClick);
			Const_data.balls = ballnum;
		}
		public function onClick(evt:MouseEvent):void {
			removeEventListener(MouseEvent.CLICK, onClick);
			removeChild(scr);
			Const_data.open_sw = true; 
		}
		
		private function onLoop(evt:Event):void {
			Const_data.mousex = mouseX;
			Const_data.mousey = mouseY;
		}		
	}
}
	import flash.events.Event;
	import org.papervision3d.core.effects.view.ReflectionView;
	import org.papervision3d.objects.primitives.Sphere;
	import org.papervision3d.lights.PointLight3D;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.materials.shadematerials.GouraudMaterial;
	import org.papervision3d.materials.utils.MaterialsList;
	
	class Part extends ReflectionView{
	    private var _xpos:Number = 0;
	    private var _ypos:Number = 0;
	    private var _zpos:Number = 0;
	    public var vx:Number;
	    public var vy:Number;
	    public var vz:Number;
	    public var ball:Sphere;
	    private var pointLight:PointLight3D;
	    private var bounce:Number = -0.7;
//		public var radius:Number = Math.random() * 35;
		public var radius:Number = 30;
		
		public function Part(col:uint) {
		    super(540,560,false, false,"free");
		    surfaceHeight = -30;
		    camera.z = -400;
		    vx = Math.random() * 10 - 3;
		    vy = Math.random() * 10 - 3;
		    vz = Math.random() * 10 - 3;
		    Const_data.b_obj.push(this);
		    pointLight = new PointLight3D();
		    pointLight.x = -200;
		    pointLight.y = 200;
		    pointLight.z = -90;
		    scene.addChild(pointLight);
		    ball = new Sphere(new GouraudMaterial(pointLight, col, 0x000000), radius, 8, 6);
		    scene.addChild(ball);
		    ball.x = Math.random() * 10 - 5;
		    ball.y = Math.random() * 10 - 5;
		    ball.z = Math.random() * 10 - 5;
		    ball.alpha = .08;
		    addEventListener(Event.ENTER_FRAME,onRun , false, 0, true);
		}
		private function onRun(evt:Event):void {
		    if (b_check.ball_check(this)) {
		        var xx:Number = ball.x;
		        var yy:Number = ball.y;
		        var zz:Number = ball.z;
		        scene.removeChild(ball);
		        ball = new Sphere(new GouraudMaterial(pointLight, Math.random() * 0xFFFFFF , 0x000000), radius, 8, 6);
		        ball.y = xx;
		        ball.y = yy;
		        ball.z = zz;
		        scene.addChild(ball);
		     }
		     _xpos += vx;
		     _ypos += vy;
		     _zpos += vz;
		     if(_xpos  > Const_data.right && !Const_data.open_sw)
		     {
		         _xpos = Const_data.right ;
		         vx *= -1;
		     }
		     else if(_xpos  < Const_data.left && !Const_data.open_sw)
		     {
		         _xpos = Const_data.left;
		         vx *= -1;
		     }else {
		         ball.x = _xpos;
		     }
		     if (_ypos < Const_data.bottom)
		     {
		         _ypos = Const_data.bottom;	
		         vy *= -1;
		     }
		     else if(_ypos > Const_data.top)
		     {
		         _ypos = Const_data.top;
		         vy *= -1;
		      }else {
		          ball.y = _ypos;
		      }
		      if(_zpos > Const_data.front && !Const_data.open_sw )
		      {
		          _zpos = Const_data.front;
		          vz *= -1;
		      }
		      else if(_zpos < Const_data.back && !Const_data.open_sw)
		      {
		          _zpos = Const_data.back;
		          vz *= -1;
		      }else {
		          ball.z = _zpos;
		      }
		      singleRender();
		      if ( ball.z < -300 ||  ball.z > 400  ) {
		          removeEventListener(Event.ENTER_FRAME, onRun);
		          parent.removeChild(this);
		      }
		   }
		}
			import flash.events.Event;
	import org.papervision3d.core.effects.view.ReflectionView;
	import org.papervision3d.core.geom.Lines3D;
	import org.papervision3d.core.geom.renderables.Line3D;
	import org.papervision3d.core.geom.renderables.Vertex3D;
	import org.papervision3d.core.geom.Vertices3D;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.objects.primitives.Plane;
	import org.papervision3d.lights.PointLight3D;
	import org.papervision3d.materials.shadematerials.GouraudMaterial;
	import org.papervision3d.materials.ColorMaterial
	import org.papervision3d.materials.special.LineMaterial;
	
	class Part_plane extends ReflectionView {
		
		private var pointLight:PointLight3D;
		private var plane:Plane;
		private var lines:Lines3D;
		
		public function Part_plane() {
			super(540, 560, false, false,"free");
			
			surfaceHeight = -30;
			camera.z = -400;
			
			var line_m:LineMaterial = new LineMaterial(0xFFFFFF, 1);
			lines = new Lines3D(line_m);
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D( -100, 0, -150), new Vertex3D(100, 0, -150)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D(-100, 170, -150), new Vertex3D(100, 170, -150)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D( -100, 0, -150), new Vertex3D( -100, 170, -150)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D(100, 0, -150), new Vertex3D(100, 170, -150)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D( -100, 0, 90), new Vertex3D(100, 0, 90)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D(-100, 170, 90), new Vertex3D(100, 170, 90)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D( -100, 0, 90), new Vertex3D( -100, 170, 90)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D(100, 0, 90), new Vertex3D(100, 170, 90)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D(100, 0, -150), new Vertex3D(100, 0, 90)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D( -100, 0, -150), new Vertex3D( -100, 0, 90)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D( -100, 170, -150), new Vertex3D( -100, 170, 90)));
			lines.addLine(new Line3D(lines, line_m, 0.5, new Vertex3D(100, 170, -150), new Vertex3D(100, 170, 90)));
			
			scene.addChild(lines);
			addEventListener(Event.ENTER_FRAME, onRun , false, 0, true);
			singleRender();
		}
		private function onRun(evt:Event):void {
			if (Const_data.open_sw) {
				scene.removeChild(lines);
				removeEventListener(Event.ENTER_FRAME, onRun );
				singleRender();	
			}							
		}
	}
		class b_check 
	{	
		
		public static function ball_check(p:Part):Boolean		
		{
			var tx:Number;
			var ty:Number;
			var tz:Number;
			var ax:Number;
			var ay:Number;
			var az:Number;
			var angle:Number;
			var dist:Number;
			var minDist:Number;
			var dx:Number;
			var dy:Number;
			var dz:Number;
			var spring:Number = 0.01;
			var part0:Part = p;
			var rtn:Boolean = false;
				
			for (var j:uint = 0; j < Const_data.balls; j++)
			{					
				var part1:Part = Const_data.b_obj[j];
				if(part0 != part1){
					dx = part1.ball.x - part0.ball.x;
					dy = part1.ball.y  - part0.ball.y;
					dz = part1.ball.z - part0.ball.z;
//					trace ("x "+dx+" y " +dy+ " z "+dz);
					dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
					minDist = part0.radius + part1.radius;
					if(dist < part0.radius + part1.radius)
					{
//						trace("hit");
						rtn = true;
						angle = Math.atan2(dy, dx);
						tx = part0.ball.x + dx / dist * minDist;
						ty = part0.ball.y + dy / dist * minDist;
						tz = part0.ball.z + dz / dist * minDist
						ax = (tx - part1.ball.x) * spring;
						ay = (ty - part1.ball.y) * spring;
						az = (tz - part1.ball.z) * spring;
						part0.vx -= ax;
						part0.vy -= ay;
						part0.vz -= az;
						part1.vx += ax;
						part1.vy += ay;
						part1.vz += az;
					}
				}
			}
				return rtn;
		}
	}
		class Const_data 
	{
		
		public static var xp:Number;
		public static var yp:Number;
		public static var mousex:Number;
		public static var mousey:Number;
		public static const stage_width:int = 540;
		public static const stage_height:int = 400;
		public static const right:int = 100;
		public static const left:int = -100;
		public static const top:int = 150;
		public static const bottom:int = 20;
		public static const front:Number = 90;
		public static const back:Number = -120;
		public static var center_width:int = stage_width / 2;
		public static var center_height:int = stage_height / 2;
		public static var open_sw:Boolean = false;
		public static var b_obj:Array = new Array();
		public static var balls:Number;
	}