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

forked from: 3D Soccer Game Prototype - pv3d,jiglibflash

Papervision3D + jiglibflash 을 이용한 축구게임 프로토 타입 
간단하게 만들어 봤습니다. Fork를 통해 향상되고 멋진 기능을 가진 게임이 탄생하기 바랍니다. 
1. click ball
2. press key w,a,s,d

author : Yongho Ji, jidolstar@gmail.com
/**
 * Copyright spock1969 ( http://wonderfl.net/user/spock1969 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/dnSH
 */

// forked from jidolstar's 3D Soccer Game Prototype - pv3d,jiglibflash
package {
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.display.Graphics;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.KeyboardEvent;
    import flash.events.MouseEvent;
    import flash.filters.BlurFilter;
    import flash.geom.Vector3D;
    import flash.system.IME;
    import flash.system.IMEConversionMode;
    import flash.ui.Keyboard;
    import flash.ui.Mouse;
    import flash.ui.MouseCursor;
    import flash.utils.getTimer;
    
    import jiglib.cof.JConfig;
    import jiglib.geometry.JBox;
    import jiglib.geometry.JCapsule;
    import jiglib.geometry.JPlane;
    import jiglib.geometry.JSphere;
    import jiglib.geometry.JTerrain;
    import jiglib.math.JMatrix3D;
    import jiglib.physics.RigidBody;
    import jiglib.plugin.papervision3d.Papervision3DPhysics;
    import jiglib.plugin.papervision3d.Pv3dMesh;
    import jiglib.plugin.papervision3d.pv3dTerrain;
    
    import net.hires.debug.Stats;
    
    import org.papervision3d.Papervision3D;
    import org.papervision3d.core.utils.InteractiveSceneManager;
    import org.papervision3d.core.utils.Mouse3D;
    import org.papervision3d.events.FileLoadEvent;
    import org.papervision3d.events.InteractiveScene3DEvent;
    import org.papervision3d.lights.PointLight3D;
    import org.papervision3d.materials.BitmapMaterial;
    import org.papervision3d.materials.ColorMaterial;
    import org.papervision3d.materials.MovieAssetMaterial;
    import org.papervision3d.materials.MovieMaterial;
    import org.papervision3d.materials.WireframeMaterial;
    import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
    import org.papervision3d.materials.shaders.FlatShader;
    import org.papervision3d.materials.shaders.GouraudShader;
    import org.papervision3d.materials.shaders.LightShader;
    import org.papervision3d.materials.shaders.PhongShader;
    import org.papervision3d.materials.shaders.ShadedMaterial;
    import org.papervision3d.materials.special.FogMaterial;
    import org.papervision3d.materials.utils.MaterialsList;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.objects.parsers.Collada;
    import org.papervision3d.objects.parsers.DAE;
    import org.papervision3d.objects.primitives.Cube;
    import org.papervision3d.objects.primitives.Cylinder;
    import org.papervision3d.objects.primitives.Plane;
    import org.papervision3d.view.BasicView;
    import org.papervision3d.view.layer.ViewportLayer;
    import org.papervision3d.view.layer.util.ViewportLayerSortMode;
    
    [SWF(width="465", height="465", backgroundColor="#000000", frameRate="24")]
    /**
     * Papervision3D + jiglibflash 을 이용한 축구게임 프로토 타입 
     * 간단하게 만들어 봤습니다. Fork를 통해 향상되고 멋진 기능을 가진 게임이 탄생하기 바랍니다. 
     * 1. click ball
     * 2. press key w,a,s,d
     * 
     * author : Yongho Ji, jidolstar@gmail.com
     */ 
    public class SoccerGamePrototype extends BasicView {
        private var _physics:Papervision3DPhysics;
        private var _light:PointLight3D;
        private var _vpBallLayer:ViewportLayer;
        
        private var _ground:Plane;
        private var _ball:RigidBody;
        private var _ballRadius:Number = 30;
        
        private var _isShooting:Boolean = false;
        private var _isIniting:Boolean = false;
        private var _firstTime:Number;
        private var _ballX:Number;
        private var _windForce:Vector3D;
                
        private var _keyForward:Boolean=false;
        private var _keyBackward:Boolean=false;
        private var _keyLeft:Boolean=false;
        private var _keyRight:Boolean=false;
        
        /**
         * 생성자 
         */ 
        public function SoccerGamePrototype() {
            super(465, 465, true, true, "Target");
            configStage();
            configScene();
            initPhysics();
            createBall();
            createGround();
            createGoalNet();
            createGoalPost();
            createBox();
            startRendering();
            addEventHandler();
            addChild(new Stats);
        }
        
        /**
         * 스테이지 환경 설정 
         */ 
        private function configStage():void {
            stage.scaleMode=StageScaleMode.NO_SCALE;
            stage.align=StageAlign.TOP_LEFT;
            stage.quality=StageQuality.BEST;
            stage.frameRate = 24;
            stage.showDefaultContextMenu = false;
        }
        
        /**
         * 이벤트 핸들러 함수 등록 
         */ 
        private function addEventHandler():void {
            stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
            stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
        }
        
        /**
         * 3D 환경 기본 설정 
         */ 
        private function configScene():void {
            viewport.containerSprite.sortMode=ViewportLayerSortMode.INDEX_SORT;
            viewport.containerSprite.addLayer(_vpBallLayer=new ViewportLayer(viewport, null));
            _vpBallLayer.sortMode=ViewportLayerSortMode.Z_SORT;    

            camera.x=-500;
            camera.y=200;
            camera.z=0;
            
            _light=new PointLight3D(true, false);
            _light.x=-400;
            _light.y=300;
            _light.z=-100;
        }
        
        /**
         * 물리엔진 기본 설정 
         */ 
        private function initPhysics():void {
            _physics=new Papervision3DPhysics(scene, 10);
        }
        
        /**
         * 바닥 생성  
         */ 
        private function createGround():void {
            _ground = new Plane( new WireframeMaterial(0xff0000), 1000, 1000, 10, 10 );
            scene.addChild(_ground);
            var jGround:JPlane = new JPlane(new Pv3dMesh(_ground));
            jGround.setOrientation(JMatrix3D.getRotationMatrixAxis(90));
            _physics.addBody(jGround);
            jGround.y = 0;
            jGround.friction = 10;
        }
        
        /**
         * 그물망 생성
         */ 
        private function createGoalNet():void {
            var i:Number, dx:Number = 15, dy:Number = 15, dd:Number = 15;
            var w:Number = 600, h:Number = 300, d:Number = 100;
            var movie : Sprite = new Sprite();
            var g:Graphics = movie.graphics;
            var jGoalNet:RigidBody;
            var material:MovieMaterial,materials:MaterialsList;
            
            //Back
            g.lineStyle(3,0xaaaaaa,2);
            for( i = 0; i <= w; i+=dx ) {
                g.moveTo(i,0);
                g.lineTo(i,h);
            }
            for( i = 0; i <= h; i+=dy ) {
                g.moveTo(0,i);
                g.lineTo(w,i);
            }
            material = new MovieMaterial(movie,true,false,false,null);
            material.oneSide = false;
            materials=new MaterialsList();
            materials.addMaterial(material, "back");
            jGoalNet = _physics.createCube( materials, w, 100, h, 5, 1, 5, 0, 0 );
            jGoalNet.movable = false;
            jGoalNet.rotationY = 90;
            jGoalNet.material.restitution = 0.01;
            jGoalNet.moveTo(new Vector3D(600+50,150,0,0));
            
            //Top
            movie = new Sprite;
            g = movie.graphics;
            g.lineStyle(3,0xaaaaaa,2);
            for( i = 0; i <= w; i+=dx ) {
                g.moveTo(i,0);
                g.lineTo(i,d);
            }
            for( i = 0; i <= d; i+=dd ) {
                g.moveTo(0,i);
                g.lineTo(w,i);
            }            
            jGoalNet = _physics.createCube( materials, w, 1, d, 3, 1, 1, 0, 0 );
            jGoalNet.movable = false;
            jGoalNet.rotationY = 90;
            jGoalNet.rotationZ = 90;
            jGoalNet.material.restitution = 0.01;
            jGoalNet.moveTo(new Vector3D(550,300,0,0));
            
            //Left
            movie = new Sprite;
            g = movie.graphics;
            g.lineStyle(3,0xaaaaaa,2);
            for( i = 0; i <= d; i+=dd ) {
                g.moveTo(i,0);
                g.lineTo(i,h);
            }
            for( i = 0; i <= h; i+=dy ) {
                g.moveTo(0,i);
                g.lineTo(d,i);
            }            
            jGoalNet = _physics.createCube( materials, d, 1, h, 1, 1, 1, 0, 0 );
            jGoalNet.movable = false;
            jGoalNet.material.restitution = 0.01;
            jGoalNet.rotationY = -180;
            jGoalNet.moveTo(new Vector3D(550,h/2,-w/2,0));
            
            //Right
            jGoalNet = _physics.createCube( materials, d, 1, h, 1, 1, 1, 0, 0 );
            jGoalNet.movable = false;
            jGoalNet.material.restitution = 0.01;
            jGoalNet.moveTo(new Vector3D(550,h/2,w/2,0));
            
        }
        
        /**
         * 볼 포스트 생성 - Cylinder 3개로 생성 
         */ 
        private function createGoalPost():void {
            function createCapsule($radius:Number,$height:Number):JCapsule {
                var material:FlatShadeMaterial = new FlatShadeMaterial(_light, 0xFFFFFF, 0x555555, 5);
                var cylinder:Cylinder = new Cylinder(material,$radius,$height,15,1,-1,true,false);
                var jCapsule:JCapsule = new JCapsule(new Pv3dMesh(cylinder),$radius,$height);
                jCapsule.movable = false;
                jCapsule.material.restitution = 0.9;
                scene.addChild(cylinder);
                _physics.addBody( jCapsule );
                return jCapsule;
            }    
            
            var jCapsule:JCapsule;
            jCapsule = createCapsule(10,300);
            jCapsule.moveTo(new Vector3D(500,150,-300,0));
            jCapsule = createCapsule(10,300);
            jCapsule.moveTo(new Vector3D(500,150,300,0));
            jCapsule = createCapsule(10,610);
            jCapsule.rotationX = 90;
            jCapsule.moveTo(new Vector3D(500,300-5,0,0));
        }
        
        /**
         * 4개의 Box들 생성 
         */ 
        private function createBox():void {
            var materials:MaterialsList=new MaterialsList();
            materials.addMaterial(new FlatShadeMaterial(_light, 0x00FF00, 0x555555, 5), "all");
            var box:RigidBody;
            for (var i:int=1; i < 5; i++) {
                box=_physics.createCube(materials, 100, 100, 100, 3, 3, 3);
                box.mass=1;
                box.x = 300;
                box.y=300 * i;
                _vpBallLayer.addDisplayObject3D(_physics.getMesh(box));
            }
        }
        
        /**
         * 축구공 생성 
         */ 
        private function createBall():void {
            var material:FlatShadeMaterial = new FlatShadeMaterial(_light, 0xFFFFFF, 0x555555, 105);
            _ball=_physics.createSphere(material, _ballRadius, 10, 8);
            material.interactive = true;
            _vpBallLayer.addDisplayObject3D(_physics.getMesh(_ball));
            _ball.x=-300;
            _ball.y=30;
            _ball.mass=1;
            _ball.friction=10;
            
            var mesh:DisplayObject3D = _physics.getMesh(_ball);
            mesh.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, press);
            
            //공을 누른다.
            function press($e:InteractiveScene3DEvent=null):void {
                mesh.removeEventListener(InteractiveScene3DEvent.OBJECT_PRESS, press );
                mesh.addEventListener(InteractiveScene3DEvent.OBJECT_RELEASE, release );
            }
            //공을 찬다!
            function release($e:InteractiveScene3DEvent=null):void {
                mesh.addEventListener(InteractiveScene3DEvent.OBJECT_PRESS, press );
                mesh.removeEventListener(InteractiveScene3DEvent.OBJECT_RELEASE, release );                
                shootBall();
            }            
        }
        
        /**
         * 축구공을 찬다.
         */ 
        private function shootBall():void {
            _isShooting = true;
            _ballX = _ball.x;
            _firstTime = getTimer();
            
            var mesh:DisplayObject3D = Pv3dMesh(_ball.skin).mesh;
            mesh.calculateScreenCoords(camera); //공의 스크린 좌표 계산. 3D->2D
            var kickPower:Number = Math.random()*500+200;
            var kickPosZTheta:Number = Math.tan( (stage.mouseX-mesh.screen.x-viewport.width/2)/_ballRadius )
            var kickPosYTheta:Number = Math.tan( (stage.mouseY-mesh.screen.y-viewport.height/2)/_ballRadius );
            var kickPowerX:Number = kickPower * Math.cos(kickPosYTheta)*Math.cos(kickPosZTheta);
            var kickPowerY:Number = kickPower * Math.sin(kickPosYTheta);
            var kickPowerZ:Number = kickPower * Math.cos(kickPosYTheta)*Math.sin(kickPosZTheta);
            _ball.addWorldForce(new Vector3D(kickPowerX,kickPowerY,kickPowerZ),_ball.currentState.position);
            _ball.addBodyTorque(new Vector3D(0, 0, 0));
            
            _windForce = new Vector3D( 0, 0, Math.random()*10-5);
        }
                
        /**
         * 3D 렌더링, 물리엔진 가동, 키보드에 따른 카메라 이동, 축구공 액션 
         */ 
        protected override function onRenderTick(event:Event=null):void {
            _physics.step(); 
            if( _isShooting ) {
                _ball.addWorldForce(_windForce,_ball.currentState.position);
                if( _ball.x > 500 || _ball.x < _ballX || getTimer() - _firstTime > 2000 ) {
                    _isShooting = false;
                    _isIniting = true;
                    _firstTime = getTimer();
                }
                _ballX = _ball.x;
            }
            if( _isIniting ) {
                if( getTimer() - _firstTime > 2000 ) {
                    _isIniting = false;
                    _ball.x=-300;
                    _ball.y=30;
                    _ball.z = 0;
                    _ball.setVelocity( new Vector3D(0,0,0) );
                }
            }
            moveCamera();
            super.onRenderTick(event);
        }
        
        /**
         * 카메라 이동 
         */     
        private function moveCamera():void {
            var dist:Number = 30;
            if (_keyForward) {
                camera.moveForward(dist);
            }
            if (_keyBackward) {
                camera.moveBackward(dist);
            }
            if (_keyLeft) {
                camera.moveLeft(dist);
            }
            if (_keyRight) {
                camera.moveRight(dist);
            }
        }
        
        /**
         * 키보드 Down 핸들러 
         */ 
        private function keyDownHandler(e:KeyboardEvent):void {
            if (e.keyCode == 229) {
                IME.conversionMode=IMEConversionMode.ALPHANUMERIC_HALF;
            }
            switch (e.keyCode) {
                case 87:
                    _keyForward=true;
                    break;
                case 83:
                    _keyBackward=true;
                    break;
                case 65:
                    _keyLeft=true;
                    break;
                case 68:
                    _keyRight=true;
                    break;
                
            }
        }
    
        /**
         * 키보드 Up 핸들러 
         */ 
        private function keyUpHandler(e:KeyboardEvent):void {
            switch (e.keyCode) {
                case 87:
                    _keyForward=false;
                    break;
                case 83:
                    _keyBackward=false;
                    break;
                case 65:
                    _keyLeft=false;
                    break;
                case 68:
                    _keyRight=false;
                    break;
            }
        }

    }
}