forked from: Pixel isometric cube

by kevinlin forked from Pixel Isometric Cube (diff: 86)
@author max.huang
@see http://code.google.com/p/pixas/

trying to get shadow
♥0 | Line 465 | Modified 2012-07-16 22:48:14 | MIT License
play

ActionScript3 source code

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

// forked from max.huang's Pixel isometric cube
package 
{
    import com.bit101.components.*;
    import flash.display.Sprite;
    import flash.events.Event;
    
    /**
     * @author max.huang
     * @see http://code.google.com/p/pixas/
     */
    public class Main extends Sprite 
    {
        private var cubeContainer:Sprite;
        private var vBox:VBox;
        private var vBoxColor:VBox;
        private var vBoxBorder:VBox;
        private var sliX:HUISlider;
        private var sliY:HUISlider;
        private var sliZ:HUISlider;
        private var colorChooser:ColorChooser;
        private var cb:CheckBox;
        
        public function Main():void 
        {
            cubeContainer = new Sprite();
            cubeContainer.x = Math.floor(stage.stageWidth / 2);
            cubeContainer.y = Math.floor(stage.stageHeight / 2);
            addChild(cubeContainer);
            
            //control menu
            vBox = new VBox(this , 5, 4);
            var lableA:Label = new Label(vBox, 0, 0, "Cube dimension:");
            sliX = new HUISlider(vBox, 0, 0, "X", updateCube);
            sliY = new HUISlider(vBox, 0, 0, "Y", updateCube);
            sliZ = new HUISlider(vBox, 0, 0, "Z", updateCube);
            var s:HUISlider;
            for each(s in [sliX, sliY, sliZ])
            {
                s.setSliderParams( 6, 220, 100);
                s.tick = 2;
                s.labelPrecision = 0;
            }
            sliZ.tick = 1;            
            vBoxColor = new VBox(this , 5, 110);
            var lableB:Label = new Label(vBoxColor, 0, 0, "Cube top side color:");
            colorChooser = new ColorChooser(vBoxColor, 0, 0, 0xE6E8E9, updateCube);            
            vBoxBorder = new VBox(this , 5, 180);
            cb = new CheckBox(vBoxBorder, 0, 0, "Cube border", updateCube);
            cb.selected = true;
                        
            updateCube();
        }
        
        private function updateCube(e:Event = null):void
        {
            while (cubeContainer.numChildren > 0)
            {
                cubeContainer.removeChildAt(0);
            }            
            var cube:Cube = new Cube({ xAxis:sliX.value, yAxis:sliY.value, zAxis:sliZ.value }, CubeColor.getByHorizontalColor(colorChooser.value),cb.selected);
            cubeContainer.addChild(cube.generate());
        }
    }
}

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Matrix;
import flash.display.Sprite;

class CubeColor
{
    public var inner:uint;
    public var border:uint;
    public var borderHighlight:uint;
    public var left:uint;
    public var right:uint;
    public var horizontal : uint;
    public var shadow : uint;
    private static const BRIGHTNESS_GAIN : int = - 20;
    public function CubeColor
    (
        _border:uint = 0x949698,
        _borderHighlight:uint = 0xFFFFFF,
        _left:uint = 0xC9CFD0,
        _right:uint = 0xE6E8E9,
        _horizontal:uint = 0xEEEFF0,
        _shadow:uint = 0xA9AFB0
    ) 
    {
        border = get32(_border);
        borderHighlight = get32(_borderHighlight);
        left = get32(_left);
        right = get32(_right);
        horizontal = get32(_horizontal);
        shadow = get32(_shadow);
    }
    
    public static function getByHorizontalColor(_horizontal:uint):CubeColor
    {
        return new CubeColor
        (
            CubeColor.applyBrightness(_horizontal, BRIGHTNESS_GAIN * 4),
            CubeColor.applyBrightness(_horizontal, 0, true),
            CubeColor.applyBrightness(_horizontal, BRIGHTNESS_GAIN * 2),
            CubeColor.applyBrightness(_horizontal, BRIGHTNESS_GAIN),
            _horizontal,
            CubeColor.applyBrightness(_horizontal, BRIGHTNESS_GAIN / 2)
        );
    }
    
