[原创]html5游戏_贪吃蛇

时间:2023-03-09 08:20:16
[原创]html5游戏_贪吃蛇

代码随便写写,尚有许多不足,PC与手机端皆可运行

手机端滑屏操作,PC端方向键操作

疑问:

生成食物,与判断是否可以移动方面

有两种实现方式,

1.使用js内存,数组循环判断

2.使用dom的query方法

哪种比较快,哪种比较好?

目前的代码是用第二种方法实现

在线地址:

http://wangxinsheng.herokuapp.com/snake

截图:

[原创]html5游戏_贪吃蛇

部分代码:

html:

 <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="html5 snake game">
<meta name="keywords" content="snake,html5,canvas,web,game">
<meta name="author" content="WangXinsheng">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="viewport" id="viewport" content="width = device-width, initial-scale = 1, minimum-scale = 1, maximum-scale = 1, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta equiv="Expires" content="0">
<meta http-equiv="content-script-type" content="text/javascript">
<title>CopyRight&copy;WangXinsheng</title>
<script src="game/requestNextAnimationFrame.js"></script>
<style type="text/css">
html {color:#000;background:gray;margin:0px; overflow:hidden;}
body {-webkit-user-select:none;margin:0px;}
#gameWorld {background-color:#C6EEC6}
#opp{color:red; font-size:30px; font-weight:bold; text-align:center;vertical-align:middle; cursor:pointer;}
</style>
</head>
<body>
<canvas id="gameWorld" style="position: absolute; left: 0px; top: 0px;">
<p>You need a modern browser to view this.</p>
</canvas>
<div id="opp" style="position: absolute; left: 0px; top: 0px;">点击开始游戏</div>
<ul style='display:none' id='dataDom'></ul>
</body>
<script src="game/snakeGame_min.js"></script>
</html>

js使用dom方法:

1.初期往页面放入dom

 /*put data dom*/
var dataDom = document.getElementById("dataDom");
// document.querySelector("#dataDom");
var domInner = "";
for(var i = 1;i<=blockWNum;i++){
for(var j = 1;j<=blockHNum;j++){
domInner += liStr
.replace("{%x%}",i)
.replace("{%y%}",j)
.replace("{%s%}","0");
}
}
dataDom.innerHTML =domInner; //domInner;

2.判断是否撞到自己

 result =
("1"==document.querySelector("#dataDom [data-x='"+nx+"'][data-y='"+ny+"']").getAttribute("data-s"))
?false
:true;

3.蛇移动:1)移动目的地作为头部插入蛇身体。2)删除蛇尾部

 switch(dir){
case "N":
this.body.splice(0,0,{"x":this.body[0].x,"y":this.body[0].y-1});
break;
case "S":
this.body.splice(0,0,{"x":this.body[0].x,"y":this.body[0].y+1});
break;
case "W":
this.body.splice(0,0,{"x":this.body[0].x-1,"y":this.body[0].y});
break;
case "E":
this.body.splice(0,0,{"x":this.body[0].x+1,"y":this.body[0].y});
break;
default:;
}
this.setSnakeSts(this.body[0].x,this.body[0].y,1);
document.querySelector("#dataDom [data-x='"+x+"'][data-y='"+y+"']").setAttribute("data-s",s);
 this.setSnakeSts(this.body[this.body.length-1].x,this.body[this.body.length-1].y,0);
this.body.splice(this.body.length-1,1);

4.事件绑定

 if(!v){
document.addEventListener("keyup", onKeyPress, false);
}else{
caObj.addEventListener("touchstart", onTouchStart, false);
caObj.addEventListener("touchmove", onTouchMove, false);
caObj.addEventListener("touchend", onTouchEnd, false);
}
window.addEventListener("resize", doSize, false);

逻辑流程:

1.初期化canvas大小,位置和蛇身体单格大小

2.生成蛇,食物

3.蛇动作:可否移动,移动,吃食

4.循环动画[定期生成食物,移动操作蛇]

这个非常简单,js完整源码:

 ;
