/** * Galaxy Strike Online - Texture Manager * Handles texture loading and missing texture fallbacks */ class TextureManager { constructor(gameEngine) { this.game = gameEngine; this.textures = new Map(); this.missingTextureUrl = 'assets/textures/missing-texture.png'; // Initialize missing texture this.loadMissingTexture(); } async loadMissingTexture() { try { const img = new Image(); img.src = this.missingTextureUrl; await img.decode(); this.textures.set('missing', img); } catch (error) { console.warn('Could not load missing texture, creating fallback'); this.createFallbackTexture(); } } createFallbackTexture() { const canvas = document.createElement('canvas'); canvas.width = 64; canvas.height = 64; const ctx = canvas.getContext('2d'); // Create a pink and black checkerboard pattern const squareSize = 8; for (let y = 0; y < 8; y++) { for (let x = 0; x < 8; x++) { ctx.fillStyle = (x + y) % 2 === 0 ? '#FF00FF' : '#000000'; ctx.fillRect(x * squareSize, y * squareSize, squareSize, squareSize); } } // Add "GSO Missing" text ctx.fillStyle = '#FFFFFF'; ctx.font = 'bold 12px Arial'; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillText('GSO', 32, 28); ctx.fillText('Missing', 32, 36); const img = new Image(); img.src = canvas.toDataURL(); this.textures.set('missing', img); } async loadTexture(textureId, textureUrl) { // Check if already loaded if (this.textures.has(textureId)) { return this.textures.get(textureId); } try { const img = new Image(); img.src = textureUrl; await img.decode(); this.textures.set(textureId, img); return img; } catch (error) { console.warn(`Failed to load texture ${textureId} from ${textureUrl}, using missing texture`); return this.getMissingTexture(); } } getTexture(textureId) { return this.textures.get(textureId) || this.getMissingTexture(); } getMissingTexture() { return this.textures.get('missing') || this.createFallbackTexture(); } // Icon fallback for FontAwesome icons getIcon(iconClass) { // Check if this is a valid FontAwesome icon const validIconPrefixes = ['fas', 'far', 'fab', 'fal']; const iconParts = iconClass.split(' '); const hasValidPrefix = iconParts.some(part => validIconPrefixes.includes(part)); if (hasValidPrefix) { return iconClass; } // Return missing icon fallback - use missing texture return 'missing-texture'; } // Get item icon as HTML element getItemIconElement(iconClass, size = '32px') { const icon = this.getIcon(iconClass); if (icon === 'missing-texture') { return `Missing texture`; } return ``; } // Preload common textures async preloadTextures() { const commonTextures = [ 'ship_fighter', 'ship_cruiser', 'room_command_center', 'room_power_core', 'item_weapon', 'item_shield' ]; const loadPromises = commonTextures.map(textureId => { const url = `assets/textures/${textureId}.png`; return this.loadTexture(textureId, url); }); try { await Promise.all(loadPromises); console.log('Common textures preloaded'); } catch (error) { console.warn('Some textures failed to preload:', error); } } // Clean up unused textures cleanup() { // Keep only essential textures in memory const essentialTextures = ['missing']; for (const [textureId, texture] of this.textures) { if (!essentialTextures.includes(textureId)) { this.textures.delete(textureId); } } } }