    private function get32(_color:uint):uint
    {
        var color:uint = _color < 0xFF000000 ? (_color + 0xFF000000) : _color;
        return color;
    }
    private static function applyBrightness (color : uint, brightness : int,highlight:Boolean = false) :uint 
    {
            
        var r :  int = ((color>>>16) & 0x000000FF);
        var g : int = ((color>>> 8) & 0x000000FF);
        var b : int = ((color) & 0x000000FF);
        
        var y : int;
        var v : int;
        var u : int;

        y  =   ((r*313524)>>20) + ((g*615514)>>20) + ((b*119538)>>20);
        u  =  -((155189*r)>>20) - ((303038*g)>>20) + ((458227*b)>>20);
        v  =   ((644874*r)>>20) - ((540016*g)>>20) - ((104857*b)>>20);

        if (!highlight)
        {
            y += brightness;
        }
        else
        {
            y = 60 + Math.pow( y , 1.2);
        }

        r = y + ((1195376*v)>>20);
        g = y - ((408944*u)>>20) - ((608174*v)>>20);
        b = y + ((2128609*u)>>20);

        r = Math.max  (0,Math.min (r,255));
        g = Math.max (0,Math.min (g,255));
        b = Math.max (0,Math.min (b,255));

        return (r << 16) | (g << 8) | b;
    }
}

class AbstractPrimitive
{
    protected var matrix:Matrix;
    protected var w:uint;
    protected var h:uint;
    protected var dms:Object;
    protected var color:Object;
    protected var src_bmd:BitmapData;
    
    public function AbstractPrimitive() 
    {
        w = h = 0;
        matrix = new Matrix();
    }
    
    public function generate():Bitmap
    {
        var bm : Bitmap = new Bitmap(src_bmd.clone());
        bm.x = matrix.tx;
        bm.y = matrix.ty;
        return bm;
    }
    
    protected function initBmd():void
    {
        if (w == 0 || h == 0 )
        {
            throw new Error("BitmapData has not been initilized.");
        }
        src_bmd = new BitmapData(w, h , true , 0x00FFFFFF);
    }
}

class Cube extends AbstractPrimitive
{
    private var border:Boolean;
    public function Cube(_dms: Object, _color:CubeColor, _border:Boolean = true)
    {
        super();
        border = _border;
        initRender(_dms, _color);
        initRectangle();
        initBmd();
        build();
    }

    private function initRender(_dms:Object,_color:CubeColor):void
    {
        dms = _dms;
        color = _color;
    }
    
    private function initRectangle():void
    {
        w = dms.xAxis + dms.yAxis*2;
        h = dms.zAxis + (dms.xAxis*2 + dms.yAxis) / 2;
        //22.6 degrees implementation
        w -= 2;
        h -= 1;        
        //the matrix offset between the bitmap and the 3d pixel coordinate ZERO point
        matrix.tx = - dms.yAxis*2 + 2;
        matrix.ty = - dms.zAxis;
    }    
    
    private function build():void
    {
        //horizontal layer
        var brick:Brick = new Brick
        (
            {xAxis:dms.xAxis, yAxis:dms.yAxis}, 
            {border:color.border, inner:color.horizontal },
            border
        );        
        //left side
        var sideX:SideX = new SideX
        (
            {xAxis:dms.xAxis, zAxis:dms.zAxis}, 
            {border:color.border, inner:color.left },
            border
        );        
        //right side
        var sideY:SideY = new SideY
        (
            {yAxis:dms.yAxis, zAxis:dms.zAxis}, 
            {border:color.border, inner:color.right },
            border
        );
        //lower shadow
        var shadowX:ShadowX = new ShadowX
        (
            {xAxis:dms.xAxis, yAxis:dms.yAxis}, 
            {border:color.border, inner:color.shadow },
            border
        );
        
        var light_bm:Bitmap = generateHighLight();
        
        var po:Sprite = new Sprite();    
        var po_sx:Sprite = new Sprite();
        po_sx.addChild(shadowX.generate());
        var po_brick:Sprite = new Sprite();
        po_brick.addChild(brick.generate());
        var po_x:Sprite = new Sprite();
        po_x.addChild(sideX.generate());
        var po_y:Sprite = new Sprite();
        po_y.addChild(sideY.generate());
        
        po_brick.x = dms.yAxis*2 - 2;
        po_x.x = dms.yAxis;
        po_x.y = dms.zAxis + dms.yAxis / 2 - 1;
        po_y.x = w - 2;
        po_y.y = dms.zAxis + dms.xAxis / 2 - 1;
        po_sx.x = dms.yAxis;
        po_sx.y = dms.zAxis + dms.yAxis / 2 - 1;
        
        po.addChild(po_sx);
        po.addChild(po_x);
        po.addChild(po_y);
        po.addChild(po_brick);
        if (border)
        {
            po.addChild(light_bm);
        }        
        src_bmd.draw(po);
        //fix the middle light
        if (!border)
        {
            for (var i:uint = 0; i < dms.zAxis; i++ )
            {
                src_bmd.setPixel32(dms.xAxis - 2, (dms.xAxis + dms.yAxis) / 2 - 1 + i, color.left);
            }
        }
    }
    
