forked from nothke/yugodot
		
	Initial, scripts
This commit is contained in:
		
							
								
								
									
										60
									
								
								scripts/CarCamera.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								scripts/CarCamera.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| using Godot; | ||||
| using System; | ||||
|  | ||||
| public class CarCamera : Camera | ||||
| { | ||||
|     [Export] public NodePath carPath; | ||||
|  | ||||
|     CarController car; | ||||
|  | ||||
|     public override void _Ready() | ||||
|     { | ||||
|         car = GetNode<CarController>(carPath); | ||||
|         camPos = Translation; | ||||
|  | ||||
|         var config = new ConfigFile(); | ||||
|         const string CONFIG_PATH = "config.ini"; | ||||
|         if (config.Load(CONFIG_PATH) == Error.Ok) | ||||
|         { | ||||
|             raceSmoothing = float.Parse(config.GetValue("camera", "smoothing_rate", 7).ToString()); | ||||
|             height = float.Parse(config.GetValue("camera", "height", 3).ToString()); | ||||
|             distance = float.Parse(config.GetValue("camera", "distance", 6).ToString()); | ||||
|         } | ||||
|         else GD.Print("Couldn't load " + CONFIG_PATH); | ||||
|     } | ||||
|  | ||||
|     Vector3 camPos; | ||||
|     Vector3 carPos; | ||||
|  | ||||
|     float startSmoothing = 1; | ||||
|     float raceSmoothing = 7; | ||||
|     float height = 3; | ||||
|     float distance = 6; | ||||
|  | ||||
|     public override void _PhysicsProcess(float dt) | ||||
|     { | ||||
|         Vector3 carForward = car.Transform.basis.z; | ||||
|         carPos = car.Translation; | ||||
|  | ||||
|         Vector3 rearTargetPoint = carPos - carForward * distance; | ||||
|         rearTargetPoint.y = carPos.y + height; | ||||
|  | ||||
|         float smoothing = car.RaceStarted ? raceSmoothing : startSmoothing; | ||||
|  | ||||
|         camPos = camPos.LinearInterpolate(rearTargetPoint, dt * smoothing); | ||||
|  | ||||
|         /* | ||||
|         float limit = 8; | ||||
|         Vector3 diff = camPos - carPos; | ||||
|         if ((diff).Length() > limit) | ||||
|         { | ||||
|             camPos = carPos + diff.Normalized() * limit; | ||||
|         }*/ | ||||
|     } | ||||
|  | ||||
|     public override void _Process(float dt) | ||||
|     { | ||||
|         Translation = camPos; | ||||
|         LookAt(carPos, Vector3.Up); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										540
									
								
								scripts/CarController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										540
									
								
								scripts/CarController.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,540 @@ | ||||
| using Godot; | ||||
| using System; | ||||
|  | ||||
| using Utility; | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| public class CarController : RigidBody | ||||
| { | ||||
|     LineDrawer3D line; | ||||
|  | ||||
|     [Export] public float raycastHeightOffset = 0; | ||||
|  | ||||
|     [Export] public float springRate = 20; | ||||
|     [Export] public float dampRate = 2; | ||||
|     [Export(PropertyHint.ExpEasing)] public float tractionEase = 2; | ||||
|     [Export] public float maxSpeedKmh = 60; | ||||
|     [Export(PropertyHint.ExpEasing)] public float sidewaysTractionEase = 1; | ||||
|     [Export] public float maxTraction = 30; | ||||
|     [Export] public float tractionForceMult = 10; | ||||
|     [Export] public float sidewaysTractionMult = 1; | ||||
|  | ||||
|     [Export] public NodePath engineAudioPath; | ||||
|     [Export] public NodePath timingPath; | ||||
|     [Export] public NodePath countdownPath; | ||||
|  | ||||
|     [Export] public NodePath checkpointSoundPath; | ||||
|     [Export] public NodePath countdownSoundPath; | ||||
|     [Export] public NodePath finishSoundPath; | ||||
|  | ||||
|     [Export] public Material material; | ||||
|     [Export] public NodePath bodyNode; | ||||
|  | ||||
|     AudioStreamPlayer checkpointSound; | ||||
|     AudioStreamPlayer countdownSound; | ||||
|     AudioStreamPlayer finishSound; | ||||
|  | ||||
|     AudioStreamPlayer3D engineAudio; | ||||
|  | ||||
|     public float torqueMult = 10; | ||||
|  | ||||
|  | ||||
|     public float wheelBase = 1.05f; | ||||
|     public float wheelTrack = 0.7f; | ||||
|  | ||||
|     Spatial wheelRoot; | ||||
|     //MeshInstance[] graphicalWheels = new MeshInstance[4]; | ||||
|     //CPUParticles[] dirts = new CPUParticles[4]; | ||||
|  | ||||
|     float smoothThrottle; | ||||
|  | ||||
|     int checkpointPassed = -1; | ||||
|  | ||||
|     RichTextLabel timingText; | ||||
|     RichTextLabel countdownText; | ||||
|  | ||||
|     public float countdown = 4; | ||||
|  | ||||
|     public float sceneStartTime; | ||||
|  | ||||
|     const int CHECKPOINT_NUM = 13; | ||||
|     static float bestTime; | ||||
|     static float[] bestCheckpointTimes = new float[CHECKPOINT_NUM]; | ||||
|     float[] checkpointTimes = new float[CHECKPOINT_NUM]; | ||||
|     float[] prevBestCheckpointTimes = new float[CHECKPOINT_NUM]; | ||||
|  | ||||
|     readonly Color red = new Color(1.0f, 0.0f, 0.0f); | ||||
|     readonly Color blue = new Color(0f, 0.0f, 1.0f); | ||||
|     readonly Color green = new Color(0.0f, 1.0f, 0.0f); | ||||
|     readonly Color darkGreen = new Color(0.0f, 0.9f, 0.0f); | ||||
|     readonly Color black = new Color(0, 0, 0); | ||||
|  | ||||
|  | ||||
|     float prevYInput; | ||||
|  | ||||
|     ConfigFile config; | ||||
|     bool drawParticles = true; | ||||
|     bool drawLines = false; | ||||
|     bool debugSplits = false; | ||||
|  | ||||
|     struct Wheel | ||||
|     { | ||||
|         public Vector3 point; | ||||
|         public Spatial graphical; | ||||
|         public Particles dirt; | ||||
|         public bool wasGrounded; | ||||
|     } | ||||
|  | ||||
|     Wheel[] wheels = new Wheel[4]; | ||||
|  | ||||
|  | ||||
|     bool stageEnded; | ||||
|  | ||||
|     public bool RaceStarted => stageTime > 0; | ||||
|  | ||||
|     float stageTime; | ||||
|  | ||||
|     float speedPitch; | ||||
|  | ||||
|     float smoothSteer; | ||||
|     int lastCountdownTime = 0; | ||||
|  | ||||
|     struct ReplaySample | ||||
|     { | ||||
|         public Transform t; | ||||
|         public float time; | ||||
|         public float throttle; | ||||
|     } | ||||
|  | ||||
|     List<ReplaySample> samples = new List<ReplaySample>(10000); | ||||
|  | ||||
|     public override void _Ready() | ||||
|     { | ||||
|         wheels[0].point = new Vector3(-wheelTrack, 0, wheelBase); | ||||
|         wheels[1].point = new Vector3(wheelTrack, 0, wheelBase); | ||||
|         wheels[2].point = new Vector3(-wheelTrack, 0, -wheelBase); | ||||
|         wheels[3].point = new Vector3(wheelTrack, 0, -wheelBase); | ||||
|  | ||||
|         var lineGeometry = GetNode("wheel_debug"); | ||||
|         //GD.Print(lineGeometry); | ||||
|         line = lineGeometry as LineDrawer3D; | ||||
|  | ||||
|         wheels[0].graphical = GetNode<MeshInstance>("car/RootNode/fl"); | ||||
|         wheels[1].graphical = GetNode<MeshInstance>("car/RootNode/fr"); | ||||
|         wheels[2].graphical = GetNode<MeshInstance>("car/RootNode/rl"); | ||||
|         wheels[3].graphical = GetNode<MeshInstance>("car/RootNode/rr"); | ||||
|         wheelRoot = wheels[0].graphical.GetParent<Spatial>(); | ||||
|  | ||||
|         wheels[0].dirt = GetNode<Particles>("dirt_fl"); | ||||
|         wheels[1].dirt = GetNode<Particles>("dirt_fr"); | ||||
|         wheels[2].dirt = GetNode<Particles>("dirt_rl"); | ||||
|         wheels[3].dirt = GetNode<Particles>("dirt_rr"); | ||||
|  | ||||
|         engineAudio = GetNode<AudioStreamPlayer3D>(engineAudioPath); | ||||
|  | ||||
|         timingText = GetNode<RichTextLabel>(timingPath); | ||||
|         countdownText = GetNode<RichTextLabel>(countdownPath); | ||||
|  | ||||
|         sceneStartTime = OS.GetTicksMsec() / 1000.0f; | ||||
|  | ||||
|         checkpointSound = GetNode<AudioStreamPlayer>(checkpointSoundPath); | ||||
|         countdownSound = GetNode<AudioStreamPlayer>(countdownSoundPath); | ||||
|         finishSound = GetNode<AudioStreamPlayer>(finishSoundPath); | ||||
|  | ||||
|         GetNode<MeshInstance>(bodyNode).MaterialOverride = material; | ||||
|  | ||||
|         foreach (var w in wheels) | ||||
|             w.dirt.Emitting = false; | ||||
|  | ||||
|         config = new ConfigFile(); | ||||
|         const string CONFIG_PATH = "config.ini"; | ||||
|         if (config.Load(CONFIG_PATH) == Error.Ok) | ||||
|         { | ||||
|             springRate = float.Parse(config.GetValue("setup", "spring_rate", 40).ToString()); | ||||
|             dampRate = float.Parse(config.GetValue("setup", "damp_rate", 3).ToString()); | ||||
|  | ||||
|             float volume = float.Parse(config.GetValue("audio", "master_volume", 1).ToString()); | ||||
|             AudioServer.SetBusVolumeDb(0, Mathf.Log(volume) * 8.685f); | ||||
|  | ||||
|             drawParticles = float.Parse(config.GetValue("graphics", "draw_particles", 1).ToString()) != 0; | ||||
|             drawLines = float.Parse(config.GetValue("debug", "lines", 0).ToString()) != 0; | ||||
|             debugSplits = float.Parse(config.GetValue("debug", "splits", 0).ToString()) != 0; | ||||
|         } | ||||
|         else GD.Print("Couldn't load " + CONFIG_PATH); | ||||
|     } | ||||
|  | ||||
|     Vector3 GetVelocityAtPoint(Vector3 point) | ||||
|     { | ||||
|         return LinearVelocity + AngularVelocity.Cross(point - GlobalTransform.origin); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     public static float Repeat(float t, float length) | ||||
|     { | ||||
|         return Mathf.Clamp(t - Mathf.Floor(t / length) * length, 0.0f, length); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     float sat(float value) | ||||
|     { | ||||
|         return Mathf.Clamp(value, 0, 1); | ||||
|     } | ||||
|  | ||||
|     float GetSectorTime(float[] splits, int i) | ||||
|     { | ||||
|         float lastCheckTime = i == 0 ? 0 : splits[i - 1]; | ||||
|         return splits[i] - lastCheckTime; | ||||
|     } | ||||
|  | ||||
|     bool isReplay; | ||||
|     int replaySample = 0; | ||||
|  | ||||
|     public override void _Input(InputEvent e) | ||||
|     { | ||||
|         if (e is InputEventKey keyEvent) | ||||
|         { | ||||
|             if (keyEvent.Scancode == (uint)KeyList.F && keyEvent.Pressed) | ||||
|             { | ||||
|                 isReplay = true; | ||||
|                 replaySample = 0; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public override void _PhysicsProcess(float dt) | ||||
|     { | ||||
|  | ||||
|         if (isReplay) | ||||
|         { | ||||
|             Transform = samples[replaySample].t; | ||||
|             replaySample++; | ||||
|  | ||||
|             if (replaySample == samples.Count) | ||||
|                 replaySample = 0; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         float time = OS.GetTicksMsec() / 1000.0f; | ||||
|  | ||||
|         if (!stageEnded) | ||||
|             stageTime = time - sceneStartTime - countdown; | ||||
|  | ||||
|         int countdownTime = (int)-stageTime + 1; | ||||
|  | ||||
|         //if (stageTime < 0) | ||||
|         //stageTime = 0; | ||||
|  | ||||
|         timingText.Clear(); | ||||
|         timingText.PushColor(black); | ||||
|  | ||||
|         string stageTimeStr = stageTime < 0 ? "0.000" : stageTime.ToString("F3"); | ||||
|  | ||||
|         string bestTimeStr = bestTime == 0 ? "--.---" : bestTime.ToString("F3"); | ||||
|         timingText.AppendBbcode("Best: " + bestTimeStr + "\n"); | ||||
|  | ||||
|         if (!stageEnded) | ||||
|             timingText.AppendBbcode( | ||||
|                 "Time: " + stageTimeStr + "\n"); | ||||
|         else | ||||
|             timingText.AppendBbcode( | ||||
|                 "Time: " + stageTimeStr + "\n"); | ||||
|  | ||||
|         if (checkpointPassed >= 0) | ||||
|         { | ||||
|             var bestTimes = stageEnded ? prevBestCheckpointTimes : bestCheckpointTimes; | ||||
|  | ||||
|             for (int c = 0; c <= checkpointPassed; c++) | ||||
|             { | ||||
|                 float sectorTime = GetSectorTime(checkpointTimes, c); | ||||
|                 float bestSectorTime = GetSectorTime(bestTimes, c); | ||||
|  | ||||
|                 if (bestTime == 0 || sectorTime < bestSectorTime) | ||||
|                     timingText.PushColor(darkGreen); | ||||
|                 else | ||||
|                     timingText.PushColor(red); | ||||
|  | ||||
|                 timingText.AppendBbcode("#"); | ||||
|             } | ||||
|  | ||||
|             float diff = GetSectorTime(checkpointTimes, checkpointPassed) - | ||||
|                 GetSectorTime(bestTimes, checkpointPassed); | ||||
|  | ||||
|             timingText.AppendBbcode("\nSplit: " + (diff > 0 ? "+" : "") + diff.ToString("F3")); | ||||
|         } | ||||
|  | ||||
|         if (stageEnded) | ||||
|         { | ||||
|             timingText.PushColor(black); | ||||
|             timingText.AppendBbcode("\nFinished! Press R to restart"); | ||||
|         } | ||||
|  | ||||
|         if (stageTime < 0) | ||||
|         { | ||||
|             if (countdownTime != lastCountdownTime) | ||||
|                 countdownSound.Play(); | ||||
|  | ||||
|             lastCountdownTime = countdownTime; | ||||
|  | ||||
|             countdownText.Text = countdownTime.ToString(); | ||||
|         } | ||||
|         else countdownText.Text = ""; | ||||
|  | ||||
|         float xInput = | ||||
|             Input.IsKeyPressed((int)KeyList.A) ? -1 : | ||||
|             (Input.IsKeyPressed((int)KeyList.D) ? 1 : 0); | ||||
|         float yInput = | ||||
|             Input.IsKeyPressed((int)KeyList.S) ? -1 : | ||||
|             (Input.IsKeyPressed((int)KeyList.W) ? 1 : 0); | ||||
|  | ||||
|         float throttleInput = yInput; | ||||
|  | ||||
|         if (isReplay) | ||||
|         { | ||||
|             yInput = samples[replaySample].throttle; | ||||
|         } | ||||
|  | ||||
|         smoothSteer = Mathf.Lerp(smoothSteer, xInput, dt * 10); | ||||
|  | ||||
|         smoothThrottle = Mathf.Lerp(smoothThrottle, yInput, dt * 3); | ||||
|  | ||||
|         if (stageTime < 0) // Disable input before stage start | ||||
|             yInput = 0; | ||||
|  | ||||
|         // Drag shit: | ||||
|         //AddCentralForce(-LinearVelocity * (1 - 0.05f)); | ||||
|         float speed = LinearVelocity.Length(); | ||||
|         //float forceFactor = 1 - (speed / 10.0f); | ||||
|         //float forceFactor = Mathf.InverseLerp(10, 0, speed); | ||||
|  | ||||
|         var state = GetWorld().DirectSpaceState; | ||||
|         var up = Transform.basis.y; | ||||
|         var forward = Transform.basis.z; | ||||
|  | ||||
|         line.ClearLines(); | ||||
|  | ||||
|         int wheelsOnGround = 0; | ||||
|  | ||||
|         float rayLength = 0.6f; | ||||
|  | ||||
|         //Color red = Color.ColorN(Colors.Red.ToString()); | ||||
|         //Color blue = Color.ColorN(Colors.Blue.ToString()); | ||||
|  | ||||
|  | ||||
|  | ||||
|         //line.AddLine(Vector3.One * -10, Vector3.One * 10, red); | ||||
|  | ||||
|         Vector3 tractionPoint = new Vector3(); | ||||
|  | ||||
|  | ||||
|  | ||||
|         Vector3 right = Transform.basis.x; | ||||
|         float sidewaysSpeed = right.Dot(LinearVelocity); | ||||
|  | ||||
|         int i = 0; | ||||
|         foreach (var w in wheels) | ||||
|         { | ||||
|             Vector3 wp = ToGlobal(w.point); | ||||
|  | ||||
|             var origin = wp + up * raycastHeightOffset; | ||||
|             var dest = origin - up * rayLength; | ||||
|  | ||||
|             var dict = state.IntersectRay(origin, dest); | ||||
|  | ||||
|             Vector3 wheelP = dest; | ||||
|  | ||||
|             bool grounded = dict.Count > 0; | ||||
|  | ||||
|             if (grounded) | ||||
|             { | ||||
|                 var obj = (Godot.Object)dict["collider"]; | ||||
|                 Vector3 hit = (Vector3)dict["position"]; | ||||
|                 Vector3 normal = (Vector3)dict["normal"]; | ||||
|  | ||||
|                 if (drawLines) | ||||
|                     line.AddLine(origin, hit, red); | ||||
|  | ||||
|                 float distFromTarget = (dest - hit).Length(); | ||||
|  | ||||
|                 float spring = springRate * distFromTarget; | ||||
|  | ||||
|                 Vector3 veloAtWheel = GetVelocityAtPoint(origin); | ||||
|                 float verticalVeloAtWheel = up.Dot(veloAtWheel); | ||||
|                 float damp = -verticalVeloAtWheel * dampRate; | ||||
|  | ||||
|                 AddForce(normal * (spring + damp), hit - Transform.origin); | ||||
|  | ||||
|                 wheelsOnGround++; | ||||
|  | ||||
|                 wheelP = hit; | ||||
|                 tractionPoint += hit; | ||||
|  | ||||
|                 //w.dirt.Direction = new Vector3(sidewaysSpeed * 0.1f, 0, -1); | ||||
|  | ||||
|             } | ||||
|             else if (drawLines) | ||||
|             { | ||||
|                 line.AddLine(origin, dest, blue); | ||||
|             } | ||||
|  | ||||
|             if (drawParticles && (grounded != w.wasGrounded || prevYInput != yInput)) | ||||
|             { | ||||
|                 w.dirt.Emitting = grounded && yInput > 0; | ||||
|             } | ||||
|  | ||||
|             float off = -0.1f; | ||||
|             float rightoff = i % 2 == 0 ? -off : off; | ||||
|             Vector3 localWheelCenter = wheelRoot.ToLocal(wheelP + up * 0.3f) + Vector3.Right * rightoff; | ||||
|             w.graphical.Translation = localWheelCenter; | ||||
|             //w.dirt.Translation = localWheelCenter; | ||||
|  | ||||
|             Vector3 wheelRot = Vector3.Zero; | ||||
|             if (i % 2 == 0) | ||||
|                 wheelRot = new Vector3(0, Mathf.Deg2Rad(180), 0); | ||||
|             else | ||||
|                 wheelRot = new Vector3(0, Mathf.Deg2Rad(0), 0); | ||||
|  | ||||
|  | ||||
|             w.graphical.Rotation = wheelRot; | ||||
|  | ||||
|             if (i < 2) | ||||
|                 w.graphical.Rotate(Vector3.Up, -smoothSteer * Mathf.Deg2Rad(30)); | ||||
|  | ||||
|             /* | ||||
|             w.dirt.Rotation = wheelRot; | ||||
|  | ||||
|             if (i % 2 == 0) | ||||
|             { | ||||
|                 w.dirt.Rotate(Vector3.Up, Mathf.Deg2Rad(180)); | ||||
|             } | ||||
|             w.dirt.Rotate(Vector3.Right, Mathf.Deg2Rad(20)); | ||||
|             */ | ||||
|  | ||||
|             if (drawParticles) | ||||
|             { | ||||
|                 float dirtSteerFactor = i < 2 ? -smoothSteer : 0; | ||||
|                 w.dirt.Rotation = new Vector3(Mathf.Deg2Rad(20), Mathf.Atan(-sidewaysSpeed * 0.1f + dirtSteerFactor), 0); | ||||
|             } | ||||
|  | ||||
|             wheels[i].wasGrounded = grounded; | ||||
|  | ||||
|             i++; | ||||
|         } | ||||
|  | ||||
|         Vector3 upPoint = Translation + up * 1.1f; | ||||
|  | ||||
|         if (drawLines) | ||||
|         { | ||||
|             line.AddLine(upPoint, upPoint + LinearVelocity, new Color(1, 1, 0)); | ||||
|             line.AddLine(upPoint, upPoint + right * sidewaysSpeed, red); | ||||
|         } | ||||
|  | ||||
|         float forwardVelocity = forward.Dot(LinearVelocity); | ||||
|  | ||||
|         int gear = Mathf.FloorToInt(forwardVelocity / 8); | ||||
|  | ||||
|         float gearPitch = Repeat(forwardVelocity, 8) / 8.0f; | ||||
|         speedPitch = Mathf.Lerp(speedPitch, speed * 0.1f * gearPitch, dt * 10); | ||||
|  | ||||
|         engineAudio.PitchScale = Mathf.Clamp(Mathf.Lerp(speedPitch, smoothThrottle * 3, 0.5f), 0.3f, 10); | ||||
|  | ||||
|         if (wheelsOnGround > 0) | ||||
|         { | ||||
|             float wheelFactor = wheelsOnGround / 4.0f; | ||||
|  | ||||
|             Vector3 midPoint = tractionPoint / wheelsOnGround; | ||||
|             if (drawLines) | ||||
|             { | ||||
|                 line.AddLine(midPoint, midPoint + up * 1, red); | ||||
|                 line.AddLine(midPoint, midPoint + Vector3.Right * 1, red); | ||||
|                 line.AddLine(midPoint, midPoint + Vector3.Forward * 1, red); | ||||
|             } | ||||
|  | ||||
|             float steeringFactor = Mathf.Clamp(Mathf.InverseLerp(0, 5, speed), 0, 1); | ||||
|  | ||||
|             AddTorque(-Transform.basis.y * xInput * torqueMult * steeringFactor); | ||||
|  | ||||
|             float maxSpeed = maxSpeedKmh / 3.6f; | ||||
|             float tractionMult = 1 - Mathf.Ease(Mathf.Abs(forwardVelocity) / maxSpeed, tractionEase); | ||||
|             float tractionForce = tractionMult * yInput * tractionForceMult * wheelFactor; | ||||
|  | ||||
|             if (drawLines) | ||||
|                 line.AddLine(Vector3.Zero, Vector3.Up * tractionMult, red); | ||||
|  | ||||
|             float sideAbs = Mathf.Abs(sidewaysSpeed); | ||||
|             int sidewaysSign = Mathf.Sign(sidewaysSpeed); | ||||
|             float earlyTraction = sat(sideAbs * 2) * sat(1 - sideAbs / 20) * 10; | ||||
|             float sidewaysTractionFac = (earlyTraction + Mathf.Ease(Mathf.Abs(sidewaysSpeed) / maxTraction, sidewaysTractionEase) * maxTraction) * sidewaysSign; | ||||
|  | ||||
|             Vector3 sidewaysTraction = -right * sidewaysTractionMult * sidewaysTractionFac; | ||||
|  | ||||
|             AddForce( | ||||
|                 forward * tractionForce + sidewaysTraction, | ||||
|                 midPoint - Transform.origin); | ||||
|  | ||||
|  | ||||
|         } | ||||
|  | ||||
|         prevYInput = yInput; | ||||
|  | ||||
|         if (debugSplits) | ||||
|         { | ||||
|             string str = ""; | ||||
|             for (int c = 0; c < checkpointTimes.Length; c++) | ||||
|             { | ||||
|                 str += checkpointTimes[c].ToString() + ", " + bestCheckpointTimes[c] + "\n"; | ||||
|             } | ||||
|             countdownText.Text = str; | ||||
|         } | ||||
|  | ||||
|         if (!isReplay) | ||||
|         { | ||||
|             samples.Add(new ReplaySample() | ||||
|             { | ||||
|                 t = Transform, | ||||
|                 time = stageTime, | ||||
|                 throttle = throttleInput | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void BodyEntered(Node body, int i) | ||||
|     { | ||||
|         if (body == this) | ||||
|         { | ||||
|             GD.Print("Entered: " + body.Name + " id: " + i); | ||||
|             if (checkpointPassed + 1 == i) | ||||
|             { | ||||
|                 Check(i); | ||||
|             } | ||||
|  | ||||
|             if (checkpointPassed == 12 && i == 0) | ||||
|             { | ||||
|                 End(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void Check(int i) | ||||
|     { | ||||
|         checkpointPassed = i; | ||||
|         checkpointSound.Play(); | ||||
|  | ||||
|         checkpointTimes[i] = stageTime; | ||||
|     } | ||||
|  | ||||
|     void End() | ||||
|     { | ||||
|         stageEnded = true; | ||||
|         finishSound.Play(); | ||||
|  | ||||
|         if (bestTime == 0 || stageTime < bestTime) | ||||
|         { | ||||
|             bestTime = stageTime; | ||||
|             for (int i = 0; i < CHECKPOINT_NUM; i++) | ||||
|             { | ||||
|                 prevBestCheckpointTimes[i] = bestCheckpointTimes[i]; | ||||
|                 bestCheckpointTimes[i] = checkpointTimes[i]; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										18
									
								
								scripts/CrateMover2.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								scripts/CrateMover2.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| using Godot; | ||||
| using System; | ||||
|  | ||||
| public class CrateMover2 : Spatial | ||||
| { | ||||
|     public override void _Ready() | ||||
|     { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     public override void _Process(float delta) | ||||
|     { | ||||
|         if (Input.IsKeyPressed((int)KeyList.A)) | ||||
|         { | ||||
|             Transform = Transform.Translated(Vector3.Forward * delta); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										55
									
								
								scripts/Game.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								scripts/Game.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| using Godot; | ||||
| using System; | ||||
|  | ||||
| public class Game : Node | ||||
| { | ||||
|     [Export] NodePath hoodCameraPath; | ||||
|     [Export] NodePath wingmanCameraPath; | ||||
|     [Export] NodePath tracksideCameraPath; | ||||
|  | ||||
|     Camera hoodCamera; | ||||
|     Camera wingmanCamera; | ||||
|     Camera tracksideCamera; | ||||
|  | ||||
|     bool hoodCameraIsActive; | ||||
|  | ||||
|     public override void _Ready() | ||||
|     { | ||||
|         wingmanCamera = GetNode<Camera>(wingmanCameraPath); | ||||
|         hoodCamera = GetNode<Camera>(hoodCameraPath); | ||||
|         tracksideCamera = GetNode<Camera>(tracksideCameraPath); | ||||
|     } | ||||
|  | ||||
|     bool hasRestarted; | ||||
|  | ||||
|     public override void _Input(InputEvent e) | ||||
|     { | ||||
|         if (e is InputEventKey keyEvent) | ||||
|         { | ||||
|             if (keyEvent.Scancode == (uint)KeyList.R && keyEvent.Pressed) | ||||
|             { | ||||
|                 GetTree().ReloadCurrentScene(); | ||||
|                 hasRestarted = true; | ||||
|             } | ||||
|  | ||||
|             if (keyEvent.Scancode == (uint)KeyList.C && keyEvent.Pressed) | ||||
|             { | ||||
|                 hoodCameraIsActive = !hoodCameraIsActive; | ||||
|  | ||||
|                 if (hoodCameraIsActive) | ||||
|                     hoodCamera.MakeCurrent(); | ||||
|                 else | ||||
|                     wingmanCamera.MakeCurrent(); | ||||
|             } | ||||
|  | ||||
|             if (keyEvent.Scancode == (uint)KeyList.V) | ||||
|             { | ||||
|                 tracksideCamera.MakeCurrent(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public override void _Process(float delta) | ||||
|     { | ||||
|     } | ||||
| } | ||||
							
								
								
									
										45
									
								
								scripts/LineDrawer3D.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								scripts/LineDrawer3D.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| using Godot; | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Utility | ||||
| { | ||||
|     class LineDrawer3D : ImmediateGeometry | ||||
|     { | ||||
|         struct Line | ||||
|         { | ||||
|             public Vector3 p1; | ||||
|             public Vector3 p2; | ||||
|             public Color color; | ||||
|         } | ||||
|  | ||||
|         List<Line> lines = new List<Line>(); | ||||
|  | ||||
|         public void AddLine(Vector3 p1, Vector3 p2, Color color) | ||||
|         { | ||||
|             lines.Add(new Line() { p1 = p1, p2 = p2, color = color }); | ||||
|         } | ||||
|  | ||||
|         public void ClearLines() | ||||
|         { | ||||
|             lines.Clear(); | ||||
|         } | ||||
|  | ||||
|         public override void _Process(float delta) | ||||
|         { | ||||
|             base._Process(delta); | ||||
|  | ||||
|             Clear(); | ||||
|  | ||||
|             Begin(Mesh.PrimitiveType.Lines); | ||||
|  | ||||
|             for (int i = 0; i < lines.Count; ++i) | ||||
|             { | ||||
|                 SetColor(lines[i].color); | ||||
|                 AddVertex(ToLocal(lines[i].p1)); | ||||
|                 AddVertex(ToLocal(lines[i].p2)); | ||||
|             } | ||||
|  | ||||
|             End(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										12
									
								
								scripts/ParticlesTest.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								scripts/ParticlesTest.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| using Godot; | ||||
| using System; | ||||
|  | ||||
| public class ParticlesTest : Particles | ||||
| { | ||||
|     public override void _Process(float delta) | ||||
|     { | ||||
|         float time = OS.GetTicksMsec() / 1000.0f; | ||||
|  | ||||
|         Emitting = Mathf.Sin(time * 20) > 0; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user