// forked from runouw's 3d Racing Game Test // Added turning, you can now freely move around the track // Arrow Keys to move around // test using boxes to render a 3d pathway // inspired by ABA's UpDownRoad package { import flash.display.* import flash.events.*; import flash.text.*; [SWF(width="465",height="465",backgroundColor="0xFFFFFF",frameRate="45")] public class AS3Code extends Sprite{ public function AS3Code() { main=this; Width = stage.stageWidth; Height = stage.stageHeight; stage.addChild(main); debugText = new TextField(); debugText.width = 400; debugText.height = 300; debugText.multiline = true; debugText.wordWrap = true; debugText.textColor = 0x0000FF; debugText.selectable = false; clip = new MovieClip(); stage.addChild(clip); clip2 = new MovieClip(); stage.addChild(clip2); clip3 = new MovieClip(); stage.addChild(clip3); stage.addChild(debugText); initialize(); stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed); stage.addEventListener(KeyboardEvent.KEY_UP, keyReleased); addEventListener(Event.ENTER_FRAME, EveryFrame); } } } import flash.display.*; import flash.events.*; import flash.ui.*; import flash.utils.*; import flash.filters.* import flash.text.*; import flash.geom.* import flash.media.* import flash.net.* // import sandy.core.*; import sandy.core.data.*; import sandy.core.scenegraph.*; import sandy.events.* import sandy.materials.*; import sandy.materials.attributes.*; import sandy.primitive.*; import sandy.core.scenegraph.mode7.*; // var main:Sprite; var clip:MovieClip; var clip2:MovieClip; var clip3:MovieClip; var Width:int; var Height:int; var debugText:TextField = new TextField(); // var camera:Camera3D; var root:Group; var scene:Scene3D; // var camera2:Camera3D; var root2:Group; var scene2:Scene3D; // var box:Box; var boxArray:Vector.<boxParticle> = new Vector.<boxParticle>; var visibleBoxArray:Vector.<boxParticle> = new Vector.<boxParticle> var particles:uint = 150; var widthparticles:uint = 4; var lookForward:Number = 2.5; var road:Array = [ [ 0, 0, 0], // start [ 0, 0, 400],[ 0, 100, 500], // anchor, end [ 0, 300, 750],[ 0, 50,1000], [ 0,-450, 1500],[-500, -50,1500], [-1000, 450, 1500],[-1000,450,1000], [-1000, 450, 0],[-500, 225,-500], [ 0, 0,-1000],[ 0, 0, 0], [ 0, 0, 0],[ 0, 0, 0] ]; var roadTilt:Array = [ [ 0,120], [ 0,80],[ 0, 80], [ 0,120],[-0.5,100], [-0.6,100],[-0.7,100], [-0.7,120],[-0.6,120], [-0.5,100],[-0.4,120], [-0.8,120],[ 0,120] ]; var roadlength:int = 6; function initialize():void { camera = new Camera3D( 465, 465); camera.x = 0; camera.y = 0; camera.z = 0; root = new Group(); //camera.lookAt( 0, -150, 300); box = new Box("box", 10, 5, 20); box.y = 10; box.x = 200; box.z = 400; var mat:ColorMaterial = new ColorMaterial ( 0x7FDDFF ); mat.attributes = new MaterialAttributes ( new LightAttributes ()); mat.lightingEnable = true; box.appearance = new Appearance (mat); root.addChild(box); scene = new Scene3D( "scene", clip3, camera, root ); for(var i:int=0;i<particles;i++){ for(var h:int=-widthparticles;h<=widthparticles;h++){ var p:boxParticle = new boxParticle(); boxArray.push(p); clip2.addChild(p); } } camera2 = new CameraMode7( 465, 465); camera2.x = 0; camera2.y = 500; camera2.z = 0; root2 = new Group(); var box2:Box = new Box("box2",100,1000,100, "tri",2) box2.y = 500; box2.x = 200; box2.z = 800; box2.appearance = new Appearance (mat); box2.useSingleContainer = true; root2.addChild(box2); var box3:Box = new Box("box3",100,1000,100, "tri",2) box3.y = 500; box3.x = -200; box3.z = 800; box3.appearance = new Appearance (mat); box3.useSingleContainer = true; root2.addChild(box3); var bmd:BitmapData = new BitmapData(400, 400, false, 0xCCCCCCCC); var channels:uint = BitmapDataChannel.RED | BitmapDataChannel.BLUE | BitmapDataChannel.GREEN; bmd.perlinNoise(400, 400, 5, int(Math.random() * 10), true, true, channels, false, null); //bmd.colorTransform(new Rectangle(0, 0, 400, 400), new ColorTransform(1,1,0.3,1, 40,20,-10, 0)); bmd.applyFilter(bmd, bmd.rect, new Point(), new ColorMatrixFilter([ .5, .2, .1, 0, 0, // red .5, .5, .1, 0, 0, // green 0, .1, .3, 0, 0, // blue 0, 0, 0, 1, 0] // alpha ) ); var ground:Mode7 = new Mode7(); ground.setBitmap(bmd, 2, true, false); ground.setHorizon(false); //ground.setNearFar (true) root2.addChild(ground); scene2 = new Scene3D( "scene2", clip, camera2, root2 ); } var courseposition:Number = roadlength; var coursepositionspeed:Number = 0; // var carHorizontal:Number = 0; var carRot:Number = 0; var carRotSpeed:Number = 0; var CourseDirection:Number = 0; function EveryFrame(event:Event):void{ debugText.text = ""; // Car model positioning var carposition:Array = TrackMath(courseposition); var carposition2:Array = TrackMath(courseposition-0.01); box.x = carposition[0]; box.y = carposition[1]; box.z = carposition[2]; box.lookAt(carposition2[0],carposition2[1],carposition2[2]); var rot:Number = Math.atan2(box.x-carposition2[0],box.z-carposition2[2]); var carRotZ:Number = Math.atan2(carposition2[2]-carposition[2],carposition2[0]-carposition[0]) box.roll += carposition[3]*180/Math.PI; box.pan += (carRot-rot)*180/Math.PI; box.moveForward(100); var carRotY:Number = Math.atan2(box.y-carposition[1], Math.sqrt( Math.pow(box.x-carposition[0],2)+Math.pow(box.z-carposition[2],2) ) ); box.moveForward(-100); box.x += Math.sin(carRotZ)*carHorizontal*Math.cos(carposition[3])*2; box.y += Math.sin(carposition[3])*carHorizontal*2; box.z += Math.sin(carRotZ-Math.PI/2)*carHorizontal*Math.cos(carposition[3])*2; box.tilt -= 90; box.moveForward(10); // floats off of the ground box.tilt += 90; // Camera //var camerapos:Array = TrackMath(courseposition-0.25); //var camerapos2:Array = TrackMath(courseposition+0.05+Math.abs(coursepositionspeed)-0.25); //var rotxz:Number = Math.atan2(camerapos2[0]-camerapos[0],camerapos2[2]-camerapos[2]) //camerapos[1] += Math.sin(camerapos[3]+Math.PI/2)*50; //camerapos2[1] += Math.sin(camerapos[3]+Math.PI/2)*50; camera.x += ((box.x-Math.sin(carRot)*200*Math.cos(carRotY))-camera.x)/4; camera.y += ((box.y+Math.sin(carRotY+Math.PI/8)*200)-camera.y)/4; camera.z += ((box.z-Math.cos(carRot)*200*Math.cos(carRotY))-camera.z)/4; camera.lookAt(box.x,box.y,box.z); // keys if(isDown(Keyboard.UP)){ coursepositionspeed+=0.005; } if(isDown(Keyboard.DOWN)){ coursepositionspeed-=0.005; } if(isDown(Keyboard.RIGHT)){ carRotSpeed += (0.25-carRotSpeed)/6; } if(isDown(Keyboard.LEFT)){ carRotSpeed += (-0.25-carRotSpeed)/6; } carRotSpeed *= 0.6; carRot += carRotSpeed; coursepositionspeed *= 0.8; // car movement var currentposition:Array = TrackMath(courseposition); var forwardposition:Array = TrackMath(courseposition+0.2); var forwardposition2:Array = TrackMath(courseposition+0.4); /* var rot:Number = Math.atan2(box.x-carposition2[0],box.z-carposition2[2]); var carRotZ:Number = Math.atan2(carposition2[2]-carposition[2],carposition2[0]-carposition[0]); box.x += Math.sin(carRotZ)*carHorizontal*Math.cos(carposition[3])*2; box.y += Math.sin(carposition[3])*carHorizontal*2; box.z += Math.sin(carRotZ-Math.PI/2)*carHorizontal*Math.cos(carposition[3])*2; */ var RotZ:Number = Math.atan2(forwardposition[2]-currentposition[2],forwardposition[0]-currentposition[0]); var RotZ2:Number = Math.atan2(forwardposition2[2]-forwardposition[2],forwardposition2[0]-forwardposition[0]); currentposition[0] += Math.sin(RotZ)*carHorizontal*Math.cos(currentposition[3])*2; currentposition[1] += Math.sin(currentposition[3])*carHorizontal*2; currentposition[2] += Math.sin(RotZ-Math.PI/2)*carHorizontal*Math.cos(currentposition[3])*2; forwardposition[0] += Math.sin(RotZ2)*carHorizontal*Math.cos(forwardposition[3])*2; forwardposition[1] += Math.sin(forwardposition[3])*carHorizontal*2; forwardposition[2] += Math.sin(RotZ2-Math.PI/2)*carHorizontal*Math.cos(forwardposition[3])*2; var dx:Number = forwardposition[0]-currentposition[0]; var dy:Number = forwardposition[1]-currentposition[1]; var dz:Number = forwardposition[2]-currentposition[2]; var d:Number = Math.sqrt(dx*dx+dy*dy+dz*dz); var rotXZ:Number = Math.atan2(-dx,-dz); // may want to change how this is calculated.... courseposition -= Math.cos(carRot-rotXZ)*coursepositionspeed*1000*(0.2/d); carHorizontal += Math.sin(carRot-rotXZ)*coursepositionspeed*500; // walls on left and right side carHorizontal = Math.min(carHorizontal,currentposition[4]/2-10); carHorizontal = Math.max(carHorizontal,-currentposition[4]/2+10); // add (possible) falling off of track maybe? CourseDirection = -Math.cos(carRot-rotXZ); // -1 for the car going backwards on the track //debugText.text = String(CourseDirection); if(courseposition <= roadlength){ courseposition += roadlength; } // construct the track var p:boxParticle var rotX:Number = 0; var rotY:Number = 0; var rotZ:Number = 0; var newpx:Number = 0; var newpy:Number = 0; var newpz:Number = 0; var oldpx:Number = 0; var oldpy:Number = 0; var oldpz:Number = 0; var h:int = -widthparticles; var i:int = 0; var positions:Array var thing:Number = (particles/lookForward)/3; for each(p in boxArray){ h++; if(h>widthparticles){ if(CourseDirection > 0){ // Camera looking ahead positions = TrackMath(i/(particles/lookForward)+Math.floor(courseposition*thing)/thing-0.5); }else{ // Camera looking back positions = TrackMath(i/(particles/lookForward)+Math.floor(courseposition*thing)/thing-0.5-(lookForward/2)); } oldpx = newpx; oldpy = newpy; oldpz = newpz; newpx = positions[0]; newpy = positions[1]; newpz = positions[2]; if(i==0){ var positions2:Array = TrackMath((i-1)/(particles/lookForward)+courseposition-0.5); oldpx = positions2[0]; oldpy = positions2[1]; oldpz = positions2[2]; //newpy -= 1000; } rotY = Math.atan2(newpx-oldpx,newpy-oldpy); rotZ = Math.atan2(oldpz-newpz,oldpx-newpx); rotX = positions[3]; var roadwidth:Number = positions[4]; i++; h = -widthparticles; } var hposition:Number = h; if(h == -widthparticles || h == widthparticles){ hposition = subtract(hposition,0.8); p.size = 8; p.red = 144+(i%3)*14; p.green = 144+(i%3)*8; p.blue = 144; }else{ p.size = 15; p.red = 118; p.green = 124+((h+i)%3)*5; p.blue = 184; } p.px = newpx+Math.sin(rotZ)*hposition*roadwidth*Math.cos(rotX)/widthparticles; p.py = newpy+Math.sin(rotX)*hposition*roadwidth/widthparticles; p.pz = newpz+Math.sin(rotZ-Math.PI/2)*hposition*roadwidth*Math.cos(rotX)/widthparticles; if(h == -widthparticles || h == widthparticles){ // later make this use the normal p.py += 12; } } // render everything camera2.y = camera.y; camera2.x = camera.x; camera2.z = camera.z; camera.moveForward(100); camera2.lookAt(camera.x,camera.y,camera.z); camera.moveForward(-100); camera2.y += 500; scene2.render(); scene.render(); clip2.graphics.clear(); for each(p in boxArray){ SortBox(p, camera); } boxArray.sort(Zsort); function Zsort(p1:boxParticle, p2:boxParticle):Number{ if (p1.depth < p2.depth) return 1; else if (p1.depth > p2.depth) return -1; else return 0; } for each(p in boxArray){ DrawBox(p, clip2); } } function SortBox(_box:boxParticle, camera:Camera3D):void{ var _v:Vertex = new Vertex(_box.px,_box.py,_box.pz); var m:Matrix4 = camera.invModelMatrix; _v.wx = _v.x * m.n11 + _v.y * m.n12 + _v.z * m.n13 + m.n14; _v.wy = _v.x * m.n21 + _v.y * m.n22 + _v.z * m.n23 + m.n24; _v.wz = _v.x * m.n31 + _v.y * m.n32 + _v.z * m.n33 + m.n34; camera.projectVertex(_v); _box.depth = _v.wz+_v.sx/1000; _box.sx = _v.sx; _box.sy = _v.sy; _box.wz = _v.wz; } function DrawBox(_box:boxParticle, _clip:MovieClip):void{ if(_box.wz >= camera.near && _box.wz <= camera.far){ var fadeout:Number = 1/(_box.wz/400); fadeout = Math.max(fadeout,0); fadeout = Math.min(fadeout,1); var _color:uint = _box.red*fadeout+200*(1-fadeout) << 16 | _box.green*fadeout+200*(1-fadeout) << 8 | _box.blue*fadeout+205*(1-fadeout); _clip.graphics.beginFill(_color); var _size:Number = _box.size*1000/_box.wz; _clip.graphics.drawRect( _box.sx-_size/2, _box.sy-_size/2, _size, _size); _clip.graphics.endFill(); } } function TrackMath(_position:Number):Array{ var c:Number = Math.floor(_position)%roadlength; var a:Number = _position%1; var b:Number = 1-a; var px:Number = a*a*road[2+c*2][0]+2*a*b*road[1+c*2][0]+b*b*road[0+c*2][0]; var py:Number = a*a*road[2+c*2][1]+2*a*b*road[1+c*2][1]+b*b*road[0+c*2][1]; var pz:Number = a*a*road[2+c*2][2]+2*a*b*road[1+c*2][2]+b*b*road[0+c*2][2]; // derivative isn't working for some reason... // (2*c+4*b+2*a)*x-2*c-2*b // 2*b*y+2*a*x //var dx:Number = 2*road[2+c*2][0]*a + 2*road[1+c*2][0]*b + 2*road[1+c*2][0]*a + 2*road[0+c*2][0]*b; //var dy:Number = 2*road[2+c*2][1]*a + 2*road[1+c*2][1]*b + 2*road[1+c*2][1]*a + 2*road[0+c*2][1]*b; //var dz:Number = 2*road[2+c*2][2]*a + 2*road[1+c*2][2]*b + 2*road[1+c*2][2]*a + 2*road[0+c*2][2]*b; //var dx:Number = (2*road[0+c*2][0]+4*road[1+c*2][0]+2*road[2+c*2][0])*a - 2*road[0+c*2][0] - 2*road[1+c*2][0]; //var dy:Number = (2*road[0+c*2][1]+4*road[1+c*2][1]+2*road[2+c*2][1])*a - 2*road[0+c*2][1] - 2*road[1+c*2][1]; //var dz:Number = (2*road[0+c*2][2]+4*road[1+c*2][2]+2*road[2+c*2][2])*a - 2*road[0+c*2][2] - 2*road[1+c*2][2]; var roll:Number = a*a*roadTilt[2+c*2][0]+2*a*b*roadTilt[1+c*2][0]+b*b*roadTilt[0+c*2][0]; var width:Number = a*a*roadTilt[2+c*2][1]+2*a*b*roadTilt[1+c*2][1]+b*b*roadTilt[0+c*2][1]; // to add later, other things (like boolean for walls existing, or halfpipe/cylinder return [px,py,pz,roll,width] } function subtract(num:Number, num2:Number):Number{ if(num > 0){ num = Math.max(0, num-num2); }else{ num = Math.min(0, num+num2); } return num; } var initialized:Boolean = false;// marks whether or not the class has been initialized var keysDown:Object = new Object();// stores key codes of all keys pressed function isDown(keyCode:uint):Boolean { return Boolean(keyCode in keysDown); } function keyPressed(event:KeyboardEvent):void { keysDown[event.keyCode] = true; } function keyReleased(event:KeyboardEvent):void { if (event.keyCode in keysDown) { delete keysDown[event.keyCode]; } } class boxParticle extends Sprite{ public var px:Number; public var py:Number; public var pz:Number; public var depth:Number; public var size:Number; public var red:Number; public var green:Number; public var blue:Number; public var sx:Number; public var sy:Number; public var wz:Number; /* public function boxParticle(_X:Number, _Y:Number, _Z:Number, _size:Number, _color:uint) { pos[0] = _X; pos[1] = _Y; pos[2] = _Z; size = _size; color = _color; } */ } forked from: 3d Racing Game Test