直入正题,用JS实现一个简单的打地鼠游戏

因为功能比较简单就直接裸奔JS了,先看看效果图,或者 在线玩玩 吧

如果点击颜色比较深的那个(俗称坏老鼠),将扣分50;如果点击颜色比较浅的那个(俗称好老鼠),将得分100

实现

老鼠好像有点难画,又不想用图片,就直接用CSS画个简单的图代表老鼠和坑吧

html结构

挺简单,用9个 li 标签代表坑,用9个 div 标签代表老鼠

  1.   <div class="container">
  2. <h4>无聊打打地鼠</h4>
  3.  
  4. <div class="game-top">
  5. <p><input type="button" value="开始游戏" id="game-start"><p>
  6. <p>得分:<span id="game-score">0</span></p>
  7. <p>剩余时间:<span id="game-time">60</span> s</p>
  8. </div>
  9. <div class="game-content">
  10. <ul>
  11. <li><div></div></li>
  12. <li><div></div></li>
  13. <li><div></div></li>
  14. <li><div></div></li>
  15. <li><div></div></li>
  16. <li><div></div></li>
  17. <li><div></div></li>
  18. <li><div></div></li>
  19. <li><div></div></li>
  20. </ul>
  21. </div>
  22. </div>

CSS的实现

有点小技巧

对于坑,加个box-shadow: ... inset 美化一下样式

  1. .game-content li {
  2. float: left;
  3. margin-top: 50px;
  4. margin-left: 30px;
  5. width: 100px;
  6. height: 50px;
  7. border-radius: 50%;
  8. background-color: #67d0b4;
  9. box-shadow: 0 0 50px #706565 inset;
  10. }

对于老鼠,用 border-radius:50%/40% 绘制,第二个参数还是有点使用价值的

  1. .game-content div {
  2. position: relative;
  3. margin-top: -15px;
  4. margin-left: 25px;
  5. width: 50px;
  6. height: 70px;
  7. border-radius: 50%/40%;
  8. background-color: #dfb25d;
  9. opacity:;
  10. }

而要让老鼠动起来,这里的处理方式就是用动画了,老鼠运动的时候,先往上再往下即可,控制好相对位置看起来和谐一点就行

  1. @keyframes mouse-move {
  2. 50% {
  3. margin-top: -40px;
  4. opacity:;
  5. }
  6. 100% {
  7. margin-top: -15px;
  8. opacity:;
  9. }
  10. }
  11. .game-content div.active {
  12. animation: mouse-move 2s ease-in-out infinite;
  13. }

注意 animation: ... infinite 的使用,让动画能一直进行下去,我们使用JS控制好时间差判断应该显示那个老鼠,应该显示多少只老鼠即可

不然的画,会发现动画完成了再也无法让它继续进行了

点击的是好老鼠还是坏老鼠,应该给出提示如:

  

可以直接用CSS的伪元素::after置入对错,在点击的时候,根据不同的性质设置不同的值及颜色

  1. .game-content div.good {
  2. background-color: #dfb25d;
  3. }
  4. .game-content div.good[clicked="1"]::after {
  5. content: "✓";
  6. line-height: 70px;
  7. font-size: 40px;
  8. color: #0ad845;
  9. }
  10.  
  11. .game-content div.bad {
  12. background-color: #a48f5c;
  13. }
  14. .game-content div.bad[clicked="1"]::after {
  15. content: "✕";
  16. line-height: 70px;
  17. font-size: 40px;
  18. color: #db1536;
  19. }
  1. .container {
  2. width: 500px;
  3. height: 300px;
  4. margin: 50px auto;
  5. border: 1px solid #ddd;
  6. text-align: center;
  7. }
  8.  
  9. .game-top {
  10. padding-top: 10px;
  11. width: 100%;
  12. height: 90px;
  13. }
  14. .game-top p {
  15. margin: 5px;
  16. }
  17.  
  18. .game-content {
  19. overflow: auto;
  20. width: 100%;
  21. border-top: 1px solid #ddd;
  22. background-color: #ddf;
  23. }
  24.  
  25. .game-content ul {
  26. list-style: none;
  27. }
  28. .game-content li {
  29. float: left;
  30. margin-top: 50px;
  31. margin-left: 30px;
  32. width: 100px;
  33. height: 50px;
  34. border-radius: 50%;
  35. background-color: #67d0b4;
  36. box-shadow: 0 0 50px #706565 inset;
  37. }
  38. .game-content li:last-child {
  39. margin-bottom: 50px;
  40. }
  41.  
  42. .game-content div {
  43. position: relative;
  44. margin-top: -15px;
  45. margin-left: 25px;
  46. width: 50px;
  47. height: 70px;
  48. border-radius: 50%/40%;
  49. background-color: #dfb25d;
  50. opacity:;
  51. }
  52.  
  53. .game-content div.good {
  54. background-color: #dfb25d;
  55. }
  56. .game-content div.good[clicked="1"]::after {
  57. content: "✓";
  58. line-height: 70px;
  59. font-size: 40px;
  60. color: #0ad845;
  61. }
  62.  
  63. .game-content div.bad {
  64. background-color: #a48f5c;
  65. }
  66. .game-content div.bad[clicked="1"]::after {
  67. content: "✕";
  68. line-height: 70px;
  69. font-size: 40px;
  70. color: #db1536;
  71. }
  72.  
  73. @media screen and (max-width: 500px) {
  74. .container {
  75. width: 290px;
  76. }
  77. .game-content ul {
  78. padding:;
  79. }
  80. .game-content li {
  81. margin-left: 5px;
  82. width: 90px;
  83. }
  84. .game-content div {
  85. margin-left: 20px;
  86. }
  87. }
  88.  
  89. @-webkit-keyframes mouse-move {
  90. 50% {
  91. margin-top: -40px;
  92. opacity:;
  93. }
  94. 100% {
  95. margin-top: -15px;
  96. opacity:;
  97. }
  98. }
  99. @keyframes mouse-move {
  100. 50% {
  101. margin-top: -40px;
  102. opacity:;
  103. }
  104. 100% {
  105. margin-top: -15px;
  106. opacity:;
  107. }
  108. }
  109.  
  110. .game-content div.active {
  111. -webkit-animation: mouse-move 2s ease-in-out infinite;
  112. animation: mouse-move 2s ease-in-out infinite;
  113. }

