Diseñe un juego de prueba de velocidad de escritura usando JavaScript

Una prueba de mecanografía está diseñada para encontrar qué tan rápido se escribe en un período de tiempo determinado. Diseñaremos un juego de mecanografía usando JavaScript que presenta un desafío de mecanografía simple y encuentra el rendimiento de mecanografiar calculando los caracteres por minuto (CPM), las palabras por minuto (WPM) y la precisión de los caracteres escritos.
El juego muestra una serie de citas que deben escribirse en un límite de tiempo específico, lo más rápido posible. Una velocidad de escritura más alta mostraría un valor de WPM más alto. Los caracteres escritos incorrectamente se marcarán en consecuencia durante la escritura.
Primero crearemos el diseño HTML, le daremos estilo usando CSS y luego escribiremos la lógica en JavaScript. 
El diseño HTML: El diseño HTML define la estructura del elemento que se mostraría en la página. Esto incluye:
 

  • Porción de encabezado: esta sección muestra las estadísticas de la sesión de escritura actual. Esto incluye la visualización del tiempo restante, el número de errores, la precisión, WPM y CPM.
  • Sección de cotización: esta sección muestra el texto actual que debe escribirse en el área de entrada.
  • Área de entrada: esta sección contiene el área de entrada donde se debe escribir el texto.
  • Botón de reinicio: este es el botón de reinicio que se mostrará una vez que se agote el tiempo y finalice el juego.
  • Código: 
     

html

<html lang="en">
<head>
    <title>Simple Speed Typer</title>
 
    <!-- link the CSS file here -->
    <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="container">
    <div class="heading">
      Simple Speed Typing
    </div>
    <div class="header">
      <div class="wpm">
        <div class="header_text">WPM</div>
        <div class="curr_wpm">100</div>
      </div>
      <div class="cpm">
        <div class="header_text">CPM</div>
        <div class="curr_cpm">100</div>
      </div>
      <div class="errors">
        <div class="header_text">Errors</div>
        <div class="curr_errors">0</div>
      </div>
      <div class="timer">
        <div class="header_text">Time</div>
        <div class="curr_time">60s</div>
      </div>
      <div class="accuracy">
        <div class="header_text">% Accuracy</div>
        <div class="curr_accuracy">100</div>
      </div>
    </div>
 
    <div class="quote">
      Click on the area below to start the game.
    </div>
    <textarea class="input_area"
      placeholder="start typing here..."
      oninput="processCurrentText()"
      onfocus="startGame()">
    </textarea>
    <button class="restart_btn"
      onclick="resetValues()">
      Restart
    </button>
  </div>
 
  <!-- link the JavaScript file here -->
  <script src="game.js">
  </script>
</body>
</html>

Nota: Cada una de las porciones está llena de datos ficticios para facilitar el estilo. El código HTML de lo anterior es el siguiente.
El estilo CSS: CSS se utiliza para diseñar las diferentes partes y hacerlas más atractivas visualmente.
 

  • La parte del encabezado se muestra con el diseño flexible.
  • A cada elemento se le asigna un relleno y un margen adecuados.
  • El tamaño del texto de cada elemento es tal que el usuario puede leerlo fácilmente cuando juega.
  • Se definen dos clases adicionales para indicar las letras que se escriben correctamente o incorrectamente. Estas clases se agregarán o eliminarán dinámicamente cuando sea necesario.
  • Código: 
     

html

body {
  background-color: #fe9801;
  color: black;
  text-align: center;
}
 
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
}
 
.heading {
  margin-bottom: 20px;
  font-size: 3rem;
  color: black;
}
 
.header {
  display: flex;
  align-items: center;
}
 
.timer, .errors, .accuracy,
.cpm, .wpm {
  background-color: #ccda46;
  height: 60px;
  width: 70px;
  margin: 8px;
  padding: 12px;
  border-radius: 20%;
  box-shadow: black 5px 8px 5px;
}
 
