本博客附赠了一个清新脱俗欲罢不能的小游戏Alphabet Challenge,游戏规则就是快速连续敲完26个英文字母,当然了,要按照字母表顺序。个人的记录是1.89秒,我简单说说游戏实现过程吧。

它真的很简单。

初衷

这是我刚入门JavaScript语言的时候练手写的,游戏当然不是原创啦。之前看到一个类似的游戏,是Flash制作的小游戏,当时我陷入游戏停不下来。顺便我还带动了实验室的小伙伴一起刷分,看谁手速快。

有一天吧,朋友在空间发了这个游戏的链接还艾特我,我看到一个评论,说“这是XXX做的游戏吗?”这个XXX就是指本人啦,而且略带嘲讽的感觉,好吧也可能是我过度解读了。于是我就想直接用HTML和JS来实现一个,哦对也得有CSS才行。

废话说了一堆,进入正题

游戏逻辑的设计

计时系统

因为是从A敲到Z,然后给出所耗的时间,那么计时就应当从按下A的一瞬间开始,按下Z的一瞬间停止。

可以用两个变量,分别记住开始时间和结束时间,两个变量相减就得出了游戏耗时,单位是毫秒(不同浏览器也许不同,测试的Chrome,Firefox,IE都没问题)。

1
2
3
4
gameStart = Date.now()
//...游戏过程
gameOver = Date.now()
score = (gameOver - gameStart)/1000.0

按键判定

我们可以让整个界面处于监听按键的状态,所以大部分逻辑将写在下面这个代码块里。

1
2
3
document.onkeydown = function(e) {
//各种按键判定 以及相对应处理
}

由于浏览器有很多快捷键,所以建议加上

1
2
//屏蔽浏览器快捷键
e.preventDefault()

我们知道每个按键都有对应的唯一的keyCode,比如32就是空格按键,65就是A按键等等。我们可以声明一个flag变量表示当前显示的字母,也就是需要按下的字母。因为刚好A~Z字母对应的keyCode是65~90(ASCII),所以这个游戏的主要逻辑就可以归纳为从65号按键开始直到90号按键

  • 按对了 flag++
  • 按错了 flag不变
  • 按空格 flag=65(重新开始)

flag变量顺便可以在网页里显示出来对应的字母

1
2
3
stats = document.getElementById("stats")
//String.fromCharCode(Int) 方法可以把数字转成对应按键
stats.innerHTML = String.fromCharCode(flag)

代码实现

JavaScript部分

贴出所有代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
var stats = document.getElementById("stats")
stats.innerHTML = 'A'
var flag = 65

//预置配色方案
//本来是有个切换配色功能的,不过还没完善,代码就暂时这样吧。
var themes = [ {
baseColor: '#2B2B2B',
textColor: '#a7a7a7',
statsColor: '#E74146'
}, {
baseColor: '#ACBA85',
textColor: '#4E8858',
statsColor: '#436A3E'
}, {
baseColor: '#E98D70',
textColor: '#AA4A30',
statsColor: '#dd6821'
}, {
baseColor: '#B3E5FC',
textColor: '#29B6F6',
statsColor: '#0277BD'
}]
var index = 0
//初始化一个配色方案
body = document.getElementsByTagName("body")[0]
body.style.backgroundColor = themes[index].baseColor
body.style.color = themes[index].textColor
stats.style.color = themes[index].statsColor

function createCanvas(score, fontColor) {
canvas = document.createElement("canvas")
canvas.width = "600"
canvas.height = "400"
canvas.innerHTML = ' ' //不知为何一定要有这个不然没有关闭标签
stats.innerHTML = ''
stats.appendChild(canvas)
ctx = canvas.getContext('2d')
ctx.fillStyle = fontColor
ctx.font = "150pt Verdana sans-serif"
ctx.fillText(score, 50, 250)
}

function playAudio(status) {
//传入起始播放时间,默认为0
startTime = arguments[1] ? arguments[1] : 0
//传入播放音量,默认0.5,以应对音量过大或过小
volume = arguments[2] ? arguments[2] : 0.5
audio = document.getElementById(status.toLowerCase())
audio.currentTime = startTime
audio.loop = false
audio.volume = volume
audio.play()
}


document.onkeydown = function(e) {
//屏蔽浏览器快捷键
e.preventDefault()

if (e.keyCode == 32) {
//(重新)开始游戏
flag = 65
stats.innerHTML = String.fromCharCode(flag)
}

if (e.keyCode <= 90 && e.keyCode >= 65) {
//按键为字母
if (e.keyCode == flag) {
//输入正确的情况
flag++
//输入正确 清除声
playAudio('CLEAR', 0.28)

if (e.keyCode == 65) {
gameStart = Date.now()
stats.innerHTML = String.fromCharCode(flag)
} else if (flag < 91 && flag > 65) {
stats.innerHTML = String.fromCharCode(flag)
} else if (flag == 91) {
gameOver = Date.now()
score = (gameOver - gameStart) / 1000.0
if (score < 10) {
//十秒内完成,胜利声
playAudio('WIN', 0, 1)
//10秒之外不显示时间避免几万秒溢出容器,并给予嘲讽
//成绩用Canvas绘制,尽力避免通过修改页面来作弊
//非要作弊可以直接改代码我也没什么办法
createCanvas(score.toFixed(3), stats.style.color) //固定小数位确保图片在中间
} else {
// 十秒外完成,失败声
playAudio('LOSE', 0.1, 0.25)
stats.innerHTML = "LOSE"
}
}

} else {
//警告声 输入错误
playAudio('WRONG', 0.29)
}

} else {
//非字母、空格按键 警告声
if (e.keyCode != 32) {
playAudio('WRONG', 0.29)
}
}
}

除了主要逻辑还有额外两个方法 playAudiocreateCanvas

前者是控制音效,在不同的情况下播放特定的音效,参数还可以加入起始时间和音量。

后者是采用绘制Canvas来展现成绩,为了防止直接修改DOM来获得任意成绩的。当然了,能干出这事的人,基本也可以找得到这个方法,我连参数文档都写好了,在console里调用一下就可以。 后来混淆加密了一下JS代码,应该没谁这么闲来研究破解了…

HTML部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="Jason">
<title>Alphabet Challenge</title>
<link rel="stylesheet" href="public/index.css" media="screen" charset="utf-8">
</head>
<body onselectstart="return false;">
<div id="container">
<h1>Alphabet Challenge</h1>
<div id="stats"></div>
<footer>Press <strong>Space</strong> to restart</footer>
</div>
<audio src="public/clear.wav" id="clear"> </audio>
<audio src="public/wrong.wav" id="wrong"> </audio>
<audio src="public/win.wav" id="win" > </audio>
<audio src="public/lose.wav" id="lose" > </audio>
</body>
<script type="text/javascript" src="public/app.js"></script>
</html>

其中

1
<body onselectstart="return false;">

这段代码是使页面文字不能被选中,算是提高点体验吧。

CSS部分

主要如下,新手写的很朴素…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
html{
font-family: Verdana ,sans-serif;
}

body{
text-align: center;
}

#container{
width: 80%;
height: 500px;
left: 0;
right: 0;
margin: auto;
margin-top: 40px;
padding: 50px;
}

#stats{
width: 70%;
height: 80%;
left: 0;
right: 0;
margin: auto;
font-size: 200pt;
text-align: center;
}

以上就是写这个游戏的基本过程,关于代码欢迎提出意见改进。

玻璃心,不要拍砖-A-

如有疏漏,欢迎评论指出,或者前往Github提出issue~谢谢