Skip to main content
The Pica y Fija client is built with vanilla JavaScript and Socket.IO for real-time communication. This guide covers the complete client integration including connection setup, event handling, and UI management.

Socket.IO Client Setup

Installing the Client Library

The Socket.IO client is loaded via CDN in the HTML file:
index.html
<script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>

Establishing Connection

The client connects to the server using WebSocket transport for optimal performance:
index.html:192-193
const socket = io(window.location.origin, { transports: ['websocket'] });
For local development, you can override the connection URL:
const socket = io('http://localhost:9090', { transports: ['websocket'] });

Alternative WebSocket Connection

The main.js file demonstrates a direct WebSocket connection to a production server:
main.js:4
const socket = io("wss://pica-fija.onrender.com");

DOM Element References

The client initializes references to key DOM elements for managing the UI:
index.html:194-205
const log = document.getElementById('log');
const lobby = document.getElementById('lobby');
const zonaJuego = document.getElementById('zonaJuego');
const guessInput = document.getElementById('guess');
const guessBtn = document.getElementById('guessBtn');
const secretInput = document.getElementById('secret');
const btnSecret = document.getElementById('btnSecret');
const numSecretSpan = document.getElementById('num_secret');
const table = document.getElementById('resultTable').querySelector('tbody');
const resultTable = document.getElementById('resultTable');
const overlay = document.getElementById('overlay');
const timer = document.getElementById('turnTimer');

UI Structure

The client interface is divided into two main sections:
1

Lobby Section

