working replay system

This commit is contained in:
2022-03-21 19:01:28 +02:00
parent 99637255da
commit 4997077978
17 changed files with 243 additions and 108 deletions

View File

@@ -1,7 +1,7 @@
{ {
"ID": "194e05f445ece24ec5448d886e1334df", "ID": "194e05f445ece24ec5448d886e1334df",
"TypeName": "FlaxEngine.SceneAsset", "TypeName": "FlaxEngine.SceneAsset",
"EngineBuild": 6226, "EngineBuild": 6330,
"Data": [ "Data": [
{ {
"ID": "194e05f445ece24ec5448d886e1334df", "ID": "194e05f445ece24ec5448d886e1334df",
@@ -70,13 +70,13 @@
"Transform": { "Transform": {
"Translation": { "Translation": {
"X": 0.0, "X": 0.0,
"Y": 226.0, "Y": 716.0,
"Z": 0.0 "Z": 0.0
} }
}, },
"Control": "FlaxEngine.GUI.Label", "Control": "FlaxEngine.GUI.Label",
"Data": { "Data": {
"Text": "eFPS: 61\nuFPS: 60\nrFPS: 60\npFPS: 30\nCon: NaNms\nDirectX11", "Text": "eFPS: 120\nuFPS: 120\nrFPS: 120\npFPS: 30",
"TextColor": { "TextColor": {
"R": 1.0, "R": 1.0,
"G": 1.0, "G": 1.0,
@@ -123,9 +123,9 @@
}, },
"Offsets": { "Offsets": {
"Left": 0.0, "Left": 0.0,
"Right": 71.0, "Right": 57.0,
"Top": -562.0, "Top": -97.0,
"Bottom": 96.0 "Bottom": 64.0
}, },
"Scale": { "Scale": {
"X": 1.0, "X": 1.0,
@@ -164,8 +164,8 @@
"Name": "ContainerControl 0", "Name": "ContainerControl 0",
"Transform": { "Transform": {
"Translation": { "Translation": {
"X": 45849.0, "X": 45644.0,
"Y": -12.0, "Y": 0.5,
"Z": 0.0 "Z": 0.0
} }
}, },

View File

@@ -1,7 +1,7 @@
{ {
"ID": "4bd8a4cc460399b5f1975fbe0a668e3f", "ID": "4bd8a4cc460399b5f1975fbe0a668e3f",
"TypeName": "FlaxEditor.Content.Settings.PhysicsSettings", "TypeName": "FlaxEditor.Content.Settings.PhysicsSettings",
"EngineBuild": 6226, "EngineBuild": 6330,
"Data": { "Data": {
"DefaultGravity": { "DefaultGravity": {
"X": 0.0, "X": 0.0,
@@ -17,8 +17,8 @@
"EnableAdaptiveForce": false, "EnableAdaptiveForce": false,
"MaxDeltaTime": 0.1, "MaxDeltaTime": 0.1,
"EnableSubstepping": false, "EnableSubstepping": false,
"SubstepDeltaTime": 0.008333334, "SubstepDeltaTime": 0.001,
"MaxSubsteps": 5, "MaxSubsteps": 60,
"SupportCookingAtRuntime": true, "SupportCookingAtRuntime": true,
"LayerMasks": [ "LayerMasks": [
4294967295, 4294967295,

View File

@@ -1,9 +1,9 @@
{ {
"ID": "a55dc3c04da4ea3744b7f1994565beac", "ID": "a55dc3c04da4ea3744b7f1994565beac",
"TypeName": "FlaxEditor.Content.Settings.TimeSettings", "TypeName": "FlaxEditor.Content.Settings.TimeSettings",
"EngineBuild": 6226, "EngineBuild": 6330,
"Data": { "Data": {
"UpdateFPS": 120.0, "UpdateFPS": 0.0,
"PhysicsFPS": 120.0, "PhysicsFPS": 120.0,
"DrawFPS": 120.0, "DrawFPS": 120.0,
"TimeScale": 1.0, "TimeScale": 1.0,

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -14,7 +14,7 @@
}, },
{ {
"name": "Flax", "name": "Flax",
"path": "C:\\dev\\Flax\\FlaxEngine" "path": "C:\\dev\\Flax\\Flax_master"
} }
] ]
} }

View File

@@ -461,7 +461,9 @@ namespace Cabrito
else if (key == KeyboardKeys.PageUp) else if (key == KeyboardKeys.PageUp)
{ {
ScrollOffset += GetHeightInLines() / 2; ScrollOffset += GetHeightInLines() / 2;
var maxOffset = Console.Lines.Count - GetHeightInLines(); // should count the wrapped line count here over Console.Lines.Count
//var maxOffset = Console.Lines.Count - GetHeightInLines();
var maxOffset = Console.Lines.Count - 1;
if (ScrollOffset > maxOffset) if (ScrollOffset > maxOffset)
ScrollOffset = maxOffset; ScrollOffset = maxOffset;
} }

View File

@@ -88,8 +88,7 @@ namespace Cabrito
sb.Append("\nuFPS: " + ((int) Math.Round(1.0f / updateTimeAvg)).ToString()); sb.Append("\nuFPS: " + ((int) Math.Round(1.0f / updateTimeAvg)).ToString());
sb.Append("\nrFPS: " + ((int) Math.Round(1.0f / drawTimeAvg)).ToString()); sb.Append("\nrFPS: " + ((int) Math.Round(1.0f / drawTimeAvg)).ToString());
sb.Append("\npFPS: " + ((int) Math.Round(1.0f / physicsTimeAvg)).ToString()); sb.Append("\npFPS: " + ((int) Math.Round(1.0f / physicsTimeAvg)).ToString());
sb.Append("\nCon: " + conTime.ToString() + "ms"); //sb.Append("\nCon: " + conTime.ToString() + "ms");
sb.Append("\n" + currentRenderer);
//sb.Append("\nGC memory: " + (GC.GetTotalMemory(false) / 1000000.0f).ToString() + "MB"); //sb.Append("\nGC memory: " + (GC.GetTotalMemory(false) / 1000000.0f).ToString() + "MB");
//sb.Append("\nUpdate profiler: " + updateProfTime.ToString() + "ms"); //sb.Append("\nUpdate profiler: " + updateProfTime.ToString() + "ms");

View File

@@ -16,6 +16,10 @@ namespace Game
public float moveRight; public float moveRight;
public bool attacking; public bool attacking;
public bool jumping; public bool jumping;
public Vector3 verificationPosition;
public Vector3 verificationVelocity;
public Quaternion verificationOrientation;
} }
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
@@ -36,7 +40,6 @@ namespace Game
public class PlayerInput public class PlayerInput
{ {
public PlayerState lastState;
public PlayerState currentState; public PlayerState currentState;
public ulong frame; public ulong frame;
@@ -54,9 +57,8 @@ namespace Game
{ {
} }
public void RecordCurrentActorState(PlayerActorState actorState) public virtual void RecordCurrentActorState(PlayerActorState actorState)
{ {
currentState.actor = actorState;
} }
public PlayerInputState GetCurrentInputState() public PlayerInputState GetCurrentInputState()

View File

@@ -56,21 +56,19 @@ namespace Game
bufferEnumerable = buffer.GetEnumerator(); bufferEnumerable = buffer.GetEnumerator();
Console.Print("demo numstates: " + buffer.Count); Console.Print("demo numstates: " + buffer.Count);
OnEndFrame(); // advances to first frame
} }
public override void OnUpdate() private int asdf = 0;
{
lastState = currentState;
}
public override void OnFixedUpdate()
{
}
public override void OnEndFrame() public override void OnEndFrame()
{ {
// TODO: check if the current state frame matches the current frame number before advancing // TODO: check if the current state frame matches the current frame number before advancing
/*asdf++;
if (asdf < 8)
return;*/
if (bufferEnumerable == null || !bufferEnumerable.MoveNext()) if (bufferEnumerable == null || !bufferEnumerable.MoveNext())
{ {
if (buffer.Any()) if (buffer.Any())
@@ -85,6 +83,7 @@ namespace Game
//var actorState = currentState.actor; //var actorState = currentState.actor;
currentState.input = bufferEnumerable.Current; currentState.input = bufferEnumerable.Current;
//frame++;
//currentState.actor = actorState; //currentState.actor = actorState;
} }
} }

View File

@@ -4,6 +4,7 @@ using System.IO;
using System.Net; using System.Net;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using FlaxEngine; using FlaxEngine;
using Console = Cabrito.Console;
namespace Game namespace Game
{ {
@@ -14,10 +15,6 @@ namespace Game
public bool IsRecording { get { return demoFileStream != null; } } public bool IsRecording { get { return demoFileStream != null; } }
public PlayerInputLocal()
{
}
public PlayerInputLocal(string demoPath) public PlayerInputLocal(string demoPath)
{ {
demoFileStream = File.Open(demoPath, FileMode.Create, FileAccess.Write); demoFileStream = File.Open(demoPath, FileMode.Create, FileAccess.Write);
@@ -29,32 +26,55 @@ namespace Game
public override void OnUpdate() public override void OnUpdate()
{ {
lastState = currentState; // Collect anything framerate independent here like camera movement
// All axis values here should be accumulated, and binary actions OR'ed
currentState.input.viewDeltaX += InputManager.GetAxisRaw("Mouse X");
currentState.input.viewDeltaY += InputManager.GetAxisRaw("Mouse Y");
// Record camera angles here?
currentState.input.viewDeltaX = InputManager.GetAxisRaw("Mouse X");
currentState.input.viewDeltaY = InputManager.GetAxisRaw("Mouse Y");
}
public override void OnFixedUpdate()
{
// Record intent here
currentState.input.moveForward = InputManager.GetAxis("Vertical"); currentState.input.moveForward = InputManager.GetAxis("Vertical");
currentState.input.moveRight = InputManager.GetAxis("Horizontal"); currentState.input.moveRight = InputManager.GetAxis("Horizontal");
currentState.input.attacking = InputManager.GetAction("Attack"); currentState.input.attacking = InputManager.GetAction("Attack");
currentState.input.jumping = InputManager.GetAction("Jump"); currentState.input.jumping = InputManager.GetAction("Jump");
} }
public override void OnFixedUpdate()
{
// Collect all input here
/*currentState.input.moveForward = InputManager.GetAxis("Vertical");
currentState.input.moveRight = InputManager.GetAxis("Horizontal");
currentState.input.attacking = InputManager.GetAction("Attack");
currentState.input.jumping = InputManager.GetAction("Jump");*/
}
public override void OnEndFrame() public override void OnEndFrame()
{ {
if (IsRecording) if (IsRecording)
{ {
currentState.input.verificationPosition = currentState.actor.position;
currentState.input.verificationOrientation = currentState.actor.orientation;
currentState.input.verificationVelocity = currentState.actor.velocity;
currentState.input.frame = frame; currentState.input.frame = frame;
buffer.Add(currentState.input); buffer.Add(currentState.input);
} }
// Reset anything accumulatable here
currentState.input.viewDeltaX = 0;
currentState.input.viewDeltaY = 0;
frame++; frame++;
} }
public override void RecordCurrentActorState(PlayerActorState actorState)
{
if (!IsRecording)
return;
if (actorState.position.Length <= 0.01)
Console.Print("wrong recorded position?");
currentState.actor = actorState;
}
public void FlushDemo() public void FlushDemo()
{ {
if (!IsRecording) if (!IsRecording)

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using FlaxEngine; using FlaxEngine;
using System.Diagnostics; using System.Diagnostics;
using System.Threading.Tasks; using System.Threading.Tasks;
using FlaxEditor.CustomEditors.Editors;
using FlaxEngine.Assertions; using FlaxEngine.Assertions;
using Console = Cabrito.Console; using Console = Cabrito.Console;
using Debug = FlaxEngine.Debug; using Debug = FlaxEngine.Debug;
@@ -42,6 +43,10 @@ namespace Game
private float viewYaw; private float viewYaw;
private float viewRoll; private float viewRoll;
private float viewPitchLastFrame;
private float viewYawLastFrame;
private float viewRollLastFrame;
private InputEvent onExit = new InputEvent("Exit"); private InputEvent onExit = new InputEvent("Exit");
// FIXME, should be much smaller but needed to avoid issues with box collider edges against brush edges diagonally // FIXME, should be much smaller but needed to avoid issues with box collider edges against brush edges diagonally
@@ -56,8 +61,19 @@ namespace Game
{ {
base.OnAwake(); base.OnAwake();
bool record = false;
//record = true;
if (record)
{
input = new PlayerInputLocal(@"C:\dev\GoakeFlax\testdemo.gdem"); // record input = new PlayerInputLocal(@"C:\dev\GoakeFlax\testdemo.gdem"); // record
//input = new PlayerInputDemo(@"C:\dev\GoakeFlax\testdemo.gdem"); //playback }
else
{
//input = new PlayerInputLocal();
input = new PlayerInputDemo(@"C:\dev\GoakeFlax\testdemo.gdem"); //playback
//input = new PlayerInputDemo(@"C:\dev\GoakeFlax\testdemo_desync.gdem"); //playback
}
onExit.Triggered += () => onExit.Triggered += () =>
{ {
@@ -73,6 +89,8 @@ namespace Game
//rigidBody.CollisionEnter += OnCollisionEnter; //rigidBody.CollisionEnter += OnCollisionEnter;
//rigidBody.TriggerEnter += OnTriggerEnter; //rigidBody.TriggerEnter += OnTriggerEnter;
//rigidBody.TriggerExit += OnTriggerExit; //rigidBody.TriggerExit += OnTriggerExit;
startupTime = Time.TimeSinceStartup;
} }
public override void OnDisable() public override void OnDisable()
@@ -120,13 +138,25 @@ namespace Game
viewPitch = initialEulerAngles.X; viewPitch = initialEulerAngles.X;
viewYaw = initialEulerAngles.Y; viewYaw = initialEulerAngles.Y;
viewRoll = initialEulerAngles.Z; viewRoll = initialEulerAngles.Z;
viewPitchLastFrame = viewPitch;
viewYawLastFrame = viewYaw;
viewRollLastFrame = viewRoll;
} }
private int lastInputFrame = 0;
private int currentInputFrame = 0;
private int currentInputFrame2 = 0;
private float startupTime = 0f;
public override void OnUpdate() public override void OnUpdate()
{ {
//input.OnUpdate();
if (input is PlayerInputDemo /*&& currentInputFrame2 >= currentInputFrame*/)
return;
input.OnUpdate(); input.OnUpdate();
if (input.frame > 0) /*if (input.frame > 0)
{ {
PlayerActorState actorState = input.GetCurrentActorState(); PlayerActorState actorState = input.GetCurrentActorState();
Actor.Position = actorState.position; Actor.Position = actorState.position;
@@ -134,11 +164,96 @@ namespace Game
viewYaw = actorState.viewYaw; viewYaw = actorState.viewYaw;
viewPitch = actorState.viewPitch; viewPitch = actorState.viewPitch;
viewRoll = actorState.viewRoll; viewRoll = actorState.viewRoll;
} }*/
PlayerInputState inputState = input.GetCurrentInputState(); PlayerInputState inputState = input.GetCurrentInputState();
// Update camera view viewYaw = viewYawLastFrame;
viewPitch = viewPitchLastFrame;
viewRoll = viewRollLastFrame;
ApplyInputToCamera(inputState);
/*input.RecordCurrentActorState(new PlayerActorState()
{
position = Actor.Position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewYaw = viewYaw,
viewPitch = viewPitch,
viewRoll = viewRoll
});*/
currentInputFrame2++;
}
private Vector3 fixedPosition = Vector3.Zero;
private bool newframe = false;
public override void OnFixedUpdate()
{
if (input is PlayerInputDemo)
input.OnUpdate();
input.OnFixedUpdate();
PlayerInputState inputState = input.GetCurrentInputState();
if (input is PlayerInputDemo)
ApplyInputToCamera(inputState);
SimulatePlayerMovement(inputState);
if (input is PlayerInputDemo)
{
// verify
float positionDelta = (Actor.Position - inputState.verificationPosition).Length;
if (positionDelta > 0.00001)
Console.Print("pos delta: " + positionDelta + " " + (Actor.Position - inputState.verificationPosition));
float velocityDelta = (currentVelocity - inputState.verificationVelocity).Length;
if (velocityDelta > 0.00001)
Console.Print("pos vel: " + velocityDelta);
float orientationDelta = (rootActor.Orientation - inputState.verificationOrientation).Length;
if (orientationDelta > 0.00001)
Console.Print("pos orient: " + rootActor.Orientation);
//if (currentInputFrame == 0)
/*{
//Console.Print("repos: " + inputState.verificationPosition);
Actor.Position = inputState.verificationPosition;
currentVelocity = inputState.verificationVelocity;
rootActor.Orientation = inputState.verificationOrientation;
}*/
}
input.RecordCurrentActorState(new PlayerActorState()
{
position = Actor.Position,
velocity = currentVelocity,
orientation = rootActor.Orientation,
viewYaw = viewYaw,
viewPitch = viewPitch,
viewRoll = viewRoll
});
input.OnEndFrame();
lastInputFrame = currentInputFrame;
currentInputFrame++;
viewPitchLastFrame = viewPitch;
viewYawLastFrame = viewYaw;
viewRollLastFrame = viewRoll;
fixedPosition = Actor.Position;
newframe = true;
}
private void ApplyInputToCamera(PlayerInputState inputState)
{
// Update camera viewf
float xAxis = inputState.viewDeltaX; float xAxis = inputState.viewDeltaX;
float yAxis = inputState.viewDeltaY; float yAxis = inputState.viewDeltaY;
if (xAxis != 0.0f || yAxis != 0.0f) if (xAxis != 0.0f || yAxis != 0.0f)
@@ -148,56 +263,24 @@ namespace Game
viewPitch = Mathf.Clamp(viewPitch + yAxis, -90.0f, 90.0f); viewPitch = Mathf.Clamp(viewPitch + yAxis, -90.0f, 90.0f);
viewYaw += xAxis; viewYaw += xAxis;
// root orientation must be set first // root orientation must be set first
rootActor.Orientation = Quaternion.Euler(0, viewYaw, 0); rootActor.Orientation = Quaternion.Euler(0, viewYaw, 0);
camera.Orientation = Quaternion.Euler(viewPitch, viewYaw, viewRoll); camera.Orientation = Quaternion.Euler(viewPitch, viewYaw, viewRoll);
} }
input.RecordCurrentActorState(new PlayerActorState()
{
position = Actor.Position,
velocity = currentVelocity,
viewYaw = viewYaw,
viewPitch = viewPitch,
viewRoll = viewRoll
});
} }
public override void OnFixedUpdate() private static bool SweepPlayerCollider(Actor actor, Vector3 start, Vector3 end, out RayCastHit[] hits)
{
input.OnFixedUpdate();
PlayerInputState inputState = input.GetCurrentInputState();
SimulatePlayerMovement(inputState);
input.RecordCurrentActorState(new PlayerActorState()
{
position = Actor.Position,
velocity = currentVelocity,
viewYaw = viewYaw,
viewPitch = viewPitch,
viewRoll = viewRoll
});
input.OnEndFrame();
}
private bool SweepPlayerCollider(Vector3 start, Vector3 end, out RayCastHit[] hits)
{ {
Vector3 delta = end - start; Vector3 delta = end - start;
float maxDistance = delta.Length; float maxDistance = delta.Length;
Vector3 direction = delta.Normalized; Vector3 direction = delta.Normalized;
bool collided = false; bool collided = false;
var capsuleCollider = Actor.GetChild<CapsuleCollider>(); var capsuleCollider = actor.GetChild<CapsuleCollider>();
var boxCollider = Actor.GetChild<BoxCollider>(); var boxCollider = actor.GetChild<BoxCollider>();
var meshCollider = Actor.GetChild<MeshCollider>(); var meshCollider = actor.GetChild<MeshCollider>();
PhysicsColliderActor colliderActor = null;
if (capsuleCollider && capsuleCollider.IsActive) if (capsuleCollider && capsuleCollider.IsActive)
{ {
colliderActor = capsuleCollider;
collided = Physics.CapsuleCastAll(start, collided = Physics.CapsuleCastAll(start,
capsuleCollider.Radius, capsuleCollider.Height, capsuleCollider.Radius, capsuleCollider.Height,
direction, out hits, capsuleCollider.Orientation, maxDistance, direction, out hits, capsuleCollider.Orientation, maxDistance,
@@ -206,7 +289,6 @@ namespace Game
} }
else if (meshCollider && meshCollider.IsActive) else if (meshCollider && meshCollider.IsActive)
{ {
colliderActor = meshCollider;
collided = Physics.ConvexCastAll(start, collided = Physics.ConvexCastAll(start,
meshCollider.CollisionData, meshCollider.Scale, meshCollider.CollisionData, meshCollider.Scale,
direction, out hits, meshCollider.Orientation, maxDistance, direction, out hits, meshCollider.Orientation, maxDistance,
@@ -215,7 +297,6 @@ namespace Game
} }
else if (boxCollider && boxCollider.IsActive) else if (boxCollider && boxCollider.IsActive)
{ {
colliderActor = boxCollider;
collided = Physics.BoxCastAll(start, collided = Physics.BoxCastAll(start,
boxCollider.OrientedBox.Extents, boxCollider.OrientedBox.Extents,
direction, out hits, boxCollider.Orientation, maxDistance, direction, out hits, boxCollider.Orientation, maxDistance,
@@ -291,10 +372,11 @@ namespace Game
/// <summary> /// <summary>
/// Sweeps the player rigidbody in world and returns geometry which was hit during the trace. /// Sweeps the player rigidbody in world and returns geometry which was hit during the trace.
/// </summary> /// </summary>
/// <param name="actor">Player actor</param>
/// <param name="start">Start position</param> /// <param name="start">Start position</param>
/// <param name="end">End position</param> /// <param name="end">End position</param>
/// <returns></returns> /// <returns></returns>
private TraceInfo TracePlayer(Vector3 start, Vector3 end) private static TraceInfo TracePlayer(Actor actor, Vector3 start, Vector3 end)
{ {
TraceInfo traceInfo = new TraceInfo(); TraceInfo traceInfo = new TraceInfo();
@@ -302,7 +384,7 @@ namespace Game
float maxDistance = delta.Length; float maxDistance = delta.Length;
Vector3 direction = delta.Normalized; Vector3 direction = delta.Normalized;
bool collided = SweepPlayerCollider(start, end, out traceInfo.hitInfos); bool collided = SweepPlayerCollider(actor, start, end, out traceInfo.hitInfos);
if (collided) if (collided)
{ {
List<RayCastHit> hitInfosFiltered = new List<RayCastHit>(); List<RayCastHit> hitInfosFiltered = new List<RayCastHit>();
@@ -312,7 +394,7 @@ namespace Game
{ {
//if (hitInfo.Collider == colliderActor) //if (hitInfo.Collider == colliderActor)
// continue; // continue;
if (hitInfo.Collider.Parent == Actor) if (hitInfo.Collider.Parent == actor)
continue; continue;
hitInfosFiltered.Add(hitInfo); hitInfosFiltered.Add(hitInfo);
@@ -411,7 +493,7 @@ namespace Game
} }
#endif #endif
private SlideMoveHit StepSlideMove(ref Vector3 position, ref Vector3 velocity, bool onGround) private static SlideMoveHit StepSlideMove(Actor actor, ref Vector3 position, ref Vector3 velocity, bool onGround)
{ {
if (velocity.IsZero) if (velocity.IsZero)
return SlideMoveHit.Nothing; return SlideMoveHit.Nothing;
@@ -419,7 +501,7 @@ namespace Game
Vector3 originalPosition = position; Vector3 originalPosition = position;
Vector3 originalVelocity = velocity; Vector3 originalVelocity = velocity;
SlideMoveHit slideMoveHit = SlideMove(ref position, ref velocity); SlideMoveHit slideMoveHit = SlideMove(actor, ref position, ref velocity);
if (slideMoveHit == SlideMoveHit.Nothing) if (slideMoveHit == SlideMoveHit.Nothing)
{ {
// TODO: step down here // TODO: step down here
@@ -438,16 +520,16 @@ namespace Game
// step up // step up
Vector3 stepUp = position + stepDelta; Vector3 stepUp = position + stepDelta;
TraceInfo traceUp = TracePlayer(position, stepUp); TraceInfo traceUp = TracePlayer(actor, position, stepUp);
if (traceUp.fraction > 0f) if (traceUp.fraction > 0f)
position = traceUp.endPosition; position = traceUp.endPosition;
// try moving from step up position // try moving from step up position
SlideMoveHit slideMoveStepHit = SlideMove(ref position, ref velocity); SlideMoveHit slideMoveStepHit = SlideMove(actor, ref position, ref velocity);
// step down // step down
Vector3 stepDown = position - stepDelta; Vector3 stepDown = position - stepDelta;
TraceInfo traceDown = TracePlayer(position, stepDown); TraceInfo traceDown = TracePlayer(actor, position, stepDown);
if (traceDown.fraction < 1f && -Vector3.Dot(Physics.Gravity.Normalized, traceDown.hitNormal) < slopeNormal) if (traceDown.fraction < 1f && -Vector3.Dot(Physics.Gravity.Normalized, traceDown.hitNormal) < slopeNormal)
{ {
// can't step down, slide move like normally // can't step down, slide move like normally
@@ -508,7 +590,7 @@ namespace Game
Other = 4, Other = 4,
} }
private SlideMoveHit SlideMove(ref Vector3 position, ref Vector3 velocity) private static SlideMoveHit SlideMove(Actor actor, ref Vector3 position, ref Vector3 velocity)
{ {
if (velocity.IsZero) if (velocity.IsZero)
return SlideMoveHit.Nothing; return SlideMoveHit.Nothing;
@@ -526,7 +608,7 @@ namespace Game
Vector3 startPos = position; Vector3 startPos = position;
Vector3 endPos = position + (velocity * timeleft); Vector3 endPos = position + (velocity * timeleft);
TraceInfo trace = TracePlayer(startPos, endPos); TraceInfo trace = TracePlayer(actor, startPos, endPos);
// TODO: handle portals here // TODO: handle portals here
float fraction = trace.fraction; float fraction = trace.fraction;
@@ -725,7 +807,7 @@ namespace Game
Vector3 groundDelta = Physics.Gravity.Normalized;//Physics.Gravity.Normalized * (collisionMargin * 2); Vector3 groundDelta = Physics.Gravity.Normalized;//Physics.Gravity.Normalized * (collisionMargin * 2);
//if (velocity.Y < 0f) //if (velocity.Y < 0f)
// groundDelta = Physics.Gravity.Normalized * velocity.Y * Time.DeltaTime; // groundDelta = Physics.Gravity.Normalized * velocity.Y * Time.DeltaTime;
TraceInfo traceGround = TracePlayer(position, position + groundDelta); TraceInfo traceGround = TracePlayer(Actor, position, position + groundDelta);
if (!traceGround.startSolid && traceGround.fraction < 1f && if (!traceGround.startSolid && traceGround.fraction < 1f &&
-Vector3.Dot(Physics.Gravity.Normalized, traceGround.hitNormal) < slopeNormal) -Vector3.Dot(Physics.Gravity.Normalized, traceGround.hitNormal) < slopeNormal)
@@ -742,8 +824,10 @@ namespace Game
Vector3 point = (position + groundDelta) + Vector3 point = (position + groundDelta) +
(1f - traceGround.fraction) * bounce; (1f - traceGround.fraction) * bounce;
Console.Print("backoff: " + backoff);
// retrace // retrace
traceGround = TracePlayer(position, position + point); traceGround = TracePlayer(Actor, position, position + point);
} }
if (!traceGround.startSolid && (traceGround.fraction >= 1f || if (!traceGround.startSolid && (traceGround.fraction >= 1f ||
@@ -751,9 +835,12 @@ namespace Game
{ {
// falling or sliding down a slope // falling or sliding down a slope
onGround = false; onGround = false;
} }
else else
{ {
//if (onGround != !traceGround.startSolid)
// Console.Print("slidefrac: " + traceGround.fraction);
onGround = !traceGround.startSolid; onGround = !traceGround.startSolid;
//Console.Print("issolid? :" + traceGround.startSolid); //Console.Print("issolid? :" + traceGround.startSolid);
} }
@@ -770,6 +857,7 @@ namespace Game
// jump // jump
if (onGround && jumpAction && !jumped) if (onGround && jumpAction && !jumped)
{ {
// reset velocity from gravity // reset velocity from gravity
if (-Vector3.Dot(Physics.Gravity.Normalized, velocity) < 0 && if (-Vector3.Dot(Physics.Gravity.Normalized, velocity) < 0 &&
Vector3.Dot(velocity, traceGround.hitNormal) < -0.1) Vector3.Dot(velocity, traceGround.hitNormal) < -0.1)
@@ -782,7 +870,7 @@ namespace Game
jumped = true; jumped = true;
lastJumped = Time.GameTime; lastJumped = Time.GameTime;
var jumpLandSound = JumpLandSound; /*var jumpLandSound = JumpLandSound;
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
var r = soundRandom.Next(3); var r = soundRandom.Next(3);
@@ -808,7 +896,7 @@ namespace Game
audioSource.Play(); audioSource.Play();
Destroy(audioSource, jumpLandSound.Length); Destroy(audioSource, jumpLandSound.Length);
lastJumpLandSound = jumpLandSound; lastJumpLandSound = jumpLandSound;
} }*/
} }
if (onGround) if (onGround)
@@ -874,15 +962,16 @@ namespace Game
// apply gravity // apply gravity
velocity += Physics.Gravity * Time.DeltaTime; velocity += Physics.Gravity * Time.DeltaTime;
//Console.Print(Time.DeltaTime.ToString());
} }
safePosition = rigidBody.Position; //safePosition = rigidBody.Position;
currentVelocity = velocity; currentVelocity = velocity;
if (!rigidBody.IsKinematic) /*if (!rigidBody.IsKinematic)
rigidBody.LinearVelocity = velocity; rigidBody.LinearVelocity = velocity;
else else*/
{ {
StepSlideMove(ref position, ref velocity, onGround); StepSlideMove(Actor, ref position, ref velocity, onGround);
rigidBody.Position = position; rigidBody.Position = position;
currentVelocity = velocity; currentVelocity = velocity;
@@ -890,7 +979,7 @@ namespace Game
} }
} }
void ApplyAcceleration(ref Vector3 velocity, Vector3 wishDir, float wishspeed, float maxWishspeed, private static void ApplyAcceleration(ref Vector3 velocity, Vector3 wishDir, float wishspeed, float maxWishspeed,
float acceleration) float acceleration)
{ {
float wishspeedOrig = wishspeed; float wishspeedOrig = wishspeed;

View File

@@ -27,6 +27,7 @@ namespace Game
public Dictionary<string, MaterialBase> brushMaterials; public Dictionary<string, MaterialBase> brushMaterials;
} }
[ExecuteInEditMode]
public class Q3MapImporter : Script public class Q3MapImporter : Script
{ {
//private string mapPath = @"C:\dev\GoakeFlax\Assets\Maps\cube_q1.map"; //private string mapPath = @"C:\dev\GoakeFlax\Assets\Maps\cube_q1.map";
@@ -188,6 +189,25 @@ namespace Game
public override void OnStart() public override void OnStart()
{ {
LoadMap(false);
}
private void LoadMap(bool forceLoad)
{
Actor worldSpawnActor = Actor.GetChild("WorldSpawn");
if (worldSpawnActor != null)
{
if (forceLoad)
{
worldSpawnActor.DestroyChildren();
}
else
{
//Console.Print("Map already loaded in the scene");
return;
}
}
{ {
var workDir = Directory.GetCurrentDirectory(); var workDir = Directory.GetCurrentDirectory();
var matBasePath = Path.Combine(workDir, "Content", "Materials"); var matBasePath = Path.Combine(workDir, "Content", "Materials");
@@ -218,8 +238,11 @@ namespace Game
} }
} }
var worldSpawnActor = Actor.AddChild<Actor>(); if (worldSpawnActor == null)
{
worldSpawnActor = Actor.AddChild<Actor>();
worldSpawnActor.Name = "WorldSpawn"; worldSpawnActor.Name = "WorldSpawn";
}
List<BrushGeometry> brushGeometries = new List<BrushGeometry>(root.entities[0].brushes.Count); List<BrushGeometry> brushGeometries = new List<BrushGeometry>(root.entities[0].brushes.Count);
@@ -265,7 +288,8 @@ namespace Game
materials.Add(textureName, brushMaterial); materials.Add(textureName, brushMaterial);
else else
{ {
Console.Print("Material '" + textureName + "' not found for brush"); // TODO: engine doesn't seem to always load the asset even though it exists, bug? seems to happen at low framerate
Console.Print("Material '" + textureName + "' not found for brush, assetPath: " + assetPath);
materials.Add(textureName, missingMaterial); materials.Add(textureName, missingMaterial);
brushMaterial = missingMaterial; brushMaterial = missingMaterial;
} }