javascript开发实现贪吃蛇游戏


Posted in Javascript onJuly 31, 2020

贪吃蛇的例子:

在此例子中,利用snake数组的第0个元素和direction对象中的x值和y值做加法,算出蛇的下一个位置。利用间隔函数,不停的修改类名来进行渲染操作,感觉是一个很灵活的例子。

style.css

*{
 margin: 0;
 padding: 0;
 box-sizing: border-box;
}

.page{
 width: 100vw;
 height: 100vh;
 position: absolute;
 left: 0;
 top: 0;
}
body{
 font-size: 0.16rem;
}
.startGame{
 /* display: none; */
 background: purple;
 display: flex; 
 justify-content: center;
 align-items: center;
}

.startBtn,.reStartBtn{
 width:2rem;
 height: 0.5rem;
 text-align: center;
 line-height: 0.5rem;
 background: deepskyblue;
 color: #fff;
}

.endGame{
 display: none;
 /* display:flex; */
 flex-direction: column;
 justify-content: center;
 align-items: center;
 background: lightsalmon;
}
.endGame h1{
 margin: 1rem 0;
 color: #fff;
}

.gaming{
 display: none;
 background: black;
 color: #fff;
 
}
.gaming .score{
 display: flex;
 justify-content: space-between;
 height: 0.5rem;
 align-items: center;
 width: 100vw;
 padding: 0 0.25rem;
}

.gaming .score .pauseBtn{
 
 width: 0.8rem;
 height: 0.3rem;
 line-height: 0.3rem;
 background: #999;
 text-align: center;
 
}

.gaming .mainGame{
 
 /* 15*20 */
 width: 3.45rem;
 height:4.6rem ;
 background: #555;
 margin: 0.3rem auto;
 display: flex;
 flex-wrap: wrap;
 border-top: 1px solid #ccc;
 border-left: 1px solid #ccc;
 box-sizing: content-box;
}
.gaming .mainGame .gezi{
 width: 0.23rem;
 height: 0.23rem;
 border-right: 1px solid #ccc;
 border-bottom: 1px solid #ccc;
}
.gaming .mainGame .gezi.snake{
 width: 0.23rem;
 height: 0.23rem;
 border-right: 1px solid #ccc;
 border-bottom: 1px solid #ccc;
 background-color: #fff;
}
.gaming .mainGame .gezi.food{
 width: 0.23rem;
 height: 0.23rem;
 border-right: 1px solid #ccc;
 border-bottom: 1px solid #ccc;
 /* background-color: orangered; */
}

.gaming .mainGame .gezi.food:before{
 width: 100%;
 height: 100%;
 content: "";
 display: block;
 background:yellow;
 animation: food 1s alternate infinite ;
 box-shadow: 0 0 10px #ffffcc;
}
.gaming .mainGame .gezi.food[data-food=redStar]:before{
 background:deeppink;
}
@keyframes food{
 from{
 transform: scale(1) rotate(0deg);
 }
 to{
 transform: scale(0.5) rotate(360deg);
 }
}


.gaming .mainGame .gezi.snake:before{
 content:"" ;
 display: block;
 
 width: 100%;
 height: 100%;
 background: #ccc;
 animation: snake 0.4s;
 box-sizing: border-box;
}
@keyframes snake{
 from{
 background: #fff;
 box-shadow:0 0 15px rgba(255,255,255,1);
 }
 to{
 background: #ccc;
 box-shadow:0 0 15px rgba(255,255,255,0.5);
 }
}

index.js主要实现了所有的贪吃蛇的页面的各种操作

var startBtn = document.querySelector(".startBtn")
var startPage = document.querySelector(".page.startGame")
var gamingPage = document.querySelector(".gaming")
var endGamePage = document.querySelector(".endGame")
var mainGame = document.querySelector(".mainGame")
var numDom = document.querySelector(".score .left .num")
var endGameScore = document.querySelector(".endGame .num")
var reStartBtn = document.querySelector('.reStartBtn');
var pauseBtn=document.querySelector(".pauseBtn");

var snake = [{x:0,y:1},{x:1,y:1},{x:2,y:1}];
var snakeFood = {
 x:10,y:10
}
//初始化得分
var score = 0;
var interId;
var ispaused=false;
//定义蛇运动的方向
//从右向左{x:-1,y:0}
//从左向右{x:1,y:0}
//从上到下{x:0,y:1}
//从下到上{x:0,y:-1}
var direction = {x:-1,y:0}


startBtn.onclick = function(){
 startPage.style.display = "none"
 gamingPage.style.display = "block"
 gameIng()
}