.cpm, .wpm  {
  display: none;
}
 
.header_text {
  text-transform: uppercase;
  font-size: 0.6rem;
  font-weight: 600;
}
 
.curr_time, .curr_errors,
.curr_accuracy, .curr_cpm,
.curr_wpm {
  font-size: 2.75rem;
}
 
.quote {
  background-color: #ccda46;
  font-size: 1.5rem;
  margin: 10px;
  padding: 25px;
  box-shadow: black 5px 8px 5px;
}
 
.input_area {
  background-color: #f5f5c6;
  height: 80px;
  width: 40%;
  font-size: 1.5rem;
  font-weight: 600;
  margin: 15px;
  padding: 20px;
  border: 0px;
  box-shadow: black 5px 8px 5px;
}
 
.restart_btn {
  display: none;
  background-color: #326765;
  font-size: 1.5rem;
  padding: 10px;
  border: 0px;
  box-shadow: black 5px 8px 5px;
}
 
.incorrect_char {
  color: red;
  text-decoration: underline;
}
 
.correct_char {
  color: darkgreen;
}

El resultado del diseño HTML y el estilo CSS se vería así: 
 

html_css_styling

Lógica principal del juego: La lógica principal del juego se define en un archivo JavaScript. Hay varias funciones que trabajan juntas para ejecutar el juego.
Paso 1: Seleccionar todos los elementos y definir variables
Los elementos requeridos en el diseño HTML se seleccionan primero usando el método querySelector(). Se les asignan nombres de variables para que puedan accederse y modificarse fácilmente. Otras variables a las que se accedería a lo largo del programa también se definen al principio.
 

javascript

// define the time limit
let TIME_LIMIT = 60;
 
// define quotes to be used
let quotes_array = [
  "Push yourself, because no one else is going to do it for you.",
  "Failure is the condiment that gives success its flavor.",
  "Wake up with determination. Go to bed with satisfaction.",
  "It's going to be hard, but hard does not mean impossible.",
  "Learning never exhausts the mind.",
  "The only way to do great work is to love what you do."
];
 
// selecting required elements
let timer_text = document.querySelector(".curr_time");
let accuracy_text = document.querySelector(".curr_accuracy");
let error_text = document.querySelector(".curr_errors");
let cpm_text = document.querySelector(".curr_cpm");
let wpm_text = document.querySelector(".curr_wpm");
let quote_text = document.querySelector(".quote");
let input_area = document.querySelector(".input_area");
let restart_btn = document.querySelector(".restart_btn");
let cpm_group = document.querySelector(".cpm");
let wpm_group = document.querySelector(".wpm");
let error_group = document.querySelector(".errors");
let accuracy_group = document.querySelector(".accuracy");
 
let timeLeft = TIME_LIMIT;
let timeElapsed = 0;
let total_errors = 0;
let errors = 0;
let accuracy = 0;
let characterTyped = 0;
let current_quote = "";
let quoteNo = 0;
let timer = null;

Paso 2: Preparando el texto a mostrar
Se define una función updateQuote() que maneja las siguientes cosas: 
 

  • Obtener el texto 
    Se han utilizado comillas como el texto que debe escribirse para jugar el juego. Cada cotización se toma una por una de una array predefinida. Una variable realiza un seguimiento del índice de cotización actual y lo incrementa cada vez que se solicita uno nuevo.
  • División de los caracteres en elementos 
    Cada uno de los caracteres del texto se separa en una serie de elementos <span>. Esto hace posible cambiar individualmente el color de cada carácter dependiendo de si el usuario lo ha escrito correctamente. Estos elementos se agregan a una variable quote_text.

javascript

function updateQuote() {
  quote_text.textContent = null;
  current_quote = quotes_array[quoteNo];
 
  // separate each character and make an element
  // out of each of them to individually style them
  current_quote.split('').forEach(char => {
    const charSpan = document.createElement('span')
    charSpan.innerText = char
    quote_text.appendChild(charSpan)
  })
 
  // roll over to the first quote
  if (quoteNo < quotes_array.length - 1)
    quoteNo++;
  else
    quoteNo = 0;
}

