p3d

by Cheshir
first try make simple paralax
♥0 | Line 192 | Modified 2015-06-05 02:07:09 | MIT License
play

ActionScript3 source code

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

/* first try make simple paralax */
package {
    
    import flash.ui.Keyboard;
    import flash.events.KeyboardEvent;
    import flash.geom.Point;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    import flash.events.Event;
    import flash.display.Sprite;
    public class FlashTest extends Sprite {
        private var tf:TextField = new TextField();
        private var moveSpeed:Number = 2;
        private var cameraView:Sprite;
        private var camera:MyCamera;
        public function FlashTest() {
            // Итак... эффект паралакса есть... 
            Point3D.centerX = stage.stageWidth/2;
            Point3D.centerY = stage.stageHeight/2;
            
            addChild(tf);
            
            cameraView = new Sprite();
            cameraView.graphics.beginFill(0);
            cameraView.graphics.drawRect(0,0,stage.stageWidth/2,stage.stageHeight/2);
            cameraView.x = stage.stageWidth/2;
            cameraView.y = stage.stageHeight/2;
            addChild(cameraView);
            
            addEventListener(Event.ENTER_FRAME, update);
            stage.addEventListener(MouseEvent.CLICK, stopMove);
            stage.addEventListener(MouseEvent.MOUSE_DOWN, startMove);
                        
            /* Теперь... предположим, я хочу накидать 2д сетку... уходящую к горизонту...
            for(var tz:int=0; tz<20; tz++){
                for(var tx:int=0; tx<18; tx++){
                    points.push(new Point3D(tx*30, stage.stageHeight*Math.random(), tz*30));
                }
            }    //*/
            // Теперь давай создадим то, что станет камерой...
            camera = new MyCamera(150,20,20, cameraView);    // Сейчас камера ближе... кубики начинаются с Z=100;
            for(var tx:int=0; tx<12; tx+=2){
                boxes.push(new Box(Math.random()*3,Math.random()*3,Math.random()*3));
            }
            camera.viewBoxes = boxes;
            tf.text = 'boxes:'+camera.viewBoxes.length;
        }
        private var boxes:Array = [];
        private var points:Array = [];
        private function update(e:Event):void{
            this.graphics.clear();
            this.graphics.lineStyle(0.5);
            this.graphics.beginFill(0xccffcc);
            this.graphics.drawCircle(Point3D.centerX, Point3D.centerY, 3);
            for(var i:int=0; i<boxes.length; i++){
            //    points[i].z += 2;
            //   this.graphics.moveTo(points[i].x, points[i].y);
            //      camera.y += 2;        // Падение камеры... вобщем то, я хочу чтобы у нее был собственный бокс, который бы следил за ней...
            //      camera.cameraBox.drawBoxOn(this,0xffcc00,0xffffff); // У камеры есть собственный бокс
                  camera.calculateBox();    // В принципе.. его наверное можно использовать для проверки столкновений...
                  camera.render();
                  boxes[i].drawBoxOn(this);
            }
            this.graphics.beginFill(0xff0000);
            this.graphics.drawCircle(camera.realX, camera.realY, 5-camera.z/500);
            
            if(cameraMove){
                //Point3D.centerX = mouseX; Point3D.centerY = mouseY;
                selectBoxOnView();
                // Нужно рассчитать поворот камеры в зависимости от положения мыши...
                //camera.move();    // Нужно подвинуть камеру, в том направлении, в котором она повернута...
            }
        }
        private function stopMove(e:MouseEvent):void {
            cameraMove = false;
        }
        private var cameraMove:Boolean = false;
        private function startMove(e:MouseEvent):void {
            cameraMove = true;
        }
        
        private function selectBoxOnView():void{
            // Так... попроубем найти бокс по которому попала мышь...
            //boxes[0].drawBoxOn(this, 1, 0xff0000);
            camera.x = mouseX; camera.y = mouseY;
            camera.calculateBox();
            camera.cameraBox.drawBoxOn(this, 1, 0xff0000);
            // Нужно провести луч от экрана к горизонту... 
            var p:Point3D = new Point3D(mouseX, mouseY, 0);
            var horisont:Point3D = new Point3D(Point3D.centerX, Point3D.centerY, Point3D.maxFar);
            this.graphics.lineStyle(1, 0xffff00);
            this.graphics.moveTo(p.realX, p.realY);
            this.graphics.lineTo(horisont.realX, horisont.realY);
        }
    }
}
import flash.display.Sprite;
import flash.geom.Point;

