
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 }
