HTML5 + js 貪吃蛇遊戲設計與實現
阿新 • • 發佈:2019-02-16
遊戲截圖:
遊戲架構:
此遊戲架構大概分為三層:
Game.html:
說明:包含了介面的展示,以及一些事件的入口。
完整程式碼:
<html> <head> <title>html5 snake game</title> <script src ="game.js"></script> </head> <body> <table> <tr> <td> <!-- 遊戲面板 --> <canvas id="cvsPnl"style="top:0px;border:5px solid;color:#FF9900" width="10"height="10" >你的瀏覽器不支援這個遊戲!</canvas> </td> <td valign="top"> <!-- 配置面板 --> <div id="divSpeed"> <canvas id="cvsSpeed"width="120px" height="55px" ></canvas> <select id="selSpeed"> <optionvalue="1000">1000</option> <optionvalue="800">800</option> <optionvalue="500">500</option> <optionvalue="300">300</option> <optionvalue="200">200</option> </select> </div> <div id="divGameCtl"> <input id="btnStartGame"type="button" value="開始"></input> <input id="btnPauseGame"type="button" value="暫停"></input> <br /> </div> <br /> <div id="divPlayerName"> <canvas id="cvsName"width="50px" height="52px"></canvas><inputtype="text" id="txtName"style="width:120px;"></input> <input id="btnRememberMe"value="記住我" type="button"></input> </div> <div> <canvas id="cvsScore"></canvas> </div> </td> </tr> <table> <divid="debug"></div>
<scripttype="text/javascript"> ////遊戲畫板 var canvasGamePnl =document.getElementById("cvsPnl"); var context =canvasGamePnl.getContext("2d"); ////分數 var canvasScore =document.getElementById("cvsScore"); var contxtScore =canvasScore.getContext("2d"); ////速度 var canvasSpeed =document.getElementById("cvsSpeed"); var contxtSpeed =canvasSpeed.getContext("2d"); ////姓名 var canvasName =document.getElementById("cvsName"); var contxtName =canvasName.getContext("2d"); ////開始 $("btnStartGame").onclick=function(){ GameStart(context,contxtScore); } ////暫停/繼續 $("btnPauseGame").onclick =function(){ if($("btnPauseGame").value == "繼續"){ RunGame(context,contxtScore); $("btnPauseGame").value = "暫停"; gameStatus = 1; } else{ PauseGame(); $("btnPauseGame").value = "繼續"; gameStatus = 2; } } ////載入 window.onload=function(){ $("cvsPnl").width =screenWidth; $("cvsPnl").height=screenHeight; $("selSpeed").selectedIndex = 0; DrawFont(contxtSpeed,"選擇遊戲速度",120); DrawFont(contxtName,"姓名",50); $("txtName").value =GetPlayerName(); } ////鍵盤事件handler document.onkeydown = function (){ var key = document.all ? event.keyCode : arguments[0].keyCode; ////left if(key == 37){ if(direction != "right"){ direction = "left"; } } ////up else if(key == 38){ if(direction != "down"){ direction ="up"; } } ////right else if(key == 39){ if(direction != "left"){ direction = "right"; } } ////down else if(key == 40){ if(direction != "up"){ direction = "down"; } } } ////設定速度 $("selSpeed").onchange=function(){ if(gameStatus != 3){ sleepTime =parseInt(GetSelectObj("selSpeed").value); } } /////記住我 $("btnRememberMe").onclick =function(){ ScorePlayerName($("txtName").value); alert("已儲存"); } ////繪出文字 function DrawFont(context,txt,size){ context.font='30px impact'; context.fillStyle=fontColor; context.textAlign='left'; // context.shadowColor="#00ff00"; // context.shadowOffsetX = 15; // context.shadowOffsetY=-10; context.fillText(txt,0,50,size); } </script> </body> </html> Game.js: 說明:包含了遊戲的主幹邏輯,業務邏輯層的實現。 完整程式碼: document.write("<scriptlanguage='javascript' src='config.js'></script>"); document.write("<scriptlanguage='javascript' src='utility.js'></script>"); document.write("<scriptlanguage='javascript' src='player.js'></script>"); document.write("<scriptlanguage='javascript' src='global.js'></script>"); //////////////////////// ////遊戲入口//////////// //////////////////////// function GameStart(context,contxtScore){ InitGame(context,contxtScore); RunGame(context,contxtScore); } //////////////////////// ////初始化遊戲//////////// //////////////////////// function InitGame(context,contxtScore){ ////貪吃蛇 for(var i = initSize ;i > 0;i --){ snakeArr[i - 1] = new Object(); snakeArr[i - 1].x = (initSize - i + 1) *unitSize; snakeArr[i - 1].y = 0; } ////方向 direction = "right"; ////食物 food = new Object(); ////繪製螢幕方格 DrawScreen(context); ////隨即食物 RandomFood(context); ////分數 DrawScore(contxtScore,score); } //////////////////////// ////運行遊戲//////////// //////////////////////// function RunGame(context,contxtScore){ if(timer){ clearInterval(timer); } timer = setInterval(function(){ if(IsGameOver()){ alert("gameover!"); clearInterval(timer); return; } EatFoodHandler(context,contxtScore); Refresh(context); SetPosition(); DrawSnake(context); },sleepTime); } //////////////////////// ////重新整理//////////////// //////////////////////// function Refresh(context){ FillRect(context,snakeArr[snakeArr.length -1].x,snakeArr[snakeArr.length - 1].y,unitSize,unitSize,screenColor); DrawRect(context,snakeArr[snakeArr.length -1].x,snakeArr[snakeArr.length - 1].y,unitSize,unitSize,lineColor); } //////////////////////// ////畫蛇身////////////// //////////////////////// function DrawSnake(context){ for(var i = 0;i < snakeArr.length;i ++){ FillRect(context,snakeArr[i].x,snakeArr[i].y,unitSize,unitSize,snakeColor); DrawRect(context,snakeArr[i].x,snakeArr[i].y,unitSize,unitSize,lineColor); } } //////////////////////// ////畫螢幕////////////// //////////////////////// function DrawScreen(context){ for(var i = screenLeft;i < screenLeft +screenWidth / unitSize;i ++){ for(var j = screenTop;j < screenTop +screenHeight / unitSize;j ++){ FillRect(context,i * unitSize,j *unitSize,unitSize,unitSize,screenColor); DrawRect(context,i * unitSize,j *unitSize,unitSize,unitSize,lineColor); } } } //////////////////////// ////設定座標//////////// //////////////////////// function SetPosition(){ for(var i = snakeArr.length - 2;i >= 0;i --){ snakeArr[i + 1].x = snakeArr[i].x; snakeArr[i + 1].y = snakeArr[i].y; } if(direction == "left"){ snakeArr[0].x -= unitSize; } else if(direction == "right"){ snakeArr[0].x += unitSize; } else if(direction == "up"){ snakeArr[0].y -= unitSize; } else if(direction == "down"){ snakeArr[0].y += unitSize; } } //////////////////////// ////判斷是否結束遊戲/// //////////////////////// function IsGameOver(){ if(snakeArr[0].x < 0 ||snakeArr[0].x> screenWidth){ return true; } if(snakeArr[0].y < 0 ||snakeArr[0].y> screenHeight){ return true; } for(var i = 1;i < snakeArr.length;i ++){ if(snakeArr[0].x == snakeArr[i].x&& snakeArr[0].y == snakeArr[i].y){ gameStatus= 3; return true; } } return false; } //////////////////////// ////隨即食物//////////// //////////////////////// function RandomFood(context){ food.x = GetRandom((screenWidth / unitSize)- 1) * unitSize; food.y = GetRandom((screenHeight /unitSize) - 1) * unitSize; for(var i = 0;i < snakeArr.length;i ++){ if(food.x == snakeArr[i].x &&food.y == snakeArr[i].y){ RandomFood(context); } } FillRect(context,food.x ,food.y,unitSize,unitSize,foodColor);////utility.js DrawRect(context,food.x ,food.y,unitSize,unitSize,lineColor);////utility.js } //////////////////////// ///食物處理///////////// //////////////////////// functionEatFoodHandler(context,contxtScore){ if(direction == "left"){ if((snakeArr[0].x - unitSize == food.x)&& snakeArr[0].y == food.y){ IncreaseLen(contxtScore); ClearFood(context); RandomFood(context); } } else if(direction == "right"){ if(snakeArr[0].x + unitSize == food.x&& snakeArr[0].y == food.y){ IncreaseLen(contxtScore); ClearFood(context); RandomFood(context); } } else if(direction == "up"){ if(snakeArr[0].x == food.x &&(snakeArr[0].y - unitSize == food.y)){ IncreaseLen(contxtScore); ClearFood(context); RandomFood(context); } } else if(direction == "down"){ if(snakeArr[0].x == food.x &&snakeArr[0].y + unitSize == food.y){ IncreaseLen(contxtScore); ClearFood(context); RandomFood(context); } } } //////////////////////// ////清除食物//////////// //////////////////////// function ClearFood(context){ FillRect(context,food.x,food.y,unitSize,unitSize,screenColor); DrawRect(context,food.x,food.y,unitSize,unitSize,lineColor); } //////////////////////// ////增加長度//////////// //////////////////////// function IncreaseLen(contxtScore){ var newObj = new Object(); newObj.x = food.x; newObj.y = food.y; snakeArr.unshift(newObj); ////分數增加 IncreaseScore(contxtScore);////player.js } ////暫停 function PauseGame(){ clearInterval(timer); } Utility.js: 說明:提供了一些工具方法,工具層。 完整程式碼: ////返回客戶端物件 function $(clientId){ return document.getElementById(clientId); } ////獲得SELECT選中項 function GetSelectObj(clientId){ var obj = $(clientId); var index = obj.selectedIndex; // 選中索引 return obj.options[index]; } ////除錯使用 function DebugVar(param){ $("debug").innerHTML=param; } function DebugTxt(text){ $("debug").innerHTML = text; } ////畫方塊 functionDrawRect(context,left,right,width,height,color){ //設定填充樣式 context.strokeStyle= color; context.strokeRect(left,right,width, height); } ////填充方塊 functionFillRect(context,left,right,width,height,color){ //設定填充樣式 context.fillStyle= color; context.fillRect(left,right,width,height); } ////繪畫文字 function DrawScore(context,txt){ context.moveTo(0,0); context.clearRect(0,0,500,500); context.font='60px impact'; context.fillStyle=fontColor; context.textAlign='center'; // context.shadowColor="#00ff00"; // context.shadowOffsetX = 15; // context.shadowOffsetY=-10; txt = "分數:" + txt; context.fillText(txt,100,100,fontSize); } ////繪製漸變 function ScreenGradient(context){ var grd =context.createLinearGradient(0,0,screenWidth,screenHeight); grd.addColorStop(0,"#FFCC00"); grd.addColorStop(1,"#99FFFF"); context.fillStyle = grd; context.fillRect(0,0,screenWidth,screenHeight); } ////生產隨機數 function GetRandom(n){returnMath.floor(Math.random()*n+1)} ////儲存鍵值對 function addKV(k,v){ localStorage.setItem(k,v); } ////取得鍵值對的值 function getV(k){ return localStorage.getItem(k); } ////獲得本地儲存的所有值並轉化為字串 function getAllValueToStr(){ var content = ""; for(var i=0;i<localStorage.length;i++){ //key(i)獲得相應的鍵,再用getItem()方法獲得對應的值 content += localStorage.key(i)+ " : " +localStorage.getItem(localStorage.key(i)) + "<br />"; } } Player.js: 說明:包含了玩家的一些操作,game.js下面一層,屬於業務邏輯輔助層。 完整實現: function GetPlayerName(){ varname = getV("userName"); return name != null ? name : "newplayer" ; } function IncreaseScore(context){ score += 10; DrawScore(context,score);////utility.js } function ScorePlayerName(name){ addKV("userName",name); } Config.js: 說明:遊戲相關配置以及變數,系統配置層。 完整程式碼: //////////////////////// ////變數、配置引數////// //////////////////////// var screenWidth = 800;////螢幕寬度 var screenHeight = 500;////螢幕高度 var unitSize = 20;////單元格大小 var initSize = 3;////初始長度 var screenLeft = 0;////螢幕橫起始座標 var screenTop = 0;////螢幕縱起始座標 var snakeArr = new Array();////貪吃蛇陣列 var food;////食物 var snakeColor = "#009999";////蛇身顏色 var direction;////蛇的方向 var screenColor = "#99CCFF";////螢幕顏色 var lineColor = "#ffffff";////線條顏色(方格) var lineWidth = 3;////線條寬度 var foodColor = "#FFCC00"////食物顏色 var fontColor = "#996600";////分數顏色 var fontSize = 300;////分數字體大小 var timer;////定時器 var sleepTime = 200;////休眠時間 var level=0;////級別 var score=0;////分數 var currentPlayer;////當前玩家 var gameStatus = 0;////0:未開始 1:執行 2:暫停 3:已結束 global.js:(暫時沒有用到,用於擴充套件),系統全域性控制,例如場景繪製