パーティクルを散らす-3D

昔作ったサンプル。
3D表現の勉強。きれいに4方8方に散らばってくれない。。

以下コード。

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;

	public class Firework extends Sprite {
		private var _particles:Array;
		private var _numParticles:Number = 30;
		private var _fl:Number = 150;
		private var _vpX:Number;
		private var _vpY:Number;
		private var _gravity:Number = 0.1;
		private var _fade:Number = 0.01;

		public function Firework() {
			stage.addEventListener(MouseEvent.MOUSE_DOWN, init);
		}

		private function init(e:MouseEvent):void {
			_vpX = mouseX;
			_vpY = mouseY;
			_particles = new Array();
			for (var i:int = 0; i < _numParticles; i++) {
				var p:Particle = new Particle(5, Math.random() * 0xFFFFFF);
				_particles.push(p);
				p.xpos = mouseX;
				p.ypos = mouseY;
				p.vx = Math.round(Math.random() * 10 - 5);
				p.vy = Math.round(Math.random() * 10 - 5);
				p.vz = Math.round(Math.random() * 8 - 4);
				addChild(p);
				p.addEventListener(Event.ENTER_FRAME, onEnterframe);
			}
		}

		private function onEnterframe(e:Event):void {
			var p:Particle = e.target as Particle;
			spread(p);
			sortZ();
		}
		//散らす
		private function spread(p:Particle):void {
			p.vy += _gravity;
			p.xpos += p.vx;
			p.ypos += p.vy;
			p.zpos += p.vz;

			if(p.alpha >= 0) {
				var scale:Number = _fl / (_fl + p.zpos);
				p.scaleX = p.scaleY = scale;
				p.x = p.xpos * scale;
				p.y = p.ypos * scale;
				p.alpha -= _fade * p.zpos * 0.05;
			} else if (p.alpha <= 0) {
				var index:Number = _particles.indexOf(p);
				_particles.splice(index, 1);
				p.removeEventListener(Event.ENTER_FRAME, onEnterframe);
				removeChild(p);
				p = null;
			}
		}
		//z軸の重なりのソート処理
		private function sortZ():void {
			_particles.sortOn("zpos", Array.DESCENDING | Array.NUMERIC);
			for (var i:int = 0; i < _particles.length; i++) {
				var p:Particle = _particles[i];
				setChildIndex(p, i);
			}
		}
	}
}

import flash.display.Sprite;

class Particle extends Sprite {
	public var xpos:Number = 0;
	public var ypos:Number = 0;
	public var zpos:Number = 0;
	public var vx:Number = 0;
	public var vy:Number = 0;
	public var vz:Number = 0;
	public var radius:Number;
	public var color:uint;

	public function Particle(radius:Number = 10, color:uint = 0x000000) {
		this.radius = radius;
		this.color = color;
		draw();
	} 

	private function draw():void {
		graphics.beginFill(color, 1.0);
		graphics.drawCircle(0, 0, radius);
		graphics.endFill();
	}
}

RJD2 - 1976

気合いが入るトラック。映像もかっこよし。

バネボールの列

マウスに少し反応するバネボールの列。
イメージした動きを表現させるためのゴリ押しコード。
線でつなげるの忘れた。

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;

	public class SpringBallsLine {
		private var targetList:Array = new Array();
		private var baseX:Number;
		private var baseY:Number;
		private var orgPos:Point;
		private var spring:Number = 0.08;
		private var friction:Number = 0.93;
		private var gravity:Number =4.5;
		private var space:Number = 100;

		public function SpringBallsLine(list:Array, baseX:Number, baseY:Number) {
			targetList = list;
			this.baseX = baseX;
			this.baseY = baseY;
			init();
		}

		private function init():void {
			for (var i:int = 0; i < targetList.length; i++) {
				var target:Sprite = targetList[i] as Sprite;
				target.addEventListener(MouseEvent.MOUSE_OVER, onMouseover);
			}
			target.addEventListener(Event.ENTER_FRAME, springMove);
		}

		private function onMouseover(e:MouseEvent):void {
			var target:*=e.target;
			orgPos = new Point(target.x, target.y);

			target.addEventListener(Event.ENTER_FRAME, checkMouse);
		}

		private function checkMouse(e:Event):void {
			var target:*= e.target;
			target.x += target.mouseX * 0.8;
			target.y += target.mouseY * 0.92;
			if (Math.abs(target.x - orgPos.x) > 30 || Math.abs(target.y - orgPos.y) > 30) {
				target.removeEventListener(Event.ENTER_FRAME, checkMouse);
			}
		}

		private function springMove(e:Event):void {
			move1(targetList[0], baseX, baseY);

			for (var i:int = 1; i < targetList.length; i++) {
				var targetA:* = targetList[i - 1];
				var targetB:* = targetList[i];

				move1(targetB, targetA.x, targetA.y);
				move2(targetA, targetB.x, targetB.y);
			}
		}

		private function move1( t:*, distX:Number, distY:Number):void {
			var target:*= t;
			target.vx += (distX-target.x) * spring;
			target.vy += (distY-target.y) * spring;
			target.vy += gravity;
			target.vx *= friction;
			target.vy *= friction;
			target.x += target.vx;
			target.y += target.vy;
		}

		private function move2(t:*, distX:Number, distY:Number):void {
			var target:*= t;
			target.vx += (distX-target.x) * spring;
			target.vy += (distY-target.y) * spring;
			target.vy -= gravity;
			target.vx *= friction;
			target.vy *= friction;
			target.x += target.vx;
			target.y += target.vy;
		}
	}
}

ボールラインを生成する↓

package {
	import flash.display.Sprite;

	public class SpringBallsLineTest extends Sprite {
		private const NUM_BALLS:uint = 5;

		public function SpringBallsLineTest() {
			init();
		}

		private function init():void {
			var balls:Array = new Array();
			for (var i:int = 0; i < NUM_BALLS; i++) {
				var ball:Ball = new Ball(20, 0xFFFFFF);
				addChild(ball);
				balls.push(ball);
			}

			var springBallsLine = new SpringBallsLine(balls, stage.stageWidth/2, 0);
		}
	}
}