Class {
    class Box {    // Пусть бокс будет в простых величинах
        private var _x:int;
        private var _y:int;
        private var _z:int;
        public static var BoxSize:Number = 100;
        private var boxPoints:Array;
        private var planes:Array = [0,1,3,2, 4,5,7,6, 0,4,5,1, 1,3,7,5, 0,2,6,4, 3,2,6,7];    // all 6 faces...
        public function Box(x:int,y:int,z:int) {
            // вообще бокс должен состоять из 6 сторон, однако, мы же никогда не увидим больше 3-х верно?
            _x = x; _y = y; _z = z;
            test = new Point3D(x*BoxSize,y*BoxSize,z*BoxSize);
            // все же коробке нужны все 8 точек, а вот рендер уже можно будет сделать умнее...
            boxPoints = [new Point3D(x*BoxSize,y*BoxSize,z*BoxSize),
                        new Point3D(x*BoxSize+BoxSize,y*BoxSize,z*BoxSize),
                        new Point3D(x*BoxSize,y*BoxSize+BoxSize,z*BoxSize),
                        new Point3D(x*BoxSize+BoxSize,y*BoxSize+BoxSize,z*BoxSize),
                        
                        new Point3D(x*BoxSize,y*BoxSize,z*BoxSize+BoxSize),
                        new Point3D(x*BoxSize+BoxSize,y*BoxSize,z*BoxSize+BoxSize),
                        new Point3D(x*BoxSize,y*BoxSize+BoxSize,z*BoxSize+BoxSize),
                        new Point3D(x*BoxSize+BoxSize,y*BoxSize+BoxSize,z*BoxSize+BoxSize)];
        }
        private function recalculateBoxPoints():void {
            boxPoints[0].x = _x*BoxSize; boxPoints[0].y = _y*BoxSize; boxPoints[0].z = _z*BoxSize;
            boxPoints[1].x = _x*BoxSize+BoxSize; boxPoints[1].y = _y*BoxSize; boxPoints[1].z = _z*BoxSize;
            boxPoints[2].x = _x*BoxSize; boxPoints[2].y = _y*BoxSize+BoxSize; boxPoints[2].z = _z*BoxSize;
            boxPoints[3].x = _x*BoxSize+BoxSize; boxPoints[3].y = _y*BoxSize+BoxSize; boxPoints[3].z = _z*BoxSize;
            
            boxPoints[4].x = _x*BoxSize; boxPoints[4].y = _y*BoxSize; boxPoints[4].z = _z*BoxSize+BoxSize;
            boxPoints[5].x = _x*BoxSize+BoxSize; boxPoints[5].y = _y*BoxSize; boxPoints[5].z = _z*BoxSize+BoxSize;
            boxPoints[6].x = _x*BoxSize; boxPoints[6].y = _y*BoxSize+BoxSize; boxPoints[6].z = _z*BoxSize+BoxSize;
            boxPoints[7].x = _x*BoxSize+BoxSize; boxPoints[7].y = _y*BoxSize+BoxSize; boxPoints[7].z = _z*BoxSize+BoxSize;
        }
        public function set z(val:int):void { _z = val; this.recalculateBoxPoints(); }
        public function get z():int {return _z;}
        public function set x(val:int):void { _x = val; this.recalculateBoxPoints();}
        public function get x():int {return _x;}
        public function set y(val:int):void { _y = val; this.recalculateBoxPoints();}
        public function get y():int {return _y;}
        
        public function getPoints():Array{
            return boxPoints;
        }
        
        private var test:Point3D;
        public function drawBoxOn(canvas:Sprite, stroke:uint=0, fill:uint=0xcccccc):void {
            for(var i:int=0; i<planes.length; i+=4){
                canvas.graphics.lineStyle(1,stroke);
                canvas.graphics.beginFill(fill,0.5);
                canvas.graphics.moveTo(boxPoints[planes[i]].realX,boxPoints[planes[i]].realY);
                canvas.graphics.lineTo(boxPoints[planes[i+1]].realX,boxPoints[planes[i+1]].realY);
                canvas.graphics.lineTo(boxPoints[planes[i+2]].realX,boxPoints[planes[i+2]].realY);
                canvas.graphics.lineTo(boxPoints[planes[i+3]].realX,boxPoints[planes[i+3]].realY);
            }
            canvas.graphics.moveTo(boxPoints[0].realX,boxPoints[0].realY);
        }
    }
}

