Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 91x 91x 91x 59x 91x 61x 61x 61x 61x 61x 91x | /**
* useCombatLayout Hook - Optimized Layout Calculations
*
* Custom hook for managing responsive combat screen layout calculations.
* Optimizes layout recalculations by minimizing dependencies and memoizing
* complex calculations.
*
* Uses robust device detection combining user-agent and screen size to ensure
* mobile controls are shown on all mobile devices, including high-resolution phones.
*
* Performance:
* - Reduces recalculations by checking only breakpoint changes, not exact dimensions
* - Memoizes arena bounds to prevent cascading re-renders
* - Targets <1ms execution time for layout calculations
*
* @param width - Screen width
* @param height - Screen height
*
* @returns Layout constants and arena bounds
*
* @example
* ```typescript
* const { layoutConstants, arenaBounds, isMobile } = useCombatLayout(1200, 800);
* ```
*/
import { useMemo } from "react";
import { shouldUseMobileControls } from "../../../utils/deviceDetection";
export interface LayoutConstants {
readonly padding: number;
readonly hudHeight: number;
readonly controlsHeight: number;
readonly footerHeight: number;
readonly healthBarHeight: number;
}
export interface ArenaBounds {
readonly x: number;
readonly y: number;
readonly width: number;
readonly height: number;
}
export interface CombatLayout {
readonly layoutConstants: LayoutConstants;
readonly arenaBounds: ArenaBounds;
readonly isMobile: boolean;
}
/**
* Custom hook for combat screen layout calculations
* Optimized to reduce recalculations and improve 60fps performance
*/
export function useCombatLayout(width: number, height: number): CombatLayout {
// Device detection has its own internal caching based on screen dimensions
// No need for additional React memoization here
const isMobile = shouldUseMobileControls();
const isLargeDesktop = useMemo(() => width >= 1920, [width]); // 4K/2K displays
// Centralized layout constants for easier tweaking
// Optimized: Depends on breakpoint booleans, not exact width
const layoutConstants = useMemo<LayoutConstants>(
() => ({
padding: 10,
hudHeight: isMobile ? 95 : isLargeDesktop ? 90 : 120,
controlsHeight: isMobile ? 130 : isLargeDesktop ? 120 : 160,
footerHeight: isMobile ? 22 : isLargeDesktop ? 20 : 28,
healthBarHeight: isMobile ? 48 : isLargeDesktop ? 45 : 55,
}),
[isMobile, isLargeDesktop]
);
// Fixed player positions for 2-player combat with proper bounds
// Arena bounds should account for HUD at top and controls at bottom
// Optimized: Separate calculation dependencies to reduce recalculation frequency
const arenaBounds = useMemo<ArenaBounds>(() => {
const arenaY = layoutConstants.hudHeight + layoutConstants.padding;
// Break down complex calculation for clarity and maintainability
const totalReservedHeight =
layoutConstants.hudHeight +
layoutConstants.controlsHeight +
layoutConstants.footerHeight;
const totalPadding = layoutConstants.padding * 3;
const arenaHeight = height - totalReservedHeight - totalPadding;
return {
x: width * 0.1,
y: arenaY,
width: width * 0.8,
height: arenaHeight,
};
}, [width, height, layoutConstants]);
return {
layoutConstants,
arenaBounds,
isMobile,
};
}
|