@minicode-dev/chat 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/assets/sounds/effects/confetti.mp3 +0 -0
- package/assets/sounds/effects/nudge.mp3 +0 -0
- package/dist/chunks/{BattleshipGameCard-CW_A8Nim.js → BattleshipGameCard-S-UdM6rn.js} +100 -100
- package/dist/chunks/{BattleshipGameCard-CW_A8Nim.js.map → BattleshipGameCard-S-UdM6rn.js.map} +1 -1
- package/dist/chunks/{BattleshipPrototype-Duz-S1JE.js → BattleshipPrototype-Dm6U_mCr.js} +52 -52
- package/dist/chunks/{BattleshipPrototype-Duz-S1JE.js.map → BattleshipPrototype-Dm6U_mCr.js.map} +1 -1
- package/dist/chunks/confettiScene3d-WooGwo25.js +367 -0
- package/dist/chunks/confettiScene3d-WooGwo25.js.map +1 -0
- package/dist/chunks/{connect4Sounds-Do3nvVFx.js → connect4Sounds-9u0p-dAf.js} +7 -7
- package/dist/chunks/{connect4Sounds-Do3nvVFx.js.map → connect4Sounds-9u0p-dAf.js.map} +1 -1
- package/dist/chunks/thunderScene3d-FMMuwJRP.js +218 -0
- package/dist/chunks/thunderScene3d-FMMuwJRP.js.map +1 -0
- package/dist/chunks/timeline-BLBedCYj.js +45 -0
- package/dist/chunks/timeline-BLBedCYj.js.map +1 -0
- package/dist/index.js +3468 -3104
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/index.d.ts +2 -0
- package/package.json +1 -1
package/dist/chunks/{BattleshipPrototype-Duz-S1JE.js.map → BattleshipPrototype-Dm6U_mCr.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BattleshipPrototype-Duz-S1JE.js","names":["createBoard","isShipSunk","fireShot","placeShip","FLEET","hasWebGL","ROWS","SIZE","QUALITY_ORDER","QUALITY_LABEL","cellLabel","cell","sameCell","a","b","isCell","SHIP_NAMES","DOUBLE_SELECT_MS","randomFleet","board","ship","attempt","placed","targetView","pendingShipId","prefersReducedMotion","autoQuality","coarse","weakCpu","BattleshipPrototype","stageRef","useRef","sceneRef","toastTimer","hintId","useId","status","setStatus","useState","errorMessage","setErrorMessage","selected","setSelected","hovered","setHovered","radar","setRadar","quality","setQuality","stats","setStats","result","setResult","toastVisible","setToastVisible","boardRef","busyRef","lastSelectRef","fireRef","ready","useEffect","container","disposed","scene","createBattleScene","next","now","last","error","showResult","useCallback","label","text","extra","kind","fire","target","shot","prevShots","prev","select","toggleRadar","cycleQuality","resetGame","handleStageKeyDown","event","moves","dr","dc","base","handleRootKeyDown","onClose","accuracy","qualityLabel","compact","index","Waves","TriangleAlert","X","Crosshair","Radar","LocateFixed","Gauge","RotateCcw"],"sources":["../../src/games/battleship/BattleshipPrototype.jsx"],"sourcesContent":["/* eslint-disable react/prop-types */\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport { Crosshair, Gauge, LocateFixed, Radar, RotateCcw, TriangleAlert, Waves, X } from 'lucide-react';\nimport { FLEET, createBoard, fireShot, isShipSunk, placeShip } from './logic';\nimport { hasWebGL } from './webglSupport';\nimport './battleship.css';\n\nconst ROWS = 'ABCDEFGHIJ';\nconst SIZE = 10;\nconst QUALITY_ORDER = ['auto', 'high', 'low'];\nconst QUALITY_LABEL = { auto: 'Auto', high: 'Alta', low: 'Baja' };\n\nconst cellLabel = (cell) => (cell ? `${ROWS[cell.row]}${cell.col + 1}` : '—');\nconst sameCell = (a, b) => a === b || (a && b && a.row === b.row && a.col === b.col);\nconst isCell = (cell) => cell && Number.isInteger(cell.row) && Number.isInteger(cell.col);\nconst SHIP_NAMES = { carrier: 'portaaviones', battleship: 'acorazado', cruiser: 'crucero', submarine: 'submarino', destroyer: 'destructor' };\nconst DOUBLE_SELECT_MS = 400;\n\n// Local single-player demo: a random hidden enemy fleet resolved with the shared rules.\nfunction randomFleet() {\n let board = createBoard();\n for (const ship of FLEET) {\n for (let attempt = 0; attempt < 500; attempt += 1) {\n const placed = placeShip(board, {\n shipId: ship.id, orientation: Math.random() < 0.5 ? 'horizontal' : 'vertical',\n row: Math.floor(Math.random() * SIZE), col: Math.floor(Math.random() * SIZE),\n });\n if (placed.ok) { board = placed.board; break; }\n }\n }\n return board;\n}\n\n// `pendingShipId` keeps a just-sunk ship visible but afloat so the scene can sink it on impact.\nfunction targetView(board, interactive, pendingShipId = null) {\n return {\n mode: 'target',\n ships: board.ships\n .filter((ship) => ship.id === pendingShipId || isShipSunk(board, ship.id))\n .map((ship) => ({ ...ship, sunk: ship.id !== pendingShipId && isShipSunk(board, ship.id) })),\n shots: board.shots,\n preview: null,\n interactive,\n };\n}\n\nfunction prefersReducedMotion() {\n return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;\n}\n\n// \"Auto\" has no scene API of its own once running, so resolve it to a concrete level.\nfunction autoQuality() {\n const coarse = window.matchMedia?.('(pointer: coarse)').matches;\n const weakCpu = (navigator.hardwareConcurrency || 8) <= 4;\n return coarse || weakCpu ? 'low' : 'high';\n}\n\nexport default function BattleshipPrototype({ onClose, compact = false }) {\n const stageRef = useRef(null);\n const sceneRef = useRef(null);\n const toastTimer = useRef(null);\n const hintId = useId();\n const [status, setStatus] = useState('loading');\n const [errorMessage, setErrorMessage] = useState('');\n const [selected, setSelected] = useState(null);\n const [hovered, setHovered] = useState(null);\n const [radar, setRadar] = useState(false);\n const [quality, setQuality] = useState('auto');\n const [stats, setStats] = useState({ shots: 0, hits: 0 });\n const [result, setResult] = useState(null);\n const [toastVisible, setToastVisible] = useState(false);\n const boardRef = useRef(null);\n const busyRef = useRef(false);\n const lastSelectRef = useRef({ cell: null, time: 0 });\n const fireRef = useRef(null);\n const ready = status === 'ready';\n if (!boardRef.current) boardRef.current = randomFleet();\n\n useEffect(() => {\n const container = stageRef.current;\n if (!container) return undefined;\n if (!hasWebGL()) {\n setStatus('error');\n setErrorMessage('Tu navegador o dispositivo no tiene WebGL disponible, necesario para la vista 3D.');\n return undefined;\n }\n let disposed = false;\n let scene = null;\n import('./scene/createBattleScene.js')\n .then(({ createBattleScene }) => {\n // StrictMode mounts twice: a late resolve for an unmounted instance must not create a scene.\n if (disposed) return;\n scene = createBattleScene(container, {\n quality: 'auto',\n reducedMotion: prefersReducedMotion(),\n onCellHover: (cell) => { if (!disposed) setHovered(isCell(cell) ? { row: cell.row, col: cell.col } : null); },\n onCellSelect: (cell) => {\n if (disposed || !isCell(cell)) return;\n const next = { row: cell.row, col: cell.col };\n const now = Date.now();\n const last = lastSelectRef.current;\n lastSelectRef.current = { cell: next, time: now };\n if (sameCell(last.cell, next) && now - last.time < DOUBLE_SELECT_MS) { fireRef.current?.(next); return; }\n setSelected(next);\n scene?.selectCell(next);\n },\n });\n sceneRef.current = scene;\n scene.setView(targetView(boardRef.current, true));\n setStatus('ready');\n })\n .catch((error) => {\n if (disposed) return;\n console.error('[battleship] No se pudo iniciar la escena', error);\n setStatus('error');\n setErrorMessage('No se pudo iniciar la escena 3D. Inténtalo de nuevo más tarde.');\n });\n return () => {\n disposed = true;\n sceneRef.current = null;\n try { scene?.dispose(); } catch (error) { console.error('[battleship] Error al liberar la escena', error); }\n };\n }, []);\n\n useEffect(() => () => clearTimeout(toastTimer.current), []);\n\n const showResult = useCallback((kind, cell, extra) => {\n const label = cellLabel(cell);\n const text = extra || (kind === 'hit' ? `¡Impacto en ${label}!` : kind === 'miss' ? `Agua en ${label}` : `Ya disparaste en ${label}`);\n setResult({ kind, text, id: Date.now() });\n setToastVisible(true);\n clearTimeout(toastTimer.current);\n toastTimer.current = setTimeout(() => setToastVisible(false), 2800);\n }, []);\n\n const fire = useCallback((target = selected) => {\n const scene = sceneRef.current;\n if (!scene || !isCell(target) || busyRef.current) return;\n const shot = fireShot(boardRef.current, target);\n if (!shot.ok) { showResult(shot.reason === 'repeat_shot' ? 'repeat' : 'miss', target, shot.reason === 'battle_finished' ? 'Flota enemiga hundida · reinicia para jugar otra vez' : undefined); return; }\n const prevShots = boardRef.current.shots;\n boardRef.current = shot.board;\n busyRef.current = true;\n setSelected(null);\n scene.selectCell(null);\n setStats((prev) => ({ shots: prev.shots + 1, hits: prev.hits + (shot.result === 'hit' ? 1 : 0) }));\n const text = shot.defeated ? '¡Flota enemiga hundida!' : shot.sunk ? `¡Hundiste el ${SHIP_NAMES[shot.shipId] || 'barco'}!` : undefined;\n // Pre-impact view: newly sunk ship afloat and the new shot not yet marked.\n if (shot.sunk) scene.setView({ ...targetView(shot.board, false, shot.shipId), shots: prevShots });\n Promise.resolve(scene.playShot({ row: target.row, col: target.col, result: shot.result, sunk: shot.sunk, incoming: false }))\n .catch(() => {})\n .then(() => {\n busyRef.current = false;\n if (sceneRef.current !== scene) return;\n scene.setView(targetView(boardRef.current, !shot.defeated));\n showResult(shot.result, target, text);\n });\n }, [selected, showResult]);\n fireRef.current = fire;\n\n const select = useCallback((cell) => {\n setSelected(cell);\n sceneRef.current?.selectCell(cell);\n }, []);\n\n const toggleRadar = () => {\n const next = !radar;\n setRadar(next);\n sceneRef.current?.setRadarVisible(next);\n };\n\n const cycleQuality = () => {\n const next = QUALITY_ORDER[(QUALITY_ORDER.indexOf(quality) + 1) % QUALITY_ORDER.length];\n setQuality(next);\n sceneRef.current?.setQuality(next === 'auto' ? autoQuality() : next);\n };\n\n const resetGame = () => {\n boardRef.current = randomFleet();\n busyRef.current = false;\n sceneRef.current?.setView(targetView(boardRef.current, true));\n sceneRef.current?.selectCell(null);\n setSelected(null);\n setHovered(null);\n setStats({ shots: 0, hits: 0 });\n setResult(null);\n setToastVisible(false);\n stageRef.current?.focus();\n };\n\n const handleStageKeyDown = (event) => {\n if (!ready || event.target !== event.currentTarget || event.altKey || event.ctrlKey || event.metaKey) return;\n const moves = { ArrowUp: [-1, 0], ArrowDown: [1, 0], ArrowLeft: [0, -1], ArrowRight: [0, 1] };\n if (moves[event.key]) {\n event.preventDefault();\n const [dr, dc] = moves[event.key];\n const base = selected || hovered;\n const next = base\n ? { row: Math.min(SIZE - 1, Math.max(0, base.row + dr)), col: Math.min(SIZE - 1, Math.max(0, base.col + dc)) }\n : { row: 0, col: 0 };\n if (!sameCell(next, selected)) select(next);\n } else if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n fire();\n } else if (event.key === 'r' || event.key === 'R') {\n event.preventDefault();\n sceneRef.current?.resetCamera();\n }\n };\n\n const handleRootKeyDown = (event) => {\n if (event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault();\n event.stopPropagation();\n onClose?.();\n }\n };\n\n const accuracy = stats.shots ? Math.round((stats.hits / stats.shots) * 100) : 0;\n const qualityLabel = QUALITY_LABEL[quality];\n\n return (\n <section className={`bs-proto${compact ? ' bs-proto--compact' : ''}`} aria-label=\"Batalla Naval, vista previa 3D sin rival\" onKeyDown={handleRootKeyDown}>\n <div\n ref={stageRef}\n className=\"bs-proto__stage\"\n tabIndex={0}\n role=\"application\"\n aria-label=\"Tablero 3D de Batalla Naval. Flechas para mover la selección, Enter o Espacio para disparar, R para centrar la cámara, Escape para cerrar.\"\n aria-describedby={hintId}\n aria-busy={status === 'loading'}\n onKeyDown={handleStageKeyDown}\n />\n\n {status === 'loading' && (\n <div className=\"bs-proto__state\" role=\"status\">\n <div className=\"bs-proto__skeleton\" aria-hidden=\"true\">\n {Array.from({ length: 25 }, (_, index) => <span key={index} />)}\n </div>\n <p><Waves size={16} aria-hidden=\"true\" /> Preparando el océano…</p>\n </div>\n )}\n {status === 'error' && (\n <div className=\"bs-proto__state bs-proto__state--error\" role=\"alert\">\n <TriangleAlert size={28} aria-hidden=\"true\" />\n <strong>Vista 3D no disponible</strong>\n <p>{errorMessage}</p>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={onClose}>Volver al chat</button>\n </div>\n )}\n\n <header className=\"bs-proto__top\">\n <div className=\"bs-proto__panel bs-proto__brand\">\n <span className=\"bs-proto__title\">Batalla Naval <span className=\"bs-proto__title-sub\">· Sin rival</span></span>\n <span className=\"bs-proto__badge\">Vista previa 3D</span>\n </div>\n {ready && (\n <div className=\"bs-proto__panel bs-proto__info\">\n <dl className=\"bs-proto__cells\">\n <div><dt>Objetivo</dt><dd className=\"bs-proto__cell-selected\">{cellLabel(selected)}</dd></div>\n <div className=\"bs-proto__cells-hover\"><dt>Cursor</dt><dd>{cellLabel(hovered)}</dd></div>\n </dl>\n <dl className=\"bs-proto__stats\">\n <div><dt>Disparos</dt><dd>{stats.shots}</dd></div>\n <div><dt>Impactos</dt><dd>{stats.hits}</dd></div>\n <div><dt>Precisión</dt><dd>{accuracy}%</dd></div>\n </dl>\n </div>\n )}\n <button type=\"button\" className=\"bs-proto__icon-btn bs-proto__close\" onClick={onClose} aria-label=\"Cerrar Batalla Naval\" title=\"Cerrar (Esc)\">\n <X size={18} aria-hidden=\"true\" />\n </button>\n </header>\n\n <div className=\"bs-proto__live\" aria-live=\"polite\" aria-atomic=\"true\">\n {result && (\n <span key={result.id} className={`bs-proto__toast bs-proto__toast--${result.kind}${toastVisible ? ' is-visible' : ''}`}>\n {result.text}\n </span>\n )}\n </div>\n <span className=\"bs-proto__sr\" aria-live=\"polite\">{selected ? `Casilla seleccionada ${cellLabel(selected)}` : ''}</span>\n\n {ready && (\n <footer className=\"bs-proto__bottom\">\n <p id={hintId} className=\"bs-proto__hint\">Arrastra para rotar · Rueda/pellizco para zoom · Clic para apuntar · doble clic para disparar</p>\n <div className=\"bs-proto__panel bs-proto__actions\" role=\"toolbar\" aria-label=\"Acciones de Batalla Naval\">\n <button type=\"button\" className=\"bs-proto__btn bs-proto__btn--fire\" onClick={() => fire()} disabled={!selected}\n title={selected ? `Disparar en ${cellLabel(selected)} (Enter)` : 'Selecciona una casilla para disparar'}>\n <Crosshair size={18} aria-hidden=\"true\" /><span>Disparar</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={toggleRadar} aria-pressed={radar} title=\"Mostrar u ocultar radar\">\n <Radar size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Radar</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={() => sceneRef.current?.resetCamera()} title=\"Centrar cámara (R)\">\n <LocateFixed size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Centrar cámara</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={cycleQuality} aria-label={`Calidad: ${qualityLabel}. Cambiar calidad`} title=\"Cambiar calidad de render\">\n <Gauge size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Calidad: {qualityLabel}</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={resetGame} title=\"Reiniciar tablero\">\n <RotateCcw size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Reiniciar</span>\n </button>\n </div>\n </footer>\n )}\n {!ready && <p id={hintId} className=\"bs-proto__sr\">Arrastra para rotar · Rueda/pellizco para zoom · Clic para seleccionar</p>}\n </section>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BattleshipPrototype-Dm6U_mCr.js","names":["createBoard","isShipSunk","fireShot","placeShip","FLEET","hasWebGL","ROWS","SIZE","QUALITY_ORDER","QUALITY_LABEL","cellLabel","cell","sameCell","a","b","isCell","SHIP_NAMES","DOUBLE_SELECT_MS","randomFleet","board","ship","attempt","placed","targetView","pendingShipId","prefersReducedMotion","autoQuality","coarse","weakCpu","BattleshipPrototype","stageRef","useRef","sceneRef","toastTimer","hintId","useId","status","setStatus","useState","errorMessage","setErrorMessage","selected","setSelected","hovered","setHovered","radar","setRadar","quality","setQuality","stats","setStats","result","setResult","toastVisible","setToastVisible","boardRef","busyRef","lastSelectRef","fireRef","ready","useEffect","container","disposed","scene","createBattleScene","next","now","last","error","showResult","useCallback","label","text","extra","kind","fire","target","shot","prevShots","prev","select","toggleRadar","cycleQuality","resetGame","handleStageKeyDown","event","moves","dr","dc","base","handleRootKeyDown","onClose","accuracy","qualityLabel","compact","index","Waves","TriangleAlert","X","Crosshair","Radar","LocateFixed","Gauge","RotateCcw"],"sources":["../../src/games/battleship/BattleshipPrototype.jsx"],"sourcesContent":["/* eslint-disable react/prop-types */\nimport { useCallback, useEffect, useId, useRef, useState } from 'react';\nimport { Crosshair, Gauge, LocateFixed, Radar, RotateCcw, TriangleAlert, Waves, X } from 'lucide-react';\nimport { FLEET, createBoard, fireShot, isShipSunk, placeShip } from './logic';\nimport { hasWebGL } from './webglSupport';\nimport './battleship.css';\n\nconst ROWS = 'ABCDEFGHIJ';\nconst SIZE = 10;\nconst QUALITY_ORDER = ['auto', 'high', 'low'];\nconst QUALITY_LABEL = { auto: 'Auto', high: 'Alta', low: 'Baja' };\n\nconst cellLabel = (cell) => (cell ? `${ROWS[cell.row]}${cell.col + 1}` : '—');\nconst sameCell = (a, b) => a === b || (a && b && a.row === b.row && a.col === b.col);\nconst isCell = (cell) => cell && Number.isInteger(cell.row) && Number.isInteger(cell.col);\nconst SHIP_NAMES = { carrier: 'portaaviones', battleship: 'acorazado', cruiser: 'crucero', submarine: 'submarino', destroyer: 'destructor' };\nconst DOUBLE_SELECT_MS = 400;\n\n// Local single-player demo: a random hidden enemy fleet resolved with the shared rules.\nfunction randomFleet() {\n let board = createBoard();\n for (const ship of FLEET) {\n for (let attempt = 0; attempt < 500; attempt += 1) {\n const placed = placeShip(board, {\n shipId: ship.id, orientation: Math.random() < 0.5 ? 'horizontal' : 'vertical',\n row: Math.floor(Math.random() * SIZE), col: Math.floor(Math.random() * SIZE),\n });\n if (placed.ok) { board = placed.board; break; }\n }\n }\n return board;\n}\n\n// `pendingShipId` keeps a just-sunk ship visible but afloat so the scene can sink it on impact.\nfunction targetView(board, interactive, pendingShipId = null) {\n return {\n mode: 'target',\n ships: board.ships\n .filter((ship) => ship.id === pendingShipId || isShipSunk(board, ship.id))\n .map((ship) => ({ ...ship, sunk: ship.id !== pendingShipId && isShipSunk(board, ship.id) })),\n shots: board.shots,\n preview: null,\n interactive,\n };\n}\n\nfunction prefersReducedMotion() {\n return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches;\n}\n\n// \"Auto\" has no scene API of its own once running, so resolve it to a concrete level.\nfunction autoQuality() {\n const coarse = window.matchMedia?.('(pointer: coarse)').matches;\n const weakCpu = (navigator.hardwareConcurrency || 8) <= 4;\n return coarse || weakCpu ? 'low' : 'high';\n}\n\nexport default function BattleshipPrototype({ onClose, compact = false }) {\n const stageRef = useRef(null);\n const sceneRef = useRef(null);\n const toastTimer = useRef(null);\n const hintId = useId();\n const [status, setStatus] = useState('loading');\n const [errorMessage, setErrorMessage] = useState('');\n const [selected, setSelected] = useState(null);\n const [hovered, setHovered] = useState(null);\n const [radar, setRadar] = useState(false);\n const [quality, setQuality] = useState('auto');\n const [stats, setStats] = useState({ shots: 0, hits: 0 });\n const [result, setResult] = useState(null);\n const [toastVisible, setToastVisible] = useState(false);\n const boardRef = useRef(null);\n const busyRef = useRef(false);\n const lastSelectRef = useRef({ cell: null, time: 0 });\n const fireRef = useRef(null);\n const ready = status === 'ready';\n if (!boardRef.current) boardRef.current = randomFleet();\n\n useEffect(() => {\n const container = stageRef.current;\n if (!container) return undefined;\n if (!hasWebGL()) {\n setStatus('error');\n setErrorMessage('Tu navegador o dispositivo no tiene WebGL disponible, necesario para la vista 3D.');\n return undefined;\n }\n let disposed = false;\n let scene = null;\n import('./scene/createBattleScene.js')\n .then(({ createBattleScene }) => {\n // StrictMode mounts twice: a late resolve for an unmounted instance must not create a scene.\n if (disposed) return;\n scene = createBattleScene(container, {\n quality: 'auto',\n reducedMotion: prefersReducedMotion(),\n onCellHover: (cell) => { if (!disposed) setHovered(isCell(cell) ? { row: cell.row, col: cell.col } : null); },\n onCellSelect: (cell) => {\n if (disposed || !isCell(cell)) return;\n const next = { row: cell.row, col: cell.col };\n const now = Date.now();\n const last = lastSelectRef.current;\n lastSelectRef.current = { cell: next, time: now };\n if (sameCell(last.cell, next) && now - last.time < DOUBLE_SELECT_MS) { fireRef.current?.(next); return; }\n setSelected(next);\n scene?.selectCell(next);\n },\n });\n sceneRef.current = scene;\n scene.setView(targetView(boardRef.current, true));\n setStatus('ready');\n })\n .catch((error) => {\n if (disposed) return;\n console.error('[battleship] No se pudo iniciar la escena', error);\n setStatus('error');\n setErrorMessage('No se pudo iniciar la escena 3D. Inténtalo de nuevo más tarde.');\n });\n return () => {\n disposed = true;\n sceneRef.current = null;\n try { scene?.dispose(); } catch (error) { console.error('[battleship] Error al liberar la escena', error); }\n };\n }, []);\n\n useEffect(() => () => clearTimeout(toastTimer.current), []);\n\n const showResult = useCallback((kind, cell, extra) => {\n const label = cellLabel(cell);\n const text = extra || (kind === 'hit' ? `¡Impacto en ${label}!` : kind === 'miss' ? `Agua en ${label}` : `Ya disparaste en ${label}`);\n setResult({ kind, text, id: Date.now() });\n setToastVisible(true);\n clearTimeout(toastTimer.current);\n toastTimer.current = setTimeout(() => setToastVisible(false), 2800);\n }, []);\n\n const fire = useCallback((target = selected) => {\n const scene = sceneRef.current;\n if (!scene || !isCell(target) || busyRef.current) return;\n const shot = fireShot(boardRef.current, target);\n if (!shot.ok) { showResult(shot.reason === 'repeat_shot' ? 'repeat' : 'miss', target, shot.reason === 'battle_finished' ? 'Flota enemiga hundida · reinicia para jugar otra vez' : undefined); return; }\n const prevShots = boardRef.current.shots;\n boardRef.current = shot.board;\n busyRef.current = true;\n setSelected(null);\n scene.selectCell(null);\n setStats((prev) => ({ shots: prev.shots + 1, hits: prev.hits + (shot.result === 'hit' ? 1 : 0) }));\n const text = shot.defeated ? '¡Flota enemiga hundida!' : shot.sunk ? `¡Hundiste el ${SHIP_NAMES[shot.shipId] || 'barco'}!` : undefined;\n // Pre-impact view: newly sunk ship afloat and the new shot not yet marked.\n if (shot.sunk) scene.setView({ ...targetView(shot.board, false, shot.shipId), shots: prevShots });\n Promise.resolve(scene.playShot({ row: target.row, col: target.col, result: shot.result, sunk: shot.sunk, incoming: false }))\n .catch(() => {})\n .then(() => {\n busyRef.current = false;\n if (sceneRef.current !== scene) return;\n scene.setView(targetView(boardRef.current, !shot.defeated));\n showResult(shot.result, target, text);\n });\n }, [selected, showResult]);\n fireRef.current = fire;\n\n const select = useCallback((cell) => {\n setSelected(cell);\n sceneRef.current?.selectCell(cell);\n }, []);\n\n const toggleRadar = () => {\n const next = !radar;\n setRadar(next);\n sceneRef.current?.setRadarVisible(next);\n };\n\n const cycleQuality = () => {\n const next = QUALITY_ORDER[(QUALITY_ORDER.indexOf(quality) + 1) % QUALITY_ORDER.length];\n setQuality(next);\n sceneRef.current?.setQuality(next === 'auto' ? autoQuality() : next);\n };\n\n const resetGame = () => {\n boardRef.current = randomFleet();\n busyRef.current = false;\n sceneRef.current?.setView(targetView(boardRef.current, true));\n sceneRef.current?.selectCell(null);\n setSelected(null);\n setHovered(null);\n setStats({ shots: 0, hits: 0 });\n setResult(null);\n setToastVisible(false);\n stageRef.current?.focus();\n };\n\n const handleStageKeyDown = (event) => {\n if (!ready || event.target !== event.currentTarget || event.altKey || event.ctrlKey || event.metaKey) return;\n const moves = { ArrowUp: [-1, 0], ArrowDown: [1, 0], ArrowLeft: [0, -1], ArrowRight: [0, 1] };\n if (moves[event.key]) {\n event.preventDefault();\n const [dr, dc] = moves[event.key];\n const base = selected || hovered;\n const next = base\n ? { row: Math.min(SIZE - 1, Math.max(0, base.row + dr)), col: Math.min(SIZE - 1, Math.max(0, base.col + dc)) }\n : { row: 0, col: 0 };\n if (!sameCell(next, selected)) select(next);\n } else if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n fire();\n } else if (event.key === 'r' || event.key === 'R') {\n event.preventDefault();\n sceneRef.current?.resetCamera();\n }\n };\n\n const handleRootKeyDown = (event) => {\n if (event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault();\n event.stopPropagation();\n onClose?.();\n }\n };\n\n const accuracy = stats.shots ? Math.round((stats.hits / stats.shots) * 100) : 0;\n const qualityLabel = QUALITY_LABEL[quality];\n\n return (\n <section className={`bs-proto${compact ? ' bs-proto--compact' : ''}`} aria-label=\"Batalla Naval, vista previa 3D sin rival\" onKeyDown={handleRootKeyDown}>\n <div\n ref={stageRef}\n className=\"bs-proto__stage\"\n tabIndex={0}\n role=\"application\"\n aria-label=\"Tablero 3D de Batalla Naval. Flechas para mover la selección, Enter o Espacio para disparar, R para centrar la cámara, Escape para cerrar.\"\n aria-describedby={hintId}\n aria-busy={status === 'loading'}\n onKeyDown={handleStageKeyDown}\n />\n\n {status === 'loading' && (\n <div className=\"bs-proto__state\" role=\"status\">\n <div className=\"bs-proto__skeleton\" aria-hidden=\"true\">\n {Array.from({ length: 25 }, (_, index) => <span key={index} />)}\n </div>\n <p><Waves size={16} aria-hidden=\"true\" /> Preparando el océano…</p>\n </div>\n )}\n {status === 'error' && (\n <div className=\"bs-proto__state bs-proto__state--error\" role=\"alert\">\n <TriangleAlert size={28} aria-hidden=\"true\" />\n <strong>Vista 3D no disponible</strong>\n <p>{errorMessage}</p>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={onClose}>Volver al chat</button>\n </div>\n )}\n\n <header className=\"bs-proto__top\">\n <div className=\"bs-proto__panel bs-proto__brand\">\n <span className=\"bs-proto__title\">Batalla Naval <span className=\"bs-proto__title-sub\">· Sin rival</span></span>\n <span className=\"bs-proto__badge\">Vista previa 3D</span>\n </div>\n {ready && (\n <div className=\"bs-proto__panel bs-proto__info\">\n <dl className=\"bs-proto__cells\">\n <div><dt>Objetivo</dt><dd className=\"bs-proto__cell-selected\">{cellLabel(selected)}</dd></div>\n <div className=\"bs-proto__cells-hover\"><dt>Cursor</dt><dd>{cellLabel(hovered)}</dd></div>\n </dl>\n <dl className=\"bs-proto__stats\">\n <div><dt>Disparos</dt><dd>{stats.shots}</dd></div>\n <div><dt>Impactos</dt><dd>{stats.hits}</dd></div>\n <div><dt>Precisión</dt><dd>{accuracy}%</dd></div>\n </dl>\n </div>\n )}\n <button type=\"button\" className=\"bs-proto__icon-btn bs-proto__close\" onClick={onClose} aria-label=\"Cerrar Batalla Naval\" title=\"Cerrar (Esc)\">\n <X size={18} aria-hidden=\"true\" />\n </button>\n </header>\n\n <div className=\"bs-proto__live\" aria-live=\"polite\" aria-atomic=\"true\">\n {result && (\n <span key={result.id} className={`bs-proto__toast bs-proto__toast--${result.kind}${toastVisible ? ' is-visible' : ''}`}>\n {result.text}\n </span>\n )}\n </div>\n <span className=\"bs-proto__sr\" aria-live=\"polite\">{selected ? `Casilla seleccionada ${cellLabel(selected)}` : ''}</span>\n\n {ready && (\n <footer className=\"bs-proto__bottom\">\n <p id={hintId} className=\"bs-proto__hint\">Arrastra para rotar · Rueda/pellizco para zoom · Clic para apuntar · doble clic para disparar</p>\n <div className=\"bs-proto__panel bs-proto__actions\" role=\"toolbar\" aria-label=\"Acciones de Batalla Naval\">\n <button type=\"button\" className=\"bs-proto__btn bs-proto__btn--fire\" onClick={() => fire()} disabled={!selected}\n title={selected ? `Disparar en ${cellLabel(selected)} (Enter)` : 'Selecciona una casilla para disparar'}>\n <Crosshair size={18} aria-hidden=\"true\" /><span>Disparar</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={toggleRadar} aria-pressed={radar} title=\"Mostrar u ocultar radar\">\n <Radar size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Radar</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={() => sceneRef.current?.resetCamera()} title=\"Centrar cámara (R)\">\n <LocateFixed size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Centrar cámara</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={cycleQuality} aria-label={`Calidad: ${qualityLabel}. Cambiar calidad`} title=\"Cambiar calidad de render\">\n <Gauge size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Calidad: {qualityLabel}</span>\n </button>\n <button type=\"button\" className=\"bs-proto__btn\" onClick={resetGame} title=\"Reiniciar tablero\">\n <RotateCcw size={18} aria-hidden=\"true\" /><span className=\"bs-proto__btn-label\">Reiniciar</span>\n </button>\n </div>\n </footer>\n )}\n {!ready && <p id={hintId} className=\"bs-proto__sr\">Arrastra para rotar · Rueda/pellizco para zoom · Clic para seleccionar</p>}\n </section>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { AdditiveBlending as e, AmbientLight as t, BoxGeometry as n, BufferAttribute as r, BufferGeometry as i, CanvasTexture as a, CatmullRomCurve3 as o, Color as s, ConeGeometry as c, CylinderGeometry as l, DirectionalLight as u, DoubleSide as d, DynamicDrawUsage as f, ExtrudeGeometry as p, InstancedMesh as m, Mesh as ee, MeshLambertMaterial as te, MeshStandardMaterial as ne, Object3D as h, PerspectiveCamera as re, PlaneGeometry as ie, PointLight as g, Points as ae, PointsMaterial as oe, Scene as se, Shape as _, SphereGeometry as v, TorusGeometry as ce, TubeGeometry as y, Vector3 as b, WebGLRenderer as x } from "three";
|
|
2
|
+
// src/effects/confetti/confettiScene3d.js
|
|
3
|
+
var S = [
|
|
4
|
+
"#ff4d8d",
|
|
5
|
+
"#ffd23f",
|
|
6
|
+
"#3ddc97",
|
|
7
|
+
"#4cc9f0",
|
|
8
|
+
"#9b5de5",
|
|
9
|
+
"#ff7b29",
|
|
10
|
+
"#f15bb5",
|
|
11
|
+
"#ffffff"
|
|
12
|
+
].map((e) => new s(e)), C = 12, w = (e, t) => e + Math.random() * (t - e), T = (e) => e[Math.floor(Math.random() * e.length)], E = () => typeof matchMedia == "function" && matchMedia("(pointer: coarse)").matches || (navigator.hardwareConcurrency || 8) <= 4;
|
|
13
|
+
function le(e = 64) {
|
|
14
|
+
let t = document.createElement("canvas");
|
|
15
|
+
t.width = e, t.height = e;
|
|
16
|
+
let n = t.getContext("2d"), r = n.createRadialGradient(e / 2, e / 2, 0, e / 2, e / 2, e / 2);
|
|
17
|
+
return r.addColorStop(0, "rgba(255,255,255,1)"), r.addColorStop(.35, "rgba(255,255,255,.6)"), r.addColorStop(1, "rgba(255,255,255,0)"), n.fillStyle = r, n.fillRect(0, 0, e, e), new a(t);
|
|
18
|
+
}
|
|
19
|
+
function ue() {
|
|
20
|
+
let e = new _();
|
|
21
|
+
for (let t = 0; t < 10; t += 1) {
|
|
22
|
+
let n = t % 2 ? .14 : .32, r = t / 10 * Math.PI * 2 + Math.PI / 2, i = Math.cos(r) * n, a = Math.sin(r) * n;
|
|
23
|
+
t ? e.lineTo(i, a) : e.moveTo(i, a);
|
|
24
|
+
}
|
|
25
|
+
let t = new p(e, {
|
|
26
|
+
depth: .08,
|
|
27
|
+
bevelEnabled: !0,
|
|
28
|
+
bevelThickness: .03,
|
|
29
|
+
bevelSize: .02,
|
|
30
|
+
bevelSegments: 1
|
|
31
|
+
});
|
|
32
|
+
return t.center(), t;
|
|
33
|
+
}
|
|
34
|
+
function de(e) {
|
|
35
|
+
let t = [], n = w(2.5, 4);
|
|
36
|
+
for (let e = 0; e <= 24; e += 1) {
|
|
37
|
+
let r = e / 24, i = r * n * Math.PI * 2;
|
|
38
|
+
t.push(new b(Math.cos(i) * .18, r * 2.2 - 1.1, Math.sin(i) * .18));
|
|
39
|
+
}
|
|
40
|
+
return new y(new o(t), e ? 60 : 110, .022, e ? 3 : 4, !1);
|
|
41
|
+
}
|
|
42
|
+
function D(e, t, n, r) {
|
|
43
|
+
let i = new h(), a = t.map(({ geometry: t, material: r, tinted: a }) => {
|
|
44
|
+
let o = new m(t, r, n);
|
|
45
|
+
if (o.instanceMatrix.setUsage(f), o.frustumCulled = !1, a) {
|
|
46
|
+
for (let e = 0; e < n; e += 1) o.setColorAt(e, S[0]);
|
|
47
|
+
o.instanceColor.setUsage(f);
|
|
48
|
+
}
|
|
49
|
+
i.scale.setScalar(0), i.updateMatrix();
|
|
50
|
+
for (let e = 0; e < n; e += 1) o.setMatrixAt(e, i.matrix);
|
|
51
|
+
return e.add(o), {
|
|
52
|
+
mesh: o,
|
|
53
|
+
tinted: a
|
|
54
|
+
};
|
|
55
|
+
}), o = Array.from({ length: n }, () => ({
|
|
56
|
+
alive: !1,
|
|
57
|
+
pos: new b(),
|
|
58
|
+
vel: new b(),
|
|
59
|
+
rot: new b(),
|
|
60
|
+
spin: new b(),
|
|
61
|
+
size: 1,
|
|
62
|
+
life: 0,
|
|
63
|
+
phase: 0
|
|
64
|
+
})), s = 0;
|
|
65
|
+
return {
|
|
66
|
+
spawn(e, t, i = 1, c = w(4, 6)) {
|
|
67
|
+
let l = s;
|
|
68
|
+
s = (s + 1) % n;
|
|
69
|
+
let u = o[l];
|
|
70
|
+
u.alive = !0, u.pos.copy(e), u.vel.copy(t), u.rot.set(w(0, 6.3), w(0, 6.3), w(0, 6.3)), u.spin.set(w(-1, 1), w(-1, 1), w(-1, 1)).multiplyScalar(r.spin), u.size = i, u.life = c, u.phase = w(0, 6.3);
|
|
71
|
+
let d = T(S);
|
|
72
|
+
a.forEach(({ mesh: e, tinted: t }) => {
|
|
73
|
+
t && (e.setColorAt(l, d), e.instanceColor.needsUpdate = !0);
|
|
74
|
+
});
|
|
75
|
+
},
|
|
76
|
+
update(e, t, s) {
|
|
77
|
+
let c = Math.max(0, 1 - r.drag * e);
|
|
78
|
+
for (let l = 0; l < n; l += 1) {
|
|
79
|
+
let n = o[l];
|
|
80
|
+
if (!n.alive) continue;
|
|
81
|
+
n.life -= e, n.vel.y += r.gravity * e, n.vel.multiplyScalar(c), n.pos.addScaledVector(n.vel, e), r.sway && (n.pos.x += Math.sin(t * r.swayRate + n.phase) * r.sway * e), n.rot.addScaledVector(n.spin, e);
|
|
82
|
+
let u = n.pos.y < -s.halfHeight - 2 || n.pos.y > s.halfHeight + 3;
|
|
83
|
+
(n.life <= 0 || u) && (n.alive = !1);
|
|
84
|
+
let d = n.alive ? n.size * Math.min(1, n.life / .4) : 0;
|
|
85
|
+
i.position.copy(n.pos), i.rotation.set(n.rot.x, n.rot.y, n.rot.z), i.scale.setScalar(d), i.updateMatrix();
|
|
86
|
+
for (let e = 0; e < a.length; e += 1) a[e].mesh.setMatrixAt(l, i.matrix);
|
|
87
|
+
}
|
|
88
|
+
a.forEach(({ mesh: e }) => {
|
|
89
|
+
e.instanceMatrix.needsUpdate = !0;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function O(e) {
|
|
95
|
+
let t = E(), n = new x({
|
|
96
|
+
canvas: e,
|
|
97
|
+
alpha: !0,
|
|
98
|
+
antialias: !t,
|
|
99
|
+
powerPreference: "high-performance"
|
|
100
|
+
});
|
|
101
|
+
try {
|
|
102
|
+
return k(n, t);
|
|
103
|
+
} catch (e) {
|
|
104
|
+
throw n.dispose(), n.forceContextLoss?.(), e;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function k(a, o) {
|
|
108
|
+
a.setPixelRatio(Math.min(o ? 1.5 : 2, window.devicePixelRatio || 1)), a.setClearColor(0, 0);
|
|
109
|
+
let s = new se(), f = new re(50, 1, .1, 80);
|
|
110
|
+
f.position.set(0, 0, C);
|
|
111
|
+
let p = {
|
|
112
|
+
halfWidth: 6,
|
|
113
|
+
halfHeight: 5.6
|
|
114
|
+
}, m = o ? .5 : 1, h = new u(16777215, 1.1 * m);
|
|
115
|
+
h.position.set(2, 4, 6);
|
|
116
|
+
let _ = new g(16736168, 1.4 * m, 30, 1.5), y = new g(5032432, 1.4 * m, 30, 1.5), x = new g(16773570, 0, 40, 1.4);
|
|
117
|
+
x.position.set(0, .5, 4), s.add(new t(16777215, .55 * m), h, _, y, x);
|
|
118
|
+
let E = (e, t = {}) => o ? new te(e) : new ne({
|
|
119
|
+
roughness: .35,
|
|
120
|
+
metalness: .2,
|
|
121
|
+
...e,
|
|
122
|
+
...t
|
|
123
|
+
}), O = (e) => E({ color: 16777215 }, e), k = E({
|
|
124
|
+
color: 16764746,
|
|
125
|
+
emissive: 4861184
|
|
126
|
+
}, {
|
|
127
|
+
metalness: .75,
|
|
128
|
+
roughness: .25
|
|
129
|
+
}), A = o ? .5 : 1, j = D(s, [{
|
|
130
|
+
geometry: new ie(.14, .22),
|
|
131
|
+
material: E({
|
|
132
|
+
color: 16777215,
|
|
133
|
+
side: d
|
|
134
|
+
}, {
|
|
135
|
+
metalness: .35,
|
|
136
|
+
roughness: .4
|
|
137
|
+
}),
|
|
138
|
+
tinted: !0
|
|
139
|
+
}], Math.round(2400 * A), {
|
|
140
|
+
gravity: -3.2,
|
|
141
|
+
drag: 2.2,
|
|
142
|
+
spin: 9,
|
|
143
|
+
sway: .7,
|
|
144
|
+
swayRate: 3
|
|
145
|
+
}), M = {
|
|
146
|
+
gravity: -5.5,
|
|
147
|
+
drag: .5,
|
|
148
|
+
spin: 4
|
|
149
|
+
}, fe = D(s, [{
|
|
150
|
+
geometry: ue(),
|
|
151
|
+
material: O({
|
|
152
|
+
metalness: .6,
|
|
153
|
+
roughness: .25
|
|
154
|
+
}),
|
|
155
|
+
tinted: !0
|
|
156
|
+
}], Math.round(70 * A), M), pe = D(s, [{
|
|
157
|
+
geometry: new ce(.2, .07, o ? 8 : 12, o ? 18 : 28),
|
|
158
|
+
material: O({
|
|
159
|
+
metalness: .55,
|
|
160
|
+
roughness: .3
|
|
161
|
+
}),
|
|
162
|
+
tinted: !0
|
|
163
|
+
}], Math.round(50 * A), M), me = D(s, [
|
|
164
|
+
{
|
|
165
|
+
geometry: new n(.38, .38, .38),
|
|
166
|
+
material: O(),
|
|
167
|
+
tinted: !0
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
geometry: new n(.4, .4, .08),
|
|
171
|
+
material: k
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
geometry: new n(.08, .4, .4),
|
|
175
|
+
material: k
|
|
176
|
+
}
|
|
177
|
+
], Math.round(50 * A), M), he = new v(.07, 10, 8).translate(0, .27, 0), ge = D(s, [{
|
|
178
|
+
geometry: new c(.2, .5, o ? 12 : 20),
|
|
179
|
+
material: O(),
|
|
180
|
+
tinted: !0
|
|
181
|
+
}, {
|
|
182
|
+
geometry: he,
|
|
183
|
+
material: O()
|
|
184
|
+
}], Math.round(50 * A), M), N = D(s, [
|
|
185
|
+
{
|
|
186
|
+
geometry: new v(.32, o ? 14 : 24, o ? 12 : 18).scale(1, 1.18, 1),
|
|
187
|
+
material: O({
|
|
188
|
+
roughness: .15,
|
|
189
|
+
metalness: .1
|
|
190
|
+
}),
|
|
191
|
+
tinted: !0
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
geometry: new c(.06, .08, 8).translate(0, -.41, 0),
|
|
195
|
+
material: O(),
|
|
196
|
+
tinted: !0
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
geometry: new l(.006, .006, 1.1, 4).translate(0, -1, 0),
|
|
200
|
+
material: O()
|
|
201
|
+
}
|
|
202
|
+
], Math.round(24 * A), {
|
|
203
|
+
gravity: .9,
|
|
204
|
+
drag: 1.2,
|
|
205
|
+
spin: .4,
|
|
206
|
+
sway: .5,
|
|
207
|
+
swayRate: 1.4
|
|
208
|
+
}), P = [
|
|
209
|
+
fe,
|
|
210
|
+
pe,
|
|
211
|
+
me,
|
|
212
|
+
ge
|
|
213
|
+
], F = Array.from({ length: 3 }, () => de(o)), I = S.map((e) => E({
|
|
214
|
+
color: e,
|
|
215
|
+
side: d
|
|
216
|
+
}, { metalness: .3 })), L = Array.from({ length: o ? 8 : 16 }, () => {
|
|
217
|
+
let e = new ee(F[0], I[0]);
|
|
218
|
+
return e.visible = !1, s.add(e), {
|
|
219
|
+
mesh: e,
|
|
220
|
+
vel: new b(),
|
|
221
|
+
spin: new b(),
|
|
222
|
+
life: 0
|
|
223
|
+
};
|
|
224
|
+
}), R = 0, z = le(), B = o ? 260 : 600, V = new Float32Array(B * 3), H = new Float32Array(B * 3), U = new Float32Array(B * 3), W = new Float32Array(B), G = new i();
|
|
225
|
+
G.setAttribute("position", new r(V, 3)), G.setAttribute("color", new r(H, 3));
|
|
226
|
+
let K = new ae(G, new oe({
|
|
227
|
+
size: o ? .22 : .18,
|
|
228
|
+
map: z,
|
|
229
|
+
vertexColors: !0,
|
|
230
|
+
transparent: !0,
|
|
231
|
+
blending: e,
|
|
232
|
+
depthWrite: !1
|
|
233
|
+
}));
|
|
234
|
+
K.frustumCulled = !1, s.add(K);
|
|
235
|
+
let q = 0, J = 0, Y = 0, X = 0, Z = (e, t, n) => new b(e + w(-n, n), t + w(-n, n), w(-n, n) * .8).normalize(), Q = (e, t, n, { paperCount: r = 0, objectCount: i = 0, streamerCount: a = 0, spread: o = .35, speed: s = 11 }) => {
|
|
236
|
+
for (let i = 0; i < r * A; i += 1) j.spawn(e, Z(t, n, o).multiplyScalar(s * w(.5, 1.25)), w(.8, 1.3), w(4, 6.5));
|
|
237
|
+
for (let r = 0; r < i * A; r += 1) T(P).spawn(e, Z(t, n, o).multiplyScalar(s * w(.55, 1)), w(1.1, 1.8));
|
|
238
|
+
for (let r = 0; r < a; r += 1) ve(e, Z(t, n, o).multiplyScalar(s * w(.4, .75)));
|
|
239
|
+
}, _e = (e, { paperCount: t, objectCount: n = 0, streamerCount: r = 0, speed: i }) => {
|
|
240
|
+
for (let n = 0; n < t * A; n += 1) j.spawn(e, new b(w(-1, 1), w(-.6, 1.2), w(-1, 1)).normalize().multiplyScalar(i * w(.3, 1)), w(.8, 1.3), w(3.5, 6));
|
|
241
|
+
for (let t = 0; t < n * A; t += 1) T(P).spawn(e, new b(w(-1, 1), w(-.3, 1.2), w(-.6, .6)).normalize().multiplyScalar(i * w(.4, .8)), w(1.2, 2));
|
|
242
|
+
for (let t = 0; t < r; t += 1) ve(e, new b(w(-1, 1), w(0, 1), w(-.5, .5)).normalize().multiplyScalar(i * .5));
|
|
243
|
+
};
|
|
244
|
+
function ve(e, t) {
|
|
245
|
+
let n = L[R];
|
|
246
|
+
R = (R + 1) % L.length, n.mesh.geometry = T(F), n.mesh.material = T(I), n.mesh.position.copy(e), n.mesh.rotation.set(w(0, 6.3), w(0, 6.3), w(0, 6.3)), n.mesh.scale.setScalar(w(.7, 1.1)), n.mesh.visible = !0, n.vel.copy(t), n.spin.set(w(-2, 2), w(-3, 3), w(-2, 2)), n.life = w(3.5, 5.5);
|
|
247
|
+
}
|
|
248
|
+
let $ = (e, t, n, r = 0) => {
|
|
249
|
+
for (let i = 0; i < t * A; i += 1) {
|
|
250
|
+
let t = q;
|
|
251
|
+
q = (q + 1) % B;
|
|
252
|
+
let i = w(0, Math.PI * 2), a = r ? w(2.5, 5) : w(0, .4), o = [
|
|
253
|
+
e.x + Math.cos(i) * a,
|
|
254
|
+
e.y + Math.sin(i) * a * .7,
|
|
255
|
+
e.z + w(-1, 1)
|
|
256
|
+
];
|
|
257
|
+
V.set(o, t * 3);
|
|
258
|
+
let s = r ? [
|
|
259
|
+
-Math.sin(i) * r - Math.cos(i) * 1.4,
|
|
260
|
+
Math.cos(i) * r * .7 - Math.sin(i) * 1.4,
|
|
261
|
+
0
|
|
262
|
+
] : [
|
|
263
|
+
w(-1, 1) * n,
|
|
264
|
+
w(-.4, 1) * n,
|
|
265
|
+
w(-1, 1) * n
|
|
266
|
+
];
|
|
267
|
+
U.set(s, t * 3), W[t] = w(1.2, 2.6);
|
|
268
|
+
}
|
|
269
|
+
}, ye = {
|
|
270
|
+
cannons(e) {
|
|
271
|
+
let { halfWidth: t, halfHeight: n } = p;
|
|
272
|
+
Q(new b(-t * .95, -n * .95, 0), .45, 1, {
|
|
273
|
+
paperCount: 420 * e,
|
|
274
|
+
objectCount: 12,
|
|
275
|
+
streamerCount: 2
|
|
276
|
+
}), Q(new b(t * .95, -n * .95, 0), -.45, 1, {
|
|
277
|
+
paperCount: 420 * e,
|
|
278
|
+
objectCount: 12,
|
|
279
|
+
streamerCount: 2
|
|
280
|
+
}), $(new b(0, -n * .6, 0), 80, 3);
|
|
281
|
+
},
|
|
282
|
+
left(e) {
|
|
283
|
+
Q(new b(-p.halfWidth, -p.halfHeight * .4, .5), 1, .85, {
|
|
284
|
+
paperCount: 450 * e,
|
|
285
|
+
objectCount: 14,
|
|
286
|
+
streamerCount: 3,
|
|
287
|
+
speed: 12
|
|
288
|
+
});
|
|
289
|
+
},
|
|
290
|
+
right(e) {
|
|
291
|
+
Q(new b(p.halfWidth, -p.halfHeight * .4, .5), -1, .85, {
|
|
292
|
+
paperCount: 450 * e,
|
|
293
|
+
objectCount: 14,
|
|
294
|
+
streamerCount: 3,
|
|
295
|
+
speed: 12
|
|
296
|
+
});
|
|
297
|
+
},
|
|
298
|
+
rain(e) {
|
|
299
|
+
for (let t = 0; t < 520 * e * A; t += 1) j.spawn(new b(w(-p.halfWidth, p.halfWidth), p.halfHeight + w(.2, 2), w(-2, 2)), new b(w(-.5, .5), w(-2, 0), 0), w(.8, 1.3), w(4, 6));
|
|
300
|
+
for (let e = 0; e < 14 * A; e += 1) T(P).spawn(new b(w(-p.halfWidth, p.halfWidth) * .8, p.halfHeight + .5, w(-1, 1)), new b(0, w(-2, 0), 0), w(1.2, 1.9));
|
|
301
|
+
$(new b(0, p.halfHeight * .5, 0), 120, 2);
|
|
302
|
+
},
|
|
303
|
+
balloons(e) {
|
|
304
|
+
for (let e = 0; e < 14 * A; e += 1) N.spawn(new b(w(-p.halfWidth, p.halfWidth) * .85, -p.halfHeight - w(.5, 2.5), w(-2, 1)), new b(0, w(1.2, 2.4), 0), w(.85, 1.3), 8);
|
|
305
|
+
Q(new b(0, -p.halfHeight, 0), 0, 1, {
|
|
306
|
+
paperCount: 300 * e,
|
|
307
|
+
objectCount: 10,
|
|
308
|
+
spread: .6
|
|
309
|
+
});
|
|
310
|
+
},
|
|
311
|
+
sky(e) {
|
|
312
|
+
let t = new b(w(-.4, .4) * p.halfWidth, p.halfHeight * .45, 0);
|
|
313
|
+
_e(t, {
|
|
314
|
+
paperCount: 600 * e,
|
|
315
|
+
objectCount: 16,
|
|
316
|
+
streamerCount: 2,
|
|
317
|
+
speed: 7
|
|
318
|
+
}), $(t, 160, 4);
|
|
319
|
+
},
|
|
320
|
+
swirl() {
|
|
321
|
+
$(new b(0, .3, 0), 260, 0, 3.2);
|
|
322
|
+
},
|
|
323
|
+
finale() {
|
|
324
|
+
let e = new b(0, .3, 0);
|
|
325
|
+
_e(e, {
|
|
326
|
+
paperCount: 1500,
|
|
327
|
+
objectCount: 80,
|
|
328
|
+
streamerCount: 10,
|
|
329
|
+
speed: 14
|
|
330
|
+
}), $(e, 320, 7);
|
|
331
|
+
for (let e = 0; e < 8 * A; e += 1) N.spawn(new b(w(-p.halfWidth, p.halfWidth) * .8, -p.halfHeight - w(.5, 2), w(-1.5, 1)), new b(0, w(2, 3.2), 0), w(.9, 1.3), 5);
|
|
332
|
+
X = .7;
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
return {
|
|
336
|
+
burst(e, t = 1) {
|
|
337
|
+
ye[e]?.(t), Y = Math.max(Y, e === "finale" ? 1 : t * .5);
|
|
338
|
+
},
|
|
339
|
+
render(e) {
|
|
340
|
+
J += e, Y = Math.max(0, Y - e * 2.5), X = Math.max(0, X - e * 1.8), x.intensity = Y * 6 * m, _.position.set(Math.cos(J * .7) * 6, Math.sin(J * .9) * 3, 4), y.position.set(Math.cos(J * .7 + Math.PI) * 6, Math.sin(J * 1.1 + 1) * 3, 4), j.update(e, J, p), P.forEach((t) => t.update(e, J, p)), N.update(e, J, p), L.forEach((t) => {
|
|
341
|
+
t.mesh.visible && (t.life -= e, t.vel.y -= 2.2 * e, t.vel.multiplyScalar(Math.max(0, 1 - 1.5 * e)), t.mesh.position.addScaledVector(t.vel, e), t.mesh.rotation.x += t.spin.x * e, t.mesh.rotation.y += t.spin.y * e, t.mesh.rotation.z += t.spin.z * e, t.life <= 0 && (t.mesh.visible = !1));
|
|
342
|
+
});
|
|
343
|
+
for (let t = 0; t < B; t += 1) {
|
|
344
|
+
let n = t * 3;
|
|
345
|
+
if (W[t] <= 0) {
|
|
346
|
+
H[n] = 0, H[n + 1] = 0, H[n + 2] = 0;
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
W[t] -= e, U[n + 1] -= .8 * e, V[n] += U[n] * e, V[n + 1] += U[n + 1] * e, V[n + 2] += U[n + 2] * e;
|
|
350
|
+
let r = Math.min(1, W[t]) * (.35 + Math.random() * .65);
|
|
351
|
+
H[n] = r, H[n + 1] = r * .88, H[n + 2] = r * .6;
|
|
352
|
+
}
|
|
353
|
+
G.attributes.position.needsUpdate = !0, G.attributes.color.needsUpdate = !0, f.position.x = (Math.random() - .5) * X * .3, f.position.y = (Math.random() - .5) * X * .3, a.render(s, f);
|
|
354
|
+
},
|
|
355
|
+
resize(e, t) {
|
|
356
|
+
a.setSize(e, t, !1), f.aspect = e / t, f.fov = f.aspect < 1 ? Math.min(85, 50 / Math.max(f.aspect, .55) * .8) : 50, f.updateProjectionMatrix(), p.halfHeight = Math.tan(f.fov * Math.PI / 360) * C, p.halfWidth = p.halfHeight * f.aspect;
|
|
357
|
+
},
|
|
358
|
+
dispose() {
|
|
359
|
+
s.traverse((e) => {
|
|
360
|
+
e.isInstancedMesh && e.dispose(), e.geometry?.dispose(), e.material && [].concat(e.material).forEach((e) => e.dispose());
|
|
361
|
+
}), F.forEach((e) => e.dispose()), I.forEach((e) => e.dispose()), z.dispose(), a.dispose(), a.forceContextLoss?.();
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
export { O as createConfettiScene };
|
|
366
|
+
|
|
367
|
+
//# sourceMappingURL=confettiScene3d-WooGwo25.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"confettiScene3d-WooGwo25.js","names":["PALETTE","Color","hex","DISTANCE","rand","min","max","pick","items","isLowPower","softDot","canvas","size","ctx","gradient","CanvasTexture","starGeometry","shape","Shape","i","radius","angle","x","y","geometry","ExtrudeGeometry","streamerGeometry","points","turns","t","Vector3","TubeGeometry","CatmullRomCurve3","lowPower","createPool","dummy","Object3D","meshes","parts","mesh","InstancedMesh","material","count","DynamicDrawUsage","tinted","scene","bodies","cursor","index","body","position","velocity","physics","life","color","drag","dt","time","outside","bounds","scale","m","createConfettiScene","renderer","WebGLRenderer","buildScene","error","Scene","camera","PerspectiveCamera","light","key","DirectionalLight","pink","PointLight","cyan","flash","AmbientLight","MeshLambertMaterial","options","MeshStandardMaterial","standard","white","gold","paper","PlaneGeometry","DoubleSide","rigid","stars","rings","TorusGeometry","gifts","BoxGeometry","pom","SphereGeometry","hats","ConeGeometry","balloons","CylinderGeometry","objects","streamerGeometries","streamerMaterials","streamers","Mesh","streamerCursor","dot","GLITTER","glitterPositions","glitterColors","glitterVelocity","glitterLife","glitterGeometry","BufferGeometry","BufferAttribute","glitter","Points","PointsMaterial","AdditiveBlending","glitterCursor","flashLevel","shake","direction","spread","cannon","paperCount","origin","speed","objectCount","streamerCount","shell","spawnStreamer","streamer","sparkle","n","swirl","bursts","w","h","power","kind","pool","p","twinkle","width","height","child","entry"],"sources":["../../src/effects/confetti/confettiScene3d.js"],"sourcesContent":["// Three.js party for the Confeti effect. Loaded lazily; `three` is an optional peer, so\n// ConfettiEffect falls back to the CSS confetti when this module or WebGL is unavailable.\n// Every body kind is one InstancedMesh per part, so thousands of pieces cost a few draw calls.\nimport {\n AdditiveBlending, AmbientLight, BoxGeometry, BufferAttribute, BufferGeometry, CanvasTexture, CatmullRomCurve3, Color,\n ConeGeometry, CylinderGeometry, DirectionalLight, DoubleSide, DynamicDrawUsage, ExtrudeGeometry, InstancedMesh, Mesh,\n MeshLambertMaterial, MeshStandardMaterial, Object3D, PerspectiveCamera, PlaneGeometry, PointLight, Points, PointsMaterial,\n Scene, Shape, SphereGeometry, TorusGeometry, TubeGeometry, Vector3, WebGLRenderer,\n} from 'three';\n\nconst PALETTE = ['#ff4d8d', '#ffd23f', '#3ddc97', '#4cc9f0', '#9b5de5', '#ff7b29', '#f15bb5', '#ffffff'].map((hex) => new Color(hex));\nconst DISTANCE = 12;\nconst rand = (min, max) => min + Math.random() * (max - min);\nconst pick = (items) => items[Math.floor(Math.random() * items.length)];\n\n// Phones and low-core devices get smaller pools, Lambert shading, no MSAA and a lower pixel ratio.\nconst isLowPower = () => (typeof matchMedia === 'function' && matchMedia('(pointer: coarse)').matches)\n || (navigator.hardwareConcurrency || 8) <= 4;\n\nfunction softDot(size = 64) {\n const canvas = document.createElement('canvas');\n canvas.width = size;\n canvas.height = size;\n const ctx = canvas.getContext('2d');\n const gradient = ctx.createRadialGradient(size / 2, size / 2, 0, size / 2, size / 2, size / 2);\n gradient.addColorStop(0, 'rgba(255,255,255,1)');\n gradient.addColorStop(0.35, 'rgba(255,255,255,.6)');\n gradient.addColorStop(1, 'rgba(255,255,255,0)');\n ctx.fillStyle = gradient;\n ctx.fillRect(0, 0, size, size);\n return new CanvasTexture(canvas);\n}\n\nfunction starGeometry() {\n const shape = new Shape();\n for (let i = 0; i < 10; i += 1) {\n const radius = i % 2 ? 0.14 : 0.32;\n const angle = (i / 10) * Math.PI * 2 + Math.PI / 2;\n const x = Math.cos(angle) * radius;\n const y = Math.sin(angle) * radius;\n if (i) shape.lineTo(x, y); else shape.moveTo(x, y);\n }\n const geometry = new ExtrudeGeometry(shape, { depth: 0.08, bevelEnabled: true, bevelThickness: 0.03, bevelSize: 0.02, bevelSegments: 1 });\n geometry.center();\n return geometry;\n}\n\n// Curly ribbon: a loose helix that tumbles as one rigid streamer.\nfunction streamerGeometry(lowPower) {\n const points = [];\n const turns = rand(2.5, 4);\n for (let i = 0; i <= 24; i += 1) {\n const t = i / 24;\n const angle = t * turns * Math.PI * 2;\n points.push(new Vector3(Math.cos(angle) * 0.18, t * 2.2 - 1.1, Math.sin(angle) * 0.18));\n }\n return new TubeGeometry(new CatmullRomCurve3(points), lowPower ? 60 : 110, 0.022, lowPower ? 3 : 4, false);\n}\n\n/**\n * A ring buffer of rigid bodies drawn by one InstancedMesh per part.\n * `tinted` parts take each body's palette color; the others keep their material color.\n */\nfunction createPool(scene, parts, count, physics) {\n const dummy = new Object3D();\n const meshes = parts.map(({ geometry, material, tinted }) => {\n const mesh = new InstancedMesh(geometry, material, count);\n mesh.instanceMatrix.setUsage(DynamicDrawUsage);\n mesh.frustumCulled = false;\n if (tinted) {\n for (let i = 0; i < count; i += 1) mesh.setColorAt(i, PALETTE[0]);\n mesh.instanceColor.setUsage(DynamicDrawUsage);\n }\n dummy.scale.setScalar(0);\n dummy.updateMatrix();\n for (let i = 0; i < count; i += 1) mesh.setMatrixAt(i, dummy.matrix);\n scene.add(mesh);\n return { mesh, tinted };\n });\n const bodies = Array.from({ length: count }, () => ({\n alive: false, pos: new Vector3(), vel: new Vector3(), rot: new Vector3(), spin: new Vector3(), size: 1, life: 0, phase: 0,\n }));\n let cursor = 0;\n return {\n spawn(position, velocity, size = 1, life = rand(4, 6)) {\n const index = cursor;\n cursor = (cursor + 1) % count;\n const body = bodies[index];\n body.alive = true;\n body.pos.copy(position);\n body.vel.copy(velocity);\n body.rot.set(rand(0, 6.3), rand(0, 6.3), rand(0, 6.3));\n body.spin.set(rand(-1, 1), rand(-1, 1), rand(-1, 1)).multiplyScalar(physics.spin);\n body.size = size;\n body.life = life;\n body.phase = rand(0, 6.3);\n const color = pick(PALETTE);\n meshes.forEach(({ mesh, tinted }) => {\n if (!tinted) return;\n mesh.setColorAt(index, color);\n mesh.instanceColor.needsUpdate = true;\n });\n },\n update(dt, time, bounds) {\n const drag = Math.max(0, 1 - physics.drag * dt);\n for (let i = 0; i < count; i += 1) {\n const body = bodies[i];\n if (!body.alive) continue;\n body.life -= dt;\n body.vel.y += physics.gravity * dt;\n body.vel.multiplyScalar(drag);\n body.pos.addScaledVector(body.vel, dt);\n // Paper and balloons sway as they drift; rigid objects only tumble.\n if (physics.sway) body.pos.x += Math.sin(time * physics.swayRate + body.phase) * physics.sway * dt;\n body.rot.addScaledVector(body.spin, dt);\n const outside = body.pos.y < -bounds.halfHeight - 2 || body.pos.y > bounds.halfHeight + 3;\n if (body.life <= 0 || outside) body.alive = false;\n // Shrink out over the last 0.4 s instead of popping.\n const scale = body.alive ? body.size * Math.min(1, body.life / 0.4) : 0;\n dummy.position.copy(body.pos);\n dummy.rotation.set(body.rot.x, body.rot.y, body.rot.z);\n dummy.scale.setScalar(scale);\n dummy.updateMatrix();\n for (let m = 0; m < meshes.length; m += 1) meshes[m].mesh.setMatrixAt(i, dummy.matrix);\n }\n meshes.forEach(({ mesh }) => { mesh.instanceMatrix.needsUpdate = true; });\n },\n };\n}\n\nexport function createConfettiScene(canvas) {\n const lowPower = isLowPower();\n const renderer = new WebGLRenderer({ canvas, alpha: true, antialias: !lowPower, powerPreference: 'high-performance' });\n // A failed setup must not keep the GL context alive.\n try {\n return buildScene(renderer, lowPower);\n } catch (error) {\n renderer.dispose();\n renderer.forceContextLoss?.();\n throw error;\n }\n}\n\nfunction buildScene(renderer, lowPower) {\n renderer.setPixelRatio(Math.min(lowPower ? 1.5 : 2, window.devicePixelRatio || 1));\n renderer.setClearColor(0x000000, 0);\n const scene = new Scene();\n const camera = new PerspectiveCamera(50, 1, 0.1, 80);\n camera.position.set(0, 0, DISTANCE);\n const bounds = { halfWidth: 6, halfHeight: 5.6 };\n\n // Lambert reflects more than the standard material, so its rig is dimmed to keep colors saturated.\n const light = lowPower ? 0.5 : 1;\n const key = new DirectionalLight(0xffffff, 1.1 * light);\n key.position.set(2, 4, 6);\n const pink = new PointLight(0xff5fa8, 1.4 * light, 30, 1.5);\n const cyan = new PointLight(0x4cc9f0, 1.4 * light, 30, 1.5);\n const flash = new PointLight(0xfff1c2, 0, 40, 1.4);\n flash.position.set(0, 0.5, 4);\n scene.add(new AmbientLight(0xffffff, 0.55 * light), key, pink, cyan, flash);\n\n const material = (options, standard = {}) => (lowPower\n ? new MeshLambertMaterial(options)\n : new MeshStandardMaterial({ roughness: 0.35, metalness: 0.2, ...options, ...standard }));\n const white = (standard) => material({ color: 0xffffff }, standard);\n const gold = material({ color: 0xffcf4a, emissive: 0x4a2d00 }, { metalness: 0.75, roughness: 0.25 });\n\n const scale = lowPower ? 0.5 : 1;\n const paper = createPool(scene, [{ geometry: new PlaneGeometry(0.14, 0.22), material: material({ color: 0xffffff, side: DoubleSide }, { metalness: 0.35, roughness: 0.4 }), tinted: true }],\n Math.round(2400 * scale), { gravity: -3.2, drag: 2.2, spin: 9, sway: 0.7, swayRate: 3 });\n const rigid = { gravity: -5.5, drag: 0.5, spin: 4 };\n const stars = createPool(scene, [{ geometry: starGeometry(), material: white({ metalness: 0.6, roughness: 0.25 }), tinted: true }], Math.round(70 * scale), rigid);\n const ringGeometry = new TorusGeometry(0.2, 0.07, lowPower ? 8 : 12, lowPower ? 18 : 28);\n const rings = createPool(scene, [{ geometry: ringGeometry, material: white({ metalness: 0.55, roughness: 0.3 }), tinted: true }], Math.round(50 * scale), rigid);\n const gifts = createPool(scene, [\n { geometry: new BoxGeometry(0.38, 0.38, 0.38), material: white(), tinted: true },\n { geometry: new BoxGeometry(0.4, 0.4, 0.08), material: gold },\n { geometry: new BoxGeometry(0.08, 0.4, 0.4), material: gold },\n ], Math.round(50 * scale), rigid);\n const pom = new SphereGeometry(0.07, 10, 8).translate(0, 0.27, 0);\n const hats = createPool(scene, [\n { geometry: new ConeGeometry(0.2, 0.5, lowPower ? 12 : 20), material: white(), tinted: true },\n { geometry: pom, material: white() },\n ], Math.round(50 * scale), rigid);\n const balloonBody = new SphereGeometry(0.32, lowPower ? 14 : 24, lowPower ? 12 : 18).scale(1, 1.18, 1);\n const balloons = createPool(scene, [\n { geometry: balloonBody, material: white({ roughness: 0.15, metalness: 0.1 }), tinted: true },\n { geometry: new ConeGeometry(0.06, 0.08, 8).translate(0, -0.41, 0), material: white(), tinted: true },\n { geometry: new CylinderGeometry(0.006, 0.006, 1.1, 4).translate(0, -1, 0), material: white() },\n ], Math.round(24 * scale), { gravity: 0.9, drag: 1.2, spin: 0.4, sway: 0.5, swayRate: 1.4 });\n const objects = [stars, rings, gifts, hats];\n\n const streamerGeometries = Array.from({ length: 3 }, () => streamerGeometry(lowPower));\n const streamerMaterials = PALETTE.map((color) => material({ color, side: DoubleSide }, { metalness: 0.3 }));\n const streamers = Array.from({ length: lowPower ? 8 : 16 }, () => {\n const mesh = new Mesh(streamerGeometries[0], streamerMaterials[0]);\n mesh.visible = false;\n scene.add(mesh);\n return { mesh, vel: new Vector3(), spin: new Vector3(), life: 0 };\n });\n let streamerCursor = 0;\n\n const dot = softDot();\n const GLITTER = lowPower ? 260 : 600;\n const glitterPositions = new Float32Array(GLITTER * 3);\n const glitterColors = new Float32Array(GLITTER * 3);\n const glitterVelocity = new Float32Array(GLITTER * 3);\n const glitterLife = new Float32Array(GLITTER);\n const glitterGeometry = new BufferGeometry();\n glitterGeometry.setAttribute('position', new BufferAttribute(glitterPositions, 3));\n glitterGeometry.setAttribute('color', new BufferAttribute(glitterColors, 3));\n const glitter = new Points(glitterGeometry, new PointsMaterial({ size: lowPower ? 0.22 : 0.18, map: dot, vertexColors: true, transparent: true, blending: AdditiveBlending, depthWrite: false }));\n glitter.frustumCulled = false;\n scene.add(glitter);\n let glitterCursor = 0;\n\n let time = 0;\n let flashLevel = 0;\n let shake = 0;\n\n const direction = (x, y, spread) => new Vector3(x + rand(-spread, spread), y + rand(-spread, spread), rand(-spread, spread) * 0.8).normalize();\n // A cone of pieces from `origin`; every kind gets its own share and speed.\n const cannon = (origin, x, y, { paperCount = 0, objectCount = 0, streamerCount = 0, spread = 0.35, speed = 11 }) => {\n for (let i = 0; i < paperCount * scale; i += 1) paper.spawn(origin, direction(x, y, spread).multiplyScalar(speed * rand(0.5, 1.25)), rand(0.8, 1.3), rand(4, 6.5));\n for (let i = 0; i < objectCount * scale; i += 1) pick(objects).spawn(origin, direction(x, y, spread).multiplyScalar(speed * rand(0.55, 1)), rand(1.1, 1.8));\n for (let i = 0; i < streamerCount; i += 1) spawnStreamer(origin, direction(x, y, spread).multiplyScalar(speed * rand(0.4, 0.75)));\n };\n // A sphere of pieces, like a firework shell.\n const shell = (origin, { paperCount, objectCount = 0, streamerCount = 0, speed }) => {\n for (let i = 0; i < paperCount * scale; i += 1) paper.spawn(origin, new Vector3(rand(-1, 1), rand(-0.6, 1.2), rand(-1, 1)).normalize().multiplyScalar(speed * rand(0.3, 1)), rand(0.8, 1.3), rand(3.5, 6));\n for (let i = 0; i < objectCount * scale; i += 1) pick(objects).spawn(origin, new Vector3(rand(-1, 1), rand(-0.3, 1.2), rand(-0.6, 0.6)).normalize().multiplyScalar(speed * rand(0.4, 0.8)), rand(1.2, 2));\n for (let i = 0; i < streamerCount; i += 1) spawnStreamer(origin, new Vector3(rand(-1, 1), rand(0, 1), rand(-0.5, 0.5)).normalize().multiplyScalar(speed * 0.5));\n };\n function spawnStreamer(origin, velocity) {\n const streamer = streamers[streamerCursor];\n streamerCursor = (streamerCursor + 1) % streamers.length;\n streamer.mesh.geometry = pick(streamerGeometries);\n streamer.mesh.material = pick(streamerMaterials);\n streamer.mesh.position.copy(origin);\n streamer.mesh.rotation.set(rand(0, 6.3), rand(0, 6.3), rand(0, 6.3));\n streamer.mesh.scale.setScalar(rand(0.7, 1.1));\n streamer.mesh.visible = true;\n streamer.vel.copy(velocity);\n streamer.spin.set(rand(-2, 2), rand(-3, 3), rand(-2, 2));\n streamer.life = rand(3.5, 5.5);\n }\n const sparkle = (origin, count, speed, swirl = 0) => {\n for (let n = 0; n < count * scale; n += 1) {\n const i = glitterCursor;\n glitterCursor = (glitterCursor + 1) % GLITTER;\n const angle = rand(0, Math.PI * 2);\n const radius = swirl ? rand(2.5, 5) : rand(0, 0.4);\n const position = [origin.x + Math.cos(angle) * radius, origin.y + Math.sin(angle) * radius * 0.7, origin.z + rand(-1, 1)];\n glitterPositions.set(position, i * 3);\n // Swirling glitter orbits inward to charge up the final blast.\n const velocity = swirl\n ? [-Math.sin(angle) * swirl - Math.cos(angle) * 1.4, Math.cos(angle) * swirl * 0.7 - Math.sin(angle) * 1.4, 0]\n : [rand(-1, 1) * speed, rand(-0.4, 1) * speed, rand(-1, 1) * speed];\n glitterVelocity.set(velocity, i * 3);\n glitterLife[i] = rand(1.2, 2.6);\n }\n };\n\n const bursts = {\n cannons(power) {\n const { halfWidth: w, halfHeight: h } = bounds;\n cannon(new Vector3(-w * 0.95, -h * 0.95, 0), 0.45, 1, { paperCount: 420 * power, objectCount: 12, streamerCount: 2 });\n cannon(new Vector3(w * 0.95, -h * 0.95, 0), -0.45, 1, { paperCount: 420 * power, objectCount: 12, streamerCount: 2 });\n sparkle(new Vector3(0, -h * 0.6, 0), 80, 3);\n },\n left(power) {\n cannon(new Vector3(-bounds.halfWidth, -bounds.halfHeight * 0.4, 0.5), 1, 0.85, { paperCount: 450 * power, objectCount: 14, streamerCount: 3, speed: 12 });\n },\n right(power) {\n cannon(new Vector3(bounds.halfWidth, -bounds.halfHeight * 0.4, 0.5), -1, 0.85, { paperCount: 450 * power, objectCount: 14, streamerCount: 3, speed: 12 });\n },\n rain(power) {\n for (let i = 0; i < 520 * power * scale; i += 1) {\n paper.spawn(new Vector3(rand(-bounds.halfWidth, bounds.halfWidth), bounds.halfHeight + rand(0.2, 2), rand(-2, 2)), new Vector3(rand(-0.5, 0.5), rand(-2, 0), 0), rand(0.8, 1.3), rand(4, 6));\n }\n for (let i = 0; i < 14 * scale; i += 1) pick(objects).spawn(new Vector3(rand(-bounds.halfWidth, bounds.halfWidth) * 0.8, bounds.halfHeight + 0.5, rand(-1, 1)), new Vector3(0, rand(-2, 0), 0), rand(1.2, 1.9));\n sparkle(new Vector3(0, bounds.halfHeight * 0.5, 0), 120, 2);\n },\n balloons(power) {\n for (let i = 0; i < 14 * scale; i += 1) {\n balloons.spawn(new Vector3(rand(-bounds.halfWidth, bounds.halfWidth) * 0.85, -bounds.halfHeight - rand(0.5, 2.5), rand(-2, 1)), new Vector3(0, rand(1.2, 2.4), 0), rand(0.85, 1.3), 8);\n }\n cannon(new Vector3(0, -bounds.halfHeight, 0), 0, 1, { paperCount: 300 * power, objectCount: 10, spread: 0.6 });\n },\n sky(power) {\n const origin = new Vector3(rand(-0.4, 0.4) * bounds.halfWidth, bounds.halfHeight * 0.45, 0);\n shell(origin, { paperCount: 600 * power, objectCount: 16, streamerCount: 2, speed: 7 });\n sparkle(origin, 160, 4);\n },\n swirl() {\n sparkle(new Vector3(0, 0.3, 0), 260, 0, 3.2);\n },\n finale() {\n const origin = new Vector3(0, 0.3, 0);\n shell(origin, { paperCount: 1500, objectCount: 80, streamerCount: 10, speed: 14 });\n sparkle(origin, 320, 7);\n for (let i = 0; i < 8 * scale; i += 1) {\n balloons.spawn(new Vector3(rand(-bounds.halfWidth, bounds.halfWidth) * 0.8, -bounds.halfHeight - rand(0.5, 2), rand(-1.5, 1)), new Vector3(0, rand(2, 3.2), 0), rand(0.9, 1.3), 5);\n }\n shake = 0.7;\n },\n };\n\n return {\n burst(kind, power = 1) {\n bursts[kind]?.(power);\n flashLevel = Math.max(flashLevel, kind === 'finale' ? 1 : power * 0.5);\n },\n render(dt) {\n time += dt;\n flashLevel = Math.max(0, flashLevel - dt * 2.5);\n shake = Math.max(0, shake - dt * 1.8);\n flash.intensity = flashLevel * 6 * light;\n pink.position.set(Math.cos(time * 0.7) * 6, Math.sin(time * 0.9) * 3, 4);\n cyan.position.set(Math.cos(time * 0.7 + Math.PI) * 6, Math.sin(time * 1.1 + 1) * 3, 4);\n\n paper.update(dt, time, bounds);\n objects.forEach((pool) => pool.update(dt, time, bounds));\n balloons.update(dt, time, bounds);\n streamers.forEach((streamer) => {\n if (!streamer.mesh.visible) return;\n streamer.life -= dt;\n streamer.vel.y -= 2.2 * dt;\n streamer.vel.multiplyScalar(Math.max(0, 1 - 1.5 * dt));\n streamer.mesh.position.addScaledVector(streamer.vel, dt);\n streamer.mesh.rotation.x += streamer.spin.x * dt;\n streamer.mesh.rotation.y += streamer.spin.y * dt;\n streamer.mesh.rotation.z += streamer.spin.z * dt;\n if (streamer.life <= 0) streamer.mesh.visible = false;\n });\n\n for (let i = 0; i < GLITTER; i += 1) {\n const p = i * 3;\n if (glitterLife[i] <= 0) { glitterColors[p] = 0; glitterColors[p + 1] = 0; glitterColors[p + 2] = 0; continue; }\n glitterLife[i] -= dt;\n glitterVelocity[p + 1] -= 0.8 * dt;\n glitterPositions[p] += glitterVelocity[p] * dt;\n glitterPositions[p + 1] += glitterVelocity[p + 1] * dt;\n glitterPositions[p + 2] += glitterVelocity[p + 2] * dt;\n // Random twinkle in warm gold-white.\n const twinkle = Math.min(1, glitterLife[i]) * (0.35 + Math.random() * 0.65);\n glitterColors[p] = twinkle;\n glitterColors[p + 1] = twinkle * 0.88;\n glitterColors[p + 2] = twinkle * 0.6;\n }\n glitterGeometry.attributes.position.needsUpdate = true;\n glitterGeometry.attributes.color.needsUpdate = true;\n\n camera.position.x = (Math.random() - 0.5) * shake * 0.3;\n camera.position.y = (Math.random() - 0.5) * shake * 0.3;\n renderer.render(scene, camera);\n },\n resize(width, height) {\n renderer.setSize(width, height, false);\n camera.aspect = width / height;\n // Portrait chat windows widen the lens so cannons at the edges stay on screen.\n camera.fov = camera.aspect < 1 ? Math.min(85, (50 / Math.max(camera.aspect, 0.55)) * 0.8) : 50;\n camera.updateProjectionMatrix();\n bounds.halfHeight = Math.tan((camera.fov * Math.PI) / 360) * DISTANCE;\n bounds.halfWidth = bounds.halfHeight * camera.aspect;\n },\n dispose() {\n scene.traverse((child) => {\n // InstancedMesh owns the instanceMatrix/instanceColor GPU buffers.\n if (child.isInstancedMesh) child.dispose();\n child.geometry?.dispose();\n if (child.material) [].concat(child.material).forEach((entry) => entry.dispose());\n });\n streamerGeometries.forEach((geometry) => geometry.dispose());\n streamerMaterials.forEach((entry) => entry.dispose());\n dot.dispose();\n renderer.dispose();\n renderer.forceContextLoss?.();\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -2,8 +2,8 @@ import { a as e, c as t, i as n, n as r, r as i, s as a, t as o } from "./battle
|
|
|
2
2
|
import { useSyncExternalStore as s } from "react";
|
|
3
3
|
import { createStore as c } from "zustand/vanilla";
|
|
4
4
|
import { useStore as l } from "zustand";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { Volume2 as u, VolumeX as d } from "lucide-react";
|
|
6
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
7
7
|
// src/games/shared/protocol.js
|
|
8
8
|
var m = "LIRA_GAME_V1:", h = 4096, g = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, _ = (e) => typeof e == "object" && !!e && !Array.isArray(e), v = (e) => typeof e == "string" && e.length > 0 && e.length <= 256 && e.trim() === e, y = (e) => typeof e == "string" && g.test(e), b = (e) => Array.isArray(e) && e.length <= 42 && e.every((e) => Array.isArray(e) && e.length === 2 && Number.isInteger(e[0]) && e[0] >= 0 && e[0] < 7 && y(e[1])) && new Set(e.map((e) => e[1])).size === e.length, x = (e) => b(e.moves) && e.rev === e.moves.length && (e.accept_event_id === void 0 ? e.moves.length === 0 : y(e.accept_event_id)), S = [
|
|
9
9
|
"carrier",
|
|
@@ -1621,17 +1621,17 @@ function Jt(e) {
|
|
|
1621
1621
|
// src/games/shared/GameSoundControls.jsx
|
|
1622
1622
|
function Yt({ manager: e }) {
|
|
1623
1623
|
let { volume: t, muted: n } = Jt(e), r = n || t === 0;
|
|
1624
|
-
return /* @__PURE__ */
|
|
1624
|
+
return /* @__PURE__ */ p("div", {
|
|
1625
1625
|
className: "chat-game-sound",
|
|
1626
|
-
children: [/* @__PURE__ */
|
|
1626
|
+
children: [/* @__PURE__ */ f("button", {
|
|
1627
1627
|
type: "button",
|
|
1628
1628
|
className: "chat-game-sound-toggle",
|
|
1629
1629
|
onClick: e.toggleMuted,
|
|
1630
1630
|
"aria-pressed": r,
|
|
1631
1631
|
"aria-label": r ? "Activar sonido del juego" : "Silenciar sonido del juego",
|
|
1632
1632
|
title: r ? "Activar sonido" : "Silenciar",
|
|
1633
|
-
children:
|
|
1634
|
-
}), /* @__PURE__ */
|
|
1633
|
+
children: f(r ? d : u, { size: 15 })
|
|
1634
|
+
}), /* @__PURE__ */ f("input", {
|
|
1635
1635
|
type: "range",
|
|
1636
1636
|
min: "0",
|
|
1637
1637
|
max: "100",
|
|
@@ -1844,4 +1844,4 @@ function fn() {
|
|
|
1844
1844
|
}
|
|
1845
1845
|
export { m as C, At as S, zt as _, nn as a, Pt as b, Ht as c, J as d, Vt as f, Rt as g, Lt as h, fn as i, qt as l, q as m, dn as n, Yt as o, Bt as p, cn as r, Kt as s, X as t, Wt as u, It as v, O as w, K as x, Ft as y };
|
|
1846
1846
|
|
|
1847
|
-
//# sourceMappingURL=connect4Sounds-
|
|
1847
|
+
//# sourceMappingURL=connect4Sounds-9u0p-dAf.js.map
|