var debug = true;
var gameWorld = function () {
/*function init params*/
function doVarInit() {
//started = true;
if(debug)
console.log("hello snake powered by WangXinsheng");
}
/*function on resize the window*/
function doSize() {
// should start again
var minLength = window.innerWidth>window.innerHeight
?window.innerHeight
:window.innerWidth,
maxLength = window.innerWidth<window.innerHeight
?window.innerHeight
:window.innerWidth;
blockW = Math.floor(minLength / blockMinNum);
var caMin = blockW * blockMinNum;
var caMax = Math.floor(maxLength / blockW) * blockW; caW = window.innerWidth>window.innerHeight
?caMax
:caMin;
caH = window.innerWidth<window.innerHeight
?caMax
:caMin; blockWNum = caW / blockW;
blockHNum = caH / blockW; var top = (window.innerHeight - caH) * 0.5,
left = (window.innerWidth - caW) * 0.5; //if(debug)
//console.log(blockWNum,blockHNum,top,left);// caObj.width = caW;
caObj.height = caH;
caObj.style.width = caW + "px";
caObj.style.height = caH + "px";
caObj.style.left = left + "px";
caObj.style.top = top + "px";
oppDiv.width = caW;
oppDiv.height = caH;
oppDiv.style.width = caW + "px";
oppDiv.style.height = caH + "px";
oppDiv.style.left = left + "px";
oppDiv.style.top = top + "px";
oppDiv.style.lineHeight = caH + "px"; /*put data dom*/
var dataDom = document.getElementById("dataDom");
// document.querySelector("#dataDom");
var domInner = "";
for(var i = 1;i<=blockWNum;i++){
for(var j = 1;j<=blockHNum;j++){
domInner += liStr
.replace("{%x%}",i)
.replace("{%y%}",j)
.replace("{%s%}","0");
}
}
dataDom.innerHTML =domInner; //domInner;
//var oldDom = document.querySelector("#dataDom");
//removeDom(oldDom); lastFpsUpdateTime = (+new Date);
lastFpsUpdateTimeFood = (+new Date);
}
function setSnakeSts(x,y,s){
document.querySelector("#dataDom [data-x='"+x+"'][data-y='"+y+"']").setAttribute("data-s",s);
}
function gen(name) {
/*product object*/
switch(name){
case "snake":
var body = [];
body.splice(0,0,{"x":1,"y":1});
body.splice(0,0,{"x":2,"y":1});
body.splice(0,0,{"x":3,"y":1});
body.splice(0,0,{"x":4,"y":1});
setSnakeSts(1,1,1);
setSnakeSts(2,1,1);
setSnakeSts(3,1,1);
setSnakeSts(4,1,1); snakeObj = new snake(snakeColor,true,"E",blockW,initSpeed,body);
snakeObj.draw(caCt);
break;
case "food":
var allFood = document.querySelectorAll("#dataDom [data-s='0']"),
foodX,foodY,index;
if(allFood.length==1){
index = 0;
}else if(allFood.length>1){
index = Math.round(Math.random()*(allFood.length-1));
}
if(allFood.length>=1){
foodX = parseInt(allFood[index].getAttribute("data-x"));
foodY = parseInt(allFood[index].getAttribute("data-y"));
allFood[index].getAttribute("data-s","2");
foodObj.x = foodX;
foodObj.y = foodY;
foodObj.live = true;
}
drawFood();
break;
default:
}
}
function picIsLoaded() {
return true;
}
function loadPics() {
/*load pic to objectList*/
}
function loadedImg() {
/*if image loaded do here*/
}
function drawObject(name){
/*draw object to canvas*/
}
function animate(time) {
if (started) {
var now = (+new Date);
if (now - lastFpsUpdateTime > snakeObj.speed) {
/*animate*/
if(snakeObj.canMove(snakeObj.dir,blockWNum,blockHNum)){
if(snakeObj.canEat(snakeObj.dir,foodObj)){
snakeObj.doEat(snakeObj.dir,foodObj);
}else{
snakeObj.doMove(snakeObj.dir);
}
}else{
// over
started = false;
oppDiv.style.display = "block";
oppDiv.innerHTML = "点击再次游戏";
return;
} caCt.save();
caCt.fillStyle = "#C6EEC6";
caCt.fillRect(0,0,caW,caH); caCt.font = '40px Helvetica';
caCt.textAlign = "center";
caCt.textBaseline = "middle";
caCt.fillStyle = '#8CCDD8';
caCt.strokeStyle = '#8CCDD8';
caCt.fillText("WangXinsheng", caW/2,caH/2);
caCt.strokeText("WangXinsheng", caW/2,caH/2); caCt.restore(); snakeObj.draw(caCt); // draw food
drawFood(); lastFpsUpdateTime = (+new Date);
} if (now - lastFpsUpdateTimeFood > snakeObj.speed*5) {
if(!foodObj.live){
gen("food");
}else{
lastFpsUpdateTimeFood = (+new Date);
}
}
}
window.requestNextAnimationFrame(animate);
}
function drawFood(){
if(foodObj.live){
caCt.save();
caCt.fillStyle = foodObj.color;
caCt.fillRect(
(foodObj.x-1)*blockW,
(foodObj.y-1)*blockW,
blockW,
blockW
);
caCt.restore();
}
}
function eventBund(){
if(!v){
document.addEventListener("keyup", onKeyPress, false);
}else{
caObj.addEventListener("touchstart", onTouchStart, false);
caObj.addEventListener("touchmove", onTouchMove, false);
caObj.addEventListener("touchend", onTouchEnd, false);
caObj.addEventListener("touchcancel", stopEvent, false);
caObj.addEventListener("gesturestart", stopEvent, false);
caObj.addEventListener("gesturechange", stopEvent, false);
caObj.addEventListener("gestureend", stopEvent, false);
}
window.addEventListener("resize", doSize, false);
}
function onKeyPress(e){
//console.log(e);
var dir = "";
switch(e.keyCode){
case 38:
dir =snakeObj.dir=="S"?"":"N";
break;
case 40:
dir =snakeObj.dir=="N"?"":"S";
break;
case 37:
dir =snakeObj.dir=="E"?"":"W";
break;
case 39:
dir =snakeObj.dir=="W"?"":"E";
break;
default:;
}
if(dir!="")
snakeObj.dir = dir;
}
function onTouchEnd(e){
e.preventDefault();
if(mouseTObj.x!=null && mouseTObj.y!=null
&& mouseTMObj.x!=null && mouseTMObj.y!=null){
var diffX = mouseTMObj.x - mouseTObj.x,
diffY = mouseTMObj.y - mouseTObj.y,
dir = "";
if(Math.abs(diffY)>Math.abs(diffX)){
dir = diffY>0?"S":"N";
}else if(Math.abs(diffY)<Math.abs(diffX)){
dir = diffX>0?"E":"W";
}
switch(dir){
case "N":
snakeObj.dir =snakeObj.dir=="S"?"S":"N";
break;
case "S":
snakeObj.dir =snakeObj.dir=="N"?"N":"S";
break;
case "W":
snakeObj.dir =snakeObj.dir=="E"?"E":"W";
break;
case "E":
snakeObj.dir =snakeObj.dir=="W"?"W":"E";
break;
default:;
}
mouseTObj.x = null;
mouseTObj.y = null;
mouseTMObj.x = null;
mouseTMObj.y = null;
}
e.stopPropagation();
return false;
}
function onTouchMove(e){
e.preventDefault();
var touch = e.touches[0];
mouseTMObj.x = touch.pageX;
mouseTMObj.y = touch.pageY;
e.stopPropagation();
return false;
}
function onTouchStart(e){
e.preventDefault();
var touch = e.touches[0];
mouseTObj.x = touch.pageX;
mouseTObj.y = touch.pageY;
e.stopPropagation();
return false;
}
function stopEvent(e) { e.preventDefault(); e.stopPropagation(); }
var v = navigator.userAgent.toLowerCase().indexOf("android") != -1 || navigator.userAgent.toLowerCase().indexOf("iphone") != -1 || navigator.userAgent.toLowerCase().indexOf("ipad") != -1,
caW = window.innerWidth,
caH = window.innerHeight,
caObj = document.getElementById("gameWorld"),
caCt = caObj.getContext("2d"),
oppDiv = document.getElementById("opp"),
lastFpsUpdateTime = new Date,
lastFpsUpdateTimeFood = new Date,
started = false,
blockW = 0,
blockMinNum = 20,
blockWNum = 0,
blockHNum = 0,
snakeObj = null,
snakeColor = "gray",
initSpeed = 150,
liStr = "<li data-x='{%x%}' data-y='{%y%}' data-s='{%s%}'></li>", //s:0-empty,1-snake,2-food
foodObj = {"x":0,"y":0,"live":false,"color":"red"},
mouseTObj = {"x":null,"y":null},
mouseTMObj = {"x":null,"y":null}
; this.init = function () {
//*********init params*******
doVarInit();
//*********init size and vars*******
doSize();
//*********product bell and rabit*******
gen("snake");
gen("food");
//gen("yyy");
//*********Event***********
eventBund();
//*********Gen***********
//*********animate***********
animate();
}
this.start = function(){
oppDiv.style.display = "none";
started = true;
}
} /*
* object
*/
function snake(bgC,live,dir,blockW,speed,body) {
this.bgC = bgC; // 涂色
this.live=live; // 存活状态 true,false
this.dir=dir; // 移动方向 N,S,W,E
this.blockW=blockW; // 方块边大小
this.speed=speed; // 速度 1000
this.body = body; // 蛇身体
}
snake.prototype.draw = function (context) {
context.save();
context.fillStyle = "gray";
for(var i = 0;i<this.body.length;i++){
context.fillRect(
(this.body[i].x-1)*this.blockW,
(this.body[i].y-1)*this.blockW,
this.blockW,
this.blockW
);
}
context.restore();
}
snake.prototype.canMove = function (dir,xMax,yMax) {
var result = false,
nx = this.body[0].x,
ny = this.body[0].y;
// 边框检测
switch(dir){
case "N":
result = this.body[0].y==1?false:true;
ny--;
break;
case "S":
result = this.body[0].y==yMax?false:true;
ny++;
break;
case "W":
result = this.body[0].x==1?false:true;
nx--;
break;
case "E":
result = this.body[0].x==xMax?false:true;
nx++;
break;
default:;
}
// 自己检测
//console.log(document.querySelector("#dataDom [data-x='"+nx+"'][data-y='"+ny+"']").getAttribute("data-s"));
if(result)
result =
("1"==document.querySelector("#dataDom [data-x='"+nx+"'][data-y='"+ny+"']").getAttribute("data-s"))
?false
:true;
return result;
}
snake.prototype.canEat = function (dir,food) {
var sx=this.body[0].x,
sy=this.body[0].y;
switch(dir){
case "N":
sy--;
break;
case "S":
sy++;
break;
case "W":
sx-1;
break;
case "E":
sx+1;
break;
default:;
}
return (food.x==sx && food.y==sy);
}
// push第一个,pop最后一个
snake.prototype.doMove = function (dir) {
this.doEat(dir,null);
this.setSnakeSts(this.body[this.body.length-1].x,this.body[this.body.length-1].y,0);
this.body.splice(this.body.length-1,1);
}
// push第一个
snake.prototype.doEat = function (dir,food) {
switch(dir){
case "N":
this.body.splice(0,0,{"x":this.body[0].x,"y":this.body[0].y-1});
break;
case "S":
this.body.splice(0,0,{"x":this.body[0].x,"y":this.body[0].y+1});
break;
case "W":
this.body.splice(0,0,{"x":this.body[0].x-1,"y":this.body[0].y});
break;
case "E":
this.body.splice(0,0,{"x":this.body[0].x+1,"y":this.body[0].y});
break;
default:;
}
this.setSnakeSts(this.body[0].x,this.body[0].y,1);
if(food!=null)
food.live = false;
}
snake.prototype.setSnakeSts = function(x,y,s){
document.querySelector("#dataDom [data-x='"+x+"'][data-y='"+y+"']").setAttribute("data-s",s);
} var gameWorldObj = null;
window.onload = function () {
document.getElementsByTagName('title')[0].innerHTML = "[WXS]贪吃蛇";
snakeGameGo();
}
function snakeGameGo(){
if(gameWorldObj == null)
gameWorldObj = new gameWorld();
gameWorldObj.init();
var opp = document.getElementById("opp");
opp.addEventListener("click", doPlay, false);
}
function doPlay(){gameWorldObj.init();gameWorldObj.start();}

运行文件下载地址:

http://download.csdn.net/detail/wangxsh42/8515975