完整CSS

JS的处理

逻辑是点击开始游戏,倒计时开始,同时好坏老鼠不断运动,控制好坑中好坏老鼠及其数量的随机性,点击好老鼠加分,点击坏老鼠减分,时间到结束游戏。

先看看老鼠的运动

  1.   // 运动操作
  2. moveUpAndDown: function() {
  3. var that = this;
  4.  
  5. // 定时器随机定义good|bad老鼠个数,以及需要显示的个数
  6. that.moveTime = setInterval(function() {
  7.  
  8. for (var i = 0, j = that.mouses.length; i < j; ++i) {
  9. that.mouses[i].setAttribute('clicked', '0');
  10. that.mouses[i].className = 'good active';
  11. that.mouses[i].style.display = 'none';
  12. }
  13.  
  14. // bad 的个数
  15. var badNum = that.getRandom(0, 8);
  16. for (var i = 0; i < badNum; i++) {
  17. that.mouses[that.getRandom(0, 8)].className = 'bad active';
  18. }
  19.  
  20. // 要显示的个数
  21. var showNum = that.getRandom(0, 8);
  22. for (var i = 0; i < showNum; i++) {
  23. that.mouses[that.getRandom(0, 8)].style.display = 'block';
  24. }
  25. }, 2000);
  26. },

使用定时器,定时器的循环与CSS中的动画设置一致,保证循环连贯性

设置class为good 即可定义出一只好老鼠,同理bad 为坏老鼠

在开始游戏,进行调用时,设置class为active 即可让老鼠运动起来

对于打老鼠的操作,要注意到只有运动的老鼠才能点击,每只老鼠只能点击一次

  1.   // 打地鼠操作
  2. that.mousesWrap[0].addEventListener('click', function(e) {
  3. e = e || window.event;
  4. var elem = e.target || e.srcElement;
  5. // 如果当前项被隐藏则不操作,多次点击只取第一次分数
  6. if (elem.style.display !== 'block' || elem.getAttribute('clicked') === '1') {
  7. return;
  8. }
  9. // 扣分
  10. if (elem.className.indexOf('bad') !== -1) {
  11. that.score -= that.badScore;
  12. }
  13. // 加分
  14. else {
  15. that.score += that.goodScore;
  16. }
  17.  
  18. elem.setAttribute('clicked', '1');
  19. that.text(that.gameScore[0], that.score);
  20. }, false);

