html5游戏_贪吃蛇

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

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

疑问:

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

有两种实现方式,

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

2.使用dom的query方法

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

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

在线地址:

http://wangxinsheng.herokuapp.com/snake

截图:

html5游戏_贪吃蛇

部分代码:

html:

 1 <!DOCTYPE html>

 2 <html>

 3     <head>

 4         <meta charset="utf-8">

 5         <meta name="description" content="html5 snake game">

 6         <meta name="keywords" content="snake,html5,canvas,web,game">

 7         <meta name="author" content="WangXinsheng">

 8         <meta name="apple-mobile-web-app-capable" content="yes">

 9         <meta name="apple-mobile-web-app-status-bar-style" content="black">

10         <meta name="viewport" id="viewport" content="width = device-width, initial-scale = 1, minimum-scale = 1, maximum-scale = 1, user-scalable=no">

11         <meta http-equiv="X-UA-Compatible" content="chrome=1">

12         <meta http-equiv="Pragma" content="no-cache">

13         <meta http-equiv="Cache-Control" content="no-cache">

14         <meta equiv="Expires" content="0">

15         <meta http-equiv="content-script-type" content="text/javascript">

16         <title>CopyRight&copy;WangXinsheng</title>

17         <script src="game/requestNextAnimationFrame.js"></script>

18         <style type="text/css">

