75 lines
2.5 KiB
JavaScript
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;
|
|
})(); |