如何使用JavaScript建立一个快速打字游戏

268 阅读11分钟

如何使用JavaScript构建一个快速打字游戏

Javascript是一种编程语言,网络开发人员在创建动态网页功能和网络项目的互动性时使用它。

本教程将重点介绍如何使用Javascript、API调用、计时器、DOM(文档对象模型)操作等概念来构建一个快速打字游戏,以提高你的编码技能。

这应该是很有趣的,因为你将同时学习和享受乐趣。这个游戏也可能变成有用的,因为它可以测试和提高你的打字能力。

前提条件

要跟上这篇文章,读者将需要以下条件。

  • 文本编辑器。文本编辑器可以被描述为一个允许个人创建、打开和编辑文本的应用程序,例如Visual Studio Code、Atom、Sublime等。
  • HTML。超文本标记语言是用于创建网页的标准标记语言。该代码用于构造网页及其内容。
  • CSS。层叠样式表是用来给HTML文档设置样式的语言,描述HTML文档应该如何显示。
  • JavaScript。用来给网页增加互动性的编程语言。

为什么要学习JavaScript?

Sacha Greif和Raphaël Benitte的作品The State of Javascript 2020指出,一个熟练掌握Javascript的开发者的世界是多么的广阔和有益。

调查中指出。

尽管2020年很蹩脚,但Javascript作为一个整体仍能以某种方式向前发展。随着语言本身的不断改进。

关于游戏

快速打字游戏是一种用于测试、计算和提高打字速度和准确性的游戏,同时也是一种乐趣。对于一个开发者来说,培养快速打字的技能也是非常有益的,因为它可以提高人的效率和生产力。

这个游戏是如何工作的?

在成品中(这个项目的完整代码可在GitHub上找到),有一个计时器在计时,我们有一个区域可以输入我们正在输入的文本,它会告诉我们是对还是错。

如果我们是对的,它就会为我们移动到下一个问题(或引用)。

我们将使用visual studio代码作为本教程的文本编辑器,我们将使用一个API来开发一个随机报价器,为我们的快速打字游戏开发报价。

构建游戏

为了开始我们的游戏开发,我们将不得不首先创建一个index.html 文件,在那里我们要写下所有的HTML代码。

[提示:你可以直接输入一个感叹号(!)并点击 "Enter"。它将为我们生成所有的模板(模板是代码的部分或标准化的文本,通常在多个地方使用,在网络开发中几乎没有变化)]。

我们将需要为我们的CSS和Javascript创建一个link 标签,因为我们需要CSS和Javascript来构建游戏。对于我们的CSS,我们将创建一个stylesheet 链接,并将其称为styles.css

<link rel="stylesheet" href="styles.css">

同时为我们的JS创建一个脚本标签,并将其称为script.js

我们需要确保我们defer ,以便它在HTML正文之后加载,如图所示。

<script src="script.js" defer></script>

现在,我们进入HTML文件,在这里我们将添加定时器、输入、容器和引用文本。

为了创建定时器,我们创建了一个div ,其类别为timer ,一个id ,其类别为timer ,这样我们就可以在Javascript中轻松访问它。

<!-- create a 'class' and 'id' to be easily accessed by css and javascript -->
<div class="timer" id="timer"></div>

接下来,我们需要一个div ,其类别为container ,在container ,我们有报价和文本区。

首先,我们必须创建一个div ,将class 作为quote-display ,并给它一个id ,即quoteDisplay ,以便在JavaScript中访问它。

接下来,我们需要一个textarea ,它将成为我们输入的区域。我们指定classquote-inputidquoteInput

我们还需要将textarea 设置为autofocus ,这意味着当我们的页面加载时,我们的光标将通过自动聚焦在框内而使打字变得异常容易。

<!-- The 'container' will have both the quote and text area -->
<div class="container">
  <div class="quote-display" id="quoteDisplay"></div>
  <textarea id="quoteInput" class="quote-input" autofocus></textarea>
</div>

接下来,我们创建一个styles.css 文件,在这里我们将创建游戏的所有样式。

现在我们需要把box-sizing 设为border-box

/* This is to make working with 'widths', 'paddings' and 'margins' very much easier */
* {
  box-sizing: border-box;
}

这使得使用widthspaddingsmargins 更加容易。

然后,我们将body 样式设置为我们的container 的中心。要做到这一点,我们将margin 设置为0 ,以摆脱游戏显示时的滚动条,我们设置首选的background-color

/* Getting rid of the scroll bar, placing all of our contents at the center and setting our background color */
body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  margin: 0;
  background-color: #1E0555;
}