19          html {color:#000;background:gray;margin:0px; overflow:hidden;}

20          body {-webkit-user-select:none;margin:0px;}

21          #gameWorld {background-color:#C6EEC6}

22          #opp{color:red; font-size:30px; font-weight:bold; text-align:center;vertical-align:middle; cursor:pointer;}

23         </style>

24     </head>

25     <body>

26         <canvas id="gameWorld" style="position: absolute; left: 0px; top: 0px;">

27             <p>You need a modern browser to view this.</p>

28         </canvas>

29         <div id="opp" style="position: absolute; left: 0px; top: 0px;">点击开始游戏</div>

30         <ul style='display:none' id='dataDom'></ul>

31     </body>

32     <script src="game/snakeGame_min.js"></script>

33 </html>
View Code

js使用dom方法:

1.初期往页面放入dom

 1 /*put data dom*/

 2 var dataDom = document.getElementById("dataDom");

 3 // document.querySelector("#dataDom");

 4 var domInner = "";

 5 for(var i = 1;i<=blockWNum;i++){

 6     for(var j = 1;j<=blockHNum;j++){

 7         domInner += liStr

 8             .replace("{%x%}",i)

 9             .replace("{%y%}",j)

10             .replace("{%s%}","0");

11     }

12 }

13 dataDom.innerHTML =domInner; //domInner;

2.判断是否撞到自己

1 result = 

2 ("1"==document.querySelector("#dataDom [data-x='"+nx+"'][data-y='"+ny+"']").getAttribute("data-s"))

3 ?false

4 :true;

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

 1 switch(dir){

 2     case "N":

 3         this.body.splice(0,0,{"x":this.body[0].x,"y":this.body[0].y-1});

 4         break;

 5     case "S":

 6         this.body.splice(0,0,{"x":this.body[0].x,"y":this.body[0].y+1});

 7         break;

 8     case "W":

 9         this.body.splice(0,0,{"x":this.body[0].x-1,"y":this.body[0].y});

10         break;

11     case "E":

12         this.body.splice(0,0,{"x":this.body[0].x+1,"y":this.body[0].y});

13         break;

14     default:;

15 }

16 this.setSnakeSts(this.body[0].x,this.body[0].y,1);

17 document.querySelector("#dataDom [data-x='"+x+"'][data-y='"+y+"']").setAttribute("data-s",s);
1 this.setSnakeSts(this.body[this.body.length-1].x,this.body[this.body.length-1].y,0);

2 this.body.splice(this.body.length-1,1);

4.事件绑定

1 if(!v){

2     document.addEventListener("keyup", onKeyPress, false);

3 }else{

4     caObj.addEventListener("touchstart", onTouchStart, false);

5     caObj.addEventListener("touchmove", onTouchMove, false);

6     caObj.addEventListener("touchend", onTouchEnd, false);

7 }

8 window.addEventListener("resize", doSize, false);

逻辑流程:

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

2.生成蛇,食物

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

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

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

  1 ;

  2 var debug = true;

  3 var gameWorld = function () {

  4     /*function init params*/

  5     function doVarInit() {

  6         //started = true;

  7         if(debug)

  8             console.log("hello snake powered by WangXinsheng");

  9     }

 10     /*function on resize the window*/

 11     function doSize() {

 12         // should start again

 13         var minLength = window.innerWidth>window.innerHeight

 14             ?window.innerHeight

 15             :window.innerWidth,

 16             maxLength = window.innerWidth<window.innerHeight

 17             ?window.innerHeight

 18             :window.innerWidth;

 19         blockW = Math.floor(minLength / blockMinNum);

 20         var caMin = blockW * blockMinNum;

 21         var caMax = Math.floor(maxLength / blockW) * blockW;

 22 

 23         caW = window.innerWidth>window.innerHeight

 24             ?caMax

 25             :caMin;

 26         caH = window.innerWidth<window.innerHeight

 27             ?caMax

 28             :caMin;

 29 

 30         blockWNum = caW / blockW;

 31         blockHNum = caH / blockW;

 32 

 33         var top = (window.innerHeight - caH) * 0.5,

 34             left = (window.innerWidth - caW) * 0.5;

 35 

 36         //if(debug)

 37             //console.log(blockWNum,blockHNum,top,left);//

 38 

 39         caObj.width = caW;

 40         caObj.height = caH;

 41         caObj.style.width = caW + "px";

 42         caObj.style.height = caH + "px";

 43         caObj.style.left = left + "px";

 44         caObj.style.top = top + "px";

 45         oppDiv.width = caW;

 46         oppDiv.height = caH;

 47         oppDiv.style.width = caW + "px";

 48         oppDiv.style.height = caH + "px";

 49         oppDiv.style.left = left + "px";

 50         oppDiv.style.top = top + "px";

 51         oppDiv.style.lineHeight = caH + "px";

 52 

 53         

 54         /*put data dom*/

 55         var dataDom = document.getElementById("dataDom");

 56         // document.querySelector("#dataDom");

 57         var domInner = "";

 58         for(var i = 1;i<=blockWNum;i++){

 59             for(var j = 1;j<=blockHNum;j++){

 60                 domInner += liStr

 61                     .replace("{%x%}",i)

 62                     .replace("{%y%}",j)

 63                     .replace("{%s%}","0");

 64             }

 65         }

 66         dataDom.innerHTML =domInner; //domInner;

 67         //var oldDom = document.querySelector("#dataDom");

 68         //removeDom(oldDom);

 69 

 70         lastFpsUpdateTime = (+new Date);

 71         lastFpsUpdateTimeFood = (+new Date);

 72     }

 73     function setSnakeSts(x,y,s){

 74         document.querySelector("#dataDom [data-x='"+x+"'][data-y='"+y+"']").setAttribute("data-s",s);

 75     }

 76     function gen(name) {

 77         /*product object*/

 78         switch(name){

 79             case "snake":

 80                 var body = [];

 81                 body.splice(0,0,{"x":1,"y":1});

 82                 body.splice(0,0,{"x":2,"y":1});

 83                 body.splice(0,0,{"x":3,"y":1});

 84                 body.splice(0,0,{"x":4,"y":1});

 85                 setSnakeSts(1,1,1);

 86                 setSnakeSts(2,1,1);

 87                 setSnakeSts(3,1,1);

 88                 setSnakeSts(4,1,1);

 89 

 90                 snakeObj = new snake(snakeColor,true,"E",blockW,initSpeed,body);

 91                 snakeObj.draw(caCt);

 92                 break;

 93             case "food":

 94                 var allFood = document.querySelectorAll("#dataDom [data-s='0']"),

 95                     foodX,foodY,index;

 96                 if(allFood.length==1){

 97                     index = 0;

 98                 }else if(allFood.length>1){

 99                     index = Math.round(Math.random()*(allFood.length-1));

100                 }

101                 if(allFood.length>=1){

102                     foodX = parseInt(allFood[index].getAttribute("data-x"));

103                     foodY = parseInt(allFood[index].getAttribute("data-y"));

104                     allFood[index].getAttribute("data-s","2");

105                     foodObj.x = foodX;

106                     foodObj.y = foodY;

107                     foodObj.live = true;

108                 }

109                 drawFood();

110                 break;

111             default:

112         }

113     }

114     function picIsLoaded() {

115         return true;

116     }

117     function loadPics() {

118         /*load pic to objectList*/

119     }

120     function loadedImg() {

121         /*if image loaded do here*/

122     }

123     function drawObject(name){

124         /*draw object to canvas*/

125     }

126     function animate(time) {

127         if (started) {

128             var now = (+new Date);

129             if (now - lastFpsUpdateTime > snakeObj.speed) {

130                 /*animate*/

131                 if(snakeObj.canMove(snakeObj.dir,blockWNum,blockHNum)){

132                     if(snakeObj.canEat(snakeObj.dir,foodObj)){

133                         snakeObj.doEat(snakeObj.dir,foodObj);

134                     }else{

135                         snakeObj.doMove(snakeObj.dir);

136                     }

137                 }else{

138                     // over

139                     started = false;

140                     oppDiv.style.display = "block";

141                     oppDiv.innerHTML = "点击再次游戏";

142                     return;

143                 }

144                 

145                 caCt.save();

146                 caCt.fillStyle = "#C6EEC6";

147                 caCt.fillRect(0,0,caW,caH);

148                 

149                 caCt.font = '40px Helvetica';

150                 caCt.textAlign = "center";

151                 caCt.textBaseline = "middle";

152                 caCt.fillStyle = '#8CCDD8';

153                 caCt.strokeStyle = '#8CCDD8';

154                 caCt.fillText("WangXinsheng", caW/2,caH/2);

155                 caCt.strokeText("WangXinsheng", caW/2,caH/2);

156 

157                 caCt.restore();

158 

159                 snakeObj.draw(caCt);

160 

161                 // draw food

162                 drawFood();

163                 

164                 lastFpsUpdateTime = (+new Date);

165             }

166             

167             if (now - lastFpsUpdateTimeFood > snakeObj.speed*5) {

168                 if(!foodObj.live){

169                     gen("food");

170                 }else{

171                     lastFpsUpdateTimeFood = (+new Date);

172                 }

173             }

174         }

175         window.requestNextAnimationFrame(animate);

176     }

177     function drawFood(){

178         if(foodObj.live){

179             caCt.save();

180             caCt.fillStyle = foodObj.color;

181             caCt.fillRect(

182                 (foodObj.x-1)*blockW,

183                 (foodObj.y-1)*blockW,

184                 blockW,

185                 blockW

186             );

187             caCt.restore();

188         }

189     }

190     function eventBund(){

191         if(!v){

192             document.addEventListener("keyup", onKeyPress, false);

193         }else{

194             caObj.addEventListener("touchstart", onTouchStart, false);

195             caObj.addEventListener("touchmove", onTouchMove, false);

196             caObj.addEventListener("touchend", onTouchEnd, false);

197             caObj.addEventListener("touchcancel", stopEvent, false);

198             caObj.addEventListener("gesturestart", stopEvent, false);

199             caObj.addEventListener("gesturechange", stopEvent, false);

200             caObj.addEventListener("gestureend", stopEvent, false);

201         }

202         window.addEventListener("resize", doSize, false);

203     }

204     function onKeyPress(e){

205         //console.log(e);

206         var dir = "";

207         switch(e.keyCode){

208             case 38:

209                 dir =snakeObj.dir=="S"?"":"N";

210                 break;

211             case 40:

212                 dir =snakeObj.dir=="N"?"":"S";

213                 break;

214             case 37:

215                 dir =snakeObj.dir=="E"?"":"W";

216                 break;

217             case 39:

218                 dir =snakeObj.dir=="W"?"":"E";

219                 break;

220             default:;

221         }

222         if(dir!="")

223             snakeObj.dir = dir;

224     }

225     function onTouchEnd(e){

226         e.preventDefault();

227         if(mouseTObj.x!=null && mouseTObj.y!=null

228             && mouseTMObj.x!=null && mouseTMObj.y!=null){

229             var diffX = mouseTMObj.x - mouseTObj.x,

230                 diffY = mouseTMObj.y - mouseTObj.y,

231                 dir = "";

232             if(Math.abs(diffY)>Math.abs(diffX)){

233                 dir = diffY>0?"S":"N";

234             }else if(Math.abs(diffY)<Math.abs(diffX)){

235                 dir = diffX>0?"E":"W";

236             }

237             switch(dir){

238                 case "N":

239                     snakeObj.dir =snakeObj.dir=="S"?"S":"N";

240                     break;

241                 case "S":

242                     snakeObj.dir =snakeObj.dir=="N"?"N":"S";

243                     break;

244                 case "W":

245                     snakeObj.dir =snakeObj.dir=="E"?"E":"W";

246                     break;

247                 case "E":

248                     snakeObj.dir =snakeObj.dir=="W"?"W":"E";

249                     break;

250                 default:;

251             }

252             mouseTObj.x = null;

253             mouseTObj.y = null;

254             mouseTMObj.x = null;

255             mouseTMObj.y = null;

256         }

257         e.stopPropagation();

258         return false;

259     }

260     function onTouchMove(e){

261         e.preventDefault();

262         var touch = e.touches[0];

263         mouseTMObj.x = touch.pageX;

264         mouseTMObj.y = touch.pageY;

265         e.stopPropagation();

266         return false;

267     }

268     function onTouchStart(e){

269         e.preventDefault();

270         var touch = e.touches[0];

271         mouseTObj.x = touch.pageX;

272         mouseTObj.y = touch.pageY;

273         e.stopPropagation();

274         return false;

275     }

276     function stopEvent(e) { e.preventDefault(); e.stopPropagation(); }

277     var v = navigator.userAgent.toLowerCase().indexOf("android") != -1 || navigator.userAgent.toLowerCase().indexOf("iphone") != -1 || navigator.userAgent.toLowerCase().indexOf("ipad") != -1,

278     caW = window.innerWidth,

279     caH = window.innerHeight,

280     caObj = document.getElementById("gameWorld"),

281     caCt = caObj.getContext("2d"),

282     oppDiv = document.getElementById("opp"),

283     lastFpsUpdateTime = new Date,

284     lastFpsUpdateTimeFood = new Date,

285     started = false,

286     blockW = 0,

287     blockMinNum = 20,

288     blockWNum = 0,

289     blockHNum = 0,

290     snakeObj = null,

291     snakeColor = "gray",

292     initSpeed = 150,

293     liStr = "<li data-x='{%x%}' data-y='{%y%}' data-s='{%s%}'></li>", //s:0-empty,1-snake,2-food

294     foodObj = {"x":0,"y":0,"live":false,"color":"red"},

295     mouseTObj = {"x":null,"y":null},

296     mouseTMObj = {"x":null,"y":null}

297     ;

298 

299     this.init = function () {

300         //*********init params*******

301         doVarInit();

302         //*********init size and vars*******

303         doSize();

304         //*********product bell and rabit*******

305         gen("snake");

306         gen("food");

307         //gen("yyy");

308         //*********Event***********

309         eventBund();

310         //*********Gen***********

311         //*********animate***********

312         animate();

313     }

314     this.start = function(){

315         oppDiv.style.display = "none";

316         started = true;

317     }

318 }

319 

320 /*

321 * object

322 */

323 function snake(bgC,live,dir,blockW,speed,body) {

324     this.bgC = bgC; // 涂色

325     this.live=live; // 存活状态 true,false

326     this.dir=dir; // 移动方向 N,S,W,E

327     this.blockW=blockW; // 方块边大小

328     this.speed=speed; // 速度 1000

329     this.body = body; // 蛇身体

330 }

331 snake.prototype.draw = function (context) {

332     context.save();

333     context.fillStyle = "gray";

334     for(var i = 0;i<this.body.length;i++){

335         context.fillRect(

336             (this.body[i].x-1)*this.blockW,

337             (this.body[i].y-1)*this.blockW,

338             this.blockW,

339             this.blockW

340         );

341     }

342     context.restore();

343 }

344 snake.prototype.canMove = function (dir,xMax,yMax) {

345     var result = false,

346         nx = this.body[0].x,

347         ny = this.body[0].y;

348     // 边框检测

349     switch(dir){

350         case "N":

351             result = this.body[0].y==1?false:true;

352             ny--;

353             break;

354         case "S":

355             result = this.body[0].y==yMax?false:true;

356             ny++;

357             break;

358         case "W":

359             result = this.body[0].x==1?false:true;

360             nx--;

361             break;

362         case "E":

363             result = this.body[0].x==xMax?false:true;

364             nx++;

365             break;

366         default:;

367     }

368     // 自己检测

369     //console.log(document.querySelector("#dataDom [data-x='"+nx+"'][data-y='"+ny+"']").getAttribute("data-s"));

370     if(result)

371         result = 

372         ("1"==document.querySelector("#dataDom [data-x='"+nx+"'][data-y='"+ny+"']").getAttribute("data-s"))

373         ?false

374         :true;

375     return result;

376 }

377 snake.prototype.canEat = function (dir,food) {

378     var sx=this.body[0].x,

379         sy=this.body[0].y;

380     switch(dir){

381         case "N":

382             sy--;

383             break;

384         case "S":

385             sy++;

386             break;

387         case "W":

388             sx-1;

389             break;

390         case "E":

391             sx+1;

392             break;

393         default:;

394     }

395     return (food.x==sx && food.y==sy);

396 }

397 // push第一个,pop最后一个

398 snake.prototype.doMove = function (dir) {

399     this.doEat(dir,null);

400     this.setSnakeSts(this.body[this.body.length-1].x,this.body[this.body.length-1].y,0);

401     this.body.splice(this.body.length-1,1);

402 }

403 // push第一个

404 snake.prototype.doEat = function (dir,food) {

405     switch(dir){

406         case "N":

407             this.body.splice(0,0,{"x":this.body[0].x,"y":this.body[0].y-1});

408             break;

409         case "S":

410             this.body.splice(0,0,{"x":this.body[0].x,"y":this.body[0].y+1});

411             break;

412         case "W":

413             this.body.splice(0,0,{"x":this.body[0].x-1,"y":this.body[0].y});

414             break;

415         case "E":

416             this.body.splice(0,0,{"x":this.body[0].x+1,"y":this.body[0].y});

417             break;

418         default:;

419     }

420     this.setSnakeSts(this.body[0].x,this.body[0].y,1);

421     if(food!=null)

422         food.live = false;

423 }

424 snake.prototype.setSnakeSts = function(x,y,s){

425     document.querySelector("#dataDom [data-x='"+x+"'][data-y='"+y+"']").setAttribute("data-s",s);

426 }

427 

428 var gameWorldObj = null;

429 window.onload = function () {

430     document.getElementsByTagName('title')[0].innerHTML = "[WXS]贪吃蛇";

431     snakeGameGo();

432 }

433 function snakeGameGo(){

434     if(gameWorldObj == null)

435         gameWorldObj = new gameWorld();

436     gameWorldObj.init();

437     var opp = document.getElementById("opp");

438     opp.addEventListener("click", doPlay, false);

439 }

440 function doPlay(){gameWorldObj.init();gameWorldObj.start();}
View Code

运行文件下载地址:

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

 

你可能感兴趣的:(html5)