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

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

疑问:

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

有两种实现方式,

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

2.使用dom的query方法

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

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

在线地址:

http://wangxinsheng.herokuapp.com/snake

截图:

部分代码:

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

[原创]html5游戏_贪吃蛇的更多相关文章

  1. [原创]html5游戏_五线谱打音符

    html5手机游戏—五线谱打音符 1.[用五线谱打唱名] 2.[用唱名打五线谱] 3.[无限练习模式] 用来熟悉五线谱上音符的位置 代码不难,这回注释还是有认真写的[只是废代码没有全部删除...] 效 ...

  2. JavaScript与html5写的贪吃蛇完整代码

    JavaScript与html5写的贪吃蛇完整代码 查看运行效果可访问http://www.codesocang.com/texiao/youxitexiao/2014/0402/7045.html# ...

  3. JS小游戏:贪吃蛇(附源码)

    javascript小游戏:贪吃蛇 此小游戏采用的是面向对象的思想,将蛇,食物,和游戏引擎分为3个对象来写的. 为方便下载,我把js写在了html中, 源码中暂时没有注释,等有空我在添加点注释吧. 游 ...

  4. Python:游戏:贪吃蛇原理及代码实现

    一.游戏介绍 贪吃蛇是个非常简单的游戏,适合练手.先来看一下我的游戏截图: 玩法介绍:回车键:开始游戏空格键:暂停 / 继续↑↓←→方向键 或 WSAD 键:控制移动方向. 食物分红.绿.蓝三种,分别 ...

  5. WebGL实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

  6. 100行JS实现HTML5的3D贪吃蛇游戏

    js1k.com收集了小于1k的javascript小例子,里面有很多很炫很酷的游戏和特效,今年规则又增加了新花样,传统的classic类型基础上又增加了WebGL类型,以及允许增加到2K的++类型, ...

  7. C语言 小游戏之贪吃蛇

    还记得非常久曾经听群里人说做贪吃蛇什么的,那时候大一刚学了C语言,认为非常难,根本没什么思路. 前不久群里有些人又在谈论C语言贪吃蛇的事了,看着他们在做,我也打算做一个出来. 如今大三,经过了这一年半 ...

  8. Canvas进阶——制作小游戏【贪吃蛇】

    今天呢,主要和小伙伴们分享一下一个贪吃蛇游戏从构思到实现的过程~因为我不是很喜欢直接PO代码,所以只copy代码的童鞋们请出门左转不谢. 按理说canvas与其应用是老生常谈了,可我在准备阶段却搜索不 ...

  9. Python实战练习_贪吃蛇 (pygame的初次使用)

    正如标题所写的那样,我将一步步的完成本次实战练习——贪吃蛇.废话不多说,感兴趣的伙伴可以一同挑战一下. 首先说明本次实战中我的配备: 开发环境:python 3.7: 开发工具:pycharm2019 ...

随机推荐

  1. 可变参数宏__VA_ARGS__

    在 GNU C 中,宏可以接受可变数目的参数,就象函数一样,例如:#define pr_debug(fmt,arg...) \printk(KERN_DEBUG fmt,##arg) 用可变参数宏(v ...

  2. EasyUI笔记

    以下功能实现朋友们若有更好的思路办法,欢迎留言交流. 1.关闭其他标签页(右键菜单触发,保留左侧第一个欢迎tab) 问题:取到的数组tabs长度会随着tab的关闭而变化 思路:先遍历需要关闭的标签页t ...

  3. excel日期格式转换为文本格式

    今天测试读取excel并修改数据库数据的时候遇到几个小问题. 1.空指针,读写io异常蛮多的,获取不到的数据就是null 2.读取文件位置,开始找不到文件 3.读取日期格式结果是一个数值,因此需要转化 ...

  4. 解决AndroidADT自带Eclipse编辑器不能自动代码提示的问题。

    今天发现,我下载的AndroidADT开发套装中自带的Eclipse没有自动代码提示功能.通过参考http://blog.csdn.net/coolszy/article/details/724195 ...

  5. 纯Shading Language绘制飞机火焰效果

    上篇<纯Shading Language绘制HTML5时钟>体现了GLSL可编程性特点,但没有体现GLSL可编程出各种酷炫效果的特点,今天我们将用纯Shading Language绘制火焰 ...

  6. 地图定位IOS8.0之前的定位

    在ios8.0之前定位的步骤如下: 1.首先将我们的项目版本切换到7.0

  7. 抓取代理IP

    写脚本从指定网站抓取数据的时候,免不了会被网站屏蔽IP.所以呢,就需要有一些IP代理.随便在网上找了一个提供免费IP的网站西刺做IP抓取.本次实践抓取的是其提供的国内匿名代理.可以打开网站查看一下源码 ...

  8. Entity Framework 实体框架的形成之旅--基类接口的统一和异步操作的实现(3)

    在本系列的第一篇随笔<Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)>中介绍了Entity Framework 实体框架的一些基础知识,以及构建 ...

  9. 数据库中char, varchar, nvarchar的差异

    char     char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值.当你输入的字符大于指定的数时,它会截取超出的字符.    nvarc ...

  10. Tomcat Server Timeouts属性的设置

    在启动Tomcat Server时,经常会出现启动时间过长的错误,如下图所示(为了方便截图,Start Timeout被设置为5秒钟,一般为45秒钟). 双击Tomcat v7.0 Server at ...