如何使用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 ,它将成为我们输入的区域。我们指定class 为quote-input ,id 为quoteInput 。
我们还需要将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;
}
这使得使用widths 、paddings 和margins 更加容易。
然后,我们将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中获取数据。为此,我们将创建一个名为getRandomQuote 的function 来获取API数据。
我们可以通过输入API的URL来实现,然后调用.then() 。
.then() 返回一个承诺,即我们将获得一个response 对象。在这里,我们把它转换为JSON 。
我们还将调用另一个.then() ,其中包含data 。data 属性基本上是我们在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 function 到renderNewQuote ,因为我们要在这个函数里面渲染我们的报价。
// 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中用timer 的id 创建了一个元素,所以我们可以直接选择timer 的id 。
// 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 是不准确的,我们不能依赖它。
所以你现在可以检查一下,一切都应该工作得很好。
祝贺你
这就是你的游戏应该有的样子。
结论
虽然这个应用程序可以工作,但它还可以改进。我们仍然可以在功能和造型上进行改进。如果你在周围有困难,只需花时间仔细遵循每一个步骤。
记住,实践出真知。一致性是关键。