Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Original JCar ported to JS:
- http://forum.unity3d.com/threads/102229-JCar-port-to-JS
- Modifications by Edy 2011.10
- www.edy.es/unity
- Modifications by Wolfos 2011
- www.wolfos.org
- */
- #pragma strict
- Screen.showCursor = false;
- enum JWheelDrive {
- Front = 0,
- Back = 1,
- All = 2
- }
- // if connected the controls will block if object not active
- // (for example steer only if car camera is active).
- var postscore_url = "Ja, nee. Laten we die maar niet geven ;)";
- var posted = false;
- var highscores: String = "loading highscores";
- var sitedown = false;
- var checkpoint : boolean = false;
- var finished : boolean = false;
- var checkForActive : GameObject;
- var playtime: float = 0;
- var startX: float = 0;
- var startY: float = 0;
- var startZ: float = 0;
- var startRot: float = 0;
- var wheelFR : Transform; // connect to Front Right Wheel transform
- var wheelFL : Transform; // connect to Front Left Wheel transform
- var wheelBR : Transform; // connect to Back Right Wheel transform
- var wheelBL : Transform; // connect to Back Left Wheel transform
- var wheelFRcollider : WheelCollider; // (Edy) WheelColliders must have been already placed at their locations and referenced here.
- var wheelFLcollider : WheelCollider; // This allows to place them at their correct positions (at the outer edge of the wheel).
- var wheelBRcollider : WheelCollider;
- var wheelBLcollider : WheelCollider;
- var vehicleColliders : Collider[]; // (Edy) List of the colliders used for the vehicle's body (WheelColliders excluded).
- // They are used for avoiding visual artifacts when positioning the wheel meshes.
- var minSpeedTireStiffness = 0.03; // (Edy) Variable tire stiffness settings:
- var minSpeedTire = 0.0; // if speed < minSpeedTire -> stiffness = minSpeedTireStiffness
- var maxSpeedTireStiffness = 0.003; // if speed > maxSpeedTire -> stiffness = maxSpeedTireStiffness
- var maxSpeedTire = 16.0; // proportional value if speed is between minSpeedTire and maxSpeedTire
- var maxSteerAngle : float = 37.0; // max angle of steering wheels
- var minSteerSpeed : float = 6.0; // (Edy) Settings for reducing the steer angle with speed
- var maxSteerSpeed : float = 20.0;
- var maxSpeedSteerAngle : float = 12.0;
- var torque : float = 100; // the base power of the engine (per wheel, and before gears)
- var brakeTorque : float = 2000; // the power of the braks (per wheel)
- var shiftCentre : Vector3 = new Vector3(0.0, -0.25, 0.0); // offset of centre of mass
- var steer : float;
- var accel : float;
- var wheelDrive : JWheelDrive = JWheelDrive.Front; // which wheels are powered
- var shiftDownRPM : float = 1500.0; // rpm script will shift gear down
- var shiftUpRPM : float = 2500.0; // rpm script will shift gear up
- var idleRPM : float = 500.0; // idle rpm
- // gear ratios (index 0 is reverse)
- var gears : float[] = [-10, 9, 6, 4.5, 3, 2.5 ];
- // automatic, if true car shifts automatically up/down
- var automatic : boolean = true;
- var killEngineSoundTimeout : float = 3.0; // time until engine sound is cut off (in s.)
- // table of efficiency at certain RPM, in tableStep RPM increases, 1.0f is 100% efficient
- // at the given RPM, current table has 100% at around 2000RPM
- var efficiencyTable : float[] = [ 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 1.0, 1.0, 0.95, 0.80, 0.70, 0.60, 0.5, 0.45, 0.40, 0.36, 0.33, 0.30, 0.20, 0.10, 0.05 ];
- // the scale of the indices in table, so with 250f, 750RPM translates to efficiencyTable[3].
- var efficiencyTableStep : float = 250.0;
- var currentGear :int = 1; // duh.
- // shortcut to the component audiosource (engine sound).
- private var audioSource : AudioSource;
- // every wheel has a wheeldata struct, contains useful wheel specific info
- class WheelData {
- public var transform : Transform;
- public var col : WheelCollider;
- public var colliderOffset : float;
- public var rotation : float = 0.0;
- public var steer : boolean;
- public var motor : boolean;
- };
- private var wheels : WheelData[]; // array with the wheel data
- // setup wheelcollider for given wheel data
- // wheel is the transform of the wheel
- // steer if wheel can steer or not
- // motor if wheel is driven by engine or not
- function SetWheelParams(wheel : Transform, col : WheelCollider, steer : boolean, motor : boolean) : WheelData {
- if (wheel == null) {
- throw new System.Exception("wheel not connected to script!");
- }
- var result : WheelData = new WheelData(); // the container of wheel specific data
- // store some useful references in the wheeldata object
- result.transform = wheel; // access to wheel transform
- result.col = col; // store the collider self
- result.steer = steer; // store if wheel can steer
- result.motor = motor; // store if wheel is connected to engine
- // (Edy) Store the offset between WheelCollider and wheel transform in the x axis.
- // This allows to place the collider at the correct position (the outer edge of the wheel)
- // and to position the wheel mesh properly later.
- result.colliderOffset = transform.InverseTransformDirection(wheel.position - col.transform.position).x;
- return result; // return the WheelData
- }
- // Use this for initialization
- function Start () {
- startX = transform.position.x;
- startY = transform.position.y;
- startZ = transform.position.z;
- //postScore("piet", 10F);
- // 4 wheels, if needed different size just modify and modify
- // the wheels[...] block below.
- wheels = new WheelData[4];
- // setup wheels
- var frontDrive : boolean = (wheelDrive == JWheelDrive.Front) || (wheelDrive == JWheelDrive.All);
- var backDrive : boolean = (wheelDrive == JWheelDrive.Back) || (wheelDrive == JWheelDrive.All);
- // we use 4 wheels, but you can change that easily if neccesary.
- // this is the only place that refers directly to wheelFL, ...
- // so when adding wheels, you need to add the public transforms,
- // adjust the array size, and add the wheels initialisation here.
- wheels[0] = SetWheelParams(wheelFR, wheelFRcollider, true, frontDrive);
- wheels[1] = SetWheelParams(wheelFL, wheelFLcollider, true, frontDrive);
- wheels[2] = SetWheelParams(wheelBR, wheelBRcollider, false, backDrive);
- wheels[3] = SetWheelParams(wheelBL, wheelBLcollider, false, backDrive);
- // we move the centre of mass (somewhere below the centre works best.)
- rigidbody.centerOfMass += shiftCentre;
- // (Edy) Allow fast angular movements (default is 7), which allows more spectacular crashes.
- // Forget about angular drag and artificial things like that. A proper setup and anti-roll bars will do the work.
- rigidbody.maxAngularVelocity = 10.0;
- // shortcut to audioSource should be engine sound, if null then no engine sound.
- audioSource = GetComponent(AudioSource);
- if (audioSource == null) {
- Debug.Log("No audio source, add one to the car with looping engine noise (but can be turned off");
- }
- //getScores();
- }
- function Update() {
- //print(Input.GetAxis("CSteer"));
- if(!finished){
- playtime += Time.deltaTime;
- }
- if (Input.GetKeyDown("page up")) {
- ShiftUp();
- }
- if (Input.GetKeyDown("page down")) {
- ShiftDown();
- }
- if (Input.GetKeyDown(KeyCode.Escape)){
- Application.Quit();
- }
- //if (Input.GetKeyDown(KeyCode.Return))
- //{
- //transform.localEulerAngles.z = 0;
- //transform.position = Vector3.up * 2;
- //}
- if(Input.GetAxis("Reset") == 1){
- reset();
- }
- // (Edy)
- // Apply rotation and suspension to the wheel meshes.
- // It must be done inside Update (not FixedUpdate) for visual accuracy.
- //
- // This part can be skipped for vehicles that are either outside of the view frustrum or far away from the camera
- // (or use the data calculated at FixedUpdate instead) for saving a few RayCasts per frame.
- // Avoid the Raycast to self-collide with the vehicle.
- for (var col in vehicleColliders)
- col.gameObject.layer = 2;
- for (var w : WheelData in wheels)
- {
- var hit : RaycastHit;
- // Locate the contact point of the tire with the nearest object underneath. If no object within the suspension distance, then the wheel is in the air.
- // Then position the mesh transform at the proper position. Also apply spin and steering.
- if (Physics.Raycast(w.col.transform.position, -w.col.transform.up, hit, (w.col.suspensionDistance + w.col.radius) * w.col.transform.lossyScale.y))
- w.transform.position = hit.point + w.col.transform.up * (w.col.radius * w.col.transform.lossyScale.y - 0.02) + transform.right * w.colliderOffset;
- else
- w.transform.position = w.col.transform.position - w.col.transform.up * (w.col.suspensionDistance * w.col.transform.lossyScale.y + 0.02) + transform.right * w.colliderOffset;
- w.rotation = Mathf.Repeat(w.rotation + Time.deltaTime * w.col.rpm * 360.0f / 60.0f, 360.0f);
- w.transform.localRotation = Quaternion.Euler(w.rotation, w.col.steerAngle, 0.0f);
- }
- // Place vehicle colliders back in their layer so wheels of other vehicles could intersect properly.
- for (var col in vehicleColliders)
- col.gameObject.layer = 0;
- // (Edy)
- // Draw a cross mark in the Center of Mass of the vehicle.
- // centerOfMass is used instead of worldCenterOfMass because the first one is interpolated according to the rigidbody's "interpolate" parameter.
- var CoM = Vector3.Scale(rigidbody.centerOfMass, Vector3(1.0/transform.localScale.x, 1.0/transform.localScale.y, 1.0/transform.localScale.z));
- CoM = transform.TransformPoint(CoM);
- var F = transform.forward * 0.05;
- var U = transform.up * 0.05;
- var R = transform.right * 0.05;
- Debug.DrawLine(CoM - F, CoM + F, Color.gray);
- Debug.DrawLine(CoM - U, CoM + U, Color.gray);
- Debug.DrawLine(CoM - R, CoM + R, Color.gray);
- }
- var shiftDelay : float = 0.0;
- // handle shifting a gear up
- function ShiftUp() {
- var now : float = Time.timeSinceLevelLoad;
- // check if we have waited long enough to shift
- if (now < shiftDelay) return;
- // check if we can shift up
- if (currentGear < gears.Length - 1) {
- currentGear ++;
- // we delay the next shift with 1s. (sorry, hardcoded)
- shiftDelay = now + 1.0;
- }
- }
- // handle shifting a gear down
- function ShiftDown() {
- var now : float = Time.timeSinceLevelLoad;
- // check if we have waited long enough to shift
- if (now < shiftDelay) return;
- // check if we can shift down (note gear 0 is reverse)
- if (currentGear > 0) {
- currentGear --;
- // we delay the next shift with 1/10s. (sorry, hardcoded)
- shiftDelay = now + 0.1f;
- }
- }
- var wantedRPM : float = 0.0; // rpm the engine tries to reach
- var motorRPM : float = 0.0;
- var killEngine : float = 0.0;
- // handle the physics of the engine
- function FixedUpdate () {
- var delta : float = Time.fixedDeltaTime;
- steer = 0; // steering -1.0 .. 1.0
- accel = 0; // accelerating -1.0 .. 1.0
- var brake : boolean = false; // braking (true is brake)
- if ((checkForActive == null) || checkForActive.active) {
- // we only look at input when the object we monitor is
- // active (or we aren't monitoring an object).
- steer = Input.GetAxis("Horizontal");//InputManager.x;
- if(Input.GetAxis("Horizontal") == 0){
- steer = Input.GetAxis("CSteer");
- }
- accel = Input.GetAxis("Vertical");//InputManager.y;
- if(Input.GetAxis("Vertical") == 0){
- if(Input.GetAxis("CThrottle") > 0){
- accel = Input.GetAxis("CThrottle");
- }
- if(Input.GetAxis("CBrake") < 0){
- accel = Input.GetAxis("CBrake");
- }
- }
- //print(accel);
- brake = Input.GetButton("Jump");
- }
- // handle automatic shifting
- if (automatic && (currentGear == 1) && (accel < 0.0f)) {
- ShiftDown(); // reverse
- }
- else if (automatic && (currentGear == 0) && (accel > 0.0f)) {
- ShiftUp(); // go from reverse to first gear
- }
- else if (automatic && (motorRPM > shiftUpRPM) && (accel > 0.0f)) {
- ShiftUp(); // shift up
- }
- else if (automatic && (motorRPM < shiftDownRPM) && (currentGear > 1)) {
- ShiftDown(); // shift down
- }
- if (automatic && (currentGear == 0)) {
- accel = -accel; // in automatic mode we need to hold arrow down for reverse
- }
- if (accel < 0.0) {
- // if we try to decelerate we brake.
- brake = true;
- accel = 0.0;
- wantedRPM = 0.0;
- }
- // the RPM we try to achieve.
- wantedRPM = (5500.0 * accel) * 0.1 + wantedRPM * 0.9;
- var rpm : float = 0.0;
- var motorizedWheels : int = 0;
- var floorContact : boolean = false;
- // calc rpm from current wheel speed and do some updating
- for (var w : WheelData in wheels) {
- var hit : WheelHit;
- var col :WheelCollider = w.col;
- // only calculate rpm on wheels that are connected to engine
- if (w.motor) {
- rpm += col.rpm;
- motorizedWheels++;
- }
- // (Edy) Adjust sideways tire stiffness
- // There's not much you can do about the WheelCollider bug, which hugely increases the grip with the slip.
- // We can however adjust the stiffness of the sideways friction curve according to the slip providing pretty nice results.
- //
- // The default parameters are calculated to work with the default WheelCollider friction parameters (1, 20000, 2, 10000, 1) which, speaking of them, are just aberrant by themselves.
- // Together with the WheelCollider bug, both define a tire with almost infinite grip.
- // If you'd see the friction vs. slip graph for a WheelCollider with those parameters you would be atonished.
- if (col.GetGroundHit(hit))
- col.sidewaysFriction.stiffness = Mathf.Lerp(minSpeedTireStiffness, maxSpeedTireStiffness, Mathf.InverseLerp(minSpeedTire, maxSpeedTire, hit.sidewaysSlip));
- }
- // calculate the actual motor rpm from the wheels connected to the engine
- // note we haven't corrected for gear yet.
- if (motorizedWheels > 1) {
- rpm = rpm / motorizedWheels;
- }
- // we do some delay of the change (should take delta instead of just 95% of
- // previous rpm, and also adjust or gears.
- motorRPM = 0.95 * motorRPM + 0.05 * Mathf.Abs(rpm * gears[currentGear]);
- if (motorRPM > 5500.0) motorRPM = 5500.0;
- // calculate the 'efficiency' (low or high rpm have lower efficiency then the
- // ideal efficiency, say 2000RPM, see table
- var index : int = Mathf.Round(motorRPM / efficiencyTableStep);
- if (index >= efficiencyTable.Length) index = efficiencyTable.Length - 1;
- if (index < 0) index = 0;
- // calculate torque using gears and efficiency table
- var newTorque : float = torque * gears[currentGear] * efficiencyTable[index];
- // go set torque to the wheels
- for(var w : WheelData in wheels) {
- col = w.col;
- // of course, only the wheels connected to the engine can get engine torque
- if (w.motor) {
- // only set torque if wheel goes slower than the expected speed
- if (Mathf.Abs(col.rpm) > Mathf.Abs(wantedRPM)) {
- // wheel goes too fast, set torque to 0
- col.motorTorque = 0;
- }
- else {
- //
- var curTorque : float = col.motorTorque;
- col.motorTorque = curTorque * 0.9 + newTorque * 0.1;
- }
- }
- // check if we have to brake
- col.brakeTorque = (brake)?brakeTorque:0.0;
- // (Edy) Set steering angle. It gets limited according with the current speed.
- if (w.steer)
- {
- var maxSteer = Mathf.Lerp(maxSteerAngle, maxSpeedSteerAngle, Mathf.InverseLerp(minSteerSpeed, maxSteerSpeed, rigidbody.velocity.magnitude));
- col.steerAngle = steer * maxSteer;
- }
- else
- col.steerAngle = 0.0;
- }
- // if we have an audiosource (motorsound) adjust pitch using rpm
- if (audioSource != null) {
- // calculate pitch (keep it within reasonable bounds)
- var pitch : float = Mathf.Clamp(1.0 + ((motorRPM - idleRPM) / (shiftUpRPM - idleRPM) * 2.5), 1.0, 10.0);
- audioSource.pitch = pitch;
- if (motorRPM > 100) {
- // turn on sound if it's not playing yet and RPM is > 100.
- if (!audioSource.isPlaying) {
- audioSource.Play();
- }
- // how long we should wait with engine RPM <= 100 before killing engine sound
- killEngine = Time.time + killEngineSoundTimeout;
- }
- else if ((audioSource.isPlaying) && (Time.time > killEngine)) {
- // standing still, kill engine sound.
- audioSource.Stop();
- }
- }
- }
- function OnGUI() {
- if (checkForActive.active) {
- // calculate actual speed in Km/H (SI metrics rule, so no inch, yard, foot,
- // stone, or other stupid length measure!)
- // Wolfos agrees and would also like to add that imperial measuring makes no sense
- var speed : float = rigidbody.velocity.magnitude * 3.6;
- // message to display
- var msg = String.Format("Time = " + playtime);
- //var msg : String = "Speed " + speed + "Km/H, " + motorRPM + "RPM, gear " + currentGear; // + " torque " + newTorque.ToString("f2") + ", efficiency " + table[index].ToString("f2");
- GUILayout.BeginArea(new Rect(Screen.width - 150, 32, 130, 50), GUI.skin.window);
- GUILayout.Label(msg);
- GUILayout.EndArea();
- if(finished){
- if(!sitedown){
- if(!posted){
- postScore(PlayerPrefs.GetString("Playername"), playtime);
- getScore();
- posted=true;
- }
- }
- GUILayout.BeginArea(new Rect(Screen.width/2-85,Screen.height/2-200,170,270), GUI.skin.window);
- GUILayout.Label("Your time was: " + playtime + " Press 'return' to restart or press 'escape' to load another level\n\nTop 10:\n" + highscores);
- GUILayout.EndArea();
- }
- }
- }
- //Wolfos' functions start here
- function reset(){
- /*(Wolfos) This function resets the car to the given position (usually the starting point), resets the time to 0 and
- sets the checkpoint boolean to false. Speed (in al directions) is also reset.*/
- transform.position = Vector3(startX,startY,startZ);
- transform.rotation.x = 0;
- transform.rotation.y = startRot;
- transform.rotation.z = 0;
- rigidbody.velocity = Vector3(0,0,0);
- checkpoint = false;
- finished = false;
- posted=false;
- playtime = 0;
- }
- function OnCollisionEnter(collision : Collision){
- //(Wolfos) This function checks for collision, specifically with "Finish" and "Checkpoint"
- if(collision.gameObject.name == "Finish" && !finished && checkpoint){
- finished = true;
- }
- if(collision.gameObject.name == "Checkpoint"){
- checkpoint = true;
- }
- if(collision.gameObject.name == "loop"){
- Camera.main.GetComponent(CamFixTo).enabled = true;
- }
- else{
- Camera.main.GetComponent(CamFixTo).enabled = false;
- }
- }
- function postScore(pname: String, score: float){
- if(!sitedown && !posted){
- var loadedlevel=Application.loadedLevelName;
- var hash=Md5Sum(pname+score+loadedlevel+"Encryptie sleutel");
- var my_url = postscore_url + "name=" + pname + "&score=" + score + "&levelname=" + loadedlevel + "&hash=" + hash;
- //print(my_url);
- var hs_post = WWW(my_url);
- yield hs_post; // Wait until the download is done
- //print("posted scores");
- if(hs_post.error) {
- sitedown = true;
- print("There was an error posting the high score: " + hs_post.error);
- }
- }
- }
- function getScore(){
- if(!sitedown && !posted){
- var loadedlevel=Application.loadedLevelName;
- var my_url = postscore_url + "list=true&levelname=" + loadedlevel;
- var hs_get = WWW(my_url);
- yield hs_get;
- if(hs_get.error) {
- sitedown = true;
- print("There was an error getting the high score: " + hs_get.error);
- } else {
- //print("got scores");
- highscores = hs_get.text.Replace("<br />", "\n");
- }
- }
- }
- static function Md5Sum(strToEncrypt: String)
- {
- var encoding = System.Text.UTF8Encoding();
- var bytes = encoding.GetBytes(strToEncrypt);
- // encrypt bytes
- var md5 = System.Security.Cryptography.MD5CryptoServiceProvider();
- var hashBytes:byte[] = md5.ComputeHash(bytes);
- // Convert the encrypted bytes back to a string (base 16)
- var hashString = "";
- for (var i = 0; i < hashBytes.Length; i++)
- {
- hashString += System.Convert.ToString(hashBytes[i], 16).PadLeft(2, "0"[0]);
- }
- return hashString.PadLeft(32, "0"[0]);
- }
Advertisement
Add Comment
Please, Sign In to add comment