reorganize

This commit is contained in:
2022-05-02 20:34:42 +03:00
parent 654e641464
commit 3f1230fdf9
34 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using FlaxEngine;
namespace Game
{
public class CustomCharacterController : CharacterController
{
}
}

View File

@@ -0,0 +1,30 @@
using System.Collections.Generic;
using FlaxEngine;
using Cabrito;
namespace Game
{
public static class InputManager
{
public static bool GetAction(string name)
{
if (Console.IsOpen)
return false;
return Input.GetAction(name);
}
public static float GetAxis(string name)
{
if (Console.IsOpen)
return 0.0f;
return Input.GetAxis(name);
}
public static float GetAxisRaw(string name)
{
if (Console.IsOpen)
return 0.0f;
return Input.GetAxisRaw(name);
}
}
}

View File

@@ -0,0 +1,52 @@
using System.Collections.Generic;
using System.Linq;
using FlaxEngine;
using Cabrito;
#if FLAX_EDITOR
using FlaxEditor.CustomEditors.Dedicated;
using FlaxEditor.Scripting;
#endif
using FlaxEngine.GUI;
namespace Game
{
#if FLAX_EDITOR
[CustomEditor(typeof(PlayerActor))]
public class PlayerActorEditor : ActorEditor
{
protected override List<ItemInfo> GetItemsForType(ScriptType type)
{
List<ItemInfo> items = GetItemsForType(type, type.IsClass, true);
// Remove all Rigid Body options
items.RemoveAll(x => x.Display.Group == "Rigid Body");
// Inject scripts editor
var scriptsMember = type.GetProperty("Scripts");
if (scriptsMember != ScriptMemberInfo.Null)
{
var item = new ItemInfo(scriptsMember)
{
CustomEditor = new CustomEditorAttribute(typeof(ScriptsEditor))
};
items.Add(item);
}
return items;
}
}
#endif
public class PlayerActor : RigidBody
{
public PlayerActor()
{
// Default internal values for RigidBody
IsKinematic = true;
EnableGravity = false;
LinearDamping = 0f;
AngularDamping = 0f;
Constraints = RigidbodyConstraints.LockRotation;
}
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using FlaxEngine;
namespace Game
{
[StructLayout(LayoutKind.Sequential)]
public struct PlayerInputState
{
public ulong frame;
public float viewDeltaX, viewDeltaY;
public float moveForward;
public float moveRight;
public bool attacking;
public bool jumping;
public Vector3 verificationPosition;
public Vector3 verificationVelocity;
public Vector3 verificationViewAngles;
public Quaternion verificationOrientation;
}
[StructLayout(LayoutKind.Sequential)]
public struct PlayerActorState
{
public Vector3 position;
public Vector3 velocity;
public Quaternion orientation;
public Vector3 viewAngles; // yaw, pitch, roll
}
[StructLayout(LayoutKind.Sequential)]
public struct PlayerState
{
public PlayerInputState input;
public PlayerActorState actor;
}
public class PlayerInput
{
public PlayerState currentState;
public ulong frame;
public const byte DemoVer = 1;
public virtual void OnUpdate()
{
}
public virtual void OnFixedUpdate()
{
}
public virtual void OnEndFrame()
{
}
public virtual void RecordCurrentActorState(PlayerActorState actorState)
{
}
public PlayerInputState GetCurrentInputState()
{
return currentState.input;
}
public PlayerActorState GetCurrentActorState()
{
return currentState.actor;
}
}
}

View File

@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices;
using FlaxEngine;
using Console = Cabrito.Console;
namespace Game
{
public class PlayerInputDemo : PlayerInput
{
protected List<PlayerInputState> buffer = new List<PlayerInputState>();
protected IEnumerator<PlayerInputState> bufferEnumerable;
public PlayerInputDemo(string demoPath)
{
if (!File.Exists(demoPath))
return;
var expectedPlayerInputStateSize = Marshal.SizeOf(typeof(PlayerInputState));
var stream = File.OpenRead(demoPath);
var ver = (int)stream.ReadByte();
var inputStateSize = (int)stream.ReadByte();
if (ver != DemoVer && inputStateSize != expectedPlayerInputStateSize)
{
Console.Print("demover mismatch: version " + ver + " != " + DemoVer + ", inputStateSize " + inputStateSize + " != " + Marshal.SizeOf(typeof(PlayerInputState)));
stream.Close();
return;
}
T RawDeserialize<T>(byte[] rawData, int position)
{
int rawsize = Marshal.SizeOf(typeof(T));
if (rawsize > rawData.Length - position)
throw new ArgumentException("Not enough data to fill struct. Array length from position: " + (rawData.Length-position) + ", Struct length: " + rawsize);
IntPtr buffer = Marshal.AllocHGlobal(rawsize);
Marshal.Copy(rawData, position, buffer, rawsize);
T retobj = (T)Marshal.PtrToStructure(buffer, typeof(T));
Marshal.FreeHGlobal(buffer);
return retobj;
}
while (true)
{
byte[] b = new byte[expectedPlayerInputStateSize];
var readBytes = stream.Read(b, 0, b.Length);
if (readBytes < expectedPlayerInputStateSize)
break;
buffer.Add(RawDeserialize<PlayerInputState>(b, 0));
}
bufferEnumerable = buffer.GetEnumerator();
Console.Print("demo numstates: " + buffer.Count);
OnEndFrame(); // advances to first frame
}
public override void OnEndFrame()
{
// 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 (buffer.Any())
{
bufferEnumerable.Dispose();
bufferEnumerable = null;
buffer.Clear();
Console.Print("Demo ended");
}
return;
}
//var actorState = currentState.actor;
currentState.input = bufferEnumerable.Current;
//frame++;
//currentState.actor = actorState;
}
}
}

View File

@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using FlaxEngine;
using Console = Cabrito.Console;
namespace Game
{
public class PlayerInputLocal : PlayerInput
{
protected List<PlayerInputState> buffer = new List<PlayerInputState>();
protected FileStream demoFileStream;
public bool IsRecording { get { return demoFileStream != null; } }
public PlayerInputLocal()
{
}
public PlayerInputLocal(string demoPath)
{
demoFileStream = File.Open(demoPath, FileMode.Create, FileAccess.Write);
//stream.Position = 0;
//stream.SetLength(0);
demoFileStream.WriteByte(DemoVer);
demoFileStream.WriteByte((byte)Marshal.SizeOf(typeof(PlayerInputState)));
}
public override void OnUpdate()
{
// Collect all input here
// All axis values here should be accumulated
currentState.input.viewDeltaX += InputManager.GetAxisRaw("Mouse X");
currentState.input.viewDeltaY += InputManager.GetAxisRaw("Mouse Y");
currentState.input.viewDeltaX += InputManager.GetAxisRaw("LookRight") * Time.DeltaTime * 100;
currentState.input.viewDeltaY += -InputManager.GetAxisRaw("LookUp") * Time.DeltaTime * 100;
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 OnFixedUpdate()
{
}
public override void OnEndFrame()
{
if (IsRecording)
{
currentState.input.verificationPosition = currentState.actor.position;
currentState.input.verificationVelocity = currentState.actor.velocity;
currentState.input.verificationViewAngles = currentState.actor.viewAngles;
currentState.input.verificationOrientation = currentState.actor.orientation;
currentState.input.frame = frame;
buffer.Add(currentState.input);
}
// Reset anything accumulatable here
currentState.input.viewDeltaX = 0;
currentState.input.viewDeltaY = 0;
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()
{
if (!IsRecording)
return;
byte[] RawSerialize(object anything)
{
int rawSize = Marshal.SizeOf(anything);
IntPtr buffer = Marshal.AllocHGlobal(rawSize);
Marshal.StructureToPtr(anything, buffer, false);
byte[] rawDatas = new byte[rawSize];
Marshal.Copy(buffer, rawDatas, 0, rawSize);
Marshal.FreeHGlobal(buffer);
return rawDatas;
}
foreach (var state in buffer)
{
var bytes = RawSerialize(state);
demoFileStream.Write(bytes, 0, bytes.Length * sizeof(byte));
}
buffer.Clear();
}
public void StopRecording()
{
if (!IsRecording)
return;
FlushDemo();
demoFileStream.Close();
demoFileStream = null;
Debug.Write(LogType.Info, "demo, wrote states: " + buffer.Count);
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using FlaxEngine;
namespace Game
{
public class PlayerInputNetwork : PlayerInput
{
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,765 @@
#if false
using System.Collections.Generic;
using FlaxEngine;
using Cabrito;
using System.Diagnostics;
using System.Threading.Tasks;
using FlaxEngine.Assertions;
namespace Game
{
public struct TraceInfo_NK
{
public RayCastHit[] hitInfos;
public bool startSolid;
// closest hit
public float fraction;
public Vector3 endPosition;
public Vector3 hitNormal;
public Vector3 hitPosition;
// furthest hit
//public float maxFraction;
//public Vector3 maxHitNormal;
//public Vector3 maxEndPosition;
}
public class PlayerMovement_NK : Script
{
[Limit(0, 9000), Tooltip("Base Movement speed")]
public float MoveSpeed { get; set; } = 320;
private float viewPitch;
private float viewYaw;
private float viewRoll;
private InputEvent onExit = new InputEvent("Exit");
private const float collisionMargin = 0.031f * 1.666f;
Actor rootActor;
public override void OnAwake()
{
base.OnAwake();
onExit.Triggered += () =>
{
if (Console.IsSafeToQuit)
Engine.RequestExit();
};
rootActor = Actor.GetChild(0);
RigidBody rigidBody = Actor.As<RigidBody>();
rigidBody.CollisionEnter += OnCollisionEnter;
rigidBody.CollisionExit += OnCollisionLeave;
rigidBody.TriggerEnter += OnTriggerEnter;
//rigidBody.SetSolverIterationCounts(40, 10);
Console.Print("playermovement init: " + rigidBody.MaxDepenetrationVelocity.ToString());
}
private void OnTriggerEnter(PhysicsColliderActor colliderActor)
{
Console.Print("trogger: ");
}
private void OnCollisionEnter(Collision collision)
{
//Console.Print("collision: " + collision.Contacts[0].Normal);
}
private void OnCollisionLeave(Collision collision)
{
//Console.Print("collision leave: " + collision.Contacts[0].Normal);
}
public override void OnDestroy()
{
base.OnDestroy();
onExit.Dispose();
}
public override void OnStart()
{
var initialEulerAngles = Actor.Orientation.EulerAngles;
viewPitch = initialEulerAngles.X;
viewYaw = initialEulerAngles.Y;
viewRoll = initialEulerAngles.Z;
}
/// <summary>
/// Checks for overlapping colliders in place using the player's rigidbody.
/// </summary>
/// <param name="position">Position</param>
/// <returns></returns>
private Collider[] TracePlayer(Vector3 position, float tolerance = 0.0f)
{
Collider[] colliders = null;
bool collided = false;
var capsuleCollider = Actor.GetChild<CapsuleCollider>();
var boxCollider = Actor.GetChild<BoxCollider>();
var meshCollider = Actor.GetChild<MeshCollider>();
PhysicsColliderActor colliderActor = null;
if (capsuleCollider && capsuleCollider.IsActive)
{
colliderActor = capsuleCollider;
collided = Physics.OverlapCapsule(position,
capsuleCollider.Radius + tolerance, capsuleCollider.Height + tolerance,
out colliders, capsuleCollider.Orientation,
uint.MaxValue,
false);
}
else if (meshCollider && meshCollider.IsActive)
{
colliderActor = meshCollider;
collided = Physics.OverlapConvex(position,
meshCollider.CollisionData, meshCollider.Scale + tolerance,
out colliders, meshCollider.Orientation,
uint.MaxValue,
false);
}
else if (boxCollider && boxCollider.IsActive)
{
colliderActor = boxCollider;
collided = Physics.OverlapBox(position,
boxCollider.OrientedBox.Extents + tolerance,
out colliders, boxCollider.Orientation,
uint.MaxValue,
false);
}
else
Assert.Fail("No supported colliders found for rigidbody");
if (!collided)
return colliders;
List<Collider> collidersFiltered = new List<Collider>();
foreach (var collider in colliders)
{
if (collider == colliderActor)
continue;
collidersFiltered.Add(collider);
}
if (collidersFiltered.Count == 0)
return colliders; // self-collision?
return collidersFiltered.ToArray();
}
/// <summary>
/// Sweeps the player rigidbody in world and returns geometry which was hit during the trace.
/// </summary>
/// <param name="start">Start position</param>
/// <param name="end">End position</param>
/// <returns></returns>
private TraceInfo TracePlayer(Vector3 start, Vector3 end, float tolerance = 0.0f)
{
TraceInfo traceInfo = new TraceInfo();
Vector3 delta = end - start;
float maxDistance = delta.Length;
Vector3 direction = delta.Normalized;
bool collided = false;
var capsuleCollider = Actor.GetChild<CapsuleCollider>();
var boxCollider = Actor.GetChild<BoxCollider>();
var meshCollider = Actor.GetChild<MeshCollider>();
PhysicsColliderActor colliderActor = null;
if (capsuleCollider && capsuleCollider.IsActive)
{
colliderActor = capsuleCollider;
collided = Physics.CapsuleCastAll(start,
capsuleCollider.Radius + tolerance, capsuleCollider.Height,
direction, out traceInfo.hitInfos, capsuleCollider.Orientation, maxDistance,
uint.MaxValue,
false);
}
else if (meshCollider && meshCollider.IsActive)
{
colliderActor = meshCollider;
collided = Physics.ConvexCastAll(start,
meshCollider.CollisionData, meshCollider.Scale + tolerance,
direction, out traceInfo.hitInfos, meshCollider.Orientation, maxDistance,
uint.MaxValue,
false);
}
else if (boxCollider && boxCollider.IsActive)
{
colliderActor = boxCollider;
collided = Physics.BoxCastAll(start,
boxCollider.OrientedBox.Extents + tolerance,
direction, out traceInfo.hitInfos, boxCollider.Orientation, maxDistance, uint.MaxValue,
false);
}
if (collided)
{
List<RayCastHit> hitInfosFiltered = new List<RayCastHit>();
RayCastHit closest = new RayCastHit();
closest.Distance = float.MaxValue;
foreach (var hitInfo in traceInfo.hitInfos)
{
if (hitInfo.Collider == colliderActor)
continue;
hitInfosFiltered.Add(hitInfo);
if (hitInfo.Distance < closest.Distance && hitInfo.Distance != 0.0f)
closest = hitInfo;
}
if (hitInfosFiltered.Count == 0)
collided = false; // self-collision?
else //if (closest.Distance > 0f)
{
if (closest.Distance == float.MaxValue)
{
foreach (var hitInfo in hitInfosFiltered)
{
if (hitInfo.Distance < closest.Distance)
closest = hitInfo;
}
}
traceInfo.hitInfos = hitInfosFiltered.ToArray();
traceInfo.fraction = closest.Distance / maxDistance;
traceInfo.hitNormal = closest.Normal;
traceInfo.hitPosition = closest.Point;
traceInfo.endPosition = start + (delta * traceInfo.fraction);
if (traceInfo.fraction == 0f && maxDistance > 0f)
traceInfo.startSolid = true;
}
/*else
{
traceInfo.startSolid = true;
traceInfo.fraction = 0f;
}*/
}
if (!collided)
{
traceInfo.hitInfos = new RayCastHit[0];
traceInfo.fraction = 1f;
traceInfo.endPosition = end;
}
return traceInfo;
}
public override void OnDebugDraw()
{
base.OnDebugDraw();
var capsuleCollider = Actor.GetChild<CapsuleCollider>();
var boxCollider = Actor.GetChild<BoxCollider>();
var meshCollider = Actor.GetChild<MeshCollider>();
if (capsuleCollider && capsuleCollider.IsActive)
{
Quaternion rotation = capsuleCollider.LocalOrientation * Quaternion.Euler(0f, 90f, 0f);
DebugDraw.DrawWireTube(capsuleCollider.Position, rotation, capsuleCollider.Radius, capsuleCollider.Height, Color.GreenYellow * 0.8f);
}
else if (meshCollider && meshCollider.IsActive)
{
//Quaternion rotation = meshCollider.LocalOrientation * Quaternion.Euler(0f, 90f, 0f);
DebugDraw.DrawWireCylinder(meshCollider.Position, meshCollider.Orientation, capsuleCollider.Radius, capsuleCollider.Height + capsuleCollider.Radius * 2, Color.GreenYellow * 0.8f);
//DebugDraw.DrawWireTube(meshCollider.Position, rotation, meshCollider.Radius, meshCollider.Height, Color.GreenYellow * 0.8f);
}
else if (boxCollider && boxCollider.IsActive)
{
DebugDraw.DrawWireBox(boxCollider.OrientedBox.GetBoundingBox(), Color.GreenYellow * 0.8f);
}
}
private void SlideMove(ref Vector3 position, bool stepUp, ref Vector3 velocity, bool asdf = false)
{
if (velocity.IsZero)
return;
Vector3 originalPosition = position;
Vector3 originalVelocity = velocity;
float timeleft = Time.DeltaTime;
List<Vector3> hitNormals = new List<Vector3>();
for (int bump = 0; bump < 4; bump++)
{
Vector3 startPos = position;
Vector3 endPos = position + (velocity * timeleft);
TraceInfo trace = TracePlayer(startPos, endPos);
// TODO: handle portals here
float fraction = trace.fraction;
Vector3 hitNormal = trace.hitNormal;
if (trace.startSolid)
{
velocity = Vector3.Zero;
break;
}
if (physicsInteractions)
{
RigidBody rigidBody = Actor.As<RigidBody>();
foreach (var hit in trace.hitInfos)
{
if (hit.Collider.AttachedRigidBody == null || hit.Collider.AttachedRigidBody.IsKinematic)
continue;
Vector3 force = -hit.Normal * velocity.Length * rigidBody.Mass;
//Console.Print("move force: " + (force.Length / timeleft));
hit.Collider.AttachedRigidBody.AddForce(force, ForceMode.Force);
}
}
if (fraction > 0f)
{
position = trace.endPosition;
hitNormals.Clear(); // this is present in some forks, not in Q3
}
if (fraction >= 1f)
break;
timeleft *= 1.0f - fraction;
// this doesn't seem to do anything, we never have any hitNormals stored here
bool hitPreviousNormal = false;
foreach (Vector3 normal in hitNormals)
{
if (Vector3.Dot(hitNormal, normal) > 0.99)
{
// nudge away from the same wall we hit earlier and try again
velocity += hitNormal;
hitPreviousNormal = true;
break;
}
}
if (hitPreviousNormal)
continue;
hitNormals.Add(hitNormal);
if (hitNormals.Count != 1)
Console.Print("hitNormals: " + hitNormals.Count);
int plane;
Vector3 normalMargin = Vector3.Zero;
for (plane = 0; plane < hitNormals.Count; plane++)
{
Vector3 normal = hitNormals[plane];
// clip velocity
velocity -= normal * Vector3.Dot(velocity, normal);
//velocity = Vector3.ProjectOnPlane(velocity, normal);
//traceOffset = normal * 1f;
normalMargin += normal;
//position += normal * 0.031f;
int plane2;
for (plane2 = 0; plane2 < hitNormals.Count; plane2++)
{
if (plane == plane2)
continue;
if (Vector3.Dot(velocity, hitNormals[plane2]) < 0f)
break;
}
if (plane2 == hitNormals.Count)
break;
}
// push off slightly away from the walls to not get stuck
position += normalMargin.Normalized * collisionMargin;
if (plane == hitNormals.Count)
{
if (hitNormals.Count == 2)
{
Vector3 dir = Vector3.Cross(hitNormals[0], hitNormals[1]);
//dir.Normalize();
float dist = Vector3.Dot(dir, velocity);
velocity = dist * dir;
}
else
{
velocity = Vector3.Zero;
break;
}
}
else
{
// nudge very slightly away from the wall to avoid getting stuck
//position += trace.hitNormal * 0.01f;
//velocity += trace.hitNormal * 0.01f;
}
// prevents bouncing against the wall
if (/*velocity.Length > 0f && */Vector3.Dot(velocity, originalVelocity) <= 0f)
{
velocity = Vector3.Zero;
break;
}
}
}
//Vector3 wishVelocity = Vector3.Zero;
//Vector3 gravityVelocity = Vector3.Zero;
//Vector3 currentVelocity = Vector3.Zero;
private bool onGround = false;
private const float friction = 4f;
private const float stopspeed = 100f;
private const float accelerationGround = 10f;
private const float jumpVelocity = 270f;
private const float maxAirSpeed = 320f;
private const float maxAirStrafeSpeed = 30f; //Q2+
private const float airAcceleration = 0.4f * 0f; //Q2+
private const float airStopAcceleration = 2.5f * 0f; //Q2+
private const float airStrafeAcceleration = 70f * 0f; //CPM?
private const float strafeAcceleration = 10f; //QW
private const float airControl = 0f; //CPM
private bool physicsInteractions = false;
private bool jumped = false;
private Vector3 safePosition;
private Vector3 currentVelocity;
public override void OnFixedUpdate()
{
RigidBody rigidBody = Actor.As<RigidBody>();
Transform rootTrans = rootActor.Transform;
Vector3 inputDirection =
new Vector3(InputManager.GetAxis("Horizontal"), 0.0f, InputManager.GetAxis("Vertical"));
Vector3 moveDirection = rootTrans.TransformDirection(inputDirection);
//Vector3 position = rigidBody.Position;
Vector3 velocity = rigidBody.LinearVelocity;//currentVelocity;
Vector3 wishVelocity = Vector3.Zero;
if (!inputDirection.IsZero)
wishVelocity = moveDirection.Normalized * MoveSpeed;
// categorize position
onGround = true;
Vector3 groundDelta = Physics.Gravity.Normalized * collisionMargin*2;
Vector3 traceGroundStart = rigidBody.Position - groundDelta;
Vector3 traceGroundEnd = rigidBody.Position + groundDelta;
TraceInfo traceGround = TracePlayer(traceGroundStart, traceGroundEnd, -0.1f);
float groundDistance = 0.1f;
if (traceGround.fraction < 1f/* && !traceGround.startSolid*//*&& ddot < 0.7f*/)
{
/*
// slope
// clip velocity
Vector3 bounce = -groundDelta;
Vector3 bounceDir = -groundDelta.Normalized;//traceGround.hitNormal;
//Vector3 velocityProjected = Vector3.ProjectOnPlane(velocity, normal);
float backoff = Vector3.Dot(bounce, bounceDir) * 2f;
bounce -= bounceDir * backoff;
//velocity = velocityProjected;
Vector3 point = (rigidBody.Position + groundDelta) +
(1f - traceGround.fraction) * bounce;
//Vector3 point = rigidBody.Position - ((1f - traceGround.fraction) * groundDelta);
//rigidBody.Position = point;
// retrace
//traceGround = TracePlayer(traceGround.endPosition, point);
*/
}
/*if (!traceGround.startSolid && traceGround.fraction < 1f &&
-Vector3.Dot(Physics.Gravity.Normalized, traceGround.hitNormal) < 0.7f)
{
// slope
// clip velocity
Vector3 bounce = groundDelta;
//Vector3 velocityProjected = Vector3.ProjectOnPlane(velocity, normal);
float backoff = Vector3.Dot(bounce, traceGround.hitNormal) * 2f;
bounce -= traceGround.hitNormal * backoff;
//velocity = velocityProjected;
Vector3 point = (rigidBody.Position + groundDelta) +
(1f - traceGround.fraction) * bounce;
// retrace
traceGround = TracePlayer(rigidBody.Position, rigidBody.Position + point);
}*/
//if (!traceGround.startSolid && (traceGround.fraction >= 1f ||
// -Vector3.Dot(Physics.Gravity.Normalized, traceGround.hitNormal) < 0.7f))
float rampDot = -Vector3.Dot(Physics.Gravity.Normalized, traceGround.hitNormal);
if (traceGround.fraction >= 1f)
rampDot = 1f;
else if (traceGround.hitNormal.IsZero)
rampDot = 99f;
if (traceGround.fraction >= 1f || rampDot < 0.7f)
{
//Console.Print("air: " + (-Vector3.Dot(Physics.Gravity.Normalized, traceGround.hitNormal)).ToString());
// falling or sliding down a slope
onGround = false;
}
else
{
float closestDist = float.MaxValue;
foreach (var hit in traceGround.hitInfos)
{
if (hit.Distance < closestDist && hit.Distance != 0f)
closestDist = hit.Distance;
}
if (traceGround.fraction == 0f && closestDist != 0f)
Console.Print("minteresting");
//Console.Print("grund: "+ (-Vector3.Dot(Physics.Gravity.Normalized, traceGround.hitNormal)).ToString());
onGround = true;//!traceGround.startSolid;
//velocity.Y = 0f;
// move slightly above the ground
// maintain distance off the ground
float dist = ((traceGroundEnd - rigidBody.Position) * (traceGround.fraction - 0.5f)).Length;
if (dist < groundDistance)
{
var newPos = rigidBody.Position;
newPos.Y += groundDistance - dist;
//rigidBody.Position = newPos;
//velocity.Y = 0f;
}
//velocity.Y = 0f;
}
onGround = true;
//Console.Print("frac: " + traceGround.fraction + "norm: " + rampDot);
//onGround |= overlaps.Length > 0;
/*if (onGround && physicsInteractions && traceGround.hitInfos.Length > 0)
{
// apply resting force to rigid bodies under the player
//bool collided = false;
foreach (var hit in traceGround.hitInfos)
{
if (hit.Collider.AttachedRigidBody == null || hit.Collider.AttachedRigidBody.IsKinematic)
continue;
if (hit.Distance <= 0f)
continue;
//Console.Print(Physics.Gravity.Length.ToString());
Vector3 force = -hit.Normal * (Physics.Gravity.Length) * rigidBody.Mass * Time.DeltaTime;
hit.Collider.AttachedRigidBody.AddForceAtPosition(force, hit.Point, ForceMode.Impulse);
//collided = true;
//Console.Print("downforce: " + force.Length / Time.DeltaTime);
}
//if (collided)
// fraction = 1.0f; // finish movement and stop
}*/
/*if (!onGround)
Console.Print("air");
else
Console.Print("ground");*/
/*if (onGround)
{
// snap to ground
if (!traceGround.startSolid)
{
Vector3 newPos = rigidBody.Position;
if (traceGround.fraction < 1f)
{
//newPos += -Physics.Gravity.Normalized * traceGround.fraction;
}
rigidBody.Position = newPos;
}
}*/
/*if (traceGround.startSolid)
{
Console.Print("stuk: ");
rigidBody.Position = safePosition;
traceGround = TracePlayer(rigidBody.Position, rigidBody.Position + Physics.Gravity.Normalized,
false);
//onGround = true;
//currentVelocity.Y = 0f;
}
if (!traceGround.startSolid)
{
foreach (var hitInfo in traceGround.hitInfos)
{
var dot = Vector3.Dot(Physics.Gravity.Normalized, hitInfo.Normal);
if (-dot >= 0.7) //~45deg slope
{
//Console.Print("d: " + hitInfo.Distance);
Vector3 newPos = rigidBody.Position;
if (hitInfo.Distance > 0f)
newPos += Physics.Gravity.Normalized * (hitInfo.Distance - 0.01f);
else
newPos += hitInfo.Normal * 0.1f;
rigidBody.Position = newPos;
onGround = true;
currentVelocity.Y = 0f;
break;
//if (currentVelocity.Length > 0.01f)
// Console.Print("groundvel: " + currentVelocity.ToString());
//currentVelocity.Y = 0.0f;
}
}
}*/
// jump
if (onGround)
{
if (!jumped && InputManager.GetAction("Jump"))
{
jumped = true;
velocity += Vector3.Up * jumpVelocity;
onGround = false;
}
}
if (jumped && !InputManager.GetAction("Jump")) // jump released
jumped = false;
// ground friction
if (onGround)
{
float currentSpeed = velocity.Length;
float control = currentSpeed < stopspeed ? stopspeed : currentSpeed;
var drop = control * friction * Time.DeltaTime;
float newspeed = currentSpeed - drop;
if (newspeed < 0)
newspeed = 0;
if (currentSpeed < 0.0001f)
velocity *= 0;
else
velocity *= newspeed / currentSpeed;
}
//bool stepUp = false;
if (onGround) // ground acceleration
{
ApplyAcceleration(ref velocity, wishVelocity.Normalized, wishVelocity.Length, float.MaxValue, accelerationGround);
}
else // air acceleration
{
var wishspeed = wishVelocity.Length;
if (wishspeed > maxAirSpeed)
wishspeed = maxAirSpeed;
if (strafeAcceleration != 0f)
ApplyAcceleration(ref velocity, wishVelocity.Normalized, wishspeed, maxAirStrafeSpeed, strafeAcceleration);
//stepUp = true;
}
if (!onGround)
{
velocity += Physics.Gravity * Time.DeltaTime;
//Console.Print("grav");
}
//else
// Console.Print("Yv: " + currentVelocity.Y);
//SlideMove(ref position, false, ref velocity);
safePosition = rigidBody.Position;
if (rigidBody.EnableSimulation)
{
//rigidBody.Position = position;
//Vector3 force = velocity - rigidBody.LinearVelocity;
rigidBody.LinearVelocity = velocity;
//rigidBody.AddForce(force, ForceMode.Impulse);
}
else
{
//rigidBody.Position = position;
rigidBody.LinearVelocity = velocity;
}
//rigidBody.LinearVelocity = velocity;
//if (currentVelocity.Length > 0.01f)
// Console.Print("vel: " + currentVelocity.ToString());
}
void ApplyAcceleration(ref Vector3 velocity, Vector3 wishDir, float wishspeed, float maxWishspeed, float acceleration)
{
float wishspeedOrig = wishspeed;
if (wishspeed > maxWishspeed)
wishspeed = maxWishspeed;
float currentSpeed = Vector3.Dot(velocity, wishDir);
float addSpeed = wishspeed - currentSpeed;
if (addSpeed <= 0f)
return;
float accelSpeed = acceleration * wishspeedOrig * Time.DeltaTime;
if (accelSpeed > addSpeed)
accelSpeed = addSpeed;
velocity += accelSpeed * wishDir;
}
public override void OnUpdate()
{
float xAxis = InputManager.GetAxisRaw("Mouse X");
float yAxis = InputManager.GetAxisRaw("Mouse Y");
if (xAxis != 0.0f || yAxis != 0.0f)
{
var camera = rootActor.GetChild<Camera>();
viewPitch += yAxis;
viewYaw += xAxis;
viewPitch = Mathf.Clamp(viewPitch, -90.0f, 90.0f);
// root orientation must be set first
rootActor.Orientation = Quaternion.Euler(0, viewYaw, 0);
camera.Orientation = Quaternion.Euler(viewPitch, viewYaw, viewRoll);
}
}
}
}
#endif