学写前端原生贪吃蛇
看了人家視頻上寫的貪吃蛇,瞬間覺得自己low爆了。。。。就學他寫了三遍,以我的記性,覺得還是有必要記錄下過程,以便記憶。
先看下截圖:
首先html分析:
注:下列的id是用在js里的,class是用在css里的
上述是貪吃蛇的全部html代碼,將貪吃蛇游戲的大致界面劃分出來。
接下來是css代碼:
還有部分css代碼,在js代碼編輯的時候一同寫出,現在上述的css算是將貪吃蛇游戲的頁面背景設置完畢。
接下來js代碼:
設置完初始值后,開始設置蛇和食物的初始狀態
function food(){ //食物的設置var food = document.createElement('div'); //生成一個div的食物foodfood.style.width = this.foodW + 'px'; //設置食物的寬高,等于上述函數中已經設置好的默認食物寬高food.style.height = this.foodH + 'px'; //同上food.style.position = 'absolute'; //設置食物的位置為絕對定位this.foodX = Math.floor(Math.random()*this.mapW/20); //食物的x坐標的隨機位置,表示0到(游戲界面的寬除以食物自己的寬)的隨機數this.foodY = Math.floor(Math.random()*this.mapH/20); //食物的y坐標的隨機位置,同上food.style.top = this.foodY * 20 + 'px'; //表示食物的上邊距距離為食物的y坐標乘以自己的高food.style.left = this.foodX * 20 + 'px'; //同上this.mapDiv.appendChild(food).setAttribute('class','food'); //給每個食物div都設置上名為food的class,再到css中設置食物的大小和載入圖片 }function snake(){ //蛇的設置for(var i = 0;i < this.snakeBody.length;i ++){ //用for循環,i小于蛇身的長度,(初始時的length為3)var snake = document.createElement('div'); //生成一個div的蛇snakesnake.style.width = this.snakeW + 20 + 'px'; //設置生成的蛇的寬高snake.style.height = this.snakeH + 20 + "px";snake.style.position = 'absolute'; //設置蛇的絕對位置snake.style.top = this.snakeBody[i][1] * 20 + 'px'; //設置每節蛇的距離上邊距的位置snake.style.left = this.snakeBody[i][0] * 20 + 'px'; //設置每節蛇的距離左邊距的位置snake.classList.add(this.snakeBody[i][2]); //給每節蛇添加class,這里的class為上述的snakeBody中設置的第3個位置上的‘head’和’body‘,因此又需要對head和body設置css代碼,用來區分蛇頭和蛇身this.mapDiv.appendChild(snake).classList.add('snake'); //在html中添加上snake的div,并加上class = ‘snake’switch(this.direct){ //蛇頭的轉向(注:由于我找的蛇頭的方向默認為右邊)case 'right': //由于默認圖片蛇頭向右所以不需要改變操作break;case 'left' : //將蛇頭的方向轉向左邊snake.style.transform = 'rotate(180deg)';break;case 'up' : //將蛇頭方向旋轉到上邊snake.style.transform = 'rotate(270deg)';break;case 'down' : //將蛇頭方向旋轉到下方snake.style.transform = 'rotate(90deg)';break;default :break;}} }食物和蛇的css代碼:
.food{background-image: url('img/pg.png'); //加入食物的圖片background-size: 100% 100%; }.head{background-image: url('img/s.png'); //加入蛇頭的圖片background-size: 100% 100%; }.body{background-image: url('img/she.png'); //加入蛇身的圖片background-size: 100% 100%; }設置完蛇和食物的狀態后,設置游戲開始時的界面:
var startPage = document.getElementById('startPage'); //從html中獲取到id = startPage的元素節點,startPage表示開始游戲的按鈕 var startP = document.getElementById('startP'); //同上,startP表示暫停的按鈕function startGame(){ //游戲開始startPage.style.display = 'none'; // 將該節點設置為不顯示startP.style.display = 'block'; //使該節點顯示food(); //調用food函數snake(); //調用snake函數 }接下來設置蛇的運動狀態js:
var scoreBox = document.getElementById('score'); //獲取用于計分的節點 function move(){for(var i = this.snakeBody.length-1;i > 0;i --){ //for循環,表示蛇運動時,后一節蛇的位置是前一節蛇之前所在的位置this.snakeBody[i][0] = this.snakeBody[i-1][0];this.snakeBody[i][1] = this.snakeBody[i-1][1];}switch(this.direct){ //表示蛇頭的轉動位置情況case 'right' :this.snakeBody[0][0] +=1; //右邊時,蛇頭的x位置加1break;case 'left' :this.snakeBody[0][0] -=1; //左邊時,蛇頭的x位置減1,break;case 'up' :this.snakeBody[0][1] -=1; //上邊時,蛇頭的y位置減1break;case 'down' :this.snakeBody[0][1] +=1; //下邊時,蛇頭的y位置加1default:break;}removeClass('snake'); //刪除class = ‘snake’的節點snake(); //重新調用snake函數if(this.snakeBody[0][0] == this.foodX && this.snakeBody[0][1] == this.foodY){ //當蛇吃到食物時var snakeEndX = this.snakeBody[this.snakeBody.length-1][0]; //表示吃到食物后,蛇尾的x坐標為蛇的長-1var snakeEndY = this.snakeBody[this.snakeBody.length-1][1]; //同上switch(this.direct){case 'right':this.snakeBody.push([snakeEndX ,snakeEndY,'body']); //蛇頭向右時,蛇尾的x位置需要+1break;case 'left':this.snakeBody.push([snakeEndX ,snakeEndY,'body']); //蛇頭向左時,蛇尾的x位置需要-1break;case 'up':this.snakeBody.push([snakeEndX,snakeEndY ,'body']); //蛇頭向上時,蛇尾的y位置需要-1break;case 'down':this.snakeBody.push([snakeEndX,snakeEndY ,'body']); //蛇頭向下時,蛇尾的y位置需要+1break;default:break;} //注:當蛇吃到食物時,添加的尾巴會在原來的尾巴的位置上加上,直到蛇頭離開食物的位置,此時的尾巴就會變成真正的尾巴this.score += 1; //吃到食物,分數+1scoreBox.innerHTML = this.score; //使html中的id = ‘scoreBox’的節點上加上此時的分數removeClass('food'); //蛇吃到食物后,所吃的食物消失food(); //又重新出現新的食物的位置}if(this.snakeBody[0][0] < 0 || this.snakeBody[0][0] > this.mapW/20){ //當蛇頭x碰到邊界時,游戲結束reloadGame(); //結束游戲,重新加載游戲}if(this.snakeBody[0][1] < 0 || this.snakeBody[0][1] > this.mapH/20){ //當蛇頭y碰到邊界時,游戲結束reloadGame(); //結束游戲,重新加載游戲}var snakeHX = this.snakeBody[0][0]; //得到蛇頭xvar snakeHY = this.snakeBody[0][1]; //得到蛇頭yfor(var i = 1;i < this.snakeBody.length;i++){ //當蛇頭碰到自己的身體時,游戲結束if(snakeHX == snakeBody[i][0] && snakeHY == snakeBody[i][1]){reloadGame();}} }接下來是刪除節點的函數:
function removeClass(className){ //給一個class類名var ele = document.getElementsByClassName(className); //用ele得到html中有該class類名的節點while(ele.length > 0){ //當節點長度大于0時,即存在該節點ele[0].parentNode.removeChild(ele[0]); //刪除該節點} }然后是重新加載游戲的js代碼:
var loseScore = document.getElementById('loseScore'); function reloadGame(){removeClass('snake'); //刪除class = ‘snake’的節點,即刪除蛇removeClass('food'); //刪除食物,同上clearInterval(snakeMove); //清除snakeMove每隔時間間隔長度運動this.snakeBody = [[4,1,'head'],[3,1,'body'],[2,1,'body']]; //再添加上默認初始的蛇身坐標this.direct = 'right'; //初始方向this.right = false; this.left = false;this.up = true;this.down = true;lose.style.display = 'block'; //使id = ‘lose’的節點出現,即出現游戲結束后的圖片loseScore.innerHTML = this.score; //記錄游戲結束后的最終得分this.score = 0; //記錄后,清0scoreBox.innerHTML = this.score; //同時將游戲開始時的動態積分也清0startGameBool = true;startPauseBool = true;startP.setAttribute('src','./img/begin.png'); //改變id = ‘startP’節點的圖片內容 }關于操作蛇時的上下左右按鍵設置:
function setDirect(code){ //給該函數一個表示對應按鍵數字switch(code){case 37: //表示左,方向為左時,上下的按鍵可觸發但是左右的按鍵不可以觸發if(this.left){this.direct = 'left';this.left = false;this.right = false;this.up = true;this.down = true;}break;case 38: //上 ,同上if(this.up){this.direct = 'up';this.left = true;this.right = true;this.up = false;this.down = false;}break;case 39: //右 ,同上if(this.right){this.direct = 'right';this.left = false;this.right = false;this.up= true;this.down = true;}break;case 40: //下 ,同上if(this.down){this.direct = 'down';this.left = true;this.right = true;this.up = false;this.down = false;}break;default:break;} }接下來是關于游戲的開始和暫停的設置:
var startGameBool = true; //表示該鑰匙是開著時 var startPauseBool = true; var snakeMove; var speed = 200;function startAndPush(){if(startPauseBool){ //關于暫停的鑰匙if(startGameBool){ //關于游戲剛開啟時的鑰匙startGame(); //游戲開始,啟動游戲開始的界面startGameBool = false; //游戲開始后,不需要再出現這個過程,將該鑰匙鎖住}startP.setAttribute('src','./img/kk.png'); //為html中的id = ‘startP’設置插入圖片document.onkeydown = function(e){ //觸發按鍵發生的時間var code = e.keyCode; //得到所觸發按鍵所表示的數字setDirect(code); //調用上述的按鍵方向函數}snakeMove = setInterval(function(){ 表示每隔speed時間啟用一次move(); 調用move函數,表示每隔speed時間,執行一次move函數事件},speed);startPauseBool = false; //執行過后,需要上鎖,防止該事件在游戲過程中被啟用出錯}else{ //當鑰匙關閉時,執行的事件startP.setAttribute('src','./img/zanting.png'); //改變id = startP的節點中的圖片內容clearInterval(snakeMove); //清除snakeMove每隔speed時間的執行document.onkeydown = function(e){ //表示禁止按鍵啟用e.returnValue = false;return false;}startPauseBool = true; //執行上述事件后,將鎖打開} }之后是關于主體啟用鍵盤按鍵和鼠標按鍵事件:
var lose = document.getElementById('lose'); var close = document.getElementById('close'); var startBtn = document.getElementById('startBtn');function bindEvent(){document.onkeydown = function(e){ //同上述描述,是按鍵的數字獲取和啟用方向事件var code = e.keyCode;setDirect(code)}close.onclick = function(){ //表示游戲結束后右上角的關閉按鍵的觸發事件lose.style.display = 'none'; //使游戲結束界面不顯示}startBtn.onclick = function(){ //表示剛啟動游戲時的開始按鈕startAndPush(); }startP.onclick = function(){ //表示游戲中的暫停和解除暫停的鼠標按鍵事件startAndPush();} }上述就是所有的js代碼。。。。
看下成果圖:
注:上述代碼如有解釋錯誤的,請大佬幫忙改善,謝謝,有不清楚的也可以留言,本人會盡量及時回復的
總結
- 上一篇: 创客教育的起源和内涵的基本理念
- 下一篇: 什么是跨域?一次性带你理解透