HollowBond/Public/ecma/Colliders/FrameCollider.ecma.js

75 lines
2.5 KiB
JavaScript

"use strict";
const FrameCollider = (function(){
const FrameCollider = function(hollow_bond, model){
const self = this;
this.model = model;
const is_horiz = model.axis === "horizontal";
const floor_h = hollow_bond.room_height || 3;
const pad_y = hollow_bond.room_padding || 0;
const base_y = (model.y * floor_h) + pad_y;
const pass_w = model.width;
const wall_depth = pad_y * 2;
const min_x = is_horiz ? model.x : model.x - wall_depth / 2;
const max_x = is_horiz ? model.x + pass_w : model.x + wall_depth / 2;
const min_z = is_horiz ? model.z - wall_depth / 2 : model.z;
const max_z = is_horiz ? model.z + wall_depth / 2 : model.z + pass_w;
this.bounds = {
min_x: min_x,
max_x: max_x,
min_z: min_z,
max_z: max_z,
min_y: base_y,
max_y: base_y + model.height
};
this.contains = (x, z) => {
return (
x >= self.bounds.min_x && x <= self.bounds.max_x &&
z >= self.bounds.min_z && z <= self.bounds.max_z
);
};
this.resolve_player = (position, controls, player_radius = 0.22) => {
if(!self.contains(position.x, position.z)) return;
const eye_height = controls.current_height || 1.75;
// 1. Apoyo sólido en el umbral mientras cruza el túnel
const target_eye_y = self.bounds.min_y + eye_height;
if(position.y <= target_eye_y){
position.y = target_eye_y;
controls.velocity_y = 0;
controls.is_grounded = true;
}
// 2. Dintel
if(position.y >= self.bounds.max_y){
position.y = self.bounds.max_y;
if(controls.velocity_y > 0) controls.velocity_y = 0;
}
// 3. Jambas laterales del marco
if(is_horiz){
const min_x = self.bounds.min_x + player_radius;
const max_x = self.bounds.max_x - player_radius;
if(position.x < min_x) position.x = min_x;
else if(position.x > max_x) position.x = max_x;
} else {
const min_z = self.bounds.min_z + player_radius;
const max_z = self.bounds.max_z - player_radius;
if(position.z < min_z) position.z = min_z;
else if(position.z > max_z) position.z = max_z;
}
};
};
return FrameCollider;
})();