Class {
    class Point3D extends Point {
        public static var centerX:Number = 200;
        public static var centerY:Number = 200;
        public static var maxFar:Number = 2000;
        public var z:Number;
        public function Point3D(x:Number=0, y:Number=0, z:Number=0):void{
            super(x,y);
            this.z = z;
        }
        private var centerDirect:Number = 0;
        private var distanceDirect:Number = 0;
        public function get realX():Number {
            if(this.z>=maxFar)
                return centerX;
            var dx:Number = centerX-this.x;
            var dy:Number = centerY-this.y;
            centerDirect = Math.atan2(dy, dx);
            distanceDirect = Math.sqrt(dx*dx+dy*dy);
            var rX:Number = this.x + Math.cos(centerDirect)*Math.sqrt(this.z/maxFar)*distanceDirect;
            return rX;
        }
        public function get realY():Number {
            // Окей обратная перспектива все еще существует, но это уже не так важно...
            // Теперь ее можно просто обезать...
            if(this.z>=maxFar)
                return centerY;
            var dx:Number = centerX-this.x;
            var dy:Number = centerY-this.y;
            centerDirect = Math.atan2(dy, dx);
            distanceDirect = Math.sqrt(dx*dx+dy*dy);
            var rY:Number = this.y + Math.sin(centerDirect)*Math.sqrt(this.z/maxFar)*distanceDirect;
            return rY;
        }
    }
}

Class {
    class MyCamera extends Point3D {    // I think that can be only one camera in this implementaion of Point3D paralax
        public var cameraBox:Box;
        public var viewBoxes:Array = [];    // Сюда мы положим объекты которые будут отобраны для рендера...
        public var viewPoints:Array = [];    // давай ка соберем точки с коробок
        
        public var rotationY:Number = 90;    // Поворот относительно вертикальной оси, по умолчанию... 90... тоесть, от экрана...
        
        private var view:Sprite;
        private var viewH:Number;
        private var viewW:Number;
    
        public function MyCamera(x:Number, y:Number, z:Number, view:Sprite){
            super(x,y,z);
            this.view = view;
            this.viewH = view.width;
            this.viewW = view.height;
            Point3D.centerX = view.width/2;
            Point3D.centerY = view.width/2;
            cameraBox = new Box(x/Box.BoxSize, y/Box.BoxSize, z/Box.BoxSize);
        }
        public function calculateBox():void {
            cameraBox.x = x/Box.BoxSize;
            cameraBox.y = y/Box.BoxSize;
            cameraBox.z = z/Box.BoxSize;
        }
        // Считаю, что пора наладить рендер... так...
        public function render():void {
            view.graphics.clear();        // очищаем экран...
            view.graphics.beginFill(0);    
            view.graphics.drawRect(0,0,viewW, viewH);    // рисуем фон...
            for(var i:int=0; i<viewBoxes.length; i++){    // Рисуем бокс для всез в массиве отображения...
                  viewBoxes[i].drawBoxOn(view,0xffffff,0xffffff);
            }
        }
    }
}