API/Client-Server/js/core/TextureManager.js

143 lines
4.4 KiB
JavaScript

/**
* 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 `<img src="assets/textures/missing-texture.png" style="width: ${size}; height: ${size}; object-fit: contain;" alt="Missing texture">`;
}
return `<i class="fas ${icon}" style="font-size: ${size};"></i>`;
}
// 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);
}
}
}
}