HollowBond/Public/ecma/Colliders/RailingCollider.ecma.js

65 lines
2.6 KiB
JavaScript

"use strict";
const RailingCollider = (function(){
const RailingCollider = function(hollow_bond, segment){
const self = this;
this.segment = segment;
const th = (segment.thickness || 0.08) * 0.5;
const min_x = Math.min(segment.xf, segment.xt);
const max_x = Math.max(segment.xf, segment.xt);
const min_z = Math.min(segment.zf, segment.zt);
const max_z = Math.max(segment.zf, segment.zt);
// Caja de colisión engrosada para impedir que el jugador la atraviese
this.bounds = {
min_x: (min_x === max_x) ? (min_x - th) : min_x,
max_x: (min_x === max_x) ? (max_x + th) : max_x,
min_z: (min_z === max_z) ? (min_z - th) : min_z,
max_z: (min_z === max_z) ? (max_z + th) : max_z,
min_y: segment.y,
max_y: segment.y + (segment.height || 1.0)
};
this.resolve_player = (position, controls, player_radius = 0.22) => {
const eye_height = controls.current_height || 1.75;
const feet_y = position.y - eye_height;
// Si los pies están por encima de la barandilla (salto de jugador >= 2.0m), cruza libremente
if(feet_y >= (self.bounds.max_y - 0.08) || feet_y < (self.bounds.min_y - 0.25)){
return;
}
const r = player_radius;
const px = position.x;
const pz = position.z;
// Comprobación de contacto AABB expandido por el radio del jugador
if(
px + r > self.bounds.min_x && px - r < self.bounds.max_x &&
pz + r > self.bounds.min_z && pz - r < self.bounds.max_z
){
// Empujar hacia el lado firme de la habitación
switch(self.segment.side){
case "north": // Foso hacia el Sur (+Z), suelo firme hacia el Norte (-Z)
position.z = self.bounds.min_z - r;
break;
case "south": // Foso hacia el Norte (-Z), suelo firme hacia el Sur (+Z)
position.z = self.bounds.max_z + r;
break;
case "west": // Foso hacia el Este (+X), suelo firme hacia el Oeste (-X)
position.x = self.bounds.min_x - r;
break;
case "east": // Foso hacia el Oeste (-X), suelo firme hacia el Este (+X)
position.x = self.bounds.max_x + r;
break;
}
}
};
};
return RailingCollider;
})();