function renderGezi(){
 for(var i=0;i<20;i++){
 for(var j=0;j<15;j++){
 var gezi = document.createElement("div");
 gezi.className = "gezi";
 gezi.id = 'x'+j+'y'+i;
 mainGame.appendChild(gezi)
 }
 }
}


renderGezi()
//随机创建蛇,
function createSnake(){
 var randomX = parseInt(Math.random()*13)
 var randomY = parseInt(Math.random()*20)
 snake = [];
 for(var i= 0;i<3;i++){
 snake.push({x:randomX+i,y:randomY})
 }
 
}


function renderSnake(){
 snake.forEach(function(item,i){
 var snakeBody = document.querySelector("#x"+item.x+"y"+item.y);
 snakeBody.className = "gezi snake";
 })
}

//渲染食物
function renderFood(){
 var randomX = parseInt(Math.random()*15)
 var randomY = parseInt(Math.random()*20)
 
 var foodDiv = document.querySelector("#x"+randomX+"y"+randomY)
 if(foodDiv.className == "gezi snake"){
 renderFood()
 }else{
 foodDiv.className = "gezi food"
 }
 
}


createSnake()

renderFood()
renderSnake()

function gameIng(){
 interId = setInterval(function(){
 var headerX = snake[0].x + direction.x;
 var headerY = snake[0].y + direction.y;
 if(headerX<0){
 headerX = 14;
 }
 if(headerX>14){
 headerX = 0;
 }
 if(headerY<0){
 headerY = 19;
 }
 if(headerY>19){
 headerY = 0;
 }
 
 var snakeHeader = {x:headerX,y:headerY};
 isSnake(snakeHeader) 
 if(!isFood(snakeHeader)) {
 //将删除的蛇,找到相对应的dom,将其class类名修改成正常的gezi
 var snakeFooter = snake.pop()//返回删除的对象
 var snakeFooterDiv = document.querySelector("#x"+snakeFooter.x+"y"+snakeFooter.y);
 snakeFooterDiv.className = "gezi";
 }
 snake.unshift(snakeHeader)//在数组最前面加入
 
 
 
 renderSnake()
 },100)
}


function isSnake(snakeHeader){
 var newHeader = document.querySelector("#x"+snakeHeader.x+"y"+snakeHeader.y)
 if(newHeader.className == "gezi snake"){
 clearInterval(interId);
 gamingPage.style.display = "none"
 endGamePage.style.display = "flex"
 endGameScore.innerHTML = score;
 
 return true;
 }else{
 return false;
 }
}


function isFood(snakeHeader){
 var newHeader = document.querySelector("#x"+snakeHeader.x+"y"+snakeHeader.y)
 if(newHeader.className == "gezi food"){
 score ++;
 numDom.innerHTML = score;
 renderFood()
 return true;
 }else{
 return false;
 }
}

var body = document.body

body.addEventListener("keydown",function(e){
 console.log(e)
 //方向不能直接颠倒向上时原来不能是向下的。
 if(e.key == "ArrowUp"&&direction.y!=1){
 direction = {x:0,y:-1}
 }
 if(e.key=="ArrowRight"&&direction.x!=-1){
 direction = {x:1,y:0}
 }
 if(e.key == "ArrowDown"&&direction.y!=-1){
 direction = {x:0,y:1}
 }
 if(e.key=="ArrowLeft"&&direction.x!=1){
 direction = {x:-1,y:0}
 }
})

ylEvent.init(body);
body.addEvent("swiperLeft",function(){
 if(direction.x!=1){
 direction = {x:-1,y:0}
 }
})

body.addEvent("swiperRight",function(){
 if(direction.x!=-1){
 direction = {x:1,y:0}
 }
})

body.addEvent("swiperTop",function(){
 if(direction.y!=1){
 direction = {x:0,y:-1}
 }
})

body.addEvent("swiperBottom",function(){
 if(direction.y!=-1){
 direction = {x:0,y:1}
 }
})

reStartBtn.onclick = function(){
 location.reload();
}
pauseBtn.onclick=function(){
 if(ispaused){
 ispaused=false;
 gameIng();
 }else{
 ispaused=true;
 clearInterval(interId);
 }
}

js辅助式响应.js

