JS+HTML实现经典游戏吃豆人

目录

  • 前言
  • HTML代码
  • JS代码
  • 游戏截图
【JS+HTML实现经典游戏吃豆人】
前言 很早就知道canvas,当时一直没应用到,最近闲来无事就顺便写写看。吃豆游戏可以说是我们80,90后共同的回忆录,小时候常常在学习机上玩,所以也就有了强烈的欲望去写。为了写这个游戏,看了很多吃豆人游戏的相关信息,包括游戏规则,历史,其它相关游戏设计。又去了各个小游戏平台玩了下,找些灵感!!!就连最简单的配色,也是反复斟酌几个小时确定的方案……哈哈,不容易啊代码分两部分,游戏引擎和游戏主程序,引擎用来类的定义,管理动画场景,事件定义等等……游戏主程序主要组织业务逻辑。算面向对象编程吧,纯手工打造是男人就吃光所有豆子!!!
项目结构
JS+HTML实现经典游戏吃豆人
文章图片

因需要四个文件即可实现,index.html 游戏主页,index.js 主页控制,game.js 游戏控制,favicon.png 图标。代码简单,易懂。后续小伙伴们还可以自己加入音乐!可以部署到服务器上,也可用浏览器直接打开index.html玩耍!!!

HTML代码
Pac-Man . 吃豆游戏 - 锐客网body{background-color: #292929}*{padding:0; margin:0; }.wrapper{width: 960px; margin:0 auto; line-height:36px; text-align:center; color:#999; }canvas{display:block; background: #000; }.mod-botton{height: 32px; padding: 15px 0; text-align: center; } 不支持画布按[空格]暂停或继续


JS代码
//主程序,业务逻辑(function(){ var _DATA = https://www.it610.com/article/[//地图数据[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1],[1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1],[1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1],[1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1],[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],[1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1],[1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1],[1,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,1],[1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,0,1,1,1,2,2,1,1,1,0,1,1,0,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,0,1,2,2,2,2,2,2,1,0,1,1,0,1,1,1,1,1,1],[0,0,0,0,0,0,0,0,0,0,1,2,2,2,2,2,2,1,0,0,0,0,0,0,0,0,0,0],[1,1,1,1,1,1,0,1,1,0,1,2,2,2,2,2,2,1,0,1,1,0,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1],[1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1],[1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1],[1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1],[1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1],[1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1],[1,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,1],[1,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,1],[1,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,1],[1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1],[1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1],[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] ], _GOODS = {//能量豆'1,3':1,'26,3':1,'1,23':1,'26,23':1 }, _COS = [1,0,-1,0], _SIN = [0,1,0,-1], _COLOR = ['#F00','#F93','#0CF','#F9C'],//红,橙, _LIFE = 3, _SCORE = 0; //得分 var game = new Game('canvas'); //启动页 (function(){var stage = game.createStage(); //logostage.createItem({x:game.width/2,y:game.height*.45,width:100,height:100,frames:3,draw:function(context){var t = Math.abs(5-this.times%10); context.fillStyle = '#FFE600'; context.beginPath(); context.arc(this.x,this.y,this.width/2,t*.04*Math.PI,(2-t*.04)*Math.PI,false); context.lineTo(this.x,this.y); context.closePath(); context.fill(); context.fillStyle = '#000'; context.beginPath(); context.arc(this.x+5,this.y-27,7,0,2*Math.PI,false); context.closePath(); context.fill(); }}); //游戏名stage.createItem({x:game.width/2,y:game.height*.6,draw:function(context){context.font = 'bold 42px Helvetica'; context.textAlign = 'center'; context.textBaseline = 'middle'; context.fillStyle = '#FFF'; context.fillText('Pac-Man',this.x,this.y); }}); //版权信息stage.createItem({x:game.width-12,y:game.height-5,draw:function(context){context.font = '14px Helvetica'; context.textAlign = 'right'; context.textBaseline = 'bottom'; context.fillStyle = '#AAA'; context.fillText('? passer-by.com',this.x,this.y); }}); //事件绑定stage.bind('keydown',function(e){switch(e.keyCode){case 13:case 32:game.nextStage(); break; }}); })(); //游戏主程序 (function(){var stage,map,beans,player,times; stage = game.createStage({update:function(){var stage = this; if(stage.status==1){//场景正常运行items.forEach(function(item){if(map&&!map.get(item.coord.x,item.coord.y)&&!map.get(player.coord.x,player.coord.y)){var dx = item.x-player.x; var dy = item.y-player.y; if(dx*dx+dy*dy<750&&item.status!=4){//物体检测if(item.status==3){item.status = 4; _SCORE += 10; }else{stage.status = 3; stage.timeout = 30; }}}}); if(JSON.stringify(beans.data).indexOf(0)<0){ //当没有物品的时候,进入结束画面game.nextStage(); }}else if(stage.status==3){//场景临时状态if(!stage.timeout){_LIFE--; if(_LIFE){stage.resetItems(); }else{game.nextStage(); return false; }}}}}); //绘制地图map = stage.createMap({x:60,y:10,data:_DATA,cache:true,draw:function(context){context.lineWidth = 2; for(var j=0; j-1){context.strokeStyle=value=https://www.it610.com/article/=2?"#FFF":"#09C"; var pos = this.coord2position(i,j); switch(code.join('')){case '1100':context.beginPath(); context.arc(pos.x+this.size/2,pos.y+this.size/2,this.size/2,Math.PI,1.5*Math.PI,false); context.stroke(); context.closePath(); break; case '0110':context.beginPath(); context.arc(pos.x-this.size/2,pos.y+this.size/2,this.size/2,1.5*Math.PI,2*Math.PI,false); context.stroke(); context.closePath(); break; case '0011':context.beginPath(); context.arc(pos.x-this.size/2,pos.y-this.size/2,this.size/2,0,.5*Math.PI,false); context.stroke(); context.closePath(); break; case '1001':context.beginPath(); context.arc(pos.x+this.size/2,pos.y-this.size/2,this.size/2,.5*Math.PI,1*Math.PI,false); context.stroke(); context.closePath(); break; default:var dist = this.size/2; code.forEach(function(v,index){if(v){context.beginPath(); context.moveTo(pos.x,pos.y); context.lineTo(pos.x-_COS[index]*dist,pos.y-_SIN[index]*dist); context.stroke(); context.closePath(); }}); }}}}}}}); //物品地图beans = stage.createMap({x:60,y:10,data:_DATA,frames:8,draw:function(context){for(var j=0; jthis.coord.x){this.orientation = 0; }else if(this.vector.xthis.coord.y){this.orientation = 1; }else if(this.vector.y80||this.times%2?true:false; }if(this.status!=4){context.fillStyle = isSick?'#BABABA':this.color; context.beginPath(); context.arc(this.x,this.y,this.width*.5,0,Math.PI,true); switch(this.times%2){case 0:context.lineTo(this.x-this.width*.5,this.y+this.height*.4); context.quadraticCurveTo(this.x-this.width*.4,this.y+this.height*.5,this.x-this.width*.2,this.y+this.height*.3); context.quadraticCurveTo(this.x,this.y+this.height*.5,this.x+this.width*.2,this.y+this.height*.3); context.quadraticCurveTo(this.x+this.width*.4,this.y+this.height*.5,this.x+this.width*.5,this.y+this.height*.4); break; case 1:context.lineTo(this.x-this.width*.5,this.y+this.height*.3); context.quadraticCurveTo(this.x-this.width*.25,this.y+this.height*.5,this.x,this.y+this.height*.3); context.quadraticCurveTo(this.x+this.width*.25,this.y+this.height*.5,this.x+this.width*.5,this.y+this.height*.3); break; }context.fill(); context.closePath(); }context.fillStyle = '#FFF'; if(isSick){context.beginPath(); context.arc(this.x-this.width*.15,this.y-this.height*.21,this.width*.08,0,2*Math.PI,false); context.arc(this.x+this.width*.15,this.y-this.height*.21,this.width*.08,0,2*Math.PI,false); context.fill(); context.closePath(); }else{context.beginPath(); context.arc(this.x-this.width*.15,this.y-this.height*.21,this.width*.12,0,2*Math.PI,false); context.arc(this.x+this.width*.15,this.y-this.height*.21,this.width*.12,0,2*Math.PI,false); context.fill(); context.closePath(); context.fillStyle = '#000'; context.beginPath(); context.arc(this.x-this.width*(.15-.04*_COS[this.orientation]),this.y-this.height*(.21-.04*_SIN[this.orientation]),this.width*.07,0,2*Math.PI,false); context.arc(this.x+this.width*(.15+.04*_COS[this.orientation]),this.y-this.height*(.21-.04*_SIN[this.orientation]),this.width*.07,0,2*Math.PI,false); context.fill(); context.closePath(); }}}); }items = stage.getItemsByType(2); //主角player = stage.createItem({width:30,height:30,type:1,location:map,coord:{x:13.5,y:23},orientation:2,speed:2,frames:10,update:function(){var coord = this.coord; if(!coord.offset){if(this.control.orientation!='undefined'){if(!map.get(coord.x+_COS[this.control.orientation],coord.y+_SIN[this.control.orientation])){this.orientation = this.control.orientation; }}this.control = {}; var value = https://www.it610.com/article/map.get(coord.x+_COS[this.orientation],coord.y+_SIN[this.orientation]); if(value==0){this.x += this.speed*_COS[this.orientation]; this.y += this.speed*_SIN[this.orientation]; }else if(value<0){this.x -= map.size*(map.x_length-1)*_COS[this.orientation]; this.y -= map.size*(map.y_length-1)*_SIN[this.orientation]; }}else{if(!beans.get(this.coord.x,this.coord.y)){ //吃豆_SCORE++; beans.set(this.coord.x,this.coord.y,1); if(_GOODS[this.coord.x+','+this.coord.y]){ //吃到能量豆items.forEach(function(item){if(item.status==1||item.status==3){ //如果NPC为正常状态,则置为临时状态item.timeout = 450; item.status = 3; }}); }}this.x += this.speed*_COS[this.orientation]; this.y += this.speed*_SIN[this.orientation]; }},draw:function(context){context.fillStyle = '#FFE600'; context.beginPath(); if(stage.status!=3){ //玩家正常状态if(this.times%2){context.arc(this.x,this.y,this.width/2,(.5*this.orientation+.20)*Math.PI,(.5*this.orientation-.20)*Math.PI,false); }else{context.arc(this.x,this.y,this.width/2,(.5*this.orientation+.01)*Math.PI,(.5*this.orientation-.01)*Math.PI,false); }}else{ //玩家被吃if(stage.timeout) {context.arc(this.x,this.y,this.width/2,(.5*this.orientation+1-.02*stage.timeout)*Math.PI,(.5*this.orientation-1+.02*stage.timeout)*Math.PI,false); }}context.lineTo(this.x,this.y); context.closePath(); context.fill(); }}); //事件绑定stage.bind('keydown',function(e){switch(e.keyCode){case 13: //回车case 32: //空格this.status = this.status==2?1:2; break; case 39: //右player.control = {orientation:0}; break; case 40: //下player.control = {orientation:1}; break; case 37: //左player.control = {orientation:2}; break; case 38: //上player.control = {orientation:3}; break; }}); })(); //结束画面 (function(){var stage = game.createStage(); //游戏结束stage.createItem({x:game.width/2,y:game.height*.35,draw:function(context){context.fillStyle = '#FFF'; context.font = 'bold 48px Helvetica'; context.textAlign = 'center'; context.textBaseline = 'middle'; context.fillText('GAME OVER',this.x,this.y); }}); //记分stage.createItem({x:game.width/2,y:game.height*.5,draw:function(context){context.fillStyle = '#FFF'; context.font = '20px Helvetica'; context.textAlign = 'center'; context.textBaseline = 'middle'; context.fillText('FINAL SCORE: '+(_SCORE+50*Math.max(_LIFE-1,0)),this.x,this.y); }}); //事件绑定stage.bind('keydown',function(e){switch(e.keyCode){case 13: //回车case 32: //空格_SCORE = 0; _LIFE = 3; var st = game.setStage(1); st.reset(); break; }}); })(); game.init(); })();


游戏截图 JS+HTML实现经典游戏吃豆人
文章图片

JS+HTML实现经典游戏吃豆人
文章图片

操作说明 ,按键盘上下左右键移动 ,按键盘空格键暂停!
到此这篇关于JS+HTML实现经典游戏吃豆人的文章就介绍到这了,更多相关JS吃豆人游戏内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    推荐阅读