写在最前面

本文主要锻炼的是原生JavaScript的编程能力,运用了函数式编程的思想!

1.页面的排版与布局

主要分成两个页面:a.初始呈现出来的界面;b.点击开始进入游戏的界面。

a界面: 比较丑,大家注重功能实现就好,忽略ui


说明:
a.画页面不是我的目的,所以背景潦草的使用了一张图片简单实现了一下。
b.三个dom元素:两个按钮(开始、说明),点击说明按钮出现的说明内容。

// 初始呈现出来的界面<div id="gameStart"><!-- 1.开始游戏按钮 --><div id="start"></div><!-- 2.游戏说明按钮 --><div id="describe"></div><!-- 3.游戏说明内容 --><div id="des">我是一段认认真真的游戏说明。<div id="cl">关闭</div></div>
</div>
/* container 是最外层的包裹容器 */
#container{/* 宽高就是背景图片的尺寸 */width: 521px; height: 342px;margin: 50px auto;/* 设置相对定位 */position: relative;/* 后续下落字母落到背景图以下时候,进行隐藏 */overflow: hidden;
}/* 把背景图片放进 gameStart 里 */
#gameStart{background: url(./img/background.png) no-repeat;/* 宽高百分之百,继承父级 */width: 100%;height: 100%;/* display: none; */
}/* 按钮的定位,两按钮除了距离底部高度不一致外其余都相同 */
#start, #describe{width: 101px;height: 30px;/* border: 1px solid black; */position: absolute;left: 7px;border-radius: 20px;cursor: pointer;
}
#start{bottom: 51px;
}
#describe{bottom: 6px;
}/* 游戏说明部分 */
#des{width: 300px;height: 100px;position: absolute;top: 100px;left: 100px;border: 7px solid skyblue;background-color: #fff;text-align: center;display: none;
}
/* 关闭叉叉 */
#cl{position: absolute;top: 0;right: 0;cursor: pointer;border: 1px solid #ccc;font-weight: bold;display: none;
}

b.界面: 点击开始按钮进入游戏界面
四个操作按钮:

  • 开始按钮 —> 游戏的暂停
  • 结束按钮
  • 退出游戏 —> 退出到游戏开始的界面
  • 设置 —> 设置当前游戏的难度

    点击设置,显示游戏难度选择。
<!-- 进入游戏界面 -->
<div id="game"><!-- 四个操作按钮,使用了事件委托进行js交互 --><div id="oprate"><span class="start">开始</span><span class="exit">退出</span><span class="finish">结束</span><span class="set">设置</span></div><!-- 点击设置弹出游戏难度选择 --><div id="select"><!-- 一开始是隐藏的 --><select name="" id=""><option value="3">慢</option><option value="2">中</option><option value="1">快</option></select><!-- 关闭按钮 --><span id="close">关闭</span></div><!-- 提示打字的得分、正确率和速度 --><div id="tip"><p>得分: <span>0</span> 分</p><p>正确率:<span>0 %</span></p><p>速度:<span>0 </span>个 / 分</p></div>
</div>
/* 一开始游戏界面是隐藏的 */
#game{display: none;width: 100%;height: 100%;border: 1px solid #666;background-color: #ccc;
}
/* 四个选项:开始、退出、设置、结束 */
#oprate{position: absolute;bottom: 0;left: 0;width: 100px;height: 100px;
}
#oprate span{display: inline-block;width: 40px;height: 40px;text-align: center;line-height: 40px;border-radius: 50%;cursor: pointer;position: absolute;background-color: skyblue;color: #fff;font-weight: bolder;
}
#oprate span:hover{background-color: green;
}
#oprate span:nth-child(1) {left: 0;top: 30px;
}
#oprate span:nth-child(2) {left: 30px;top: 0;
}
#oprate span:nth-child(3) {left: 30px;bottom: 0;
}
#oprate span:nth-child(4) {top: 30px;right: 0;
}/* 点击设置弹出游戏难度选择 */
#select{display: none;width: 140px;height: 60px;border: 7px solid skyblue;position: absolute;top: 50px;left: 50px;background-color: #fff;
}
#select select{width: 80px;height: 30px;text-indent: 22px;font-size: 19px;margin-left: 30px;margin-top: 15px;
}
#close{position: absolute;top: 0;right: 0;cursor: pointer;display: none;
}
#close:hover{background-color: pink;
}/* 提示打字的得分、正确率和速度 */
#tip{position: absolute;top: 0;right: 0;width: 150px;line-height: 30px;padding: 5px 10px;letter-spacing: 2px;color: red;opacity: 0.5;
}