然后,我们设置我们的首选字体和它的样式,如图所示。

/* Setting the text-font for the game */
body, .quote-input {
  font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
}

接下来,我们为我们的.container

/* Styling the text and quote container */
.container {
  background-color: #F0DB4F;
  padding: 1rem;
  border-radius: .5rem;
  width: 700px;
  max-width: 90%;
}

稍后,我们要为timer ,使其置于文本之上。(在我们添加一些Javascript之前,定时器不会工作)。

/* Styling the timer */
.timer {
  position: absolute;
  top: 2rem;
  font-size: 3rem;
  color: #F0DB4F;
  font-weight: bold;
}

下一件事,我们要做的是.quote-display

/* Styling the quote area */
.quote-display {
  margin-bottom: 1rem;
  margin-left: calc(1rem + 2px);
  margin-right: calc(1rem + 2px);
}

.quoteInput 样式。

/* Styling where the texts would be typed (text area) */
.quote-input {
  background-color: transparent;
  border: 2px solid #A1922E;
  outline: none;
  width: 100%;
  height: 8rem;
  margin: auto;
  resize: none;
  padding: .5rem 1rem;
  font-size: 1rem;
  border-radius: .5rem;
}

选择.quoteInput ,并把它放在focus 的状态,border-color 将被做成black ,这样当我们点击一个文本时,它就会以黑色突出显示。

/* Creating a focus in the text  area to help know where the focus is */
.quote-input:focus {
  border-color: black;
}

我们将在我们的CSS中创建一个.correct.incorrect 类,我们最终将把它与我们的Javascript连接起来。

/* Style for the color of text when typing correctly */
.correct {
  color: green;
}
 
.incorrect {
/* Style for the color of text when typing incorrectly */
  color: red;
  text-decoration: underline;
}

添加JavaScript

(这是它变得有趣的地方)。

我们创建一个script.js 文件,在那里我们将编写所有的JavaScript。

将我们的引号放入文本框是我们要做的第一件事。这可以通过使用一个名为随机报价生成器的免费API来实现。

每当我们访问URL时,我们会从API的content 属性中得到一个随机的报价。我们复制该URL,然后回到我们的script.js 文件,创建一个const 变量,存储该URL。

// creating a 'const' variable to store the URL for API of quote generator 
const RANDOM_QUOTE_API_URL = 'http://api.quotable.io/random'

现在,我们需要做的是从我们的API中获取数据。为此,我们将创建一个名为getRandomQuotefunction 来获取API数据。

我们可以通过输入API的URL来实现,然后调用.then()

.then() 返回一个承诺,即我们将获得一个response 对象。在这里,我们把它转换为JSON

我们还将调用另一个.then() ,其中包含datadata 属性基本上是我们在API平台上看到的整个文本。

因此,对于我们来说,要想获得content 的密钥,这就是我们应该做的。

// Fetching our API for quote generator and returning a promise
function getRandomQuote() {
  return fetch(RANDOM_QUOTE_API_URL)
    .then(response => response.json())
    .then(data => data.content)
}

接下来我们要做的是创建async functionrenderNewQuote ,因为我们要在这个函数里面渲染我们的报价。

// Creating an  `async function` to return a promise
async function renderNewQuote() {
  const quote = await getRandomQuote()
}

记得在我们的HTML中,我们为quoteInput 创建了一个Id ,我们将在这里输入我们的报价,为quoteDisplay 创建了一个id ,我们将在这里显示我们的报价。

因此,在JavaScript文件中,我们将创建一个const 变量,我们可以调用quoteDisplayElement ,并将其设置为document.getElementById('quoteDisplay')

// Creating a const variable of 'quoteDisplay'
const quoteDisplayElement = document.getElementById('quoteDisplay')

然后,我们去我们的async function ,在那里我们renderNewQuote ,并说quoteDisplayElement.innerText=quote

// Adding quotes to the quote area. 
async function renderNewQuote() {
  const quote = await getRandomQuote()
  quoteDisplayElement.innerText=quote
}

现在,我们的报价可以放在它的部分,每当我们刷新时,就会产生一个新的报价。

因此,为了添加我们的输入,我们需要做的是调用quoteInputElement ,然后我们将其设置为。

// Adding our texts value document.getElementByID('quoteInput')
const quoteInputElement = document.getElementById('quoteInput')

然后,我们去我们的async function ,在那里我们renderNewQuote ,然后说。

//To clear out the texts inside the text area anytime a new quote is generated
quoteInputElement.value = null

记住,我们应该能够改变每个报价的颜色,以表示用户在输入时是对还是错。

