Cargando..
info@fofueduca.com
Inicio
Juegos
Editor
Recursos
Videos
Cuadernos
EnglishWorld
Mosaico didáctico
Editor juegos
Acerca de
Iniciar sesión
Buscar
MIS JUEGOS en este Navegador+Dispositivo
Regístrate para acceder a tus proyectos desde cualquer dispositivo.
Volver
Crear juego
SINÓNIMOS Y ANTÓNIMOS
Nombre del juego
Tipo plantilla
Cod.HTML juego
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{global_title}}</title> {{global_pushmeta}} <style> * { margin: 0; padding: 0; box-sizing: border-box; } html { height: 100%; overflow-y: auto; } body { font-family: 'Arial', sans-serif; background: linear-gradient(135deg, #2d1b4e 0%, #3d2463 100%); display: flex; justify-content: center; padding: 10px; width: 100%; } .container { width: 100%; max-width: 900px; background: #2d1b4e; border-radius: 10px; overflow: auto; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); touch-action: auto; } .header { background: linear-gradient(135deg, #5b4a8a 0%, #4d3d78 100%); /*padding: 15px 20px;*/ display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; border-bottom: 3px solid #8b7bb8; } .logo-title { display: flex; align-items: center; gap: 10px; color: white; font-size: 24px; font-weight: bold; } .logo-title span { font-size: 32px; } .header-controls { display: flex; padding: 15px 20px; gap: 10px; align-items: center; flex-wrap: wrap; } .timer { background: rgba(255, 255, 255, 0.2); padding: 8px 15px; border-radius: 25px; color: white; font-weight: bold; font-size: 20px; min-width: 100px; text-align: center; } .score-display { background: rgba(255, 255, 255, 0.2); padding: 8px 15px; border-radius: 25px; color: white; font-weight: bold; font-size: 14px; display: none; } .score-display.active { display: block; } button { padding: 10px 20px; border: none; border-radius: 25px; font-weight: bold; cursor: pointer; font-size: 16px; transition: all 0.3s ease; white-space: nowrap; } .btn-primary { background: #6c349d; color: white; display: inline-flex; align-items: center; gap: 8px; } .btn-primary:hover { background: #7a3bb1; transform: translateY(-2px); box-shadow: 0 4px 12px rgba(85, 0, 232, 0.3); } .btn-secondary { background: #199f11; color: white; } .btn-secondary:hover { background: #1eaa16; } .btn-fullscreen { background: rgba(255, 255, 255, 0.2); color: white; width: 40px; height: 40px; padding: 0; display: flex; align-items: center; justify-content: center; border-radius: 5px; } .btn-fullscreen:hover { background: rgba(255, 255, 255, 0.3); } .btn-info { background: rgba(0, 168, 232, 0.7); color: white; width: 40px; height: 40px; padding: 0; border-radius: 50%; font-size: 18px; display: flex; align-items: center; justify-content: center; } .btn-info:hover { background: #00a8e8; } .content { padding: 20px; min-height: auto; overflow: visible; touch-action: auto; background: linear-gradient(135deg, {{color_fondo1}} 0%, {{color_fondo2}} 100%); } .blocks-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px; } @media (max-width: 768px) { .blocks-grid { grid-template-columns: 1fr; } } .block { background: white; border-radius: 10px; padding: 15px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); } .word-row { display: grid; /*grid-template-columns: 100px 1fr 1fr;*/ gap: 8px; align-items: center; margin-bottom: 10px; } .word-label { background: #e6e3ec; color: #3d2463; padding: 12px; border-radius: 8px; text-align: center; font-weight: bold; font-size: 18px; } .drop-zone { min-height: 50px; border: 2px dashed #ccc; border-radius: 8px; display: flex; align-items: center; justify-content: center; position: relative; background: #f9f9f9; transition: all 0.3s ease; } .drop-zone.synonym { border-color: #00bcd4; } .drop-zone.antonym { border-color: #e91e63; } .drop-zone.drag-over { background: #e3f2fd; border-color: #2196f3; border-style: solid; transform: scale(1.05); } .drop-zone-label { position: absolute; top: -10px; left: 10px; background: white; padding: 2px 8px; font-size: 16px; font-weight: bold; border-radius: 10px; } .drop-zone-label.synonym { color: #00bcd4; } .drop-zone-label.antonym { color: #e91e63; } .draggable-word { background: #5b4a8a; color: white; font-size:18px; padding: 10px 15px; border-radius: 8px; cursor: move; user-select: none; touch-action: none; font-weight: bold; text-align: center; display: inline-block; transition: all 0.2s ease; } .draggable-word.dragging { opacity: 0.5; box-shadow: 0 0 0 3px #4caf50; } .draggable-word.placed { cursor: pointer; position: relative; } .words-pool { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; padding: 15px; } .validation-icon { position: absolute; top: -8px; right: -8px; width: 24px; height: 24px; border-radius: 50%; display: none; align-items: center; justify-content: center; font-weight: bold; font-size: 16px; } .validation-icon.correct { background: #4caf50; color: white; display: flex; } .validation-icon.incorrect { background: #f44336; color: white; display: flex; } .overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.7); display: flex; align-items: center; justify-content: center; z-index: 1000; opacity: 0; pointer-events: none; transition: opacity 0.3s ease; touch-action: none; } .overlay.active { opacity: 1; pointer-events: all; } .modal { background: white; padding: 40px; border-radius: 15px; text-align: center; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); max-width: 90%; } .modal h2 { color: #2d1b4e; margin-bottom: 20px; font-size: 32px; } .modal-message { color: #555; margin: 15px 0 20px 0; font-size: 16px; font-weight: bold; } .modal p { color: #555; margin: 10px 0; font-size: 18px; } .modal button { margin-top: 20px; } .footer { background: rgba(0, 0, 0, 0.3); padding: 15px 20px; text-align: center; color: white; font-size: 12px; display: flex; align-items: center; justify-content: center; gap: 10px; border-top: 2px solid #8b7bb8; } .footer-logo { width: 95%; height: 50px; display: flex; align-items: center; justify-content: center; font-weight: bold; } .info-panel { position: fixed; top: 0; right: -400px; width: 350px; height: 100%; background: white; box-shadow: -5px 0 15px rgba(0,0,0,0.3); transition: right 0.3s; z-index: 999; padding: 20px; overflow-y: auto; } .info-panel.open { right: 0; } .info-panel h3 { color: #1e3a8a; margin-bottom: 15px; } .info-panel p { margin-bottom: 10px; line-height: 1.6; } .btn-close-info { background: #ef4444; color: white; border: none; padding: 8px 16px; border-radius: 8px; cursor: pointer; margin-top: 15px; } .draggable-clone { position: fixed; width: auto; height: 70px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 22px; font-weight: bold; pointer-events: none; z-index: 9999; border: 3px solid #7ed321; box-shadow: 0 0 15px rgba(126, 211, 33, 0.6); } @media (max-width: 768px) { .header { padding: 12px 15px; } .container { max-width: 100%; border-radius: 0; } .content { padding: 15px; } .logo-title { font-size: 20px; } .block { padding: 12px; } button { padding: 8px 15px; font-size: 14px; } .modal { padding: 30px 20px; } .modal h2 { font-size: 24px; } .info-panel { width: 100%; right: -100%; } .word-row { /*grid-template-columns: 80px 1fr 1fr;*/ gap: 5px; } .word-label { font-size: 16px; padding: 10px 5px; } .draggable-word { padding: 8px 10px; font-size: 18px; } } </style> <style> /* ==================== ESTILOS CSS PARA LA PANTALLA DE RESULTADO Y PUNTAJE ==================== */ /* Contenedor principal de la pantalla de puntuación */ #puntuacionFinal { position: relative; top: 0; left: 0; width: 100%; background-color: rgba(0, 0, 0, 0.9); /* Fondo oscuro con transparencia */ color: white; display: flex; align-items: center; justify-content: center; z-index: 900; opacity: 0; /* Controlado por JS para transiciones */ transition: opacity 0.5s ease; pointer-events: none; /* No permite interacción cuando está oculto */ border-radius:25px; } .puntuacionfinal-hidden { display: none !important; opacity: 0 !important; pointer-events: none !important; } .puntuacionfinal-active { opacity: 1 !important; pointer-events: auto !important; } /* Contenido central de la puntuación */ .contenido-puntuacion { /*background-color: #333;*/ padding: 50px; margin: 50px; border-radius: 20px; text-align: center; box-shadow: 0 0 40px rgba(200, 20, 200, 0.7); /* Sombra */ z-index: 901; position: relative; transform: scale(0.9); animation: zoomIn-contenido-puntuacion 0.5s forwards; /* Animacion*/ } @keyframes zoomIn-contenido-puntuacion { to { transform: scale(1); } } .mensaje-puntuacion { font-size: 2.0em; color: #fefefe; margin-bottom: 25px; text-shadow: 3px 3px 6px #000; } .trofeo-icon { font-size: 8em; margin: 25px 0; line-height: 1; /* Animación de rebote para el trofeo */ animation: bounce-trofeo 1s infinite alternate; } .puntos-label { font-size: 1.5em; color: #dedede; margin-bottom: 5px; } .puntos-contador { font-size: 6em; color: #9762ce; /* Color Vistoso */ font-weight: 900; margin-top: 0; min-height: 1.2em; } /* Keyframes para el rebote del trofeo */ @keyframes bounce-trofeo { from { transform: translateY(0); } to { transform: translateY(-20px); } } /* ------------------- Animación de Confeti (Mixtura) ------------------- */ .confetti-container { position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden; pointer-events: none; z-index: 899; } /* Estilo para los elementos de confeti, generados dinámicamente */ .confetti { position: absolute; width: 8px; height: 15px; opacity: 0; background-color: white; /* Color por defecto, será sobrescrito */ transform-origin: center; animation: fall-confetti linear infinite; } /* Keyframes para la caída y rotación del confeti */ @keyframes fall-confetti { 0% { transform: translate(0, -100px) rotate(0deg); opacity: 0; } 10% { opacity: 1; } 100% { transform: translate(0, 100vh) rotate(1000deg); opacity: 0; } } .score-details { display: flex; justify-content: center; gap: 30px; flex-wrap: wrap; } .score-item { display: flex; flex-direction: column; align-items: center; } .score-label { font-size: 14px; opacity: 0.9; margin-bottom: 5px; } .score-value { font-size: 32px; font-weight: bold; color: #fff; } </style> </head> <body> <div id="infoPanel" class="info-panel"> {{textarea_informaciones}} <button class="btn-close-info" onclick="toggleInfo()">Cerrar</button> </div> <div class="container"> <div class="header"> <div class="logo-title"> <span><img src="{{global_logofofu}}" style="width: 100px;height: 59px;padding-top: 6px;padding-left: 6px;"></span> </div> <div class="header-controls"> <div class="timer" id="timer">00:00:00</div> <div class="score-display" id="scoreDisplay"></div> <button class="btn-primary" id="pauseBtn" onclick="togglePause()" style="display:none;"> ⏸ PAUSAR </button> <button class="btn-secondary" id="checkBtn" onclick="checkAnswers()" style="display:none;"> ✓ REVISAR </button> <button class="btn-fullscreen" onclick="toggleFullscreen()">⛶</button> <button class="btn-info" onclick="toggleInfo()">☰</button> </div> </div> <div id="puntuacionFinal" class="puntuacionfinal-hidden"> <div class="confetti-container" id="confettiContainer"></div> <div class="contenido-puntuacion"> <div class="mensaje-puntuacion" id="mensaje-puntuacion">HAS GANADO, lo hiciste muy bien 🎉</div> <div class="trofeo-icon" id="trofeo-icon">🏆</div> {{textarea_titulojuego}} <p class="puntos-label">Puntos Obtenidos:</p> <div id="puntosContador" class="puntos-contador">0</div> <div class="score-details"> <div class="score-item"> <div class="score-label">PUNTAJE</div> <div id="mensaje-puntaje" class="score-value">50/100</div> </div> <div class="score-item"> <div class="score-label">TIEMPO</div> <div id="mensaje-tiempo" class="score-value">00:00:00</div> </div> </div> <br> <button onclick="javascript:resetGame()" class="btn-secondary">🔄 REINTENTAR</button> </div> </div> <div class="overlay active" id="startOverlay"> <div class="modal"> {{textarea_titulojuego}} {{textarea_instrucciones}} <button class="btn-primary" onclick="startGame()"> ▶ COMENZAR </button> </div> </div> <div class="overlay" id="pauseOverlay"> <div class="modal"> <h2>PAUSA</h2> <button class="btn-primary" onclick="togglePause()"> ▶ CONTINUAR </button> </div> </div> <div class="content" id="content" style="display:none;"> <div style="width:95%;color:#ffffff;text-align:center;padding-bottom:15px;"> {{textarea_titulojuego}} {{textarea_instrucciones}} </div> <div class="blocks-grid" id="blocksContainer"></div> </div> <div class="footer"> <div class="footer-logo"><img src="{{global_logofofu}}" style="width:100px;height:59px;"></div> <span><a target="_blank" href="https://fofueduca.com" style="color:#ffffff;">fofueduca.com</a></span> </div> </div> <div style="display:none;"> <audio id="reproductorAudioPop" controls> <source src="{{global_audiopop}}" type="audio/ogg"> </audio> </div> <script> let gameNumberData = {{text_cantidad_palabras}}; const gameData = [ { word: '{{text_palabra1}}', synonym: '{{text_sinonimo1}}', antonym: '{{text_antonimo1}}' }, { word: '{{text_palabra2}}', synonym: '{{text_sinonimo2}}', antonym: '{{text_antonimo2}}' }, { word: '{{text_palabra3}}', synonym: '{{text_sinonimo3}}', antonym: '{{text_antonimo3}}' }, { word: '{{text_palabra4}}', synonym: '{{text_sinonimo4}}', antonym: '{{text_antonimo4}}' }, { word: '{{text_palabra5}}', synonym: '{{text_sinonimo5}}', antonym: '{{text_antonimo5}}' }, { word: '{{text_palabra6}}', synonym: '{{text_sinonimo6}}', antonym: '{{text_antonimo6}}' }, { word: '{{text_palabra7}}', synonym: '{{text_sinonimo7}}', antonym: '{{text_antonimo7}}' }, { word: '{{text_palabra8}}', synonym: '{{text_sinonimo8}}', antonym: '{{text_antonimo8}}' }, { word: '{{text_palabra9}}', synonym: '{{text_sinonimo9}}', antonym: '{{text_antonimo9}}' }, { word: '{{text_palabra10}}', synonym: '{{text_sinonimo10}}', antonym: '{{text_antonimo10}}' } ]; let gameState = { started: false, paused: false, checked: false, timerInterval: null, seconds: 0, score: 0, draggedElement: null, draggedOriginalParent: null, clonedElement: null, shuffledWords: [], shuffledPool: [] }; function shuffleArray(array) { const arr = [...array]; for (let i = arr.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [arr[i], arr[j]] = [arr[j], arr[i]]; } return arr; } function startGame() { gameState.started = true; gameState.paused = false; gameState.checked = false; gameState.seconds = 0; gameState.score = 0; gameState.shuffledWords = shuffleArray(gameData.slice(0,gameNumberData)); const allWords = []; gameData.slice(0,gameNumberData).forEach(item => { allWords.push({ text: item.synonym, word: item.word, type: 'synonym' }); allWords.push({ text: item.antonym, word: item.word, type: 'antonym' }); }); gameState.shuffledPool = shuffleArray(allWords); document.getElementById('startOverlay').classList.remove('active'); document.getElementById('content').style.display = 'block'; document.getElementById('pauseBtn').style.display = 'flex'; document.getElementById('checkBtn').style.display = 'flex'; document.getElementById('scoreDisplay').classList.remove('active'); renderBlocks(); startTimer(); } function renderBlocks() { const container = document.getElementById('blocksContainer'); container.innerHTML = ''; const leftBlock = document.createElement('div'); leftBlock.className = 'block'; leftBlock.style.height='400px'; leftBlock.style.marginLeft='40px'; leftBlock.style.marginRight='40px'; leftBlock.style.overflow='auto'; leftBlock.innerHTML = '<h3 style="text-align:center;margin-bottom:15px;color:#5b4a8a;">Palabras Base</h3>'; gameState.shuffledWords.forEach(item => { const row = document.createElement('div'); row.className = 'word-row'; const label = document.createElement('div'); label.className = 'word-label'; label.textContent = item.word; const synZone = document.createElement('div'); synZone.className = 'drop-zone synonym'; synZone.dataset.word = item.word; synZone.dataset.type = 'synonym'; const synLabel = document.createElement('div'); synLabel.className = 'drop-zone-label synonym'; synLabel.textContent = 'Sinónimo'; synZone.appendChild(synLabel); const antZone = document.createElement('div'); antZone.className = 'drop-zone antonym'; antZone.dataset.word = item.word; antZone.dataset.type = 'antonym'; const antLabel = document.createElement('div'); antLabel.className = 'drop-zone-label antonym'; antLabel.textContent = 'Antónimo'; antZone.appendChild(antLabel); setupDropZone(synZone); setupDropZone(antZone); row.appendChild(label); row.appendChild(synZone); row.appendChild(antZone); leftBlock.appendChild(row); }); const rightBlock = document.createElement('div'); rightBlock.className = 'block'; rightBlock.innerHTML = '<h3 style="text-align:center;margin-bottom:15px;color:#5b4a8a;">Banco de Palabras</h3>'; const pool = document.createElement('div'); pool.className = 'words-pool'; pool.id = 'wordsPool'; gameState.shuffledPool.forEach((item, index) => { const word = document.createElement('div'); word.className = 'draggable-word'; word.textContent = item.text; word.draggable = true; word.dataset.word = item.word; word.dataset.type = item.type; word.dataset.id = 'word-' + index; setupDraggable(word); pool.appendChild(word); }); rightBlock.appendChild(pool); container.appendChild(leftBlock); container.appendChild(rightBlock); } function setupDraggable(element) { element.addEventListener('dragstart', handleDragStart); element.addEventListener('dragend', handleDragEnd); element.addEventListener('click', handleWordClick); element.addEventListener('touchstart', handleTouchStart, { passive: false }); element.addEventListener('touchmove', handleTouchMove, { passive: false }); element.addEventListener('touchend', handleTouchEnd, { passive: false }); } function setupDropZone(zone) { zone.addEventListener('dragover', handleDragOver); zone.addEventListener('drop', handleDrop); zone.addEventListener('dragleave', handleDragLeave); } function handleDragStart(e) { if (gameState.checked || gameState.paused) return; gameState.draggedElement = e.target; gameState.draggedOriginalParent = e.target.parentElement; e.target.classList.add('dragging'); e.dataTransfer.effectAllowed = 'move'; } function handleDragEnd(e) { e.target.classList.remove('dragging'); document.querySelectorAll('.drop-zone').forEach(zone => { zone.classList.remove('drag-over'); }); document.getElementById('reproductorAudioPop').play(); } function handleDragOver(e) { if (gameState.checked || gameState.paused) return; e.preventDefault(); e.dataTransfer.dropEffect = 'move'; e.currentTarget.classList.add('drag-over'); } function handleDragLeave(e) { e.currentTarget.classList.remove('drag-over'); } function handleDrop(e) { if (gameState.checked || gameState.paused) return; e.preventDefault(); e.currentTarget.classList.remove('drag-over'); const dropZone = e.currentTarget; if (dropZone.querySelector('.draggable-word')) { returnToPool(gameState.draggedElement); return; } dropZone.appendChild(gameState.draggedElement); gameState.draggedElement.classList.add('placed'); } function handleWordClick(e) { if (gameState.checked || gameState.paused) return; const word = e.currentTarget; if (word.parentElement.classList.contains('drop-zone')) { returnToPool(word); } } function returnToPool(word) { const pool = document.getElementById('wordsPool'); word.classList.remove('placed'); pool.appendChild(word); } function handleTouchStart(e) { if (gameState.checked || gameState.paused) return; e.preventDefault(); const touch = e.touches[0]; const element = e.currentTarget; gameState.draggedElement = element; gameState.draggedOriginalParent = element.parentElement; element.classList.add('dragging'); // Crear elemento clonado gameState.clonedElement = document.createElement('div'); gameState.clonedElement.className = 'draggable-clone'; gameState.clonedElement.textContent = e.target.textContent; gameState.clonedElement.style.left = touch.clientX - 35 + 'px'; gameState.clonedElement.style.top = touch.clientY - 35 + 'px'; document.body.appendChild(gameState.clonedElement); } function handleTouchMove(e) { if (gameState.checked || gameState.paused || !gameState.draggedElement) return; e.preventDefault(); const touch = e.touches[0]; // Actualizar posición del elemento clonado if (gameState.clonedElement) { gameState.clonedElement.style.left = touch.clientX - 35 + 'px'; gameState.clonedElement.style.top = touch.clientY - 35 + 'px'; } const elementBelow = document.elementFromPoint(touch.clientX, touch.clientY); document.querySelectorAll('.drop-zone').forEach(zone => { zone.classList.remove('drag-over'); }); if (elementBelow) { const dropZone = elementBelow.closest('.drop-zone'); if (dropZone) { dropZone.classList.add('drag-over'); } } } function handleTouchEnd(e) { if (gameState.checked || gameState.paused || !gameState.draggedElement) return; e.preventDefault(); const touch = e.changedTouches[0]; const elementBelow = document.elementFromPoint(touch.clientX, touch.clientY); const dropZone = elementBelow ? elementBelow.closest('.drop-zone') : null; if (dropZone && !dropZone.querySelector('.draggable-word')) { dropZone.appendChild(gameState.draggedElement); gameState.draggedElement.classList.add('placed'); } else if (dropZone && dropZone.querySelector('.draggable-word')) { returnToPool(gameState.draggedElement); } gameState.draggedElement.classList.remove('dragging'); // Eliminar elemento clonado if (gameState.clonedElement) { gameState.clonedElement.remove(); gameState.clonedElement = null; } document.querySelectorAll('.drop-zone').forEach(zone => { zone.classList.remove('drag-over'); }); gameState.draggedElement = null; document.getElementById('reproductorAudioPop').play(); } function checkAnswers() { if (!gameState.started) return; gameState.checked = true; clearInterval(gameState.timerInterval); document.getElementById('pauseBtn').style.display = 'none'; document.getElementById('checkBtn').style.display = 'none'; let score = 0; document.querySelectorAll('.drop-zone').forEach(zone => { const word = zone.querySelector('.draggable-word'); if (word) { const correctWord = zone.dataset.word; const correctType = zone.dataset.type; const placedWord = word.dataset.word; const placedType = word.dataset.type; const icon = document.createElement('div'); icon.className = 'validation-icon'; if (correctWord === placedWord && correctType === placedType) { icon.classList.add('correct'); icon.textContent = '✓'; score += 1; } else { icon.classList.add('incorrect'); icon.textContent = '✗'; score -= 1; } word.style.position = 'relative'; word.appendChild(icon); } }); gameState.score = score; const maxScore = gameNumberData*2; const timeStr = formatTime(gameState.seconds); document.getElementById('scoreDisplay').classList.add('active'); document.getElementById('scoreDisplay').textContent = `Puntaje: ${gameState.score}/${maxScore} | Tiempo: ${timeStr}`; let message = ''; let trofeo = ''; if (gameState.score === maxScore) { message = '{{text_feedback1}}'; trofeo = '🏆'; } else if (gameState.score > maxScore / 2) { message = '{{text_feedback2}}'; trofeo = '⭐'; } else { message = '{{text_feedback3}}'; trofeo = '🤲'; } // Mostrar mensaje debajo del menu mostrarPuntuacion(message,gameState.score,maxScore,timeStr,trofeo); } function resetGame() { // Limpiar elemento clonado si existe if (gameState.clonedElement) { gameState.clonedElement.remove(); } gameState = { started: false, paused: false, checked: false, timerInterval: null, seconds: 0, score: 0, draggedElement: null, draggedOriginalParent: null, clonedElement: null, shuffledWords: [], shuffledPool: [] }; document.getElementById('content').style.display = 'none'; document.getElementById('pauseBtn').style.display = 'none'; document.getElementById('checkBtn').style.display = 'none'; document.getElementById('scoreDisplay').classList.remove('active'); document.getElementById('pauseOverlay').classList.remove('active'); document.getElementById('timer').textContent = '00:00:00'; ocultarPuntuacion(); document.getElementById('startOverlay').classList.add('active'); } function togglePause() { if (!gameState.started || gameState.checked) return; gameState.paused = !gameState.paused; document.getElementById('pauseOverlay').classList.toggle('active', gameState.paused); if (gameState.paused) { clearInterval(gameState.timerInterval); } else { startTimer(); } } function startTimer() { gameState.timerInterval = setInterval(() => { gameState.seconds++; document.getElementById('timer').textContent = formatTime(gameState.seconds); }, 1000); } function formatTime(seconds) { const hrs = Math.floor(seconds / 3600); const mins = Math.floor((seconds % 3600) / 60); const secs = seconds % 60; return `${String(hrs).padStart(2, '0')}:${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`; } function toggleInfo() { const panel = document.getElementById('infoPanel'); panel.classList.toggle('open'); } function toggleFullscreen() { if (!document.fullscreenElement) { document.documentElement.requestFullscreen(); } else { document.exitFullscreen(); } } </script> <script> //FUNCIONES Y VARIABLES PARA LA PANTALLA GRANDE DE RESULTADO Y PUNTAJE const puntuacionFinal = document.getElementById('puntuacionFinal'); const puntosContador = document.getElementById('puntosContador'); const confettiContainer = document.getElementById('confettiContainer'); const DURACION_CONTADOR_MS = 1500; // Duración de la animación del contador en milisegundos const NUM_CONFETIS = 60; // Cantidad de confetis a generar let contadorAnimationFrame = null; // Para el contador de puntos let confetis = []; // Colores para el confeti const confettiColors = ['#ffc107', '#17a2b8', '#dc3545', '#28a745', '#6f42c1', '#fd7e14']; /** * Anima el contador numérico de 0 a la meta final. * Utiliza requestAnimationFrame para una animación suave. */ function animarContador(meta) { const timestampInicio = performance.now(); function actualizarContador(timestampActual) { const tiempoTranscurrido = timestampActual - timestampInicio; const progreso = Math.min(1, tiempoTranscurrido / DURACION_CONTADOR_MS); const valorActual = Math.floor(progreso * meta); puntosContador.textContent = valorActual; if (progreso < 1) { contadorAnimationFrame = requestAnimationFrame(actualizarContador); } else { puntosContador.textContent = meta; // Asegura el valor exacto al final } } contadorAnimationFrame = requestAnimationFrame(actualizarContador); } /** * Crea un elemento de confeti con propiedades de estilo aleatorias. */ function crearConfeti() { const confeti = document.createElement('div'); confeti.classList.add('confetti'); const randomColor = confettiColors[Math.floor(Math.random() * confettiColors.length)]; const randomLeft = Math.random() * 100; // Posición horizontal (0-100% viewport width) const randomDuration = Math.random() * 3 + 2; // Duración de 2s a 5s const randomDelay = Math.random() * 2; // Retraso de 0s a 2s const randomSize = Math.random() * 8 + 7; // Tamaño de 7px a 15px confeti.style.backgroundColor = randomColor; confeti.style.width = `${randomSize}px`; confeti.style.height = `${randomSize / 2}px`; /* Rectangular */ confeti.style.left = `${randomLeft}vw`; confeti.style.animationDuration = `${randomDuration}s`; confeti.style.animationDelay = `${randomDelay}s`; confettiContainer.appendChild(confeti); confetis.push(confeti); } /** * Inicia la animación de confeti creando los elementos. */ function iniciarConfeti() { for (let i = 0; i < NUM_CONFETIS; i++) { crearConfeti(); } } /** * Detiene todas las animaciones, limpia los elementos y oculta la pantalla. */ function ocultarPuntuacion() { // 1. Detener el contador if (contadorAnimationFrame !== null) { cancelAnimationFrame(contadorAnimationFrame); contadorAnimationFrame = null; } // 2. Remover los elementos de confeti (detiene su animación CSS) confetis.forEach(c => c.remove()); confetis = []; // 3. Ocultar la pantalla de puntuación puntuacionFinal.classList.remove('puntuacionfinal-active'); puntuacionFinal.classList.add('puntuacionfinal-hidden'); // 4. Resetear el contador visual puntosContador.textContent = '0'; } // Evento para mostrar la puntuación function mostrarPuntuacion(x_message,x_score,x_maxScore,x_timeStr,x_trofeo){ // Limpiar y resetear antes de mostrar para asegurar un inicio limpio ocultarPuntuacion(); document.getElementById('mensaje-puntuacion').innerHTML=x_message; document.getElementById('mensaje-puntaje').innerHTML=x_score+"/"+x_maxScore; document.getElementById('mensaje-tiempo').innerHTML=x_timeStr; document.getElementById('trofeo-icon').innerHTML=x_trofeo; puntuacionFinal.classList.remove('puntuacionfinal-hidden'); // Un pequeño retardo para asegurar que la clase puntuacionfinal-hidden se remueva antes de aplicar active setTimeout(() => { puntuacionFinal.classList.add('puntuacionfinal-active'); // Iniciar las animaciones animarContador(x_score); iniciarConfeti(); }, 10); } </script> </body> </html>
Cod.HTML form
<div class="form-group"> <label for="textarea_titulojuego">Título del juego</label> <xtextarea name="textarea_titulojuego" id="textarea_titulojuego" class="form-control" rows="7" style="width:100%;">{{textarea_titulojuego}}</xtextarea> </div> <div class="form-group" style="margin-top:5px;"> <label for="textarea_instrucciones">Instrucciones del juego</label> <xtextarea name="textarea_instrucciones" id="textarea_instrucciones" class="form-control" rows="7" style="width:100%;">{{textarea_instrucciones}}</xtextarea> </div> <div class="form-group" style="margin-top:5px;"> <label for="textarea_informaciones">Información del juego</label> <xtextarea name="textarea_informaciones" id="textarea_informaciones" class="form-control" rows="7" style="width:100%;">{{textarea_informaciones}}</xtextarea> </div> <div class="form-group" style="margin-top:5px;"> <label for="text_cantidad_palabras">Cantidad de palabras a usar:</label> <div style="display:none;"> <input type="text" name="text_cantidad_palabras" id="text_cantidad_palabras" class="form-control" value="{{text_cantidad_palabras}}"> </div> <select id="elegir_cantidad_palabras" size="1" onchange="mostrarSeccionesPalabras()"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> <option value="4">4</option> <option value="5">5</option> <option value="6">6</option> <option value="7">7</option> <option value="8">8</option> <option value="9">9</option> <option value="10">10</option> </select> </div> <div class="row"> <div class="col-md-6" id="seccion_palabra1"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> <div class="form-group"> <label for="text_palabra1">Palabra 1</label> <input type="text" name="text_palabra1" id="text_palabra1" class="form-control" value="{{text_palabra1}}"> </div> <div class="form-group"> <label for="text_sinonimo1">Sinónimo</label> <input type="text" name="text_sinonimo1" id="text_sinonimo1" class="form-control" value="{{text_sinonimo1}}"> </div> <div class="form-group"> <label for="text_antonimo1">Antónimo</label> <input type="text" name="text_antonimo1" id="text_antonimo1" class="form-control" value="{{text_antonimo1}}"> </div> </div> </div> <div class="col-md-6" id="seccion_palabra2"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> <div class="form-group"> <label for="text_palabra2">Palabra 2</label> <input type="text" name="text_palabra2" id="text_palabra2" class="form-control" value="{{text_palabra2}}"> </div> <div class="form-group"> <label for="text_sinonimo2">Sinónimo</label> <input type="text" name="text_sinonimo2" id="text_sinonimo2" class="form-control" value="{{text_sinonimo2}}"> </div> <div class="form-group"> <label for="text_antonimo2">Antónimo</label> <input type="text" name="text_antonimo2" id="text_antonimo2" class="form-control" value="{{text_antonimo2}}"> </div> </div> </div> </div> <div class="row"> <div class="col-md-6" id="seccion_palabra3"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> <div class="form-group"> <label for="text_palabra3">Palabra 3</label> <input type="text" name="text_palabra3" id="text_palabra3" class="form-control" value="{{text_palabra3}}"> </div> <div class="form-group"> <label for="text_sinonimo3">Sinónimo</label> <input type="text" name="text_sinonimo3" id="text_sinonimo3" class="form-control" value="{{text_sinonimo3}}"> </div> <div class="form-group"> <label for="text_antonimo3">Antónimo</label> <input type="text" name="text_antonimo3" id="text_antonimo3" class="form-control" value="{{text_antonimo3}}"> </div> </div> </div> <div class="col-md-6" id="seccion_palabra4"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> <div class="form-group"> <label for="text_palabra4">Palabra 4</label> <input type="text" name="text_palabra4" id="text_palabra4" class="form-control" value="{{text_palabra4}}"> </div> <div class="form-group"> <label for="text_sinonimo4">Sinónimo</label> <input type="text" name="text_sinonimo4" id="text_sinonimo4" class="form-control" value="{{text_sinonimo4}}"> </div> <div class="form-group"> <label for="text_antonimo4">Antónimo</label> <input type="text" name="text_antonimo4" id="text_antonimo4" class="form-control" value="{{text_antonimo4}}"> </div> </div> </div> </div> <div class="row"> <div class="col-md-6" id="seccion_palabra5"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> <div class="form-group"> <label for="text_palabra5">Palabra 5</label> <input type="text" name="text_palabra5" id="text_palabra5" class="form-control" value="{{text_palabra5}}"> </div> <div class="form-group"> <label for="text_sinonimo5">Sinónimo</label> <input type="text" name="text_sinonimo5" id="text_sinonimo5" class="form-control" value="{{text_sinonimo5}}"> </div> <div class="form-group"> <label for="text_antonimo5">Antónimo</label> <input type="text" name="text_antonimo5" id="text_antonimo5" class="form-control" value="{{text_antonimo5}}"> </div> </div> </div> <div class="col-md-6" id="seccion_palabra6"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> <div class="form-group"> <label for="text_palabra6">Palabra 6</label> <input type="text" name="text_palabra6" id="text_palabra6" class="form-control" value="{{text_palabra6}}"> </div> <div class="form-group"> <label for="text_sinonimo6">Sinónimo</label> <input type="text" name="text_sinonimo6" id="text_sinonimo6" class="form-control" value="{{text_sinonimo6}}"> </div> <div class="form-group"> <label for="text_antonimo6">Antónimo</label> <input type="text" name="text_antonimo6" id="text_antonimo6" class="form-control" value="{{text_antonimo6}}"> </div> </div> </div> </div> <div class="row"> <div class="col-md-6" id="seccion_palabra7"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> <div class="form-group"> <label for="text_palabra7">Palabra 7</label> <input type="text" name="text_palabra7" id="text_palabra7" class="form-control" value="{{text_palabra7}}"> </div> <div class="form-group"> <label for="text_sinonimo7">Sinónimo</label> <input type="text" name="text_sinonimo7" id="text_sinonimo7" class="form-control" value="{{text_sinonimo7}}"> </div> <div class="form-group"> <label for="text_antonimo7">Antónimo</label> <input type="text" name="text_antonimo7" id="text_antonimo7" class="form-control" value="{{text_antonimo7}}"> </div> </div> </div> <div class="col-md-6" id="seccion_palabra8"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> <div class="form-group"> <label for="text_palabra8">Palabra 8</label> <input type="text" name="text_palabra8" id="text_palabra8" class="form-control" value="{{text_palabra8}}"> </div> <div class="form-group"> <label for="text_sinonimo8">Sinónimo</label> <input type="text" name="text_sinonimo8" id="text_sinonimo8" class="form-control" value="{{text_sinonimo8}}"> </div> <div class="form-group"> <label for="text_antonimo8">Antónimo</label> <input type="text" name="text_antonimo8" id="text_antonimo8" class="form-control" value="{{text_antonimo8}}"> </div> </div> </div> </div> <div class="row"> <div class="col-md-6" id="seccion_palabra9"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> <div class="form-group"> <label for="text_palabra9">Palabra 9</label> <input type="text" name="text_palabra9" id="text_palabra9" class="form-control" value="{{text_palabra9}}"> </div> <div class="form-group"> <label for="text_sinonimo9">Sinónimo</label> <input type="text" name="text_sinonimo9" id="text_sinonimo9" class="form-control" value="{{text_sinonimo9}}"> </div> <div class="form-group"> <label for="text_antonimo9">Antónimo</label> <input type="text" name="text_antonimo9" id="text_antonimo9" class="form-control" value="{{text_antonimo9}}"> </div> </div> </div> <div class="col-md-6" id="seccion_palabra10"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> <div class="form-group"> <label for="text_palabra10">Palabra 10</label> <input type="text" name="text_palabra10" id="text_palabra10" class="form-control" value="{{text_palabra10}}"> </div> <div class="form-group"> <label for="text_sinonimo10">Sinónimo</label> <input type="text" name="text_sinonimo10" id="text_sinonimo10" class="form-control" value="{{text_sinonimo10}}"> </div> <div class="form-group"> <label for="text_antonimo10">Antónimo</label> <input type="text" name="text_antonimo10" id="text_antonimo10" class="form-control" value="{{text_antonimo10}}"> </div> </div> </div> </div> <div class="row"> <div class="col-md-12"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> Mensajes al revisar el juego según los puntos obtenidos <div class="form-group"> <label for="text_feedback1">Si obtuvo el 100% del puntaje</label> <input type="text" name="text_feedback1" id="text_feedback1" class="form-control" value="{{text_feedback1}}"> </div> <div class="form-group"> <label for="text_feedback2">Si obtuvo más del 50% del puntaje</label> <input type="text" name="text_feedback2" id="text_feedback2" class="form-control" value="{{text_feedback2}}"> </div> <div class="form-group"> <label for="text_feedback3">Si obtuvo menos del 50% del puntaje</label> <input type="text" name="text_feedback3" id="text_feedback3" class="form-control" value="{{text_feedback3}}"> </div> </div> </div> </div> <div class="row"> <div class="col-md-4"> <div style="border-radius:5px;border:solid 2px #dedede;margin:5px;padding:5px;text-align:center;"> Color de fondo <div style="width:100%;align-content:center;clear:both;"> <div style="float:left;"> <div style="display: none;"> <input type="text" name="color_fondo1" id="color_fondo1" class="form-control" value="{{color_fondo1}}"> </div> <input type="text" name="color_fondo1_picker" id="color_fondo1_picker" class="form-control" style="width:60px;display:initial;" value="{{color_fondo1}}" /> <script> initColorSpectrum("color_fondo1","color_fondo1_picker","{{color_fondo1}}"); </script> </div> <div style="float:left;"> <div style="display: none;"> <input type="text" name="color_fondo2" id="color_fondo2" class="form-control" value="{{color_fondo2}}"> </div> <input type="text" name="color_fondo2_picker" id="color_fondo2_picker" class="form-control" style="width:60px;display:initial;" value="{{color_fondo2}}" /> <script> initColorSpectrum("color_fondo2","color_fondo2_picker","{{color_fondo2}}"); </script> </div> </div> </div> </div> </div> <script> var max_secciones_palabras=10; function mostrarSeccionesPalabras() { document.getElementById('text_cantidad_palabras').value=document.getElementById('elegir_cantidad_palabras').value; var cantidad=parseInt(document.getElementById('text_cantidad_palabras').value); for(let dd=1;dd<=cantidad;dd++){ document.getElementById('seccion_palabra'+dd.toString()).style.display='block'; } for(let dd=cantidad+1;dd<=max_secciones_palabras;dd++){ document.getElementById('seccion_palabra'+dd.toString()).style.display='none'; } } document.getElementById('elegir_cantidad_palabras').value=document.getElementById('text_cantidad_palabras').value; mostrarSeccionesPalabras(); </script>
Cod.HTML js
{"text_feedback1":"Excelente, lo hiciste muy bien.","text_feedback2":"Lo hiciste bien, vuelve a intentarlo","text_feedback3":"Vamos tu puedes, intentalo de nuevo","color_fondo1":"#0b5394","color_fondo2":"#6d4794","textarea_informaciones":"<h3>\ud83d\udcda Información del Juego</h3>\r\n<p><strong>Objetivo:</strong> Identifica los sinónimos y antónimos.</p>\r\n<p><strong>Tipo de puntuación:</strong></p>\r\n<ul>\r\n<li>Respuesta correcta: +1 punto</li>\r\n<li>Respuesta incorrecta: -1 punto</li>\r\n<li>Máximo: 2 puntos por cada palabra</li>\r\n</ul>\r\n<p><strong>Instrucciones:</strong> Identifica y arrastra el sinónimo y antónimo a su respectiva casilla correcta.</p>","textarea_titulojuego":"<h1>Sinónimos y Antónimos</h1>","textarea_instrucciones":"<h2>Arrastra y completa con un sinónimo y antónimo de cada palabra</h2>","text_palabra1":"abundante","text_sinonimo1":"mucho","text_antonimo1":"escaso","text_palabra2":"bonito","text_sinonimo2":"hermoso","text_antonimo2":"feo","text_palabra3":"f\u00e1cil","text_sinonimo3":"sencillo","text_antonimo3":"dif\u00edcil","text_palabra4":"flaco","text_sinonimo4":"delgado","text_antonimo4":"gordo","text_palabra5":"grande","text_sinonimo5":"enorme","text_antonimo5":"peque\u00f1o","text_palabra6":"miedo","text_sinonimo6":"p\u00e1nico","text_antonimo6":"valent\u00eda","text_palabra7":"sumar","text_sinonimo7":"agregar","text_antonimo7":"restar","text_palabra8":"triunfo","text_sinonimo8":"victoria","text_antonimo8":"derrota","text_palabra9":"veloz","text_sinonimo9":"r\u00e1pido","text_antonimo9":"lento","text_palabra10":"conocer","text_sinonimo10":"saber","text_antonimo10":"ignorar","text_cantidad_palabras":"6"}
FOFUEDUCA
, Copyright 2025