    private function generateHighLight():Bitmap
    {
        var bmd:BitmapData = new BitmapData(w, h , true , 0x00FFFFFF);
        var offsetX : uint = dms.xAxis*2 - 2;
        var offsetY : uint = (dms.xAxis + dms.yAxis) / 2 - 2;        
        //the 2px in bounding without hightlight
        for (var i:uint = 0; i < dms.xAxis - 2; i++ )
        {
            bmd.setPixel32(offsetX + 1 - i, offsetY - Math.floor(i / 2), color.borderHighlight);
        }        
        //the 2px in bounding without hightlight
        for (var j:uint = 0; j < dms.yAxis - 2; j++ )
        {
            bmd.setPixel32(offsetX + j, offsetY - Math.floor(j / 2), color.borderHighlight);
        }
        for (var k:uint = 0; k < dms.zAxis; k++ )
        {
            bmd.setPixel32(offsetX, offsetY + k, color.borderHighlight);
        }        
        return new Bitmap(bmd);
    }    
}

class SideY extends AbstractPrimitive
{
    private var border:Boolean;
    public function SideY(_dms:Object,_color:Object,_border: Boolean = true) 
    {
        super();
        border = _border;
        initRender(_dms, _color);
        initRectangle();
        initBmd();
        build();
    }
    
    private function initRender(_dms:Object,_color:Object):void
    {
        dms = _dms;
        color = _color;
        if (!border)
        {
            color.border = color.inner;
        }
    }
            
    private function initRectangle():void
    {
        w = dms.yAxis;
        h = dms.zAxis + dms.yAxis / 2;        
        //the matrix offset between the bitmap and the 3d pixel coordinate ZERO point
        matrix.tx = - dms.yAxis + 2;
        matrix.ty = - dms.zAxis;
    }
    
    private function build():void
    {
        var xOffsetInner:int = 0;
        var yOffsetInner:int = h - dms.zAxis - 1
        var xOffsetOut:int = dms.yAxis - 1;
        var yOffsetOut:int = dms.zAxis;

        src_bmd.lock();        
        //y axis
        for (var i:uint = 0; i < dms.yAxis ; i++) 
        {
            src_bmd.setPixel32(xOffsetInner + i, yOffsetInner - Math.floor(i / 2), color.border);
            src_bmd.setPixel32(xOffsetOut - i, yOffsetOut + Math.floor(i / 2), color.border);
        }        
        //z axis
        for (var j:uint = 0; j < dms.zAxis ; j++) 
        {
            src_bmd.setPixel32(xOffsetInner, yOffsetInner + j, color.border);
            src_bmd.setPixel32(xOffsetOut , yOffsetOut - j, color.border);
        }        
        //fill an pixel graphic enclosed
        src_bmd.floodFill(Math.floor(w / 2), Math.floor(h / 2),  color.inner);        
        src_bmd.unlock();
    }
    
}

class SideX extends AbstractPrimitive
{
    private var border:Boolean;
    public function SideX(_dms:Object,_color:Object,_border:Boolean = true)
    {
        super();
        border = _border;
        initRender(_dms, _color);
        initRectangle();
        initBmd();
        build();
    }
    
    private function initRender(_dms:Object,_color:Object):void
    {
        dms = _dms;
        color = _color;
        if (!border)
        {
            color.border = color.inner;
        }
    }
    
    private function initRectangle():void
    {
        w = dms.xAxis;
        h = dms.zAxis + dms.xAxis / 2;        
        //the matrix offset between the bitmap and the 3d pixel coordinate ZERO point
        matrix.tx = 0;
        matrix.ty = - dms.zAxis;
    }
    
    private function build():void
    {
        var xOffsetInner:int = 0;
        var yOffsetInner:int = dms.zAxis;
        var xOffsetOut:int = dms.xAxis - 1;
        var yOffsetOut:int = h - dms.zAxis - 1;

        src_bmd.lock();        
        //x axis
        for (var i:uint = 0; i < dms.xAxis ; i++) 
        {
            src_bmd.setPixel32(xOffsetInner + i, yOffsetInner + Math.floor(i / 2), color.border);
            src_bmd.setPixel32(xOffsetOut - i, yOffsetOut - Math.floor(i / 2), color.border);
        }        
        //z axis
        for (var j:uint = 0; j < dms.zAxis ; j++) 
        {
            src_bmd.setPixel32(xOffsetInner, yOffsetInner - j, color.border);
            src_bmd.setPixel32(xOffsetOut , yOffsetOut +j, color.border);
        }        
        //fill an pixel graphic enclosed
        src_bmd.floodFill(Math.floor(w / 2), Math.floor(h / 2),  color.inner);        
        src_bmd.unlock();
    }    
}

