In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

[Papervision3D] Rubik's Cube (v1.0) [WORKING]

I decided that I like PV3D better.  I just know it better.
Note:Had to stop using TweenLite.
Next Step: Auto Scramble.
Final Step: Auto Solve.
Get Adobe Flash player
by PESakaTFM 22 Mar 2010
/**
 * Copyright PESakaTFM ( http://wonderfl.net/user/PESakaTFM )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/hJ7r
 */

// forked from PESakaTFM's [Alternativa3D] Rubik's Cube (v0.2)
// forked from PESakaTFM's [Alternativa3D] Rubik's Cube (v0.1)
/**
I decided that I like PV3D better.  I just know it better.
Note:Had to stop using TweenLite.
Next Step: Auto Scramble.
Final Step: Auto Solve.
**/

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.text.TextField;
	
	import net.hires.debug.Stats;
	
	import org.papervision3d.core.math.Matrix3D;
	import org.papervision3d.core.math.Number3D;
	import org.papervision3d.render.QuadrantRenderEngine;
	import org.papervision3d.view.BasicView;

	[SWF(backgroundColor=0x0, width=465, height=456, frameRate=30)]
	public class Main extends Sprite
	{
		public var rubik:RubiksCube;
		public var view:BasicView;
		public var mdp:Point = new Point(); // mouse down point
		public var dragPoint:Point = new Point();
		public var bgClicked:Boolean = false;
		public var background:Sprite;
		
		public static var tween:Sprite = new Sprite();
		
		public function Main()
		{
			background = new Sprite();
			background.graphics.beginFill(0x0,1);
			background.graphics.drawRect(0,0,465,465);
			background.graphics.endFill();
			addChild(background);
			
			addChild(new Stats());
			
			init3DEngine();			
			
			rubik = new RubiksCube();
			view.scene.addChild(rubik);
		}
		
		private function init3DEngine():void
		{
			view = new BasicView(0, 0, true, true, "Target");						
			view.camera.z = -100;
			view.buttonMode = true;
			view.renderer = new QuadrantRenderEngine(QuadrantRenderEngine.CORRECT_Z_FILTER);
			
			this.addChild(view);
			this.addEventListener(Event.ENTER_FRAME, onEventRender3D);
			
			stage.addEventListener(MouseEvent.MOUSE_DOWN, startRotation);
		}
		
		private function startRotation(event:MouseEvent):void
		{
			bgClicked = event.target == background;
			
			stage.addEventListener(MouseEvent.MOUSE_UP, endDrag);
			stage.addEventListener(Event.MOUSE_LEAVE, endDrag);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
			
			mdp.x = mouseX;
			mdp.y = mouseY;
			onMove();
		}
		
		public function endDrag(event:Event = null):void
		{
			stage.removeEventListener(MouseEvent.MOUSE_UP, endDrag);
			stage.removeEventListener(Event.MOUSE_LEAVE, endDrag);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
		}
		
		public function onMove(event:Event=null):void
		{
			if(bgClicked)
			{
				var m:Matrix3D = Matrix3D.rotationY((mouseX - mdp.x)/150);
				m = Matrix3D.multiply(m, Matrix3D.rotationX(-(mouseY - mdp.y)/150));
				rubik.transform = Matrix3D.multiply(m, rubik.transform);
				
				mdp.x = mouseX;
				mdp.y = mouseY;
			}
			else
			{
				dragPoint.x = mouseX;
				dragPoint.y = mouseY;
				
				if(Point.distance(mdp, dragPoint) > 10)
				{
					var n:Number3D = MyUtils.transformNumber(new Number3D(mdp.x - dragPoint.x, dragPoint.y - mdp.y, 0), Matrix3D.inverse(rubik.transform));
					n = Number3D.cross(n, rubik.selSide);
					
					var axis:String = 'x';
					var largest:Number = Math.abs(n.x);
					
					if(Math.abs(n.y) > largest)
					{
						largest = Math.abs(n.y);
						axis = 'y';
					}
					if(Math.abs(n.z) > largest)
					{
						largest = Math.abs(n.z);
						axis = 'z';
					}
					
					rubik.move(axis, Math.round(n[axis]/largest));
					
					endDrag();
				}
			}
		}
		
		private function onEventRender3D(e:Event):void
		{	
			view.singleRender();
		}
	}
}
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.events.Event;
	
	import org.papervision3d.core.math.Matrix3D;
	import org.papervision3d.core.math.Number3D;
	import org.papervision3d.materials.ColorMaterial;
	import org.papervision3d.materials.MovieMaterial;
	import org.papervision3d.materials.utils.MaterialsList;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Cube;

class RubiksCube extends DisplayObject3D
{
	public var selected:Number3D;
	public var selSide:Number3D;
	
	private var miniCubes:Vector.<MiniCube> = new Vector.<MiniCube>();
	private var temp:Vector.<MiniCube>;
	private var endParams:Object;
	
	private var inMotion:Boolean = false;
	private var opperation:String;
	
	public function RubiksCube()
	{
		createCube();
	}
	
	private function createCube():void
	{
		var cube:MiniCube;
		for(var i:int = 0; i<3; i++)
		{
			for(var j:int = 0; j<3; j++)
			{
				for(var k:int = 0; k<3; k++)
				{
					cube = new MiniCube(k,j,i);
					cube.addEventListener(MouseEvent.MOUSE_DOWN, onCubeSelected);
					
					miniCubes.push(cube);
					addChild(cube);
				}
			}
		}
		
		name = "rubik";
	}
	
	private function onCubeSelected(event:MouseEvent):void
	{
		if(!inMotion)
		{
			selected = MiniCube(event.currentTarget).location;
			selSide = event.target.selectedSide;
		}
	}
	
	public function move(axis:String, dir:int):void
	{
		if(inMotion || selected == null) return;
		inMotion = true;
		
		endParams = {rotationX:0, rotationY:0, rotationZ:0};
		endParams['rotation'+axis.toUpperCase()] = 90*dir;
		
		temp = new Vector.<MiniCube>();
		for(var i:int=0; i<27; i++)
		{
			if(miniCubes[i].location[axis] == selected[axis])
			{
				temp.push(miniCubes[i]);
			}
		}
		Main.tween.addEventListener(Event.ENTER_FRAME, tweenSection);
	}
	
	private function tweenSection(event:Event):void
	{
		var finished:Boolean = true;
		for(var i:int=0; i<temp.length; i++)
		{
			for(var param:String in endParams)
			{
				if(temp[i][param] < endParams[param]-9)
				{
					temp[i][param] += 9;
					finished = false;
				}
				else if(temp[i][param] > endParams[param]+9)
				{
					temp[i][param] -= 9;
					finished = false;
				}
				else
				{
					temp[i][param] = endParams[param];
				}
			}
		}
		if(finished)
		{
			Main.tween.removeEventListener(Event.ENTER_FRAME, tweenSection);
			fixRotation();
		}
	}
	
	private function fixRotation():void
	{
		if(!inMotion) return;
		
		var place:int=0;
		temp = new Vector.<MiniCube>(27);
		for(var i:int=0; i<27; i++)
		{
			miniCubes[i].update();
			place = miniCubes[i].location.z*9 + miniCubes[i].location.y*3 + miniCubes[i].location.x;
			temp[place] = miniCubes[i];
		}
		
		miniCubes = temp;
		
		inMotion = false;
	}
}

class MiniCube extends DisplayObject3D
{
	public var cube:Cube;
	private var _loc:Number3D;
	private var _selFace:String;
	
	private var faceNums:Object = {
		'back': new Number3D(0,0,1),
		'front': new Number3D(0,0,-1),
		'top': new Number3D(0,-1,0),
		'bottom': new Number3D(0,1,0),
		'right': new Number3D(-1,0,0),
		'left': new Number3D(1,0,0)
	}
	
	public function MiniCube(k:int, j:int, i:int)
	{
		var matList:Object = {all: 	new ColorMaterial(0x000000, 1, true)};
		if(i == 0) matList.back = 	createColorMC(0xD80505, 'back');
		if(i == 2) matList.front = 	createColorMC(0xFF9900, 'front');
		if(j == 2) matList.top = 	createColorMC(0xFFFFFF, 'top');
		if(j == 0) matList.bottom = createColorMC(0xFFFF00, 'bottom');
		if(k == 2) matList.right = 	createColorMC(0x0018EE, 'right');
		if(k == 0) matList.left = 	createColorMC(0x1CA91B, 'left');
		
		cube = new Cube(new MaterialsList(matList), 10, 10, 10);
		
		addChild(cube);
		
		name = "MC"+i+j+k;
		cube.x = 11*k - 11;
		cube.y = 11*j - 11;
		cube.z = 11*i - 11;
		
		_loc = new Number3D(k,j,i);
	}
	
	public function update():void
	{
		cube.transform = Matrix3D.multiply(this.transform, cube.transform);
		rotationX = rotationY = rotationZ = 0;
		
		_loc.x = Math.round((cube.x + 11)/11);
		_loc.y = Math.round((cube.y + 11)/11);
		_loc.z = Math.round((cube.z + 11)/11);
		
		//Round off position
		cube.x = 11*_loc.x - 11;
		cube.y = 11*_loc.y - 11;
		cube.z = 11*_loc.z - 11;
		
		//Round off rotation
		var m:Matrix3D = cube.transform;
		for(var i:int=1; i<4; i++)
		{
			for(var j:int=1; j<4; j++)
			{
				m['n'+i+j] = Math.round(m['n'+i+j]);
			}
		}
		cube.transform = m;
	}
	
	public function get location():Number3D { return _loc; }
	public function get selectedFace():String { return _selFace; }
	public function get selectedSide():Number3D 
	{
		var n:Number3D = faceNums[_selFace];
		n = MyUtils.transformNumber(n, cube.transform);
		
		return n;
	}
	
	private function createColorMC(color:uint, name:String):MovieMaterial
	{
		var colorBox:Sprite = new Sprite();
		colorBox.graphics.beginFill(color);
		colorBox.graphics.drawRect(0, 0, 100, 100);
		colorBox.graphics.endFill();
		colorBox.name = name;
		colorBox.mouseChildren = false;
		colorBox.addEventListener(MouseEvent.MOUSE_DOWN, onMovieMatClicked);
		
		var movieMat:MovieMaterial = new MovieMaterial(colorBox, true, true);
		movieMat.interactive = true;
		movieMat.smooth = true;
		
		return movieMat;
	}
	
	private function onMovieMatClicked(event:MouseEvent):void
	{
		_selFace = event.target.name;
		this.dispatchEvent(event);
	}
}

class MyUtils
{
	public static function transformNumber(n:Number3D, m:Matrix3D):Number3D
	{
		var v:Number3D = new Number3D(0,0,0);
		
		v.x = m.n11 * n.x + m.n12 * n.y + m.n13 * n.z;
		v.y = m.n21 * n.x + m.n22 * n.y + m.n23 * n.z;
		v.z = m.n31 * n.x + m.n32 * n.y + m.n33 * n.z;
		
		return v;
	}
}