ObiNoWanKenobi - FirstPersonController Changes

This commit is contained in:
2025-09-19 17:03:20 +00:00
parent fcbab54a0c
commit 19b79d61c7

View File

@ -1,87 +1,243 @@
package leenkx.trait; package leenkx.trait;
import iron.Trait;
import iron.math.Vec4; import iron.math.Vec4;
import iron.system.Input; import iron.system.Input;
import iron.object.Object; import iron.object.Object;
import iron.object.CameraObject; import iron.object.CameraObject;
import leenkx.trait.physics.PhysicsWorld; import leenkx.trait.physics.PhysicsWorld;
import leenkx.trait.internal.CameraController; import leenkx.trait.physics.RigidBody;
import kha.FastFloat;
class FirstPersonController extends CameraController { class FirstPersonController extends Trait {
#if (!lnx_physics) #if (!lnx_physics)
public function new() { super(); } public function new() { super(); }
#else #else
var head: Object; @prop public var rotationSpeed:Float = 0.15;
static inline var rotationSpeed = 2.0; @prop public var maxPitch:Float = 2.2;
@prop public var minPitch:Float = 0.5;
@prop public var enableJump:Bool = true;
@prop public var jumpForce:Float = 22.0;
@prop public var moveSpeed:Float = 500.0;
public function new() { @prop public var forwardKey:String = "w";
super(); @prop public var backwardKey:String = "s";
@prop public var leftKey:String = "a";
@prop public var rightKey:String = "d";
@prop public var jumpKey:String = "space";
iron.Scene.active.notifyOnInit(init); @prop public var allowAirJump:Bool = false;
}
function init() { @prop public var canRun:Bool = true;
head = object.getChildOfType(CameraObject); @prop public var runKey:String = "shift";
@prop public var runSpeed:Float = 1000.0;
PhysicsWorld.active.notifyOnPreUpdate(preUpdate); // Sistema de estamina
notifyOnUpdate(update); @prop public var stamina:Bool = false;
notifyOnRemove(removed); @prop public var staminaBase:Float = 75.0;
} @prop public var staRecoverPerSec:Float = 5.0;
@prop public var staDecreasePerSec:Float = 5.0;
@prop public var staRecoverTime:Float = 2.0;
@prop public var staDecreasePerJump:Float = 5.0;
@prop public var enableFatigue:Bool = false;
@prop public var fatigueSpeed:Float = 0.5; // the reduction of movement when fatigue is activated...
@prop public var fatigueThreshold:Float = 30.0; // Tiempo corriendo sin parar para la activacion // Time running non-stop for activation...
@prop public var fatRecoveryThreshold:Float = 7.5; // Tiempo sin correr/saltar para salir de fatiga // Time without running/jumping to get rid of fatigue...
var xVec = Vec4.xAxis();
var zVec = Vec4.zAxis();
function preUpdate() {
if (Input.occupied || !body.ready) return;
var mouse = Input.getMouse(); // Var Privadas
var kb = Input.getKeyboard(); var head:CameraObject;
var pitch:Float = 0.0;
var body:RigidBody;
if (mouse.started() && !mouse.locked) mouse.lock(); var moveForward:Bool = false;
else if (kb.started("escape") && mouse.locked) mouse.unlock(); var moveBackward:Bool = false;
var moveLeft:Bool = false;
var moveRight:Bool = false;
var isRunning:Bool = false;
if (mouse.locked || mouse.down()) { var canJump:Bool = true;
head.transform.rotate(xVec, -mouse.movementY / 250 * rotationSpeed); var staminaValue:Float = 0.0;
transform.rotate(zVec, -mouse.movementX / 250 * rotationSpeed); var timeSinceStop:Float = 0.0;
body.syncTransform();
var fatigueTimer:Float = 0.0;
var fatigueCooldown:Float = 0.0;
var isFatigueActive:Bool = false;
public function new() {
super();
iron.Scene.active.notifyOnInit(init);
}
function init() {
body = object.getTrait(RigidBody);
head = object.getChildOfType(CameraObject);
PhysicsWorld.active.notifyOnPreUpdate(preUpdate);
notifyOnUpdate(update);
notifyOnRemove(removed);
staminaValue = staminaBase;
}
function removed() {
PhysicsWorld.active.removePreUpdate(preUpdate);
}
var zVec = Vec4.zAxis();
function preUpdate() {
if (Input.occupied || body == null) return;
var mouse = Input.getMouse();
var kb = Input.getKeyboard();
if (mouse.started() && !mouse.locked)
mouse.lock();
else if (kb.started("escape") && mouse.locked)
mouse.unlock();
if (mouse.locked || mouse.down()) {
var deltaTime:Float = iron.system.Time.delta;
object.transform.rotate(zVec, -mouse.movementX * rotationSpeed * deltaTime);
var deltaPitch:Float = -(mouse.movementY * rotationSpeed * deltaTime);
pitch += deltaPitch;
pitch = Math.max(minPitch, Math.min(maxPitch, pitch));
head.transform.setRotation(pitch, 0.0, 0.0);
body.syncTransform();
}
}
var dir:Vec4 = new Vec4();
function isFatigued():Bool {
return enableFatigue && isFatigueActive;
}
function update() {
if (body == null) return;
var deltaTime:Float = iron.system.Time.delta;
var kb = Input.getKeyboard();
moveForward = kb.down(forwardKey);
moveBackward = kb.down(backwardKey);
moveLeft = kb.down(leftKey);
moveRight = kb.down(rightKey);
var isMoving = moveForward || moveBackward || moveLeft || moveRight;
var isGrounded:Bool = false;
#if lnx_physics
var vel = body.getLinearVelocity();
if (Math.abs(vel.z) < 0.1) {
isGrounded = true;
}
#end
// Dejo establecido el salto para tener en cuenta la (enableFatigue) si es que es false/true....
if (isGrounded && !isFatigued()) {
canJump = true;
} }
} // Saltar con estamina
if (enableJump && kb.started(jumpKey) && canJump) {
var jumpPower = jumpForce;
// Disminuir el salto al 50% si la (stamina) esta por debajo o en el 20%.
if (stamina) {
if (staminaValue <= 0) {
jumpPower = 0;
} else if (staminaValue <= staminaBase * 0.2) {
jumpPower *= 0.5;
}
function removed() { staminaValue -= staDecreasePerJump;
PhysicsWorld.active.removePreUpdate(preUpdate); if (staminaValue < 0.0) staminaValue = 0.0;
} timeSinceStop = 0.0;
}
var dir = new Vec4(); if (jumpPower > 0) {
function update() { body.applyImpulse(new Vec4(0, 0, jumpPower));
if (!body.ready) return; if (!allowAirJump) canJump = false;
}
}
if (jump) { // Control de estamina y correr
body.applyImpulse(new Vec4(0, 0, 16)); if (canRun && kb.down(runKey) && isMoving) {
jump = false; if (stamina) {
if (staminaValue > 0.0) {
isRunning = true;
staminaValue -= staDecreasePerSec * deltaTime;
if (staminaValue < 0.0) staminaValue = 0.0;
} else {
isRunning = false;
}
} else {
isRunning = true;
}
} else {
isRunning = false;
}
// (temporizadores aparte)
if (isRunning) {
timeSinceStop = 0.0;
fatigueTimer += deltaTime;
fatigueCooldown = 0.0;
} else {
timeSinceStop += deltaTime;
fatigueCooldown += deltaTime;
}
// Evitar correr y saltar al estar fatigado...
if (isFatigued()) {
isRunning = false;
canJump = false;
} }
// Move // Activar fatiga despues de correr continuamente durante cierto umbral
dir.set(0, 0, 0); if (enableFatigue && fatigueTimer >= fatigueThreshold) {
if (moveForward) dir.add(transform.look()); isFatigueActive = true;
if (moveBackward) dir.add(transform.look().mult(-1)); }
if (moveLeft) dir.add(transform.right().mult(-1));
if (moveRight) dir.add(transform.right());
// Push down // Eliminar la fatiga despues de recuperarse
var btvec = body.getLinearVelocity(); if (enableFatigue && isFatigueActive && fatigueCooldown >= fatRecoveryThreshold) {
body.setLinearVelocity(0.0, 0.0, btvec.z - 1.0); isFatigueActive = false;
fatigueTimer = 0.0;
}
if (moveForward || moveBackward || moveLeft || moveRight) { // Recuperar estamina si no esta corriendo
var dirN = dir.normalize(); if (stamina && !isRunning && staminaValue < staminaBase && !isFatigued()) {
dirN.mult(6); if (timeSinceStop >= staRecoverTime) {
body.activate(); staminaValue += staRecoverPerSec * deltaTime;
body.setLinearVelocity(dirN.x, dirN.y, btvec.z - 1.0); if (staminaValue > staminaBase) staminaValue = staminaBase;
} }
}
// Keep vertical // Movimiento ejes (local)
body.setAngularFactor(0, 0, 0); dir.set(0, 0, 0);
camera.buildMatrix(); if (moveForward) dir.add(object.transform.look());
} if (moveBackward) dir.add(object.transform.look().mult(-1));
#end if (moveLeft) dir.add(object.transform.right().mult(-1));
if (moveRight) dir.add(object.transform.right());
var btvec = body.getLinearVelocity();
body.setLinearVelocity(0.0, 0.0, btvec.z - 1.0);
if (isMoving) {
var dirN = dir.normalize();
var baseSpeed = moveSpeed;
if (isRunning && moveForward) {
baseSpeed = runSpeed;
}
var currentSpeed = isFatigued() ? baseSpeed * fatigueSpeed : baseSpeed;
dirN.mult(currentSpeed * deltaTime);
body.activate();
body.setLinearVelocity(dirN.x, dirN.y, btvec.z - 1.0);
}
body.setAngularFactor(0, 0, 0);
head.buildMatrix();
}
#end
} }
// Stamina and fatigue system.....