(function(){
function xys(){
 var userAgent=navigator.userAgent
 var html=document.querySelector("html");
 //userAgent.indexOf("iPhone")通过此方法可以获取iPhone在字符串中的索引值(开头位置)
 //没有找到返回-1
 html.className="";
 if((userAgent.indexOf("iPhone"))!=-1){
 html.classList.add("iphone");
 }else if((userAgent.indexOf("Android"))!=-1)
 {
 html.classList.add("android");
 }else if((userAgent.indexOf("iPad"))!=-1){
 html.classList.add("ipad");
 }else{
 html.classList.add("pc");
 }
 if(window.innerWidth<640){
 html.classList.add('lt640');
 html.classList.add('lt960');
 html.classList.add('lt1200');
 }else if(window.innerWidth<960){
 html.classList.add('lt960');
 html.classList.add('lt1200');
 html.classList.add('gt640');
 }else if(window.innerWidth<1200){
 html.classList.add('lt1200');
 html.classList.add('gt640');
 html.classList.add('gt960');
 }else{
 html.classList.add('gt640');
 html.classList.add('gt960');
 html.classList.add('gt1200');
 
 }
 
  var screenWidth = window.innerWidth;
 var danwei = screenWidth/3.75;//屏幕的宽度/设计稿占满全屏的宽度为多少rem
 var html = document.querySelector("html")
 html.style.fontSize = danwei + 'px';
 }
 xys();
 window.onresize=function(){
 xys();
 }

})()

swiperEvent.js

var ylEvent = {
 eventAll:{
 //"自定义的事件名称":['事件要触发执行的函数1','事件要触发执行的函数2','事件要触发执行的函数3']
 
 },
 init:function(dom){
 dom.eventAll = {},
 dom.addEvent = this.addEvent;
 dom.emit = this.emit;
 dom.removeEvent = this.removeEvent
 dom.touchData = {};
 
 
 //body.emit('swiperLeft',"msg")
 
 dom.addEventListener("touchstart",function(e){
 //console.log(e)
 this.touchData.startX = e.touches[0].pageX;
 this.touchData.startY = e.touches[0].pageY
 })
 dom.addEventListener('touchmove',function(e){
 this.touchData.endX = e.touches[0].pageX;
 this.touchData.endY = e.touches[0].pageY;
 })
 dom.addEventListener("touchend",function(e){
 //console.log(e)
 var x = this.touchData.endX - this.touchData.startX;
 var y = this.touchData.endY - this.touchData.startY
 if( (Math.abs(x) > Math.abs(y)) && Math.abs(x)>100){
 if(x>0){
 //console.log('向右滑动')
 e.swiperDir = 'swiperRight'
 body.emit('swiperRight',e)
 }else{
 //console.log('向左滑动')
 e.swiperDir = 'swiperLeft'
 body.emit('swiperLeft',e)
 }
 }else if((Math.abs(x) < Math.abs(y)) && Math.abs(y)>100){
 if(y>0){
 //console.log('向下滑动')
 e.swiperDir = 'swiperBottom'
 body.emit('swiperBottom',e)
 }else{
 //console.log('向上滑动')
 e.swiperDir = 'swiperTop'
 body.emit('swiperTop',e)
 }
 }
 })
 },
 addEvent:function(eventName,callBackFn){
 
 if(this.eventAll[eventName]==undefined){
 this.eventAll[eventName] = []
 }
 this.eventAll[eventName].push(callBackFn)
 },
 emit:function(eventName,eventMsg){
 if(this.eventAll[eventName]!=undefined){
 this.eventAll[eventName].forEach(function(item,i){
 item(eventMsg)
 })
 }
 
 },
 removeEvent:function(eventName,callBackFn){
 var that = this
 this.eventAll[eventName].forEach(function(item,i){
 if(item==callBackFn){
 that.eventAll[eventName].splice(i,1)
 }
 })
 },
 
 }

index.html

<!DOCTYPE html>
<html>
 <head>
 <meta charset="utf-8" />
 <title></title>
 <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
 <script src="js/js辅助式响应.js" type="text/javascript" charset="utf-8"></script>
 <link rel="stylesheet" type="text/css" href="css/style.css" />
 </head>
 <body>
 <!-- 
 1、贪吃蛇页面结构和样式
 2、能够绘制蛇
 3、能够绘制食物
 4、让蛇运动起来
 5、蛇能够吃食物
 6、蛇碰到自己就会失败
 -->
 
 <div class="page startGame">
 <div class="startBtn">开始游戏</div>
 </div>
 <div class="page gaming">
 <div class="score">
 <div class="left">
 score:<span class="num">0</span>
 </div>
 <div class="pauseBtn">
 暂停
 </div>
 </div>
 
 <div class="mainGame">
 
 </div>
 
 </div>
 <div class="page endGame">
 <h1>您最终获取分数是<span class="num">0</span>分</h1>
 <div class="reStartBtn">重新开始</div>
 </div>
 <script src="js/swiperEvent.js" type="text/javascript" charset="utf-8"></script>
 <script src="js/index.js" type="text/javascript" charset="utf-8"></script>
 </body>
