forked from: [Papervision3D] Rubik's Cube (v1.1)

by tepe forked from [Papervision3D] Rubik's Cube (v1.1) (diff: 232)
Next Step: Add Timer. (Look for solved state)
Final Step: Auto Solve.

------------------------------------------------
♥0 | Line 214 | Modified 2012-03-19 13:56:49 | MIT License
play

ActionScript3 source code

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

/**
Next Step: Add Timer. (Look for solved state)
Final Step: Auto Solve.
**/


//------------------------------------------------
package {
    import flash.display.*;
    import flash.events.*;
    import flash.geom.Point;
    import flash.text.*;
    import flash.ui.Keyboard;
    
    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;

    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 var shift:Boolean;
        
        private  var tf:TextField = new TextField();
        
        public static const SCRAMBLE_DEPTH:int = 22;
        public static var tween:Sprite = new Sprite();

        private var axii:Array = ['x','y','z'];
        
        //エントリ
        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);
            stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
            stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
        }
        
        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;
                if(!shift){//カメラZ軸回転
                    m = Matrix3D.rotationY((mouseX - mdp.x)/150);
                    m = Matrix3D.multiply(m, Matrix3D.rotationX(-(mouseY - mdp.y)/150));
                }
                else {//オブジェクト回転
                    var rot:Number = (mouseX < 233)? (mouseY - mdp.y)/150 : (mdp.y - mouseY)/150;
                    rot += (mouseY > 233)? (mouseX - mdp.x)/150 : (mdp.x - mouseX)/150;
                    m = Matrix3D.rotationZ(rot);
                }
                //回転
                rubik.transform = Matrix3D.multiply(m, rubik.transform);
                
                
                mdp.x = mouseX;
                mdp.y = mouseY;
            }
        }
        
        private function onEventRender3D(e:Event):void        {    
            view.singleRender();
        }
        
        private function onKeyDown(event:KeyboardEvent):void        {
            shift = event.shiftKey;
        }
        
        private function onKeyUp(event:KeyboardEvent):void        {
            shift = event.shiftKey;
        }
        
    }
}



//------------------------------------------------
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.text.TextField;
    import flash.text.TextFieldAutoSize;
    
    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;

        cube = new MiniCube(1,1,1);
        //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;
        }
    }
    */

}


//------------------------------------------------
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)};
        matList.back =     createColorMC(0xD80505, 'back');
        matList.front =     createColorMC(0xFF9900, 'front');
        matList.top =     createColorMC(0xFFFFFF, 'top');
        matList.bottom = createColorMC(0xFFFF00, 'bottom');
        matList.right =     createColorMC(0x0018EE, 'right');
        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;
    }
}