The lobby (#lobby) is shown when players first connect. It provides options to:
  • Create a new game room
  • Search for available rooms
  • Join a room by code
index.html:114-128
<div id="lobby">
  <button onclick="mostrarConfigCrearSala()">🎮 Crear Sala</button>
  <button onclick="buscarSala()">🔎 Buscar Sala</button>
  <button onclick="mostrarUnirse()">📩 Unirse por Código</button>
  <!-- Forms for room creation and joining -->
</div>
2

Game Zone

The game zone (#zonaJuego) is displayed during active gameplay. It includes:
  • Secret number input field
  • Guess input field and submit button
  • Turn filter dropdown
  • Countdown timer
  • Results table
index.html:131-172
<div id="zonaJuego" style="display:none;">
  <!-- Secret input -->
  <input id="secret" maxlength="4" placeholder="Número secreto" />
  <button onclick="sendSecret()" id="btnSecret">Estoy Listo</button>
  
  <!-- Guess input -->
  <input id="guess" maxlength="4" placeholder="Tu intento" disabled />
  <button id="guessBtn" onclick="sendGuess()" disabled>Adivinar</button>
  
  <!-- Results table and timer -->
</div>

Sending Events to Server

The client sends events using socket.emit() to communicate player actions:

Creating a Room

index.html:349-356
function crearSala() {
  const tiempoTurno = parseInt(document.getElementById('tiempoTurno').value);
  const publica = document.getElementById('salaPublica').checked;
  const requiereAprobacion = document.getElementById('requiereAprobacion').checked;
  socket.emit('crearSala', { tiempoTurno, publica, requiereAprobacion });
  lobby.style.display = 'none';
  zonaJuego.style.display = 'block';
}

Joining a Room

function buscarSala() {
  socket.emit('buscarSala');
  lobby.style.display = 'none';
  zonaJuego.style.display = 'block';
}

Sending Game Actions

function sendSecret() {
  socket.emit('secret', secretInput.value);
}

Receiving Server Events

The client listens for various events from the server:

Info and Error Messages

index.html:221-229
socket.on('info', message => {
  log.innerText += `🟡 ${message}\n`;
  if (message.includes('Número secreto guardado')) {
    numSecretSpan.innerText = `Número secreto: ${secretInput.value}`;
    secretInput.style.display = 'none';
    btnSecret.style.display = 'none';
    sndEnviarSecreto.play();
  }
});
index.html:243
socket.on('error', msg => log.innerText += `❌ ${msg}\n`);

Room Events

Triggered when a room is successfully created:
index.html:239-241
socket.on('salaCreada', data => {
  document.getElementById('codigoSalaVista').innerText = `Código de sala: ${data.codigo}`;
});
Triggered when the player successfully joins a room:
index.html:231-237
socket.on('salaLista', data => {
  miJugadorId = data.jugador === 1 ? 0 : 1;
  tiempoTurnoConfigurado = data.tiempoTurno || 60;
  lobby.style.display = 'none';
  zonaJuego.style.display = 'block';
  log.innerText += `✅ Te uniste como Jugador ${data.jugador} a la sala ${data.sala}\n`;
});

Game Events

Triggered when the game begins:
index.html:245-251
socket.on('start', () => {
  lobby.style.display = 'none';
  zonaJuego.style.display = 'block';
  sndJuego.play();
  resultTable.hidden = false;
  log.innerText += '🎮 ¡El juego ha comenzado!\n';
});
Manages turn transitions between players:
index.html:253-268
socket.on('turn', data => {
  if (juegoTerminado) return;
  if (data.yourTurn) {
    guessInput.disabled = false;
    guessBtn.disabled = false;
    guessInput.value = '';
    startTimer();
    log.innerText += '🟢 ¡Es tu turno!\n';
    sndTurno.play();
  } else {
    guessInput.disabled = true;
    guessBtn.disabled = true;
    stopTimer();
    log.innerText += '🔴 Esperando turno del oponente...\n';
  }
});
Displays guess results and detects game completion:
index.html:270-303
socket.on('result', data => {
  const key = `${data.jugadorId}-${data.turno}`;
  if (turnosMostrados.has(key)) return;
  turnosMostrados.add(key);

  const jugadorLabel = data.jugadorId === miJugadorId ? 'yo' : 'oponente';
  const jugadorColor = data.jugadorId === miJugadorId ? 'white' : 'orange';

  const row = document.createElement('tr');
  row.innerHTML = `
    <td style="color:${jugadorColor}">${jugadorLabel}</td>
    <td style="color:${jugadorColor}">${data.turno}</td>
    <td style="color:${jugadorColor}">${data.intento}</td>
    <td style="color:${jugadorColor}">${data.picas}</td>
    <td style="color:${jugadorColor}">${data.fijas}</td>
  `;
  table.insertBefore(row, table.firstChild);
  filtrarTurnos();

  if (data.fijas === 4) {
    juegoTerminado = true;
    guessInput.disabled = true;
    guessBtn.disabled = true;
    sndJuego.pause(); 
    stopTimer();
    if (data.jugadorId === miJugadorId) {
      showResult('🎉 ¡Ganaste!', sndGanador);
    } else {
      showResult('💀 Perdiste', sndPerdedor);
    }
  }
});

Audio System Integration

The client includes a complete audio feedback system:

Audio Element Setup

index.html:175-179
<audio id="sndEnviarSecreto" src="assets/audio/enviar_secreto.mp3"></audio>
<audio id="sndTurno" src="assets/audio/turno.mp3"></audio>
<audio id="sndJuego" src="assets/audio/juego.mp3" loop></audio>
<audio id="sndGanador" src="assets/audio/ganador.mp3"></audio>
<audio id="sndPerdedor" src="assets/audio/perdedor.mp3"></audio>

Audio References and Configuration

index.html:207-213
const sndEnviarSecreto = document.getElementById('sndEnviarSecreto');
const sndTurno = document.getElementById('sndTurno');
const sndJuego = document.getElementById('sndJuego');
const sndGanador = document.getElementById('sndGanador');
const sndPerdedor = document.getElementById('sndPerdedor');
const turnosMostrados = new Set();
sndJuego.volume = 0.2;

Audio Playback Events

EventAudioDescription
Secret submittedsndEnviarSecretoPlays when player submits secret number
Game startssndJuegoBackground music (loops continuously)
Turn beginssndTurnoPlays when it’s the player’s turn
Player winssndGanadorVictory sound
Player losessndPerdedorDefeat sound
The background game music (sndJuego) is paused when the game ends to stop playback:
sndJuego.pause();

Result Display Overlay

The overlay system displays end-game results:
index.html:181
<div id="overlay" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.8); color:#fff; font-size:3rem; justify-content:center; align-items:center; z-index:9999;"></div>
index.html:339-343
function showResult(message, audio) {
  overlay.style.display = 'flex';
  overlay.innerText = message;
  audio.play();
}
The overlay displays either ”🎉 ¡Ganaste!” or ”💀 Perdiste” based on the game outcome.

Build docs developers (and LLMs) love