mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
305 lines
12 KiB
JavaScript
305 lines
12 KiB
JavaScript
/**
|
|
* OBJECT PHYSICS SYSTEM
|
|
* =====================
|
|
*
|
|
* Handles physics bodies, collision setup, and object behavior for chairs and other objects.
|
|
* Separated from rooms.js for better modularity and maintainability.
|
|
*/
|
|
|
|
import { TILE_SIZE } from '../utils/constants.js';
|
|
|
|
let gameRef = null;
|
|
let rooms = null;
|
|
|
|
// Initialize object physics system
|
|
export function initializeObjectPhysics(gameInstance, roomsRef) {
|
|
gameRef = gameInstance;
|
|
rooms = roomsRef;
|
|
}
|
|
|
|
// Set up collision detection between chairs and other objects
|
|
export function setupChairCollisions(chair) {
|
|
if (!chair || !chair.body) return;
|
|
|
|
// Ensure we have a valid game reference
|
|
const game = gameRef || window.game;
|
|
if (!game) {
|
|
console.error('No game reference available, cannot set up chair collisions');
|
|
return;
|
|
}
|
|
|
|
// Use window.rooms to ensure we see the latest state
|
|
const allRooms = window.rooms || {};
|
|
|
|
// Collision with other chairs
|
|
if (window.chairs) {
|
|
window.chairs.forEach(otherChair => {
|
|
if (otherChair !== chair && otherChair.body) {
|
|
game.physics.add.collider(chair, otherChair);
|
|
}
|
|
});
|
|
}
|
|
|
|
// Collision with tables and other static objects
|
|
Object.values(allRooms).forEach(room => {
|
|
if (room.objects) {
|
|
Object.values(room.objects).forEach(obj => {
|
|
if (obj !== chair && obj.body && obj.body.immovable) {
|
|
game.physics.add.collider(chair, obj);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Collision with wall collision boxes
|
|
Object.values(allRooms).forEach(room => {
|
|
if (room.wallCollisionBoxes) {
|
|
room.wallCollisionBoxes.forEach(wallBox => {
|
|
if (wallBox.body) {
|
|
game.physics.add.collider(chair, wallBox);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Collision with closed door sprites
|
|
Object.values(allRooms).forEach(room => {
|
|
if (room.doorSprites) {
|
|
room.doorSprites.forEach(doorSprite => {
|
|
// Only collide with closed doors (doors that haven't been opened)
|
|
if (doorSprite.body && doorSprite.body.immovable) {
|
|
game.physics.add.collider(chair, doorSprite);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Set up collisions between existing chairs and new room objects
|
|
export function setupExistingChairsWithNewRoom(roomId) {
|
|
if (!window.chairs) return;
|
|
|
|
// Use window.rooms to ensure we see the latest state
|
|
const room = window.rooms ? window.rooms[roomId] : null;
|
|
if (!room) return;
|
|
|
|
// Ensure we have a valid game reference
|
|
const game = gameRef || window.game;
|
|
if (!game) {
|
|
console.error('No game reference available, cannot set up chair collisions');
|
|
return;
|
|
}
|
|
|
|
// Collision with new room's tables and static objects
|
|
if (room.objects) {
|
|
Object.values(room.objects).forEach(obj => {
|
|
if (obj.body && obj.body.immovable) {
|
|
window.chairs.forEach(chair => {
|
|
if (chair.body) {
|
|
game.physics.add.collider(chair, obj);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Collision with new room's wall collision boxes
|
|
if (room.wallCollisionBoxes) {
|
|
room.wallCollisionBoxes.forEach(wallBox => {
|
|
if (wallBox.body) {
|
|
window.chairs.forEach(chair => {
|
|
if (chair.body) {
|
|
game.physics.add.collider(chair, wallBox);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Collision with new room's door sprites
|
|
if (room.doorSprites) {
|
|
room.doorSprites.forEach(doorSprite => {
|
|
// Only collide with closed doors (doors that haven't been opened)
|
|
if (doorSprite.body && doorSprite.body.immovable) {
|
|
window.chairs.forEach(chair => {
|
|
if (chair.body) {
|
|
game.physics.add.collider(chair, doorSprite);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
console.log(`Set up chair collisions for room ${roomId} with ${window.chairs.length} existing chairs`);
|
|
}
|
|
|
|
// Calculate chair spin direction based on contact point
|
|
export function calculateChairSpinDirection(player, chair) {
|
|
if (!chair.isSwivelChair) return;
|
|
|
|
// Get relative position of player to chair SPRITE center (not collision box)
|
|
const chairSpriteCenterX = chair.x + chair.width / 2;
|
|
const chairSpriteCenterY = chair.y + chair.height / 2;
|
|
const playerX = player.x + player.width / 2;
|
|
const playerY = player.y + player.height / 2;
|
|
|
|
// Calculate offset from chair sprite center
|
|
const offsetX = playerX - chairSpriteCenterX;
|
|
const offsetY = playerY - chairSpriteCenterY;
|
|
|
|
// Calculate distance from center using sprite dimensions (not collision box)
|
|
const distanceFromCenter = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
|
|
// Use the larger sprite dimension for maxDistance to make center area larger
|
|
const maxDistance = Math.max(chair.width, chair.height) / 2;
|
|
const centerRatio = distanceFromCenter / maxDistance;
|
|
|
|
|
|
// Determine spin based on distance from center (EXTREMELY large center area)
|
|
if (centerRatio > 1.2) { // 120% from center - edge hit (strong spin) - ONLY VERY EDGES
|
|
// Determine spin direction based on which side of chair player is on
|
|
if (Math.abs(offsetX) > Math.abs(offsetY)) {
|
|
// Horizontal contact - spin based on X offset
|
|
chair.spinDirection = offsetX > 0 ? 1 : -1; // Right side = clockwise, left side = counter-clockwise
|
|
} else {
|
|
// Vertical contact - spin based on Y offset and player movement
|
|
const playerVelocityX = player.body.velocity.x;
|
|
if (Math.abs(playerVelocityX) > 10) {
|
|
// Player is moving horizontally - use that for spin direction
|
|
chair.spinDirection = playerVelocityX > 0 ? 1 : -1;
|
|
} else {
|
|
// Use Y offset for spin direction
|
|
chair.spinDirection = offsetY > 0 ? 1 : -1;
|
|
}
|
|
}
|
|
|
|
// Strong spin for edge hits
|
|
const spinIntensity = Math.min(centerRatio, 1.0);
|
|
chair.maxRotationSpeed = 0.15 * spinIntensity;
|
|
chair.rotationSpeed = Math.max(chair.rotationSpeed, 0.05); // Strong rotation start
|
|
|
|
|
|
} else if (centerRatio > 0.8) { // 80-120% from center - moderate hit
|
|
// Moderate spin
|
|
if (Math.abs(offsetX) > Math.abs(offsetY)) {
|
|
chair.spinDirection = offsetX > 0 ? 1 : -1;
|
|
} else {
|
|
const playerVelocityX = player.body.velocity.x;
|
|
chair.spinDirection = Math.abs(playerVelocityX) > 10 ? (playerVelocityX > 0 ? 1 : -1) : (offsetY > 0 ? 1 : -1);
|
|
}
|
|
|
|
const spinIntensity = centerRatio * 0.3; // Reduced intensity
|
|
chair.maxRotationSpeed = 0.06 * spinIntensity;
|
|
chair.rotationSpeed = Math.max(chair.rotationSpeed, 0.015); // Moderate rotation start
|
|
|
|
|
|
} else { // 0-80% from center - center hit (minimal spin) - MASSIVE CENTER AREA
|
|
// Very minimal or no spin for center hits
|
|
chair.spinDirection = 0;
|
|
chair.maxRotationSpeed = 0.01; // Very slow spin
|
|
chair.rotationSpeed = Math.max(chair.rotationSpeed, 0.002); // Minimal rotation start
|
|
|
|
}
|
|
}
|
|
|
|
// Update swivel chair rotation based on movement
|
|
export function updateSwivelChairRotation() {
|
|
if (!window.chairs) return;
|
|
|
|
// Ensure we have a valid game reference
|
|
const game = gameRef || window.game;
|
|
if (!game) return; // Silently return if no game reference
|
|
|
|
window.chairs.forEach(chair => {
|
|
if (!chair.hasWheels || !chair.body) return;
|
|
|
|
// Update chair depth based on current position (for all chairs with wheels)
|
|
updateSpriteDepth(chair, chair.elevation || 0);
|
|
|
|
// Only process rotation for swivel chairs
|
|
if (!chair.isSwivelChair) return;
|
|
|
|
// Calculate movement speed
|
|
const velocity = Math.sqrt(
|
|
chair.body.velocity.x * chair.body.velocity.x +
|
|
chair.body.velocity.y * chair.body.velocity.y
|
|
);
|
|
|
|
// Update rotation speed based on movement
|
|
if (velocity > 10) {
|
|
// Chair is moving - increase rotation speed (slower acceleration)
|
|
chair.rotationSpeed = Math.min(chair.rotationSpeed + 0.01, chair.maxRotationSpeed);
|
|
|
|
// If no spin direction set, set a default one for testing
|
|
if (chair.spinDirection === 0) {
|
|
chair.spinDirection = 1; // Default to clockwise
|
|
}
|
|
} else {
|
|
// Chair is slowing down - decrease rotation speed (slower deceleration)
|
|
chair.rotationSpeed = Math.max(chair.rotationSpeed - 0.005, 0);
|
|
|
|
// Reset spin direction when chair stops moving
|
|
if (chair.rotationSpeed < 0.01) {
|
|
chair.spinDirection = 0;
|
|
}
|
|
}
|
|
|
|
// Update frame based on rotation speed and direction
|
|
if (chair.rotationSpeed > 0.01) {
|
|
// Apply spin direction to rotation
|
|
const rotationDelta = chair.rotationSpeed * chair.spinDirection;
|
|
chair.currentFrame += rotationDelta;
|
|
|
|
// Handle frame wrapping (8 frames total: 0-7)
|
|
if (chair.currentFrame >= 8) {
|
|
chair.currentFrame = 0; // Loop back to first frame
|
|
} else if (chair.currentFrame < 0) {
|
|
chair.currentFrame = 7; // Loop back to last frame (for counter-clockwise)
|
|
}
|
|
|
|
// Set the texture based on current frame and chair type
|
|
const frameIndex = Math.floor(chair.currentFrame) + 1; // Convert to 1-based index
|
|
let newTexture;
|
|
|
|
// Determine texture prefix based on original texture
|
|
if (chair.originalTexture && chair.originalTexture.startsWith('chair-exec-rotate')) {
|
|
newTexture = `chair-exec-rotate${frameIndex}`;
|
|
} else if (chair.originalTexture && chair.originalTexture.startsWith('chair-white-1-rotate')) {
|
|
newTexture = `chair-white-1-rotate${frameIndex}`;
|
|
} else if (chair.originalTexture && chair.originalTexture.startsWith('chair-white-2-rotate')) {
|
|
newTexture = `chair-white-2-rotate${frameIndex}`;
|
|
} else {
|
|
// Fallback to exec chair if original texture is unknown
|
|
newTexture = `chair-exec-rotate${frameIndex}`;
|
|
}
|
|
|
|
// Check if texture exists before setting
|
|
if (game.textures.exists(newTexture)) {
|
|
chair.setTexture(newTexture);
|
|
} else {
|
|
console.warn(`Texture not found: ${newTexture}`);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Reusable function to update sprite depth based on Y position and elevation
|
|
export function updateSpriteDepth(sprite, elevation = 0) {
|
|
if (!sprite || !sprite.active) return;
|
|
|
|
// Get the bottom of the sprite (feet position)
|
|
const spriteBottomY = sprite.y + (sprite.height * sprite.scaleY);
|
|
|
|
// Calculate depth: world Y position + layer offset + elevation
|
|
const spriteDepth = spriteBottomY + 0.5 + elevation;
|
|
|
|
// Set the sprite depth
|
|
sprite.setDepth(spriteDepth);
|
|
}
|
|
|
|
// Export for global access
|
|
window.setupChairCollisions = setupChairCollisions;
|
|
window.setupExistingChairsWithNewRoom = setupExistingChairsWithNewRoom;
|
|
window.calculateChairSpinDirection = calculateChairSpinDirection;
|
|
window.updateSwivelChairRotation = updateSwivelChairRotation;
|
|
window.updateSpriteDepth = updateSpriteDepth;
|