class Brick extends AbstractPrimitive
{
    private var border:Boolean;    
    public function Brick(_dms: Object,_color:Object,_border:Boolean = true)
    {
        super();
        border = _border;
        initRender(_dms, _color);
        initRectangle();
        initBmd();
        build();
    }
    
    private function initRender(_dms:Object,_color:Object):void
    {
        dms = _dms;
        color = _color;
        if (!border)
        {
            color.border = color.inner;
        }
    }
    
    private function initRectangle():void
    {
        w = dms.xAxis + dms.yAxis;
        h = (dms.xAxis + dms.yAxis) / 2;        
        // 22.6 degrees implementation
        w -= 2;
        h -= 1;        
        //the matrix offset between the bitmap and the 3d pixel coordinate ZERO point
        matrix.tx = - dms.yAxis + 2;
        matrix.ty = 0;
    }
    
    private function build():void
    {
        var xOffsetInner:int = dms.yAxis - 2;
        var yOffsetInner:int = 0;
        var xOffsetOut:int = dms.xAxis - 1;
        var yOffsetOut:int = h - 1;
        
        src_bmd.lock();
        //x axis
        for (var i:uint = 0; i < dms.xAxis ; i++) 
        {
            src_bmd.setPixel32(xOffsetInner + i, yOffsetInner + Math.floor(i / 2), color.border);
            src_bmd.setPixel32(xOffsetOut - i, yOffsetOut - Math.floor(i / 2), color.border);
        }        
        //z axis
        for (var j:uint = 0; j < dms.yAxis ; j++) 
        {
            src_bmd.setPixel32(xOffsetInner + 1 - j, yOffsetInner + Math.floor(j / 2), color.border);
            src_bmd.setPixel32(xOffsetOut - 1 + j, yOffsetOut - Math.floor(j / 2), color.border);
        }        
        //fill an pixel graphic enclosed
        src_bmd.floodFill(Math.floor(w / 2), Math.floor(h / 2),  color.inner);        
        src_bmd.unlock();
    }
}

class ShadowX extends AbstractPrimitive
{
    private var border:Boolean;    
    public function ShadowX(_dms: Object,_color:Object,_border:Boolean = true)
    {
        super();
        border = _border;
        initRender(_dms, _color);
        initRectangle();
        initBmd();
        build();
    }
    
    private function initRender(_dms:Object,_color:Object):void
    {
        dms = _dms;
        color = _color;
        if (!border)
        {
            color.border = color.inner;
        }
    }
    
    private function initRectangle():void
    {
        w = dms.xAxis + dms.yAxis;
        h = (dms.xAxis + dms.yAxis) / 2;        
        // 22.6 degrees implementation
        w -= 2;
        h -= 1;        
        //the matrix offset between the bitmap and the 3d pixel coordinate ZERO point
        matrix.tx = - dms.yAxis + 2;
        matrix.ty = 0;
    }
    
    private function build():void
    {
        var xOffsetInner:int = dms.yAxis - 2;
        var yOffsetInner:int = 0;
        var xOffsetOut:int = dms.xAxis - 1;
        var yOffsetOut:int = h - 1;
        
        src_bmd.lock();
        //x axis
        for (var i:uint = 0; i < dms.xAxis ; i++) 
        {
            src_bmd.setPixel32(xOffsetInner + i, yOffsetInner + Math.floor(i / 2), color.inner);
            src_bmd.setPixel32(xOffsetOut - i, yOffsetOut/2 - Math.floor(i / 2), color.inner);
        }        
        //z axis
        for (var j:uint = 0; j < dms.yAxis ; j++) 
        {
            src_bmd.setPixel32(xOffsetInner + 1 - j, 0, color.inner);
            src_bmd.setPixel32(xOffsetOut - 1 + j, yOffsetOut/2, color.inner);
        }        
        //fill an pixel graphic enclosed
        src_bmd.floodFill(Math.floor(w/2 + 1), Math.floor(h/2 - 1),  color.inner);        
        src_bmd.unlock();
    }
}