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

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 jidolstar ( http://wonderfl.net/user/jidolstar )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/j8ly
 */

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;
			}
		}

	}
}