要做到这一点,我们需要为每个字符或引语建立一个单独的元素,在这里我们需要通过一个loop

//Getting individual element for each character to be able to change color to either right or wrong
quote.split('').forEach(character => {
  const characterSpan = document.createElement('span')
  characterSpan.innerText = character
  quoteDisplayElement.appendChild(characterSpan)
}

// What we are trying to achieve here is that we are creating a 'span' for each character we get in our string then we set the text of that 'span' to that individual character

当我们在文本区输入字符时,我们要检查我们所输入的字符是否正确。为此,我们需要设置一个EventListener

EventListener 中的输入元素将在文本区的内容发生变化时被调用。我们要做的是循环查看所有不同的span ,即quote 数组中所有不同的字符。

然后我们根据每个字符的位置将其与输入中的单个字符进行比较,这样显示区的第一个字符就与输入区的第一个字符进行比较。

如果它们相似,将添加correct 类,如果它们不同,将添加incorrect 类。

如果我们到了用户正确输入所有内容的时候,我们想转到下一个引号,所以我们必须创建一个变量,并把它称为correct

correct 变量将被默认设置为true 。它将被假定所有的东西都是正确的,如果有些东西碰巧是incorrect ,那么变量将是false

因此,在变量恰好是true 的情况下,我们只想让它呈现下一个引号。

// Setting up an event listener to determine if the typing is right or wrong and to move to the next quote if the typing is right
quoteInputElement.addEventListener('input', () => { // The 'input' gets called everytime something in the text area changes
  const arrayQuote = quoteDisplayElement.querySelectorAll('span')
  const arrayValue = quoteInputElement.value.split('')
 
  let correct = true       // If we typed the right characters
  arrayQuote.forEach((characterSpan, index) => {
    const character = arrayValue[index]
    if (character == null) {
        characterSpan.classList.remove('correct')
      characterSpan.classList.remove('incorrect')
      correct = false      // If we typed the wrong characters
    } else if (character === characterSpan.innerText) {
      characterSpan.classList.add('correct')
      characterSpan.classList.remove('incorrect')
    } else {
      characterSpan.classList.remove('correct')
      characterSpan.classList.add('incorrect')
      correct = false
    }
  })
})

我们所要做的就是修复我们的timer

我们创建一个startTimer 函数,并获得我们的timer 元素。

如果你记得,我们在HTML中用timerid 创建了一个元素,所以我们可以直接选择timerid

// Using const variable to store our 'timer' 
const timerElement = document.getElementById('timer')

现在,我们将timer 设置为 "零"。

//Setting our timer to start at '0'
function startTimer() {
  timerElement.innerText = 0

然后,我们在我们的renderNewQuote 中调用startTimer

每当一个新的报价被呈现出来,我们希望我们的timer 重新开始。因此,在我们希望我们的计时器被更新的每一秒钟,setInterval 将被使用,因为它接受一个函数和第二个参数,指定你希望函数运行的次数(以毫秒为单位),如所示。

// To update our timer and to run it every millisecond 
setInterval(() => {
    timer.innerText = getTimerTime()
  }, 1000)

这个函数要每隔一秒运行一次,但setInterval 并不精确--它不会精确到每秒钟运行一次。为了弥补setInterval 的不精确性,我们将创建一个名为startTime 的变量,当我们的定时器开始时,它将是date

startTime 的值将被设置为当前的时间和日期。

我们不调用setInterval ,而是调用getTimerTime ,它获取当前时间,并从我们的startTime 中减去。

这将是以毫秒为单位,我们要将其转换为秒。为了做到这一点,我们将除以1000,这将给我们提供以秒为单位的时间(小数)。为了使其成为整数,我们使用Math.floor()

现在剩下的就是设置定时器的text

我们的定时器的最终代码应该是。

// Setting a new date 
let startTime
function startTimer() {
  timerElement.innerText = 0
  startTime = new Date()
  setInterval(() => {
    timer.innerText = getTimerTime()
  }, 1000)
}
 
function getTimerTime() {
  return Math.floor((new Date() - startTime) / 1000) // For the timer to work accurately in seconds
}

我们的游戏应该每秒钟开始计数。由于startTime 和currentDate(newDate)总是精确到毫秒,所以它应该再往上跳一跳。而setInterval 是不准确的,我们不能依赖它。

所以你现在可以检查一下,一切都应该工作得很好。

祝贺你

这就是你的游戏应该有的样子。

结论

虽然这个应用程序可以工作,但它还可以改进。我们仍然可以在功能和造型上进行改进。如果你在周围有困难,只需花时间仔细遵循每一个步骤。

记住,实践出真知。一致性是关键。