HTML5 + js 贪吃蛇游戏设计与实现
m47c
9年前
游戏截图:
游戏架构:
此游戏架构大概分为三层:
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"> <optionvalueoptionvalue="1000">1000</option> <optionvalueoptionvalue="800">800</option> <optionvalueoptionvalue="500">500</option> <optionvalueoptionvalue="300">300</option> <optionvalueoptionvalue="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><inputtypeinputtype="text" id="txtName"style="width:120px;"></input> <input id="btnRememberMe"value="记住我" type="button"></input> </div> <div> <canvas id="cvsScore"></canvas> </div> </td> </tr> <table> <dividdivid="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:(暂时没有用到,用于扩展),系统全局控制,例如场景绘制
来自:http://blog.csdn.net/lan_liang/article/details/6657697