END: 至此,结构样式部分全部结束

JavaScript部分:

1.封装函数拿到所有需要的DOM节点。

function $(idName) {return document.getElementById(idName);
}var gameStart = $('gameStart');
var start = $('start');
var describe = $('describe');
var des = $('des');
var cl = $('cl');
var game = $('game');
var oprate = $('oprate');
var close = $('close');

需求A:点击开始游戏,隐藏游戏初始界面,显示进入游戏界面。

// 开始游戏的按钮的 id=start
// gameStart是初始界面最外层的id
// game是游戏开始界面最外层的id
// 思路很简单: 让页面最外层包裹元素display=none/block;即可start.onclick = function() {gameStart.style.display = "none";game.style.display = "block";
}

需求B:进入游戏界面之后点击退出按钮实现页面回到初始界面。以及设置按钮。

// 使用了事件委托,将事件全部委托到父元素上实现功能
// oprate是包裹四个操作按钮元素的父容器id
// 事件委托,将子元素的点击事件全部赋到父元素上,点击父元素触发子元素的点击事件oprate.onclick = function(event) {// 事件兼容处理,兼容 IEvar e = event || window.event;var target = e.srcElement || e.target;// 退出if(target.className === 'exit') {gameStart.style.display = "block";game.style.display = "none";}// 设置,出现游戏难度if(target.className == 'set') {select.style.display = 'block';}
}

需求C:初始页点击游戏说明按钮显示游戏说明及关闭。游戏难度

// 点击说明按钮显示游戏说明
// describe是游戏说明按钮的 id
// des是说明内容的 id
// cl是关闭文字的 id
// select是设置游戏难度最外层的 id
// close是关闭文字的 iddescribe.onclick = function() {des.style.display = 'block';
}
// 鼠标经过游戏说明区域时,显示关闭按钮
des.onmouseover = function() {cl.style.display = 'block';
}
// 鼠标移除时候隐藏
des.onmouseout = function() {cl.style.display = 'none';
}
// 关闭游戏说明内容
cl.onclick = function() {des.style.display = 'none';
}// 游戏难度的关闭按钮
select.onmouseover = function() {close.style.display = 'block';
}
select.onmouseout = function() {close.style.display = 'none';
}
// 点击关闭设置游戏难度的按钮
close.onclick = function() {select.style.display = "none";// 当我们进行游戏难度设置以后,关闭游戏难度设置之后,level数值生效!level = selFir.value;
}

2.封装函数,获取到元素使用样式的最终值,保证兼容。

function getStyle(ele, attr) {// 定义变量,用以保存最终获取到的值var res = null; // 判断当前浏览器是否支持 currentStyle 这个属性if(ele.currentStyle) { // 有这个属性的话,使用ele对象的currentStyle属性来获取 attr 元素属性,并储存res = ele.currentStyle[attr];}else {// 否则res = window.getComputedStyle(ele, null)[attr];}// 将储存的值返回出去return parseFloat(res);
}

3.封装运动函数。

// 获取游戏界面的高度和宽度
var gameH = getStyle(gameStart, "height");
var gameW = getStyle(gameStart, "width");// 运动的元素 运动到的最终值 运动元素哪个属性在变化
function startMove(ele, end, attr) {// 控制字母下落速度// 随着分数越来越高,让速度越来越快var speed = 0.5 + score / 100;// 将定时器赋值给一个变量,以便后续去清除ele.timer = setInterval(function() {// 获取当前元素的运动值var moveVal = getStyle(ele, attr);if(moveVal >= end) { clearInterval(ele.timer);// 删除元素,防止长时间页面卡死game.removeChild(ele);// 当ele 目标元素达到清除的时候,就让目标元素 ele 里面的内容清除,最后再删除掉letters = letters.replace(ele.innerHTML, '');}else {ele.style[attr] = moveVal + speed + 'px';}}, 10)
}

需求d:进入游戏界面后的开始和暂停游戏
注意:该部分是位于需求2中的事件代理下的后续if操作。

// 定时器
var c;
// 动态创建的所有字母元素,我怎么去获取呢?去到创建字母的函数中看看
var letterEles;// 如果用户点击了开始按钮
if(target.className === 'start') {target.innerHTML = target.innerHTML == "开始" ? "暂停" : '开始';// 游戏的暂停if(target.innerHTML == '开始') {// 当前状态是暂停的时候,游戏的设置功能开启oprate.lastElementChild.style.cursor = 'pointer';clearInterval(c);// 重置 cc = undefined; // 清除所有字母元素上的定时器clearAllLetters();}else {// 当前状态是开始的时候,不允许点击游戏设置按钮oprate.lastElementChild.style.cursor = 'not-allowed';// 游戏的开始// 注意: 当我们反复点击开始暂停按钮的时候,需要判断当前是否已经存在定时器了,已经存在就不再开启了,防止开启多个定时器之后页面卡死。if(c) {return;}// 定义开始时间,用以统计打字速度startTimeStamp = new Date() * 1;// 设置定时器,每隔0.5s下落一个文字c = setInterval(function() {// 定义结束时间,用以统计打字速度endTimeStamp = new Date() * 1;// 不满1分钟按1分钟进行计算if(endTimeStamp - startTimeStamp <= 60 * 1000) {// tip.children[2].firstElementChild 找到速度tip.children[2].firstElementChild.innerHTML = score;}else {// 超过1分钟不足两分钟// Math.ceil((endTimeStamp - startTimeStamp)/(60*1000)) 得到分钟tip.children[2].firstElementChild.innerHTML = Math.ceil(score/Math.ceil((endTimeStamp - startTimeStamp)/(60*1000))); }// 下面创建字母的封装函数createLetter();console.log(letters);// 拿到所有字母所在的元素,看下面封装函数4,发现每个创建的元素的class类名都是 active// 防止通过 className 获取到的方式不兼容所有浏览器,下面进行兼容处理letterEles = document.getElementsByClassName('active'); // 通过改变 level 的数值改变游戏进行的快慢}, level * 1000)// 暂停之后的开始游戏gameStarts();}
}

兼容处理:如果用户浏览器不支持document.getElementsByclassName方法,默认使用下面这个我们封装的方法。

if(!document.getElementsByClassName) {document.getElementsByClassName = function(clsName) {// 获取所有标签元素var all = document.all;// 放数组容器,进行遍历筛选var all = [];for(var i = 0;i < all.length;i ++) {Array.push(all[i]);}return all;}
}

4.封装函数,创建下落字母。

.active{position: absolute;top: -30px;width: 30px;height: 30px;border-radius: 50%;text-align: center;line-height: 30px;color: #fff;font-weight: bolder;
}
function createLetter() {var span = document.createElement('span');// 赋予样式span.className = 'active'// 随机创建一个字母var l = randLetter();// 将字母插入到 span 里面span.innerHTML = l;// letters全局变量是存放所有随机产生的容器,需求g中有定义letters += l;// left数值 = 游戏界面的宽度 - 一个字母的宽度30span.style.left = Math.floor(Math.random() * (gameW - 30)) + 'px';// 使用下面封装的随机颜色函数span.style.background = randBg();// 创建完成之后追加到游戏界面中game.appendChild(span); // 字母运动startMove(span, gameH, "top");
}

5.封装函数,随机产生字母。

function randLetter() {var str = "abcdefghijklmnopqrstuvwxyz";// 将大写的字母也包含进去str += str.toUpperCase();return str.charAt(Math.floor(Math.random() * str.length));
}

6.封装函数,生成16进制随机颜色值。

function randBg() {var str = '0123456789abcdef';var colorVal = '#';for(var i = 0;i < 6;i ++) {colorVal += str.charAt(Math.floor(Math.random() * str.length));}return colorVal;
}

7.封装函数,清除掉所有字母所在元素的定时器。

function clearAllLetters() {for(var i = 0;i < letterEles.length;i ++) {clearInterval(letterEles[i].timer);}
}

8.封装函数,暂停之后点击开始按钮,继续开始游戏

function gameStarts() {// 因为在调用这个函数的时候由于定义的letterEles还没有赋值,是undefined,所以我们这边进行排除一下if(!letterEles) return;for(var i = 0;i < letterEles.length;i ++) {startMove(letterEles[i],gameH,"top");// 在游戏开始的时候调用}
}

9.封装函数,结束游戏。

function finished() {// 清除单位时间内产生字母的定时器clearInterval(c);c = undefined;// 当点击结束按钮的时候,将得分,速度,正确率都清零score = 0;s = 0;accu = "0%";// 清零完成后的重新加载数据tip.children[0].firstElementChild.innerHTML = score;tip.children[1].firstElementChild.innerHTML = accu;tip.children[2].firstElementChild.innerHTML = s;// 删除所有字母for(var i = letterEles.length - 1;i >= 0;i --) {// 从父元素开始查找game.removeChild(letterEles[i]);}// 此时游戏画面已经清空,但是按钮不知道停留在什么状态。下面进行一步判断,将按钮状态调整为待开始状态。if(oprate.firstElementChild.innerHTML == '暂停') {oprate.firstElementChild.innerHTML = '开始'}
}

需求e: 处理结束游戏
注意:该部分是位于需求2中的事件代理下的后续if操作。

// 处理结束游戏
if(target.className == 'finish') {finished();
}// 处理退出游戏
if(target.className == 'exit') {// 首先处理结束游戏finished();// 显示游戏开始的界面,隐藏进入游戏的界面game.style.display = 'none';gameStart.style.display = 'block';
}

需求f:设置游戏难度

<div id="select"><!-- 一开始是隐藏的 --><select name="" id=""><option value="3">慢</option><option value="2">中</option><option value="1">快</option></select><!-- 关闭按钮 --><span id="close">关闭</span>
</div>

var selFir = select.firstElementChild;
// 默认游戏难度是慢的
var level = 3;

需求g:实现键盘打字,字母消失。

// 声明一个全局变量容器,用来存放 createLetter 函数所创建出来的字母
var letters = ''

需求h:键盘事件,敲击键盘,实现dom节点的消失

// 如果使用`onkeypress`的话,会区分大小写,这里我们不需要去区分
document.onkeyup = function(evt) {// 兼容处理var e = evt || window.event;var codeVal = e.keyCode;console.log(codeVal);// 统计用户一共按了多少次规定范围下的按键,用于后面统计正确率if(codeVal >= 65 && codeVal < 90) {count ++;}// 根据键值找到对应的字符var char = keyVal[codeVal];if(char) {var index = letters.search(eval('/' + char + "/gi"));// index != -1; 说明找到了if(index != -1) {// 将对应元素的 dom 节点干掉game.removeChild(letterEles[index]);// 全局匹配 + 忽略大小写var exp = eval('/' + char + '/gi');// 将 exp 匹配成 ''letters = letters.replace(exp, '');// 成功消灭了一个 dom 元素,得一分tip.firstElementChild.firstElementChild.innerHTML = ++ score;endTimeStamp = new Date() * 1;if(endTimeStamp - startTimeStamp <= 60 * 1000) {tip.children[2].firstElementChild.innerHTML = score;}else {tip.children[2].firstElementChild.innerHTML = Math.ceil(score/Math.ceil((endTimeStamp - startTimeStamp)/(60*1000))); }}// 实现正确率,toFixed(2)保留两位小数位// 将数值插入到 tip 下的第二个子元素的第一个元素内容部分tip.children[1].firstElementChild.innerHTML = (score / count * 100).toFixed(2) + '%'}// console.log(char)
}

需求i:找到键值

// 新建一个 js 文件,命名为 keyValue.js
var keyVal = {};
var str = 'abcdefghijklmnopqrstuvwxyz';
// a键的键值是65,往后加26个字母
for(var i = 65;i < 90;i ++) {// 将对应字符以及其键值相对应。keyVal[i] = str.charAt(i - 65);
}
console.log(keyVal)

需求j:实现得分、正确率、速度。以下是定义全局变量,具体实现步骤在以上需求内。

// count 键盘一共按下多少次
var score = 0,accu = '0%',s = 0,count = 0;
// 定义开始时间和结束时间
var startTimeStamp = null,endTimeStamp = null;

总体实现思路总结:

  • 进入游戏界面之后的开始游戏
    点击开始游戏,实现字母的掉落
    游戏暂停之后,能够实现游戏的暂停
  • 实现游戏的暂停
    清除定时器:清除单位时间内掉落多少个字母的定时器
    清除字母掉落速度的定时器 —> 每个字母元素上都存在一个定时器
    退出游戏 --> 结束游戏以及显示游戏开始界面,隐藏进入游戏的界面
    结束游戏 --> 清除掉1的定时器和2的所有字母所在的元素
  • 实现游戏难度的设置
    游戏的默认难度是慢
    游戏在进行的过程中,是不允许设置游戏难度的
    在游戏暂停和开始之前,是允许设置游戏难度的
    游戏难度设置之后,是在关闭游戏难度设置之后生效的
  • 实现键盘打字,字母消失
    全局变量: 把当前游戏界面内出现的所有的字符放在该变量里
    根据键盘输入的字符,在全局变量字符串里,找到该字符的位置
    删除该字符所在的元素
  • 实现得分、正确率、速度
    得分: 输入与界面内出现的字符相同的时候,字母消失,得一份,累加
    正确率:游戏界面内出现的字符和按下的字母键不相符的时候,属于错误
    速度:一分钟之内输入正确的字符,不是一分钟的时候,按下的所有正确的字符的个数
  • 最后细节优化
    随着打字分数越来越高,让字母掉落的速度越来越快
    点击结束或者退出的时候,把正确率、得分、速度清零

以上便是全部的讲解
源码我放在了github上,欢迎下载!!!

原生JavaScript实现打字游戏相关推荐

  1. 原生JavaScript实现连连看游戏

    向大家推荐一款原生JavaScript版连连看游戏,源码可在http://download.csdn.net/detail/zhangjinpeng66/6276583中下载,首页如下图所示: 首先看 ...

  2. 原生JavaScript实现弹球游戏

    原生JavaScript实现弹球游戏.游戏源码请到http://download.csdn.net/detail/zhangjinpeng66/6276567下载.点击图中央的三角图形开始. 开始后的 ...

  3. 原生js实现打字游戏

    本文实例为大家分享了js实现打字游戏的具体代码,供大家参考,具体内容如下 1.HTML代码如下 <!DOCTYPE html> <html lang="en"&g ...

  4. html简单打字游戏,javascript实现简单打字游戏

    本文实例为大家分享了javascript打字游戏的具体代码,供大家参考,具体内容如下 传智打字游戏 .label{ position:absolute;left: 0px; } var CODE = ...

  5. JavaScript实现简单的打字游戏

    完整项目下载:https://download.csdn.net/download/weixin_44893902/13131694 演示地址:https://url_777.gitee.io/typ ...

  6. 原生JavaScript抒写——贪吃蛇小游戏

    原生JavaScript抒写--贪吃蛇小游戏 文章目录 原生JavaScript抒写--贪吃蛇小游戏 前言 一.需求分析 二.效果展示 三.具体逻辑代码分析 1.首先创建一个html文件,然后我们利用 ...

  7. javascript打字游戏

    为什么80%的码农都做不了架构师?>>>    学一门语言光看书是不够的,最好是边练边学,所以这次我就用javascript写了这个简单的打字游戏,虽然说起来简单,但是对于第一次写游 ...

  8. php拼图游戏开发,原生javascript制作的拼图游戏实现方法详解

    本文实例讲述了原生javascript制作的拼图游戏实现方法.分享给大家供大家参考,具体如下: 实现方法 //1.让所有的li(在ul里)可以拖拽 //2.交换li的位置  计算背景图位置 //1.让 ...

  9. 纯javascript仿金山苹果打字游戏

    周末2天在家无聊,女朋友要练打字,一直都是在用金山的苹果打字,哈哈,干脆就自己用JS写一个苹果打字游戏,内容比较简单,本人不会美工,页面没有美化,贴出来跟大家一起学习. 本打字游戏共分10关,第一关: ...

最新文章

  1. 平方的观测值表概率_中央气象台:“三九”大概率不会比“二九”更冷
  2. 也谈谈:《设计师如何掌握主动权》读后感
  3. jmeter脚本_性能工具之Jmeter脚本python启动
  4. [深度学习] 自然语言处理---Transformer原理(一)
  5. Windows Azure SDK 1.6让Visual Studio下的Azure开发更高效
  6. python条形堆积图_python – 使用DataFrame.plot显示堆积条形图中...
  7. 文本强制不换行并隐藏
  8. /* compiled code */ ?
  9. java md5加密解密_java MD5加密解密 | 学步园
  10. 11.* 指针 引用
  11. 【Day34】Pyhotn之路——网络编程
  12. uBLAS——Boost 线性代数基础程序库 (三)
  13. Spark修炼之道(基础篇)——Linux大数据开发基础:第二节:Linux文件系统、文件夹(一)...
  14. 《正则表达式经典实例(第2版)》——2.18 向正则表达式中添加注释
  15. 微软提出Layout,多模态任务也有预训练模型啦
  16. brew更新的时候不更新某个应用_可以不可以第六集剧情介绍,日剧可以不可以什么时候更新...
  17. activitymq 登录界面地址
  18. RANSAC算法与原理(一)
  19. 【java】java Jvm内存结构
  20. OpenCv4在Win10 VS2019上环境搭建

热门文章

  1. 遗忘的国度-梦幻西游(男人的中庸之道)
  2. python怎样导入游戏库_Python库如何安装和导入
  3. 冯诺依曼计算机的运行原理
  4. 同济大学数理强化计算机,同济大学考研之学科设置介绍
  5. day 44 练习题讲解 多表查询
  6. PTA-c语言 新胖子公式
  7. Linux ARP 代理专题
  8. 一位软科大一的周结(week 1)
  9. 常见分辨率和码率对应关系
  10. 首先,打破一切常规读书笔记