Paso 3: obtener el texto escrito actualmente por el usuario
Se define una función procesarTextoActual() que se invocará cada vez que el usuario escriba o cambie algo en el cuadro de entrada. Por lo tanto, se usa con el controlador de eventos oninput del cuadro de entrada. Esta función maneja las siguientes cosas:
 

  • Obtener el valor actual del cuadro de entrada 
    La propiedad de valor del área de entrada se utiliza para obtener el texto actual escrito por el usuario. Esto se divide en una array de caracteres para comparar con el texto de la cita. Esto se almacena en curr_input_array.
  • Colorear los caracteres del texto de la cita 
    Los caracteres de la cita mostrada se colorean en ‘rojo’ o ‘verde’ dependiendo de si se ha escrito correctamente. Esto se hace seleccionando los elementos de intervalo de la cita que hemos creado anteriormente y recorriéndolos. Luego, el elemento ha aplicado las clases creadas anteriormente dependiendo de si coincide con el texto escrito.
  • Cálculo de errores y precisión 
    Cada vez que el usuario comete un error al teclear, la variable errores se incrementa. Esto se utiliza para calcular el valor de precisión dividiendo el número de caracteres escritos correctamente por el número total de caracteres escritos por el usuario. 
     
  • Pasar a la siguiente cita 
    Cuando la longitud del texto de entrada coincide con la longitud del texto de la cita, se llama a la función updateQuote() que cambia la cita y borra el área de entrada. El número de errores totales también se actualiza para ser utilizado para la próxima cotización.

javascript

function processCurrentText() {
 
  // get current input text and split it
  curr_input = input_area.value;
  curr_input_array = curr_input.split('');
 
  // increment total characters typed
  characterTyped++;
 
  errors = 0;
 
  quoteSpanArray = quote_text.querySelectorAll('span');
  quoteSpanArray.forEach((char, index) => {
    let typedChar = curr_input_array[index]
 
    // character not currently typed
    if (typedChar == null) {
      char.classList.remove('correct_char');
      char.classList.remove('incorrect_char');
 
      // correct character
    } else if (typedChar === char.innerText) {
      char.classList.add('correct_char');
      char.classList.remove('incorrect_char');
 
      // incorrect character
    } else {
      char.classList.add('incorrect_char');
      char.classList.remove('correct_char');
 
      // increment number of errors
      errors++;
    }
  });
 
  // display the number of errors
  error_text.textContent = total_errors + errors;
 
  // update accuracy text
  let correctCharacters = (characterTyped - (total_errors + errors));
  let accuracyVal = ((correctCharacters / characterTyped) * 100);
  accuracy_text.textContent = Math.round(accuracyVal);
 
  // if current text is completely typed
  // irrespective of errors
  if (curr_input.length == current_quote.length) {
    updateQuote();
 
    // update total errors
    total_errors += errors;
 
    // clear the input area
    input_area.value = "";
  }
}
colorear_personajes

Coloreado de los personajes basado en su corrección.

Paso 4: Iniciar un nuevo juego
Se define una función startGame() que se invocará cuando el usuario se centre en el cuadro de entrada. Por lo tanto, se usa con el controlador de eventos onfocus del cuadro de entrada. Esta función maneja las siguientes cosas:
 

  • Restablecer todos los valores 
    Todos los valores se restablecen a sus valores predeterminados antes del inicio de un nuevo juego. Creamos una función diferente llamada resetValues() que maneja esto. 
     
  • Actualizar el texto de la cotización 
    Se prepara y se muestra un nuevo texto de la cotización llamando a la función updateQuote(). 
     
  • Creación de un nuevo temporizador 
    Un temporizador realiza un seguimiento de la cantidad de segundos restantes y se los muestra al usuario. Se crea utilizando el método setInterval() que llama repetidamente a la función updateTimer() definida a continuación. Antes de crear un nuevo temporizador, la instancia del temporizador anterior se borra mediante clearInterval().

