Создайте игру для теста скорости набора текста с помощью JavaScript
Тест на набор текста предназначен для определения того, насколько быстро человек печатает за заданный промежуток времени. Мы будем разрабатывать игру с набором текста с использованием JavaScript, которая представляет собой простую задачу набора текста и определяет производительность набора путем расчета символов в минуту (CPM), слов в минуту (WPM) и точности набранных символов.
Игра показывает серию цитат, которые необходимо ввести в указанный срок и как можно быстрее. Чем выше скорость набора текста, тем выше значение WPM. Неправильно набранные символы будут соответствующим образом отмечены во время набора.
Сначала мы создадим HTML-макет, стилизуем его с помощью CSS, а затем напишем логику на JavaScript.
Макет HTML: макет HTML определяет структуру элементов, которые будут отображаться на странице. Это включает:
- Заголовок: в этом разделе отображается статистика текущего сеанса набора текста. Это включает отображение оставшегося времени, количества ошибок, точности, WPM и CPM.
- Раздел цитат: в этом разделе отображается текущий текст, который необходимо ввести в область ввода.
- Область ввода: этот раздел содержит область ввода, в которой необходимо ввести текст.
- Кнопка перезапуска: это кнопка перезапуска, которая будет отображаться, когда время истечет и игра закончится.
- Код:
<
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
>
Примечание. Каждая часть заполнена фиктивными данными, чтобы упростить стилизацию. HTML-код вышеизложенного выглядит следующим образом.
Стили CSS: CSS используется для стилизации различных частей и придания им большей визуальной привлекательности.
- Часть заголовка отображается с использованием гибкого макета.
- Каждому элементу даны соответствующие отступы и поля.
- Размер текста каждого элемента таков, что он легко читается пользователем во время игры.
- Два дополнительных класса определены для обозначения букв, которые набираются правильно или неправильно. Эти классы будут динамически добавляться или удаляться при необходимости.
- Код:
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;
}
Результат макета HTML и стиля CSS будет выглядеть следующим образом:
Основная логика игры: Основная логика игры определяется в файле JavaScript. Есть несколько функций, которые работают вместе для запуска игры.
Шаг 1. Выбор всех элементов и определение переменных
Необходимые элементы в макете HTML сначала выбираются с помощью метода querySelector()
Им присваиваются имена переменных, чтобы к ним можно было легко получить доступ и изменить. Другие переменные, к которым будет осуществляться доступ во всей программе, также определены в начале.
// 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 ; |
Шаг 2: Подготовка текста для отображения
Определена функция updateQuote()
которая обрабатывает следующие вещи:
- Получение текста
Цитаты использовались в качестве текста, который нужно набирать, чтобы играть в игру. Каждая цитата берется одна за другой из предопределенного массива. Переменная отслеживает текущий индекс котировки и увеличивает его при каждом запросе нового. - Разбиение персонажей на элементы
Каждый из символов в тексте разделен на серию элементов<span>
. Это позволяет индивидуально изменять цвет каждого символа в зависимости от того, правильно ли он набран пользователем. Эти элементы добавляются к переменнойquote_text
.
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; } |
Шаг 3. Получение пользователем текста, набранного в данный момент.
Определена функция processCurrentText()
которая будет вызываться всякий раз, когда пользователь вводит или изменяет что-либо в поле ввода. Следовательно, он используется с oninput
события oninput поля ввода. Эта функция обрабатывает следующие вещи:
- Получение текущего значения поля ввода
Свойствоvalue
области ввода используется для получения текущего текста, вводимого пользователем. Он разбивается на массив символов для сравнения с текстом цитаты. Это хранится вcurr_input_array
. - Раскрашивание символов текста цитаты
Символы отображаемой цитаты окрашиваются в красный или зеленый цвет в зависимости от того, правильно ли она набрана. Для этого нужно выбрать элементы диапазона цитаты, которую мы создали ранее, и просмотреть их в цикле. Затем элемент применил классы, созданные выше, в зависимости от того, соответствует ли он набранному тексту. - Расчет погрешностей и точности
Каждый раз, когда пользователь делает ошибку во время набора текста,errors
увеличивается. Это используется для расчета значения точности путем деления количества правильно набранных символов на общее количество символов, набранных пользователем. - Переход к следующей цитате
Когда длина вводимого текста совпадает с длиной текста цитаты,updateQuote()
которая изменяет цитату и очищает область ввода. Количество общих ошибок также обновляется для использования в следующей расценке.
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 = "" ; } } |
Шаг 4: Запуск новой игры
Определена функция startGame()
которая будет вызываться, когда пользователь фокусируется на поле ввода. Следовательно, он используется с onfocus
событий onfocus поля ввода. Эта функция обрабатывает следующие вещи:
- Сбросить все значения
Все значения сбрасываются до значений по умолчанию перед началом новой игры. Мы создаем другую функцию с именемresetValues()
которая этим занимается. - Обновить текст цитаты
Новый текст цитаты подготавливается и отображается путем вызова функцииupdateQuote()
. - Создание нового таймера
Таймер отслеживает количество оставшихся секунд и отображает его пользователю. Он создается с помощьюsetInterval()
который многократно вызываетupdateTimer()
определенную ниже. Перед созданием нового таймера предыдущий экземпляр таймера очищается с помощьюclearInterval()
.
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" ; } |
Шаг 5: Обновление таймера
Определена функция updateTimer()
которая будет вызываться каждую секунду для отслеживания времени. Эта функция обрабатывает следующие вещи:
- Обновите значения времени
Все переменные, которые отслеживают время, обновляются. ЗначениеtimeLeft
уменьшается,timeElapsed
увеличивается, а текст таймера обновляется до текущего оставшегося времени. - Завершение игры
Эта часть запускается при достижении лимита времени. Он вызываетfinishGame()
определенную ниже, которая завершает игру.
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(); } } |
Шаг 6: завершение игры
Определена функция finishGame()
которая будет вызываться, когда игра должна быть завершена. Эта функция обрабатывает следующие вещи:
- Удаление таймера
Созданный ранее экземпляр таймера удаляется. - Отображение текста и кнопки перезапуска игры
Цитируемый текст, отображаемый для пользователя, изменяется на текст, указывающий на то, что игра окончена. Кнопка «Перезагрузка» также отображается, если для свойства display установлено значение «block». - Расчет CPM и WPM текущего сеанса
- Число символов в минуту (CPM) рассчитывается путем деления общего количества набранных символов на прошедшее время и последующего умножения результата на 60. Оно округляется во избежание запятой.
- Количество слов в минуту (WPM) рассчитывается путем деления CPM на 5 и последующего умножения результата на 60. 5 обозначает среднее количество символов в слове. Оно округлено, чтобы не было десятичных знаков.
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" ; } |
Заключительная демонстрация
Теперь игра готова к игре в любом браузере.
Исходный код: https://github.com/sayantanm19/js-simple-typing-game