倒计时结束之后,清除两个计时器,同时将所有老鼠项display都设为none 即可(否则动画会一直循环展示出来)

  1. // 倒计时,当前剩余游戏时间
  2. countDown: function() {
  3. var that = this;
  4.  
  5. var t = setInterval(function() {
  6. that.text(that.gameTime[0], --that.totalTime);
  7.  
  8. if (that.totalTime === 0) {
  9. clearInterval(t);
  10. clearInterval(that.moveTime);
  11.  
  12. for (var i = 0, j = that.mouses.length; i < j; ++i) {
  13. that.mouses[i].style.display = 'none';
  14. }
  15.  
  16. alert('游戏结束,得分为:' + that.score);
  17. }
  18. }, 1000);
  19. },
  1. function MouseGame() {
  2. this.mousesWrap = this.$('.game-content');
  3. this.mouses = this.$('.game-content div');
  4. this.gameStart = this.$('#game-start');
  5. this.gameTime = this.$('#game-time');
  6. this.gameScore = this.$('#game-score');
  7. this.goodScore = 100;
  8. this.badScore = 50;
  9.  
  10. this.bindEvent();
  11. }
  12.  
  13. MouseGame.prototype = {
  14. constructor: MouseGame,
  15.  
  16. /**
  17. * 获取元素
  18. * @param {String} elem 元素的字符串标识
  19. * @example
  20. * $('div') | $('p.active')
  21. * @return {NodeList} 获取的元素集
  22. */
  23. $: function(elem) {
  24. return document.querySelectorAll(elem);
  25. },
  26.  
  27. /**
  28. * 获取给定范围的随机数
  29. * @param {Number} from 起始
  30. * @param {Number} to 结束
  31. * @return {Number} 随机数
  32. */
  33. getRandom: function(from, to) {
  34. return Math.floor(Math.random() * (to - from + 1)) + from;
  35. },
  36.  
  37. /**
  38. * 设置元素内容
  39. * @param {HTMLElement} elem 要设置的元素
  40. * @param {String} val 设置的内容
  41. * @return {String} 设置好的内容|元素本身的内容
  42. */
  43. text: function(elem, val) {
  44. if (elem.textContent) {
  45. return val !== undefined ? elem.textContent = val : elem.textContent;
  46. } else if (elem.innerText) {
  47. return val !== undefined ? elem.innerText = val : elem.innerText;
  48. }
  49. },
  50.  
  51. // 运动操作
  52. moveUpAndDown: function() {
  53. var that = this;
  54.  
  55. // 定时器随机定义good|bad老鼠个数,以及需要显示的个数
  56. that.moveTime = setInterval(function() {
  57.  
  58. for (var i = 0, j = that.mouses.length; i < j; ++i) {
  59. that.mouses[i].setAttribute('clicked', '0');
  60. that.mouses[i].className = 'good active';
  61. that.mouses[i].style.display = 'none';
  62. }
  63.  
  64. // bad 的个数
  65. var badNum = that.getRandom(0, 8);
  66. for (var i = 0; i < badNum; i++) {
  67. that.mouses[that.getRandom(0, 8)].className = 'bad active';
  68. }
  69.  
  70. // 要显示的个数
  71. var showNum = that.getRandom(0, 8);
  72. for (var i = 0; i < showNum; i++) {
  73. that.mouses[that.getRandom(0, 8)].style.display = 'block';
  74. }
  75. }, 2000);
  76. },
  77.  
  78. // 打地鼠操作
  79. bindEvent: function() {
  80. var that = this;
  81.  
  82. // 监听游戏开始/重新开始
  83. that.gameStart[0].addEventListener('click', function() {
  84. that.startGame();
  85. }, false);
  86.  
  87. // 打地鼠操作
  88. that.mousesWrap[0].addEventListener('click', function(e) {
  89. e = e || window.event;
  90. var elem = e.target || e.srcElement;
  91. // 如果当前项被隐藏则不操作,多次点击只取第一次分数
  92. if (elem.style.display !== 'block' || elem.getAttribute('clicked') === '1') {
  93. return;
  94. }
  95. // 扣分
  96. if (elem.className.indexOf('bad') !== -1) {
  97. that.score -= that.badScore;
  98. }
  99. // 加分
  100. else {
  101. that.score += that.goodScore;
  102. }
  103.  
  104. elem.setAttribute('clicked', '1');
  105. that.text(that.gameScore[0], that.score);
  106. }, false);
  107. },
  108.  
  109. // 倒计时,当前剩余游戏时间
  110. countDown: function() {
  111. var that = this;
  112.  
  113. var t = setInterval(function() {
  114. that.text(that.gameTime[0], --that.totalTime);
  115.  
  116. if (that.totalTime === 0) {
  117. clearInterval(t);
  118. clearInterval(that.moveTime);
  119.  
  120. for (var i = 0, j = that.mouses.length; i < j; ++i) {
  121. that.mouses[i].style.display = 'none';
  122. }
  123.  
  124. alert('游戏结束,得分为:' + that.score);
  125. }
  126. }, 1000);
  127. },
  128.  
  129. // 开始游戏
  130. startGame: function() {
  131. this.score = 0;
  132. this.totalTime = 60;
  133. this.text(this.gameTime[0], this.totalTime);
  134. this.text(this.gameScore[0], this.score);
  135.  
  136. this.countDown();
  137. this.moveUpAndDown();
  138. }
  139. };
  140.  
  141. new MouseGame();

完整JS

代码有注释应该不难看懂了

那么..快来fork吧..

无聊的人用JS实现了一个简单的打地鼠游戏的更多相关文章

  1. Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏

    Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏 即使是如今,非常多初学游戏开发的同学.在谈到Unity的时候.依旧会觉得Unity仅仅能用于制作3D游戏的. 实际上.Unity在2013 ...

  2. 通过创建一个简单的骰子游戏来探究 Python

    在我的这系列的第一篇文章 中, 我已经讲解如何使用 Python 创建一个简单的.基于文本的骰子游戏.这次,我将展示如何使用 Python 模块 Pygame 来创建一个图形化游戏.它将需要几篇文章才 ...

  3. 用canvas和原生js写的一个笨鸟先飞的小游戏(暂时只有一个关卡)

    其中一个画布背景是一张图片,还有小鸟,两个管子的图片.暂时不知道怎么附上去就不添加了.这里只有源代码,css和js都是在html写着的,感觉比他们的容易吧,hah <!DOCTYPE html& ...

  4. 利用前端三大件(html+css+js)开发一个简单的“todolist”项目

    一.介绍 todolist,即待办事项.在windows android ios上参考微软家出的那个To-Do应用,大概就是那样的.我这个更简单,功能只有“待办” “已完成”两项,并且是在浏览器打开的 ...

  5. react.js+easyui 做一个简单的商品表

    效果图:     import React from 'react'; import { Form, FormField, Layout,DataList,LayoutPanel,Panel, Lab ...

  6. js写的一个简单的手风琴菜单

    1 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&q ...

  7. 原生js写的一个简单slider

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 用JS写的一个简单的时钟

    没什么技术含量,单纯的想传上去.手痒了 <!DOCTYPE html> <html> <head> <meta charset="utf-8&quo ...

  9. Cocos2dx系列笔记7:一个简单的跑酷游戏《萝莉快跑》的消化(附下载)

    懒骨头(http://blog.csdn.com/iamlazybone) 或许有天 我们羡慕和崇拜的人 因为我们的努力 也会来了解我们 说不定 还会成为好友 骨头喜欢这样与哲哲共勉 多少个夜晚 一张 ...

随机推荐

  1. Opencv算法学习二

    1.直方图:图片中像素值分布情况的坐标图. 直方图均衡化:按一定规律拉伸像素值,提高像素值少的点,增加原图的对比度,使人感觉更清晰的函数. equalizeHist( src, dst ); 2.ha ...

  2. Eclipse自动补全设置

    如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的自动补全没有VS那么好是因为ecl ...

  3. 基于Redis的开源分布式服务Codis

    Redis在豌豆荚的使用历程--单实例==>多实例,业务代码中做sharding==>单个Twemproxy==>多个Twemproxy==>Codis,豌豆荚自己开发的分布式 ...

  4. 解读2015年互联网UGC内容发展态势,安全事件频发

    <2015内容安全年报> 阿里移动安全 第一章 2015年内容安全形势 随着互联网业务的迅速发展,互联网上的信息内容带来了爆炸式的增长.由于缺乏对网络活动进行有效监督和管理的措施,致使互联 ...

  5. 将asp.net core站点发布到IIS上遇到的问题

    今天第一次将整个 asp.net core 站点发布到 IIS 上,以前都是发布到 Linux 服务器上. 开始使用 dotnet publish -c release 命令发布,用浏览器访问站点时出 ...

  6. AnguarJS 第一天----Hello World

    AngularJS是什么? AngularJS是目前很火的前端JS框架之一, AngularJS的开发团队将其描述为一种构建动态Web应用的结构化框架.它是完全使用JavaScript编写的客户端技术 ...

  7. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  8. 【Java并发编程实战】-----“J.U.C”:ReentrantLock之二lock方法分析

    前一篇博客简单介绍了ReentrantLock的定义和与synchronized的区别,下面跟随LZ的笔记来扒扒ReentrantLock的lock方法.我们知道ReentrantLock有公平锁.非 ...

  9. 《Entity Framework 6 Recipes》中文翻译系列 (42) ------ 第八章 POCO之使用POCO

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 第八章 POCO 对象不应该知道如何保存它们,加载它们或者过滤它们.这是软件开发中熟 ...

  10. 在微软伪静态处理机制下action导致伪静态的地址重现的问题

    伪静态前的地址:/sc/ProductList.aspx?pClass=0&descType=2&minPrice=1&maxPrice=11 伪静态后的地址:/product ...