package { import flash.display.DisplayObject; import flash.display.MovieClip; import flash.events.KeyboardEvent; import flash.events.TimerEvent; import flash.geom.ColorTransform; import flash.geom.Point; import flash.geom.Transform; import flash.utils.Timer; public class Car extends MovieClip { private var steerSpeed:Number = 2.5; private var accelerateSpeed:Number = 0.14; private var brakeSpeed:Number = -0.06; private var coastSpeed:Number = 0.975; private var intertiaRotationProportion:Number = 0.20; private var skidLossFactor:Number = 3.5; var steerAway:Number = 2; var prop0:Number = 0.970; var prop1:Number = 0.030; private var deltaX:Number = 0; private var deltaY:Number = 0; // keeps a record of the track for collision private var track:Track = null; private var keys:Object = new Object(); public function Car():void { stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDown); stage.addEventListener(KeyboardEvent.KEY_UP, KeyUp); } public function set Track(value:Track):void { this.track = value; } private function KeyDown(event:KeyboardEvent):void { keys[event.keyCode] = true; switch (event.keyCode) { case 16: var testGraphic:TestGraphic = new TestGraphic(); var trackPosition:Point = track.globalToLocal(localToGlobal(new Point(0, 0))); testGraphic.x = trackPosition.x; testGraphic.y = trackPosition.y; track.addChild(testGraphic); break; } } private function KeyUp(event:KeyboardEvent):void { keys[event.keyCode] = false; } public function Process():void { var deltaRotation:Number = 0; if (keys[37]) { // left deltaRotation = -steerSpeed; } if (keys[39]) { // right deltaRotation = steerSpeed; } if (deltaRotation != 0) { var inertiaRotation = deltaRotation / 180 * Math.PI * intertiaRotationProportion; var newDeltaX = Math.cos(inertiaRotation) * deltaX - Math.sin(inertiaRotation) * deltaY; var newDeltaY = Math.sin(inertiaRotation) * deltaX + Math.cos(inertiaRotation) * deltaY; deltaX = newDeltaX; deltaY = newDeltaY; rotation += deltaRotation; } if (keys[38]) { // up deltaX += Math.cos(rotation / 180 * Math.PI) * accelerateSpeed; deltaY += Math.sin(rotation / 180 * Math.PI) * accelerateSpeed; } if (keys[40]) { // down deltaX += Math.cos(rotation / 180 * Math.PI) * brakeSpeed; deltaY += Math.sin(rotation / 180 * Math.PI) * brakeSpeed; } x += deltaX; y += deltaY; var maxTurns:int = 5; while (maxTurns > 0 && !track.CheckPoint(localToGlobal(new Point(collisionPointFrontRight.x, collisionPointFrontRight.y)))) { var newDeltaX = deltaX * prop0 + deltaY * prop1; var newDeltaY = deltaY * prop0 - deltaX * prop1; deltaX = newDeltaX; deltaY = newDeltaY; rotation -= steerAway; maxTurns--; } while (maxTurns > 0 && !track.CheckPoint(localToGlobal(new Point(collisionPointFrontLeft.x, collisionPointFrontLeft.y)))) { var newDeltaX = deltaX * prop0 - deltaY * prop1; var newDeltaY = deltaY * prop0 + deltaX * prop1; deltaX = newDeltaX; deltaY = newDeltaY; rotation += steerAway; maxTurns--; } var inertiaDirection = Math.atan2(deltaY, deltaX); // use dot product of direction and inertia to calculate skid factor var skidding:Number = Math.cos(rotation / 180 * Math.PI) * Math.cos(inertiaDirection) + Math.sin(rotation / 180 * Math.PI) * Math.sin(inertiaDirection); if (skidding < 0) { skidding = -skidding; } var adjustedSkidding:Number = 1 - Math.pow(1 - skidding, skidLossFactor); var speedLoss:Number = coastSpeed * adjustedSkidding; deltaX *= speedLoss; deltaY *= speedLoss; } } }