import Phaser from "phaser"; import type { Item } from "../core/types"; import { ALL_VARIANTS, type ItemVariantId } from "../core/config/ItemVariants"; /** * Factory for creating item sprites with optional variant glow effects. * Centralizes item rendering logic to ensure consistent glow styling across * inventory, quick slots, and world drops. */ export class ItemSpriteFactory { /** * Creates an item sprite with optional glow effect for variants. * Returns a container with the glow (if applicable) and main sprite. */ static createItemSprite( scene: Phaser.Scene, item: Item, x: number, y: number, scale: number = 1 ): Phaser.GameObjects.Container { const container = scene.add.container(x, y); // Create glow effect if item has a variant if (item.variant) { const glowColor = this.getGlowColor(item.variant as ItemVariantId); if (glowColor !== null) { const glow = this.createGlow(scene, item, scale, glowColor); container.add(glow); } } // Create main item sprite const sprite = scene.add.sprite(0, 0, item.textureKey, item.spriteIndex); sprite.setScale(scale); container.add(sprite); // Add upgrade level badge if item has been upgraded if (item.upgradeLevel && item.upgradeLevel > 0) { const badge = this.createUpgradeBadge(scene, item.upgradeLevel, scale); container.add(badge); } return container; } /** * Creates just a sprite (no container) for simpler use cases like drag icons. * Does not include glow - use createItemSprite for full effect. */ static createSimpleSprite( scene: Phaser.Scene, item: Item, x: number, y: number, scale: number = 1 ): Phaser.GameObjects.Sprite { const sprite = scene.add.sprite(x, y, item.textureKey, item.spriteIndex); sprite.setScale(scale); return sprite; } /** * Creates a soft glow effect behind the item using graphics. * Uses a radial gradient-like effect with multiple circles. */ private static createGlow( scene: Phaser.Scene, _item: Item, scale: number, color: number ): Phaser.GameObjects.Graphics { const glow = scene.add.graphics(); // Base size for the glow (16x16 sprite scaled) const baseSize = 16 * scale; const glowRadius = baseSize * 0.8; // Extract RGB from hex color const r = (color >> 16) & 0xff; const g = (color >> 8) & 0xff; const b = color & 0xff; // Draw multiple circles with decreasing alpha for soft glow effect const layers = 5; for (let i = layers; i >= 1; i--) { const layerRadius = glowRadius * (i / layers) * 1.2; const layerAlpha = 0.15 * (1 - (i - 1) / layers); glow.fillStyle(Phaser.Display.Color.GetColor(r, g, b), layerAlpha); glow.fillCircle(0, 0, layerRadius); } // Add pulsing animation to the glow scene.tweens.add({ targets: glow, alpha: { from: 0.7, to: 1.0 }, scaleX: { from: 0.9, to: 1.1 }, scaleY: { from: 0.9, to: 1.1 }, duration: 800, yoyo: true, repeat: -1, ease: 'Sine.easeInOut' }); return glow; } /** * Gets the glow color for a variant. */ private static getGlowColor(variantId: ItemVariantId): number | null { const variant = ALL_VARIANTS[variantId]; return variant?.glowColor ?? null; } /** * Creates a badge displaying the upgrade level (e.g., "+1"). */ private static createUpgradeBadge( scene: Phaser.Scene, level: number, scale: number ): Phaser.GameObjects.Text { // Position at top-right corner, slightly inset const offset = 5 * scale; // Level text with strong outline for readability without background const text = scene.add.text(offset, -offset, `+${level}`, { fontSize: `${9 * scale}px`, color: "#ffd700", fontStyle: "bold", fontFamily: "monospace", stroke: "#000000", strokeThickness: 3 }); text.setOrigin(0.5); return text; } /** * Checks if an item has a variant with a glow. */ static hasGlow(item: Item): boolean { return !!item.variant && !!ALL_VARIANTS[item.variant as ItemVariantId]; } }