html代码:
1 <div class="content"> 2 <div class="btn startBtn"> <!-- 开始按钮 --> 3 <button type="button"></button> 4 </div> 5 <div class="btn stopBtn"> <!-- 暂停按钮 --> 6 <button type="button"></button> 7 </div> 8 <div id="snakeWrap"></div> <!-- 主题内容 --> 9 </div>
css代码:
1 * { 2 margin: 0; 3 padding: 0; 4 } 5 body { 6 background-color: #565F65; 7 width: 100%; 8 height: 10vh; 9 overflow: hidden; 10 } 11 12 .content { 13 width: 500px; 14 height: 500px; 15 position: absolute; 16 top: 50%; 17 left: 50%; 18 margin-top: -250px; 19 margin-left: -250px; 20 background-color: #565F65; 21 border: 10px solid #E7E7E7; 22 box-shadow: inset 0px 0px 5px 2px #000; 23 } 24 .btn { 25 width: 100%; 26 height: 100%; 27 position: absolute; 28 top: 0; 29 left: 0; 30 background-color: rgba(0, 0, 0, .3); /*游戏未开始时和暂停时的遮罩*/ 31 z-index: 2; 32 } 33 .btn button { 34 background: none; 35 border: none; 36 background-size: 100% 100%; 37 cursor: pointer; 38 outline: none; 39 position: absolute; 40 left: 50%; 41 top: 50%; 42 } 43 .startBtn button{ 44 width: 170px; 45 height: 80px; 46 background-image: url(img/startbtn.png); 47 margin-top: -40px; 48 margin-left: -85px; 49 } 50 .stopBtn { 51 display: none; 52 } 53 .stopBtn button{ 54 width: 70px; 55 height: 70px; 56 background-image: url(img/stopbtn.png); 57 margin-top: -35px; 58 margin-left: -35px; 59 } 60 61 #snakeWrap { 62 width: 500px; 63 height: 500px; 64 position: relative; 65 } 66 .snakeHead { /*蛇头样式*/ 67 background-color: aqua; 68 border-radius: 50%; 69 } 70 .snakeBody { /*蛇身样式*/ 71 background-color: navajowhite; 72 border-radius: 50%; 73 } 74 .food { /*食物样式*/ 75 background-image: url(img/food.png); 76 background-size: cover; 77 }
javascript 代码:
1 var sw = 20, //一个方块的宽 2 sh = 20, //一个方块的高 3 tr = 25, //行数 4 td = 25; //列数 5 var snake = null, //蛇的实例 6 food = null, //食物的实例 7 game = null; //游戏的实例
8 function Square(x, y, classname) { 9 this.x = x * sw; //方块实际的位置 10 this.y = y * sh; //方块实际的位置 11 this.class = classname; 12 13 this.viewContent = document.createElement('div'); //方块对应的DOM元素 14 this.viewContent.className = this.class; 15 this.parent = document.getElementById('snakeWrap'); //方块的父级 16 } 17 18 Square.prototype.create = function() { //创建方块 DOM,并添加到页面里 19 this.viewContent.style.position = 'absolute'; 20 this.viewContent.style.width = sw + 'px'; 21 this.viewContent.style.height = sh + 'px'; 22 this.viewContent.style.left = this.x + 'px'; 23 this.viewContent.style.top = this.y + 'px'; 24 25 this.parent.appendChild(this.viewContent); 26 }; 27 28 Square.prototype.remove = function() { 29 this.parent.removeChild(this.viewContent); 30 } 31 32 //蛇 33 function Snake() { 34 this.head = null; //存一下蛇头的信息 35 this.tail = null; //存一下蛇尾的信息 36 this.pos = []; //存储蛇身上的每一个方块的位置,二维数组 37 38 this.directionNum = { //存储蛇走的方向,用一个对象来表示 39 left : { 40 x : -1, 41 y : 0, 42 rotate : 180 43 }, 44 right : { 45 x : 1, 46 y : 0, 47 rotate : 0 48 }, 49 up : { 50 x : 0, 51 y : -1, 52 rotate : -90 53 }, 54 down : { 55 x : 0, 56 y : 1, 57 rotate : 90 58 } 59 } 60 } 61 62 Snake.prototype.init = function() { 63 //创建蛇头 64 var snakeHead = new Square(2, 0, 'snakeHead'); 65 snakeHead.create(); 66 this.head = snakeHead; // 存储蛇头信息 67 this.pos.push([2, 0]); //把蛇头的位置存起来 68 69 //创建蛇身体 70 var snakeBody1 = new Square(1, 0, 'snakeBody'); 71 snakeBody1.create(); 72 this.pos.push([1, 0]); //把蛇身1的位置存起来 73 74 var snakeBody2 = new Square(0, 0, 'snakeBody'); 75 snakeBody2.create(); 76 this.tail = snakeBody2; //把蛇尾的信息存起来 77 this.pos.push([0, 0]); //把蛇身1的位置存起来 78 79 //让蛇头蛇身形成链表关系 80 snakeHead.last = null; 81 snakeHead.next = snakeBody1; 82 83 snakeBody1.last = snakeHead; 84 snakeBody1.next = snakeBody2; 85 86 snakeBody2.last = snakeBody1; 87 snakeBody2.next = null; 88 89 //给蛇添加一条属性,用来表示蛇走的方向 90 this.direction = this.directionNum.right; //默认让蛇往右走 91 92 } 93 94 //这个方法用来获取蛇头的下一个位置对应的元素, 要根据元素做不同的事情 95 Snake.prototype.getNextPos = function() { 96 var nextPos = [ //蛇头要走的下一个点的坐标 97 this.head.x/sw + this.direction.x, 98 this.head.y/sh + this.direction.y 99 ]; 100 101 //下一个点是自己,代表撞到了自己,游戏结束 102 var selfCollind = false; //是否撞到自己 103 this.pos.forEach(function(value) { 104 if(value[0] == nextPos[0] && value[1] == nextPos[1]) { 105 //如果数组中的两个数据都相等,就说明下一个点在蛇身上里面能找到,代表撞到自己了 106 selfCollind = true; 107 } 108 }); 109 if(selfCollind) { 110 console.log('撞到自己了!'); 111 112 this.strategies.die.call(this); 113 114 return; 115 } 116 117 //下一个点是墙,游戏结束 118 if(nextPos[0] < 0 || nextPos[1] < 0 || nextPos[0] > td - 1 || nextPos[1] > tr - 1) { 119 console.log('撞墙了!'); 120 121 this.strategies.die.call(this); 122 123 return; 124 } 125 //下一个点是食物,吃 126 if(food && food.pos[0] == nextPos[0] && food.pos[1] == nextPos[1]) { 127 //如果这个条件成立说明现在蛇头要走的下一个点是食物的那个点 128 console.log('撞到食物了了!'); 129 this.strategies.eat.call(this); 130 return; 131 } 132 //下一个点什么都不是,走 133 this.strategies.move.call(this); 134 }; 135 136 //处理碰撞后要做的事 137 Snake.prototype.strategies = { 138 move : function(format) { //这个参数用于决定要不要删除最后一个方块(蛇尾), 当传了这个参数后就表示要做的事情是吃 139 //创建新身体(在蛇头位置) 140 var newBody = new Square(this.head.x/sw, this.head.y/sh, 'snakeBody'); 141 //更新链表关系 142 newBody.next = this.head.next; 143 newBody.next.last = newBody; 144 newBody.last = null; 145 146 147 this.head.remove(); //旧舌头从原来的位置删除 148 newBody.create(); 149 150 //创建一个新蛇头(蛇头下一个要走到的点) 151 var newHead = new Square(this.head.x/sw + this.direction.x, this.head.y/sh + this.direction.y, 'snakeHead') 152 //更新链表关系 153 newHead.next = newBody; 154 newHead.last = null; 155 newBody.last = newHead; 156 newHead.viewContent.style.transform = 'rotate('+this.direction.rotate+'deg)'; 157 newHead.create(); 158 159 160 //蛇身上每一个方块的坐标也要更新 161 this.pos.splice(0,0, [this.head.x/sw + this.direction.x, this.head.y/sh + this.direction.y]); 162 this.head = newHead; //还要把this.head的信息更新一下 163 164 if(!format) { //如何format 的值为 false, 表示需要删除(除了吃之外的操作) 165 this.tail.remove(); 166 this.tail = this.tail.last; 167 168 this.pos.pop(); 169 } 170 171 }, 172 eat : function() { 173 this.strategies.move.call(this, true); 174 createFood(); 175 game.score ++; 176 }, 177 die : function() { 178 game.over(); 179 } 180 } 181 182 snake = new Snake(); 183 184 //创建食物 185 function createFood() { 186 //食物小方块的随机坐标 187 var x = null; 188 var y = null; 189 190 var include = true; //循环跳出的条件, true表示食物的坐标在蛇身上(需要继续循环),false表示食物坐标不在蛇身上(不循环了) 191 while(include) { 192 x = Math.round(Math.random() * (td - 1)); //0-29 193 y = Math.round(Math.random() * (tr - 1)); 194 195 snake.pos.forEach(function(value) { 196 if(x != value[0] && y != value[1]) { 197 //这个条件成立说明现在随机出来的这个坐标,在蛇身上并没有找到 198 include = false; 199 } 200 }); 201 202 } 203 //生成食物 204 food = new Square(x, y, 'food'); 205 food.pos = [x,y]; //存储一下生成食物的坐标,用于跟蛇头要走的下一个点作对比 206 var foodDom = document.querySelector('.food'); 207 if(foodDom) { 208 foodDom.style.left = x*sw + 'px'; 209 foodDom.style.top = y*sh + 'px'; 210 }else { 211 food.create(); 212 } 213 } 214 215 216 217 //创建游戏逻辑 218 function Game() { 219 this.timer = null; 220 this.score = 0; 221 this.speed = 200; 222 } 223 Game.prototype.init = function() { 224 snake.init(); 225 snake.getNextPos(); 226 createFood(); 227 228 document.onkeydown = function(ev) { //用户按下方向键触发事件 229 if(ev.which == 37 && snake.direction != snake.directionNum.right) { 230 //用户按下左键是,蛇不能是往右走 231 snake.direction = snake.directionNum.left; 232 }else if(ev.which == 38 && snake.direction != snake.directionNum.dowm) { 233 snake.direction = snake.directionNum.up; 234 }else if(ev.which == 39 && snake.direction != snake.directionNum.left) { 235 snake.direction = snake.directionNum.right; 236 }else if(ev.which == 40 && snake.direction != snake.directionNum.up) { 237 snake.direction = snake.directionNum.down; 238 } 239 } 240 241 this.start(); 242 } 243 244 Game.prototype.start = function() { //开始游戏 245 this.timer = setInterval(function() { 246 snake.getNextPos(); 247 248 }, this.speed); 249 } 250 Game.prototype.pause = function() { 251 clearInterval(this.timer); 252 } 253 Game.prototype.over = function() { //开始游戏 254 clearInterval(this.timer); 255 alert('你的得分为' + this.score); 256 257 //游戏回到最初的状态 258 var snakeWrap = document.getElementById('snakeWrap'); 259 snakeWrap.innerHTML = ''; 260 snake = new Snake(); 261 game = new Game(); 262 var startBtnWrap = document.querySelector('.startBtn'); 263 startBtnWrap.style.display = 'block'; 264 } 265 //开启游戏 266 game = new Game(); 267 var startBtn = document.querySelector('.startBtn button'); 268 startBtn.onclick = function() { 269 startBtn.parentNode.style.display = 'none'; 270 game.init(); 271 }; 272 273 274 //暂停 275 var snakeWrap = document.getElementById('snakeWrap'); 276 var puseBtn = document.querySelector('.stopBtn button') 277 snakeWrap.onclick = function() { 278 game.pause(); 279 puseBtn.parentNode.style.display = 'block'; 280 } 281 282 puseBtn.onclick =function() { 283 game.start(); 284 puseBtn.parentNode.style.display = 'none'; 285 }