From b1686fc5eb8340323c860971c3da30bb9b892cb7 Mon Sep 17 00:00:00 2001 From: "Z. Cliffe Schreuders" Date: Thu, 6 Nov 2025 01:54:55 +0000 Subject: [PATCH] feat(css): Enhance minigame styles with max-width and margin for better layout refactor(js): Remove unused asset loading in preload function feat(js): Implement optimal scale calculation for pixel-perfect rendering in person chat portraits --- css/container-minigame.css | 3 + css/lockpick-set-minigame.css | 286 ------------------ css/lockpicking.css | 5 +- css/minigames-framework.css | 10 +- css/password-minigame.css | 3 +- css/pin.css | 3 + js/core/game.js | 1 - .../lockpicking/lockpicking-game-phaser.js | 6 +- .../person-chat/person-chat-portraits.js | 54 +++- 9 files changed, 66 insertions(+), 305 deletions(-) delete mode 100644 css/lockpick-set-minigame.css diff --git a/css/container-minigame.css b/css/container-minigame.css index 26d9d80..f4e28c3 100644 --- a/css/container-minigame.css +++ b/css/container-minigame.css @@ -6,6 +6,9 @@ height: 100%; padding: 20px; gap: 20px; + + max-width: 600px; + margin: 20px auto; } /* Desktop Mode Styles */ diff --git a/css/lockpick-set-minigame.css b/css/lockpick-set-minigame.css deleted file mode 100644 index c5c9494..0000000 --- a/css/lockpick-set-minigame.css +++ /dev/null @@ -1,286 +0,0 @@ -/* Lockpick Set Minigame Styles */ - -.lockpick-set-minigame-container { - /* Compact interface similar to other minigames */ - position: fixed !important; - top: 5vh !important; - right: 2vw !important; - width: 350px !important; - height: auto !important; - max-height: 60vh !important; - background: linear-gradient(135deg, #1a2e1a 0%, #163e16 50%, #0f600f 100%) !important; - box-shadow: 0 0 20px rgba(76, 175, 80, 0.3), inset 0 0 10px rgba(76, 175, 80, 0.1) !important; - border: 4px solid #4caf50 !important; - clip-path: polygon( - 0px calc(100% - 10px), - 2px calc(100% - 10px), - 2px calc(100% - 6px), - 4px calc(100% - 6px), - 4px calc(100% - 4px), - 6px calc(100% - 4px), - 6px calc(100% - 2px), - 10px calc(100% - 2px), - 10px 100%, - calc(100% - 10px) 100%, - calc(100% - 10px) calc(100% - 2px), - calc(100% - 6px) calc(100% - 2px), - calc(100% - 6px) calc(100% - 4px), - calc(100% - 4px) calc(100% - 4px), - calc(100% - 4px) calc(100% - 6px), - calc(100% - 2px) calc(100% - 6px), - calc(100% - 2px) calc(100% - 10px), - 100% calc(100% - 10px), - 100% 10px, - calc(100% - 2px) 10px, - calc(100% - 2px) 6px, - calc(100% - 4px) 6px, - calc(100% - 4px) 4px, - calc(100% - 6px) 4px, - calc(100% - 6px) 2px, - calc(100% - 10px) 2px, - calc(100% - 10px) 0px, - 10px 0px, - 10px 2px, - 6px 2px, - 6px 4px, - 4px 4px, - 4px 6px, - 2px 6px, - 2px 10px, - 0px 10px - ) !important; - color: #e0e0e0 !important; - overflow: hidden !important; - transition: all 0.3s ease !important; -} - -.lockpick-set-minigame-container.expanded { - width: 450px !important; - max-height: 70vh !important; -} - -.lockpick-set-minigame-game-container { - width: 100% !important; - height: 100% !important; - max-width: none !important; - background: transparent !important; - border-radius: 0 !important; - box-shadow: none !important; - position: relative !important; - overflow: visible !important; - display: flex !important; - flex-direction: column !important; - padding: 15px !important; - box-sizing: border-box !important; -} - -/* Lockpick Header */ -.lockpick-set-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 10px; - padding: 10px; - background: rgba(76, 175, 80, 0.1); - border: 1px solid #4caf50; - /* border-radius: 6px; */ - box-shadow: 0 0 10px rgba(76, 175, 80, 0.2); -} - -.lockpick-set-title { - display: flex; - align-items: center; - gap: 8px; - font-size: 18px; - font-weight: bold; - color: #4caf50; - text-shadow: 0 0 5px rgba(76, 175, 80, 0.5); -} - -.lockpick-icon { - height: 24px; - filter: drop-shadow(0 0 3px rgba(76, 175, 80, 0.5)); - image-rendering: pixelated; -} - -.lockpick-set-status { - display: flex; - align-items: center; - gap: 6px; - font-size: 18px; - color: #4caf50; -} - -.lockpick-indicator { - width: 8px; - height: 8px; - border-radius: 50%; - background: #4caf50; - box-shadow: 0 0 6px rgba(76, 175, 80, 0.8); - animation: pulse 2s infinite; -} - -.lockpick-indicator.active { - background: #4caf50; -} - -.lockpick-indicator.inactive { - background: #f44336; - animation: none; -} - -@keyframes pulse { - 0% { opacity: 1; transform: scale(1); } - 50% { opacity: 0.5; transform: scale(1.2); } - 100% { opacity: 1; transform: scale(1); } -} - -/* Expand/Collapse Toggle */ -.lockpick-expand-toggle { - position: absolute; - top: 10px; - left: 10px; - width: 24px; - height: 24px; - background: rgba(76, 175, 80, 0.2); - border: 1px solid #4caf50; - /* border-radius: 4px; */ - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - font-size: 18px; - color: #4caf50; - transition: all 0.3s ease; - z-index: 10; -} - -.lockpick-expand-toggle:hover { - background: rgba(76, 175, 80, 0.3); - box-shadow: 0 0 8px rgba(76, 175, 80, 0.4); -} - -.lockpick-expand-toggle.expanded { - transform: rotate(180deg); -} - -/* Search Room Button */ -.lockpick-search-room-container { - margin-bottom: 15px; - display: flex; - justify-content: center; - padding: 10px; - background: rgba(76, 175, 80, 0.1); - /* border-radius: 6px; */ - box-shadow: 0 0 10px rgba(76, 175, 80, 0.2); -} - -/* Action Buttons */ -.lockpick-action-btn { - display: flex; - align-items: center; - gap: 6px; - padding: 8px 12px; - background: rgba(76, 175, 80, 0.2); - border: 1px solid #4caf50; - /* border-radius: 6px; */ - color: #4caf50; - font-size: 18px; - cursor: pointer; - transition: all 0.3s ease; - user-select: none; -} - -.lockpick-action-btn:hover { - background: rgba(76, 175, 80, 0.3); - box-shadow: 0 0 10px rgba(76, 175, 80, 0.4); - transform: translateY(-1px); -} - -.lockpick-action-btn.active { - background: rgba(255, 193, 7, 0.3); - border-color: #ffc107; - color: #ffc107; - box-shadow: 0 0 15px rgba(255, 193, 7, 0.4); -} - -.lockpick-action-btn .btn-icon { - font-size: 18px; -} - -.lockpick-action-btn .btn-text { - font-weight: bold; -} - -/* Instructions */ -.lockpick-set-instructions { - margin-top: 10px; - padding: 10px; - background: rgba(0, 0, 0, 0.2); - border: 1px solid #444; - /* border-radius: 6px; */ - font-size: 18px; - line-height: 1.4; - color: #ccc; - transition: all 0.3s ease; -} - -.lockpick-set-minigame-container:not(.expanded) .lockpick-set-instructions { - display: none; -} - -.instruction-text { - color: #aaa; -} - -.instruction-text strong { - color: #4caf50; -} - -/* Responsive Design */ -@media (max-width: 768px) { - .lockpick-set-minigame-container { - top: 2vh !important; - right: 2vw !important; - left: 2vw !important; - width: 96vw !important; - max-width: 400px !important; - } - - .lockpick-set-minigame-container.expanded { - width: 96vw !important; - max-width: 500px !important; - } - - .lockpick-set-title { - font-size: 18px; - } - - .lockpick-action-btn { - justify-content: center; - padding: 6px 10px; - font-size: 18px; - } - - .lockpick-expand-toggle { - width: 20px; - height: 20px; - font-size: 10px; - } -} - -/* Animation for new highlights */ -@keyframes lockpickAppear { - 0% { - opacity: 0; - transform: translateX(-20px); - } - 100% { - opacity: 1; - transform: translateX(0); - } -} - -.lockpick-indicator.new-highlight { - animation: lockpickAppear 0.5s ease-out; -} diff --git a/css/lockpicking.css b/css/lockpicking.css index ea26f85..54bc1fa 100644 --- a/css/lockpicking.css +++ b/css/lockpicking.css @@ -88,12 +88,11 @@ /* Phaser game container styling - prevent margin/padding shifts */ #phaser-game-container { - margin: 0 !important; - padding: 0 !important; + max-width: 600px; + margin: 20px auto; } #phaser-game-container canvas { margin: 0 !important; - padding: 0 !important; display: block; } diff --git a/css/minigames-framework.css b/css/minigames-framework.css index 20adfca..52c01fd 100644 --- a/css/minigames-framework.css +++ b/css/minigames-framework.css @@ -2,10 +2,10 @@ .minigame-container { position: fixed; - top: 2vh; - left: 2vw; - width: 96vw; - height: 96vh; + /* top: 2vh; */ + /* left: 2vw; */ + width: 100vw; + height: 100vh; background: rgba(0, 0, 0, 0.95); z-index: 2000; display: flex; @@ -46,7 +46,7 @@ .minigame-game-container { width: 100%; height: 100%; - max-width: 600px; + /* max-width: 600px; */ margin: 20px auto; background: #1a1a1a; box-shadow: 0 0 15px rgba(0, 0, 0, 0.5) inset; diff --git a/css/password-minigame.css b/css/password-minigame.css index be44300..8b4f93b 100644 --- a/css/password-minigame.css +++ b/css/password-minigame.css @@ -5,9 +5,10 @@ flex-direction: column; height: 100%; padding: 20px; - gap: 15px; background: #1a1a1a; position: relative; + max-width: 600px; + margin: 20px auto; } .password-image-section { diff --git a/css/pin.css b/css/pin.css index e252f94..f351b22 100644 --- a/css/pin.css +++ b/css/pin.css @@ -14,6 +14,9 @@ align-items: center; justify-content: center; gap: 20px; + + max-width: 600px; + margin: 20px auto; } .pin-minigame-interface { diff --git a/js/core/game.js b/js/core/game.js index c020ac3..6f317c4 100644 --- a/js/core/game.js +++ b/js/core/game.js @@ -331,7 +331,6 @@ export function preload() { this.load.image('pc10', 'assets/objects/pc10.png'); this.load.image('pc11', 'assets/objects/pc11.png'); this.load.image('pc12', 'assets/objects/pc12.png'); - this.load.image('pc13', 'assets/objects/pc13.png'); // Laptops diff --git a/js/minigames/lockpicking/lockpicking-game-phaser.js b/js/minigames/lockpicking/lockpicking-game-phaser.js index 8a8266f..ef2a6d1 100644 --- a/js/minigames/lockpicking/lockpicking-game-phaser.js +++ b/js/minigames/lockpicking/lockpicking-game-phaser.js @@ -420,11 +420,7 @@ export class LockpickingMinigamePhaser extends MinigameScene { width: 600, height: 400, backgroundColor: '#1a1a1a', - scene: LockpickingScene, - scale: { - mode: Phaser.Scale.FIT, - autoCenter: Phaser.Scale.CENTER_BOTH - } + scene: LockpickingScene }; // Adjust canvas size for mobile to crop empty space diff --git a/js/minigames/person-chat/person-chat-portraits.js b/js/minigames/person-chat/person-chat-portraits.js index 133de65..897f04e 100644 --- a/js/minigames/person-chat/person-chat-portraits.js +++ b/js/minigames/person-chat/person-chat-portraits.js @@ -92,14 +92,60 @@ export default class PersonChatPortraits { } /** - * Update canvas size to match available screen space + * Calculate optimal integer scale factor for current browser window + * Matches base resolution (640x480) with pixel-perfect scaling + * @returns {number} Optimal integer scale factor + */ + calculateOptimalScale() { + const baseWidth = 640; + const baseHeight = 480; + + // Calculate scale factors for both dimensions + const scaleX = window.innerWidth / baseWidth; + const scaleY = window.innerHeight / baseHeight; + + // Use the smaller scale to maintain aspect ratio + const maxScale = Math.min(scaleX, scaleY); + + // Find the best integer scale factor (prefer 2x or higher for pixel art) + let bestScale = 2; // Minimum for good pixel art + + // Check integer scales from 2x up to the maximum that fits + for (let scale = 2; scale <= Math.floor(maxScale); scale++) { + const scaledWidth = baseWidth * scale; + const scaledHeight = baseHeight * scale; + + // If this scale fits within the container, use it + if (scaledWidth <= window.innerWidth && scaledHeight <= window.innerHeight) { + bestScale = scale; + } else { + break; // Stop at the largest scale that fits + } + } + + return bestScale; + } + + /** + * Update canvas size to match available screen space with pixel-perfect scaling */ updateCanvasSize() { if (!this.canvas) return; - // Use full viewport size - this.canvas.width = window.innerWidth; - this.canvas.height = window.innerHeight; + // Calculate optimal scale for pixel-perfect rendering + const optimalScale = this.calculateOptimalScale(); + const baseWidth = 640; + const baseHeight = 480; + + // Set canvas internal resolution based on optimal scale + this.canvas.width = baseWidth * optimalScale; + this.canvas.height = baseHeight * optimalScale; + + // Apply CSS scale to maintain proper viewport size + this.canvas.style.width = '100%'; + this.canvas.style.height = '100%'; + + console.log(`🎨 Canvas scaled to ${optimalScale}x (${this.canvas.width}x${this.canvas.height}px)`); } /**