javascript

function startGame() {
 
  resetValues();
  updateQuote();
 
  // clear old and start a new timer
  clearInterval(timer);
  timer = setInterval(updateTimer, 1000);
}
 
function resetValues() {
  timeLeft = TIME_LIMIT;
  timeElapsed = 0;
  errors = 0;
  total_errors = 0;
  accuracy = 0;
  characterTyped = 0;
  quoteNo = 0;
  input_area.disabled = false;
 
  input_area.value = "";
  quote_text.textContent = 'Click on the area below to start the game.';
  accuracy_text.textContent = 100;
  timer_text.textContent = timeLeft + 's';
  error_text.textContent = 0;
  restart_btn.style.display = "none";
  cpm_group.style.display = "none";
  wpm_group.style.display = "none";
}

Paso 5: Actualización del temporizador
Se define una función updateTimer() que se invocará cada segundo para realizar un seguimiento del tiempo. Esta función maneja las siguientes cosas:
 

  • Actualizar los valores 
    de tiempo Se actualizan todas las variables que controlan el tiempo. El valor de timeLeft se reduce, el valor de timeElapsed se incrementa y el texto del temporizador se actualiza al tiempo restante actual.
  • Terminar el juego 
    Esta parte se activa cuando se alcanza el límite de tiempo. Llama a la función finishGame() definida a continuación, que finaliza el juego.

javascript

function updateTimer() {
  if (timeLeft > 0) {
    // decrease the current time left
    timeLeft--;
 
    // increase the time elapsed
    timeElapsed++;
 
    // update the timer text
    timer_text.textContent = timeLeft + "s";
  }
  else {
    // finish the game
    finishGame();
  }
}

Paso 6: Terminar el juego
Se define una función finishGame() que será invocada cuando el juego tenga que ser terminado. Esta función maneja las siguientes cosas:
 

  • Eliminación del temporizador 
    Se elimina la instancia del temporizador creada anteriormente.
  • Mostrar el texto y el botón de reinicio del juego 
    El texto citado que se muestra al usuario se cambia por uno que indica que el juego ha terminado. El botón ‘Reiniciar’ también se muestra configurando la propiedad de visualización en ‘bloquear’.
  • Cálculo del CPM y WPM de la sesión actual 
    1. Los caracteres por minuto (CPM) se calculan dividiendo el número total de caracteres escritos por el tiempo transcurrido y luego multiplicando el resultado por 60. Se redondea para evitar puntos decimales.
    2. Las palabras por minuto (WPM) se calculan dividiendo el CPM por 5 y luego multiplicando el resultado por 60. El 5 denota el número promedio de caracteres por palabra. Se redondea para evitar puntos decimales.

javascript

function finishGame() {
  // stop the timer
  clearInterval(timer);
 
  // disable the input area
  input_area.disabled = true;
 
  // show finishing text
  quote_text.textContent = "Click on restart to start a new game.";
 
  // display restart button
  restart_btn.style.display = "block";
 
  // calculate cpm and wpm
  cpm = Math.round(((characterTyped / timeElapsed) * 60));
  wpm = Math.round((((characterTyped / 5) / timeElapsed) * 60));
 
  // update cpm and wpm text
  cpm_text.textContent = cpm;
  wpm_text.textContent = wpm;
 
  // display the cpm and wpm
  cpm_group.style.display = "block";
  wpm_group.style.display = "block";
}

Demostración final
El juego ya está listo para jugar en cualquier navegador.
 

out-full2-min

Código fuente: https://github.com/sayantanm19/js-simple-typing-game
 

Publicación traducida automáticamente

Artículo escrito por sayantanm19 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *