Interactive Cube Dragon

by mfc314159
I made a interactive cube dragon for you.

The mouse XY pos controls the XYZ turning speeds.  The Mouse Wheel controls and the speed.  
This may seen very noobish, but how do you use the mouse wheel without having to click on the screen first?  

If it gets away from you CLICK on the screen.
I haven't changed the mouse input to work with dynamic screen sizes so full screen is probably best.
♥0 | Line 201 | Modified 2011-02-14 18:50:30 | MIT License
play

ActionScript3 source code

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

package  {
	// Credit to Wonderfl for all the inspiration, and who ever made the demo I used cause
	// I can't find the original.
	// I hope someone who is where I was yeserday finds this useful today.
	// 
	// @Author Dave M.  mfc314159@yahoo.com
	// I basically took a papervision box demo and incorperated a simple 3D path system 
	// that I was aleady working on to create the basis for what I would like to become
	// a Dragon.  The path is created by constantly changeing the angle of each axis to
	// create an arcing 3D path.  If it runs away from you just click and a centered 
	// postion will begin.  
	// 
	// Any help is greatly appreciated 
	// ---Questions yet to be answered---
	// Can I set the camera position to the leading postion? cause that would be cool.
	// How do I properly change the yaw, roll, and pitch to reflect the position of the segment?
	// many .. many .. more ...
	//
	// ---Things To Do---
	// make use of number3D
	// better control input
	// make sin & cos tables
	// object to hit
	//
	// 
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import org.papervision3d.cameras.Camera3D;
        import org.papervision3d.materials.BitmapFileMaterial;
        import org.papervision3d.materials.ColorMaterial;
        import org.papervision3d.materials.utils.MaterialsList;
        import org.papervision3d.objects.primitives.Cube;
        import org.papervision3d.render.BasicRenderEngine;
        import org.papervision3d.scenes.Scene3D;
        import org.papervision3d.view.Viewport3D; 
	
	
	public class dragon extends Sprite {
	private var viewport:Viewport3D;        
	private var scene:Scene3D;        
	private var renderer:BasicRenderEngine;        
	private var camera:Camera3D;
	private var materialsList:MaterialsList;
   	private var cube:Cube;

	private var plane1:ColorMaterial; //front
	private var plane2:ColorMaterial; //back
	private var plane3:ColorMaterial; //left
	private var plane4:ColorMaterial; //right
	private var plane5:ColorMaterial; //top
	private var plane6:ColorMaterial; //bottom

	//--Everyone loves Pie
	private const piE:Number = Math.PI / 180;
	
	//--Reusuable id# to use with While loops
	private var id:int = 0; 
	
	//--Number of segments
	private var max:int = 50;
	
	//--Spread of segements
	private var spread:int = 10;
	
	private var origin:Array = []; //origin position 
	private var path:Array = [];   //traveled path
	private var _dragon:Array = []; //segment objects
	private var pathID:Array = []; //segment path ID
	
	
	//--Direction Angles
	private var xAng:Number = Math.random() * 180.00;
	private var yAng:Number = Math.random() * 180.00;
	private var zAng:Number = Math.random() * 180.00;
	
	//--Turing Speeds		
	private var turnSpeed:Number = 1;
	private var turnSpeedX:Number = turnSpeed / 1;
	private var turnSpeedY:Number = turnSpeed / 2;
	private var turnSpeedZ:Number = turnSpeed / 3;
	
	//--Leading Path vars
	private var speed:Number = 5;
	private var pathX:Number = speed *  Math.sin(piE * xAng);
	private var pathY:Number = speed *  Math.cos(piE * yAng);
	private var pathZ:Number = speed *  Math.sin(piE * zAng);
	
	public function dragon() {
		
		//--PAPERVISION INIT
		stage.frameRate = 60;
		stage.quality = "BEST";
		stage.scaleMode = "noScale";
		stage.align = StageAlign.TOP_LEFT;
		viewport = new Viewport3D();
		viewport.viewportWidth = 1000; 
		viewport.viewportHeight = 700;
		viewport.x = ( this.stage.stageWidth - viewport.viewportWidth ) / 2; 
		viewport.y = ( this.stage.stageHeight - viewport.viewportHeight ) / 2;
		addChild(viewport);
		scene = new Scene3D();
		camera = new Camera3D();
		renderer = new BasicRenderEngine();
		
		//--Planes for Cube:  Green Sides, Red Bottom, Grey Top, 50% alpha overall
		plane1 = new ColorMaterial(0x00ff00, .5); //front
		plane2 = new ColorMaterial(0x00ff00, .5); //back
		plane3 = new ColorMaterial(0x00ff00, .5); //left
		plane4 = new ColorMaterial(0x00ff00, .5); //right
		plane5 = new ColorMaterial(0xf0f0f0, .5); //top
		plane6 = new ColorMaterial(0xff0000, .5); //bottom

		//--Add planes to material list
		materialsList = new MaterialsList();
		materialsList.addMaterial(plane1 , "front");
		materialsList.addMaterial(plane2 , "back");
		materialsList.addMaterial(plane3 , "left");
		materialsList.addMaterial(plane4 , "right");
		materialsList.addMaterial(plane5 , "top");
		materialsList.addMaterial(plane6 , "bottom");

		
		
		//--origin position array
		origin["x"] = Number(500.00);  //  x position
		origin["y"] = Number(1000.00); //  y position
		origin["z"] = Number(250.00);  //  z position
		
		//--path positions array
		path["X"] = new Array(); //  x position
		path["Y"] = new Array(); //  y position
		path["Z"] = new Array(); //  z position
		path["p"] = new Array(); //  pitch
		path["r"] = new Array(); //  roll
		path["y"] = new Array(); //  yaw
		while(id < (max * spread)) {	
			path.X[id] = Number(origin.x);
			path.Y[id] = Number(origin.y);
			path.Z[id] = Number(origin.z);
			path.p[id] = Number(0.00);
			path.r[id] = Number(0.00);
			path.y[id] = Number(0.00);
			id++;
		}
		id = 0; //reset
		
		//base Size & ratio for each portion Begin/Mid/End
		var sizeBegin:int = 37;
		var numBegin:int = max * .2;
		var sizeMid:int = 50;
		var numMid:int = numBegin + (max *.2);
		var sizeEnd:int = 25;
		var numEnd:int = numMid + (max * .6);
		var segSize:int = 0;
		
                //add segments to the _dragon array	
		//set pathIDs of segments in _dragon
		while(id < max) {
			
                        if((id < numBegin) && (id >= 0))      { segSize = sizeBegin; }
			if((id < numMid) && (id >= numBegin)) { segSize = sizeMid;   }
			if((id < numEnd) && (id >= numMid))   { segSize = sizeEnd;   }
			
		        if(id != 0) {
			//Add Cube for segment
			_dragon[id] = new Cube(materialsList, segSize, segSize, segSize, 1, 1, 1); 
			} else {
			//Head Cube segment
			_dragon[id] = new Cube(materialsList, (segSize * 2), segSize, (segSize * 1.5), 1, 1, 1); 
			}
			pathID[id] = int(id * spread); //find segment id# on path
			scene.addChild(_dragon[id]);   //add segment to scene
			id++;
		}

		
		//Fill the path array with init values 
		setup();
	
		//--Reset origin
		stage.addEventListener(MouseEvent.CLICK, newPath);
		//--Generate path from mouse input
		stage.addEventListener(MouseEvent.MOUSE_MOVE, mousePath);
		//--Change Speed
		stage.addEventListener(MouseEvent.MOUSE_WHEEL, changeSpeed);
                //--start Main Loop
		stage.addEventListener(Event.ENTER_FRAME, mainLoop);
	
	}
	
	//------------------------------------------MOUSE INPUT HANDLERS
	private function newPath(evt:MouseEvent) {
			
		origin.x = evt.stageX;
		origin.y = evt.stageY;
		origin.z = 250;
		
		turnSpeed = -2 + (Math.random() * 4);
		turnSpeedX = turnSpeed / 1;
		turnSpeedY = turnSpeed / 2;
		turnSpeedZ = turnSpeed / 3;
	}
	private function mousePath(evt:MouseEvent) {
			
		turnSpeedX = (evt.stageX - 500) * .006;
		turnSpeedY = (evt.stageY - 350) * .006;
		turnSpeedZ = Math.sqrt((turnSpeedX * turnSpeedX) + (turnSpeedY * turnSpeedY));
	}
	
	private function changeSpeed(evt:MouseEvent) {
		if(evt.delta > 0) { speed += .1;
		} else {	    speed -= .1; }
		trace(speed);
	}
	//-----------------------------------------------------MAIN LOOP
	private function mainLoop(evt:Event) {
		
		//--STAGE 1
		//find next position
		
		xAng += turnSpeedX;  //change angles 
		yAng += turnSpeedY;
		zAng += turnSpeedZ;
	
		if(xAng > 360) { xAng = xAng - 360; } // limit angles
		if(yAng > 360) { yAng = yAng - 360; }
		if(zAng > 360) { zAng = zAng - 360; }
		
		pathX = speed * Math.sin(piE * xAng); // angles to coordindates
		pathY = speed * Math.cos(piE * yAng);
		pathZ = speed * Math.sin(piE * zAng);
		
		origin.x += pathX; //add path coordinates to current positions
		origin.y += pathY;
		origin.z += pathZ;
		
		//--STAGE 2:--Shift and Add positions to path array
		//shift path positions down
		path.X.pop();
		path.Y.pop();
		path.Z.pop();
		path.p.pop();
		path.r.pop();
		path.y.pop();
		//add new position to path
		path.X.unshift(origin.x);
		path.Y.unshift(origin.y);
		path.Z.unshift(origin.z);
		//path.p.unshift(turnSpeedX);
		path.r.unshift(turnSpeedZ);
		//path.y.unshift(turnSpeedZ);
		
		//--STAGE 3:--Set Positions
		id = 0; //reset
		while(id < max) {
			_dragon[id].x = path.X[pathID[id]];
			_dragon[id].y = path.Y[pathID[id]];
			_dragon[id].z = path.Z[pathID[id]];
			//dragon[id].pitch(path.p[pathID[id]]);
			_dragon[id].roll(path.r[pathID[id]]);
			//dragon[id].yaw(path.y[pathID[id]]);
			id++;
		}
		
		//--STAGE 4:--Render The Scene
		renderer.renderScene(scene, camera, viewport);
	}
		
	private function setup() {
		//fills the path array with values to cut down on inital drawing time
		id = 0;
		while(id < (max * spread)){
			//--STAGE 1
			//find next position
			xAng += turnSpeedX;
			yAng += turnSpeedY;
			zAng += turnSpeedZ;
		
			if(xAng > 360) { xAng = xAng - 360; }
			if(yAng > 360) { yAng = yAng - 360; }
			if(zAng > 360) { zAng = zAng - 360; }
			
			pathX = speed * Math.sin(piE * xAng);
			pathY = speed * Math.cos(piE * yAng);
			pathZ = speed * Math.sin(piE * zAng);
			
			origin.x += pathX;
			origin.y += pathY;
			origin.z += pathZ;
			
			//--STAGE 2
			//shift positions down 
			path.X.pop();
			path.Y.pop();
			path.Z.pop();
			path.p.pop();
			path.r.pop();
			path.y.pop();
			//add new position to path
			path.X.unshift(origin.x);
			path.Y.unshift(origin.y);
			path.Z.unshift(origin.z);
			path.p.unshift(turnSpeedX);
			path.r.unshift(turnSpeedZ);
			path.y.unshift(turnSpeedZ);
					
			id++;
			
		}

			
	}
	}
	
}