</html>

结果:

javascript开发实现贪吃蛇游戏

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript动态添加表格数据行(ASP后台数据库保存例子)
May 08 Javascript
JS 实现完美include载入实现代码
Aug 05 Javascript
深入理解Javascript中的循环优化
Nov 09 Javascript
javascript中文本框中输入法切换的问题
Dec 10 Javascript
在JavaScript中call()与apply()区别
Jan 22 Javascript
jquery ztree异步搜索(搜叶子)实践
Feb 25 Javascript
简述Matlab中size()函数的用法
Mar 20 Javascript
web 前端常用组件之Layer弹出层组件
Sep 22 Javascript
js实时获取窗口大小变化的实例代码
Nov 18 Javascript
vue2.0实战之使用vue-cli搭建项目(2)
Mar 27 Javascript
Vue.js 2.5新特性介绍(推荐)
Oct 24 Javascript
JS实现小星星特效
Dec 24 Javascript
vue 解决无法对未定义的值,空值或基元值设置反应属性报错问题
Jul 31 #Javascript
vscode中Vue别名路径提示的实现
Jul 31 #Javascript
Vue记住滚动条和实现下拉加载的完美方法
Jul 31 #Javascript
vue中渲染对象中属性时显示未定义的解决
Jul 31 #Javascript
JS可断点续传文件上传实现代码解析
Jul 30 #Javascript
Vue单文件组件开发实现过程详解
Jul 30 #Javascript
vue实现从外部修改组件内部的变量的值
Jul 30 #Javascript
You might like
实现分十页分向前十页向后十页的处理
2006/10/09 PHP
PHP5各个版本的新功能和新特性总结
2014/03/16 PHP
PHP中的日期加减方法示例
2014/08/21 PHP
php将csv文件导入到mysql数据库的方法
2014/12/24 PHP
PHP+Ajax实现验证码的实时验证
2016/07/20 PHP
PHP7.1方括号数组符号多值复制及指定键值赋值用法分析
2016/09/26 PHP
yii2 resetful 授权验证详解
2017/05/18 PHP
PHP实现的登录页面信息提示功能示例
2017/07/24 PHP
php将从数据库中获得的数据转换成json格式并输出的方法
2018/08/21 PHP
PHP使用OB缓存实现静态化功能示例
2019/03/23 PHP
PHP使用PDO实现mysql防注入功能详解
2019/12/20 PHP
Thinkphp集成抖音SDK的实现方法
2020/04/28 PHP
Jquery显示和隐藏元素或设为只读(含Ligerui的控件禁用,实例说明介绍)
2013/07/09 Javascript
js实现按Ctrl+Enter发送效果
2014/09/18 Javascript
Javascript学习笔记之相等符号与严格相等符号
2014/11/23 Javascript
点击按钮出现60秒倒计时的简单js代码(推荐)
2016/06/07 Javascript
浅谈Javascript中的Label语句
2016/12/14 Javascript
jquery实现自定义图片裁剪功能【推荐】
2017/03/08 Javascript
webstorm添加vue.js支持的方法教程
2017/07/05 Javascript
React-Native 组件之 Modal的使用详解
2017/08/08 Javascript
基于js 本地存储(详解)
2017/08/16 Javascript
node.js文件上传重命名以及移动位置的示例代码
2018/01/19 Javascript
对vue里函数的调用顺序介绍
2018/03/17 Javascript
解决vue中post方式提交数据后台无法接收的问题
2018/08/11 Javascript
vue watch深度监听对象实现数据联动效果
2018/08/16 Javascript
详解JavaScript原生封装ajax请求和Jquery中的ajax请求
2019/02/14 jQuery
vue-cli webpack配置文件分析
2019/05/20 Javascript
微信小程序开发之map地图组件定位并手动修改位置偏差
2019/08/17 Javascript
Python Socketserver实现FTP文件上传下载代码实例
2020/03/27 Python
Python实现的北京积分落户数据分析示例
2020/03/27 Python
python分布式爬虫中消息队列知识点详解
2020/11/26 Python
Html5饼图绘制实现统计图的方法
2020/08/05 HTML / CSS
社区优秀志愿者先进事迹
2014/05/09 职场文书
企业管理标语
2014/06/10 职场文书
2016猴年春节慰问信
2015/11/30 职场文书
解决mysql:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO/YES)
2021/06/26 MySQL