如何用H5实现好玩的2048小游戏

  发布时间:2022-07-18 15:34:39   作者:岚尹_Nicole   我要评论
相信大多数读者都玩过一款小游戏 2048,本文主要介绍了如何用H5实现好玩的2048小游戏,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、游戏介绍

相信大多数读者都玩过一款小游戏 2048,这款数字小游戏在几年前很是流行。2048是2014年由Gabriele Cirulli利用周末的时间写出的,果然大佬就是大佬,一个周末就写出了这么经典的游戏。游戏的玩法非常简单,利用上、下、左、右移动的方式拼出2048即算赢得游戏,因为游戏上手简单同时赢得游戏又存在一定难度,所以游戏的可玩性很高,本人当时也是十分喜爱这款游戏,下面讲解下如何用H5去实现这款游戏。

二、游戏界面

游戏界面十分简单,我截图了进行中的几个场景,基本由一块矩形游戏区,一个按钮及一个分数展示区域组成。

三、代码设计

H5代码:

H5代码十分简单,主要用16个div代表16个数字方块,再加上另外restart按钮区,还有一个分值展示区域。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
    <title>2048</title>
     <link type="text/css" rel="stylesheet" href="css/style.css">
    <script type="text/javascript" language="javascript" src="js/jquery-3.6.0.min.js">
    	
   		document.addEventListener('plusready', function(){
   			//console.log("所有plus api都应该在此事件发生后调用,否则会出现plus is undefined。"	
   		});
   		
    </script>
    
    <script type="text/javascript" language="javascript" src="js/gamerun.js"></script>
</head>
	<body onload="init()">
	<div class="authorized" >
	<p>2048</p></div>
	<div class="restart" ontouchstart="restart()">Restart </div>
	<div class="score">
	<p class="maxnum" id="num_p">最高值</p>
	<p class="maxnum" id="num_v">0</p>
	</div>
   <article class="game"> 
     <div class="square"  id="f1"> </div>
     <div class="square"  id="f2"> </div>
     <div class="square"  id="f3"> </div>
     <div class="square"  id="f4"> </div>
     <div class="square"  id="f5"> </div>
     <div class="square"  id="f6"> </div>
     <div class="square"  id="f7"> </div>
     <div class="square"  id="f8"> </div>
     <div class="square"  id="f9"> </div>
     <div class="square"  id="f10"></div>
     <div class="square"  id="f11"> </div>
     <div class="square"  id="f12"></div>
     <div class="square"  id="f13"> </div>
     <div class="square"  id="f14"></div>
     <div class="square"  id="f15"> </div>
     <div class="square"  id="f16"> </div>  
  </article>
   <audio id="yin" src="media/anniu.mp3"autoplay="autoplay"> </audio>
  <footer></footer>
</body>
</html>

js代码:

js代码相对复杂一些,游戏处理逻辑主要可以分成以下两块:

(1)移动处理逻辑,游戏玩法是通过上下左右移动进行数字的相加变换。那么首先就会有上滑、下滑、左滑、右滑四个处理函数。上下滑动的时候,将相邻两行相同的数值进行相加;左右滑动的时候,将相邻两列相同的数值进行相加。

(2)移动判断逻辑。

首先第一类判断逻辑是判断是否可以移动。整个游戏区是 4X4的格局分布,那么在上下左右移动的时候我们会通过相邻的两行或者两列是否存在相同的数值去判断,如果有则可以继续移动,如果没有,则不可以继续移动。

其次,我们需要判断游戏是否可以继续,如果整个游戏区的数值方块已经被占满,上下左右都没有移动空间了,那么游戏就是结束了,game over。

(3)其余逻辑

其余的还剩一些比较简单的逻辑,颜色分配函数、重新开始函数、最大分值记录函数等。

// JavaScript Document
var flag=[false,false,false,false,false,false,false,false,
     false,false,false,false,false,false,false,false];
var ds=document.getElementsByClassName("square");
var color=["#FF9966","#FFCCCC","#CC9966","#99CCCC","#99CC99","#99CCFF","#CCCCFF","#FFCC00","#333399","#CC9999","#009999","#996666","#CCCCCC","#CCCCFF","#99CC99"];
var max_num=parseInt("2");
var lose_view=false;
 
  function init()  //初始化界面,生成2个数字方块
 {
	 var i=Math.round(Math.random()*16);
	 var j=Math.round(Math.random()*16);
   while(i==j)
	 { j=Math.round(Math.random()*16);
	 }
   ds[i].style.backgroundColor="#FF7578";
   ds[j].style.backgroundColor="#FF7578"; 
   ds[i].innerHTML="2";
   ds[j].innerHTML="2";
  flag[i]=true;
  flag[j]=true;
  document.body.addEventListener('load',load(event),false);
  //var msg=parseInt(document.getElementsByClassName("authorized")[0].innerText);
  //alert(msg);
  }
  
function max_score()   //记录取得的最大分数
{
	for (var i=0;i<ds.length;i++){
		var c_num = parseInt(ds[i].innerText);
		if( c_num > max_num ) 
		{
			max_num=c_num;
		}	
	}
   document.getElementById("num_v").innerHTML= max_num;
}
 function restart()  //重新开始游戏,重新回到初始化页面
 {
	 if(lose_view==true)
	 {  
		 var $h2=document.getElementById("reset1");
		// var $bu2=document.getElementById("reset2");
		 var $par2=$("body");	
		  $par2[0].removeChild($h2);
		 // $par2[0].removeChild($bu2);
		lose_view=false; 
		
	 }
 	 for (var i=0;i<ds.length;i++)
 	 {
 		 ds[i].innerHTML="";
 		 flag[i]=false;
 		ds[i].removeAttribute("style");
 	 }
 	 init();
 } 
 
 
 
 function voice()   //设置移动时产生的音效
{
var vs=document.getElementById("yin");
vs.play();
}
 
 
 
function load(event)   // 捕捉屏幕滑动事件
{
$("body").on("touchstart", function(e) {
    e.preventDefault();
    startX = e.originalEvent.changedTouches[0].pageX,
    startY = e.originalEvent.changedTouches[0].pageY;
});
$("body").on("touchend", function(e) 
{
    e.preventDefault();
    moveEndX = e.originalEvent.changedTouches[0].pageX,
    moveEndY = e.originalEvent.changedTouches[0].pageY,
    X = Math.floor(moveEndX - startX),
    Y = Math.floor(moveEndY - startY);
 
    if ( Math.abs(X)> Math.abs(Y)) 
    {
    	if (Math.abs(X)>20)
    	{
    		if( X > 0)
    		{
    		rightgo();
    		voice();
    		}
    		else
    		{
    		leftgo();
    		voice();
    		}
    	}
	 }
    else if(Math.abs(X)< Math.abs(Y))
    {
    	if (Math.abs(Y)>20)
    	{
    		if(Y > 0)
    		{
    		 bottomgo();
    		 voice();
    		}
    		
    		else
    		{
    		topgo();
    		voice();
    		}
    	}
    }
}
);
}
 
 
 
function addcolor()            //设置方块颜色
 { for(var i=0;i<ds.length;i++)
 {
	 var ss=parseInt(ds[i].innerHTML);
	 
	 switch(ss)
	{
	case 2:
	ds[i].style.backgroundColor=color[0];
	break;
	case 4:
	ds[i].style.backgroundColor=color[1];
	break;
	case 8:
	ds[i].style.backgroundColor=color[2];
	break;
	case 16:
	ds[i].style.backgroundColor=color[3];
	break;
	case 32:
	ds[i].style.backgroundColor=color[4];
	break;
	case 64:
	ds[i].style.backgroundColor=color[5];
	break;
	case 128:
	ds[i].style.backgroundColor=color[6];
	break;
	case 256:
	ds[i].style.backgroundColor=color[7];
	break;	
	case 512:
	ds[i].style.backgroundColor=color[8];
	break; 
	case 1024:
	ds[i].style.backgroundColor=color[9];
	break;
	case 2048:
	ds[i].style.backgroundColor=color[10];
	break;
	case 4096:
	ds[i].style.backgroundColor=color[11];
	break;
	case 8192:
	ds[i].style.backgroundColor=color[12];
	break;
	case 16384:
	ds[i].style.backgroundColor=color[13];
	break;
	default:
	break;
		 }
 }
	 }
 
function istop()
{  					//判断是否可以继续上移,true则表示可以
	var istop=false;
 
	for(var i1=4;i1<16;i1++) 
	{
		
     if(flag[i1]==true)
	 {  
	
		 if(flag[i1-4]==true)
     	 {
		  if( ds[i1].innerHTML==ds[i1-4].innerHTML )
		 	{
			  istop=true;
		 	}
		    
      		}
	    else
		  {
			istop=true;
		 }
		 } 	 
		}
 
	return istop;
}
 
function isbottom()  //判断是否可以继续下移,true则表示可以
{
	var isbottom=false;
	
	for(var i2=11;i2>=0;i2--)
	
	{
     if(flag[i2]==true)
	 {
		 if(flag[i2+4]==true)
      {
		  if( ds[i2].innerHTML==ds[i2+4].innerHTML )
		  
		 {
			  isbottom=true;
		 }
		  }
		  
		  else
		  
		  {
			isbottom=true;
		 }
		 } 	 
		}
	
	return isbottom;
}
 
function isleft(){  //判断是否可以继续左移,true则表示可以
	var isleft=false;
 
	for(var i3=0;i3<4;i3++)
	{
		for(var j3=0;j3<3;j3++)
	{
		 if(flag[j3+4*i3+1]==true)
	 {
		 if(flag[j3+4*i3]==true)
         {
	 if( ds[j3+4*i3].innerHTML==ds[j3+4*i3+1].innerHTML )
		 {
		  isleft=true;
		 }
		  }
		  else
		  {
			isleft=true;
			
		 }
		    }	 
	}
  }
 
 return isleft;
}
 
function isright(){     //判断是否可以继续右移,true则表示可以
	var isright=false;
	
	for(var i4=3;i4>=0;i4--)
	{
		for(var j4=2;j4>=0;j4--)
	{
		 if(flag[j4+4*i4]==true)
	 {
		 if(flag[j4+4*i4+1]==true)
      {
		   if( ds[j4+4*i4].innerHTML==ds[j4+4*i4+1].innerHTML )
		   {
		  isright=true;
		   }
		  }
		  else
		  {
			isright=true;
			  }
		 }	 
			}
	}
	
	return isright;
}
 
function islose()
{                //判断是否输掉游戏
   if (lose_view==false) {
	 var los=0;
	 for(var i5=0;i5<16;i5++)
	 { if(flag[i5]==true)
	   {
		   los++;
		   }
		 }
		 if(los==16)
		 {
			 var left=isleft();
             var right=isright();
			 var top=istop();
			 var bottom=isbottom();
			 
			 if((left||right||top||bottom)==false)
			 {	
				max_score();	
				var $h1=$('<div>');
				//var $bu1=$('<button>');
				var $par=$("body");
				$h1.attr("id","reset1");
				$h1.text('Game Over !');
				//$bu1.text('重新开始');
				//$bu1.attr("id","reset2");		
				$par.append($h1);
				//$par.append($bu1);
				
			var sleep = function(time) {
			    var startTime = new Date().getTime() + parseInt(time, 10);
			    while(new Date().getTime() < startTime) {}
			};
			lose_view=true;
		
			 //跳出失败提醒界面				
			//$bu1.click(restart());
			
			//$("body").on("touchend",restart());			
			//$("body").on("touchstart",function (){
			//	  $par[0].removeChild($h1[0]);
			// $par[0].removeChild($bu1[0]);
			// restart();
			//  });
			
			 }
  		}
	}
}
 
 
function topgo(){   
             //上移
	var top1=istop(); 
 
	for(var ss6=0;ss6<3;ss6++)
	{
	for(var i6=4;i6<16;i6++)
	{
     if(flag[i6]==true)
	 {
		 if(flag[i6-4]==true)
      {
		  if( ds[i6].innerHTML==ds[i6-4].innerHTML )
		{  var sum=parseInt(ds[i6].innerHTML)*2;
		  ds[i6-4].innerHTML=sum;
		  flag[i6]=false;
		  ds[i6].removeAttribute("style");
		  ds[i6].innerHTML="";
		}
		  }
		  else
		  {
			ds[i6-4].innerHTML=ds[i6].innerHTML;
			 ds[i6-4].style.backgroundColor="#FF9E3E";
			flag[i6-4]=true;
			 
			ds[i6].innerHTML="";
			ds[i6].removeAttribute("style");
			flag[i6]=false;		
		 }
		 } 	 
		}
		}
       
		if(top1==true) 
		{
		var kk1=Math.round(Math.random()*15);
		while(flag[kk1]==true)
		{
			var kk1=Math.round(Math.random()*15);
			}
         ds[kk1].innerHTML="2";
		 flag[kk1]=true;
	    addcolor();
	  
		}
		else
		{
			islose();
			}
	}
 
function leftgo(){                      //左移
	var left1=isleft();
	for(var ss7=0;ss7<3;ss7++)
	{
	for(var i7=0;i7<4;i7++)
	{
		for(var j7=0;j7<3;j7++)
	{
		 if(flag[j7+4*i7+1]==true)
	 {
		 if(flag[j7+4*i7]==true)
      {
		  if( ds[j7+4*i7].innerHTML==ds[j7+4*i7+1].innerHTML )
		{  var sum=parseInt(ds[j7+4*i7+1].innerHTML)*2;
		  ds[j7+4*i7].innerHTML=sum;
		  flag[j7+4*i7+1]=false;
		  ds[j7+4*i7+1].removeAttribute("style");
		  ds[j7+4*i7+1].innerHTML="";
		}
		  }
		  else
		  {
			ds[j7+4*i7].innerHTML=ds[j7+4*i7+1].innerHTML;
			 ds[j7+4*i7].style.backgroundColor="#FF9E3E";
			flag[j7+4*i7]=true;
			 
			ds[j7+4*i7+1].innerHTML="";
			ds[j7+4*i7+1].removeAttribute("style");
			flag[j7+4*i7+1]=false;
			
			  }
		 }	 
			}
	}
	}
	
	if(left1==true){
	var kk2=Math.round(Math.random()*15);
		while(flag[kk2]==true)
		{
			var kk2=Math.round(Math.random()*15);
			}
		 ds[kk2].style.backgroundColor="#FF9E3E";
         ds[kk2].innerHTML="2";
		 flag[kk2]=true;
	addcolor();
}
   else
   {
	   islose();
	   }
}
 
function rightgo(){                //右移
	var right1=isright();
	for(var ss8=0;ss8<3;ss8++)
	{
	for(var i8=3;i8>=0;i8--)
	{
		for(var j8=2;j8>=0;j8--)
	{
		 if(flag[j8+4*i8]==true)
	 {
		 if(flag[j8+4*i8+1]==true)
      {
		  if( ds[j8+4*i8].innerHTML==ds[j8+4*i8+1].innerHTML )
		{  var sum=parseInt(ds[j8+4*i8+1].innerHTML)*2;
		  ds[j8+4*i8+1].innerHTML=sum;
		  flag[j8+4*i8]=false;
		  ds[j8+4*i8].removeAttribute("style");
		  ds[j8+4*i8].innerHTML="";
		}
		  }
		  else
		  {
			ds[j8+4*i8+1].innerHTML=ds[j8+4*i8].innerHTML;
			 ds[j8+4*i8+1].style.backgroundColor="#FF9E3E";
			flag[j8+4*i8+1]=true;
			 
			ds[j8+4*i8].innerHTML="";
			ds[j8+4*i8].removeAttribute("style");
			flag[j8+4*i8]=false;
			
			  }
		 }	 
			}
	}}
	
	if(right1==true){
	var kk3=Math.round(Math.random()*15);
		while(flag[kk3]==true)
		{
			var kk3=Math.round(Math.random()*15);
			}
		 ds[kk3].style.backgroundColor="#FF9E3E";
         ds[kk3].innerHTML="2";
		 flag[kk3]=true;
	addcolor();
	}
	else
	{
		islose();
		}
		
	//	var ss=max_score();
		//alert(ss);
}
 
function bottomgo(){                 		//下移
	var bottom1=isbottom();
	for(var ss9=0;ss9<3;ss9++)
	{
	for(var i9=11;i9>=0;i9--)
	{
     if(flag[i9]==true)
	 {
		 if(flag[i9+4]==true)
      {
		  if( ds[i9].innerHTML==ds[i9+4].innerHTML )
		{  var sum=parseInt(ds[i9].innerHTML)*2;
		  ds[i9+4].innerHTML=sum;
		  flag[i9]=false;
		  ds[i9].removeAttribute("style");
		  ds[i9].innerHTML="";
		}
		  }
		  else
		  {
			ds[i9+4].innerHTML=ds[i9].innerHTML;
			 ds[i9+4].style.backgroundColor="#FF9E3E";
			flag[i9+4]=true;
			 
			ds[i9].innerHTML="";
			ds[i9].removeAttribute("style");
			flag[i9]=false;
			
		 }
		 } 	 
		}
	}
	    
		if(bottom1==true){
		var kk4=Math.round(Math.random()*15);
		while(flag[kk4]==true)
		{
			var kk4=Math.round(Math.random()*15);
			}
		 ds[kk4].style.backgroundColor="#FF9E3E";
         ds[kk4].innerHTML="2";
		 flag[kk4]=true;
		 addcolor()
		 }
		 else
		 {
			islose();
			 }
}

css代码:

@charset "utf-8";
/* CSS Document */
body,html{
	height:100vw;
	width: 100vw;
	padding: 0;
	margin: 0;
	background:fixed;
	background-color: papayawhip;
	}
	
.authorized {
	color: grey;
	margin-left: 2%;
	text-align:center;
	font-style: normal;
	font-size:210%;
	margin-top:10%;
	width: 30%;
   }
   
.restart {
	position: absolute;
	margin-left: 5%;
	width: 25vw;
	height: 10vw;
	padding-top:5%;
	text-align:center;
	font-size: 22px;
	background-color:#99CCCC;
	color: white;
	border-radius: 5% 5% 5% 5%;
}
   
.score {
	position: absolute;
	margin-left: 50%;
	padding-top: 2%;
	width:45vw ;
	background-color:#99CCCC;
	color: white;
	border-radius:5% 5% 5% 5%;
}
 
.maxnum {	
	position: relative;
	float:left;
	margin-left: 3%;
	font-size: 120%;
	text-align: center;
	color: white;
	width: 40%;
	height: 4vw;
}
#num_p {
	margin-top: 5%;
	margin-left: 5%;
}
#num_v {
	margin-top: 5%;
	color:#ffd700;
	font-size: 25px;}
  
.game{
	position:absolute;
   	top:30% ;
	left:2.5%;
	width:95vw;
    height:95vw;
	background-color:#AAAA; 
	border-radius:5% 5% 5% 5%;
	     }
		 
 #reset1{
	position:absolute;
	top:30% ;
	left:2.5%;
	width:95vw;
	height:60vw;
	font-size: 40px;
	background: rgba(250,250,250,0.5);
	text-align: center;
	padding-top: 35%;
	color: grey;
	border-radius:5% 5% 5% 5%;} 
 
#reset2 {
position:absolute;
width: 30vw;
height: 13vw;
margin:70% 20% 30% 35%;
font-size: 20px;
padding-left: 0.125rem;
background-color: lightsalmon;
font-weight: bold;
color: white;
border-radius:5% 5% 5% 5%;
}
 
.square{
	position:relative;
	width:23%;
	height:23%;
    line-height: 180%; /*行高,指的是两行文字基线之间的距离,又可以称为这行文字所占的高度 */
	float:left;
	background-color:#DDDDDD;
	border-radius:15% 15% 15% 15%;
	margin:1% 1% 1% 1%;
	color:white;
	text-align:center;
	font-size:12vw;
	}
 

四、源码及APK

可以利用Hbuilder将H5代码打包成移动端应用,这样我们就可以在手机端安装APP愉快的玩耍了。下面是我打包的安卓包,点击自取:2048-touch_jb51.rar

到此这篇关于如何用H5实现好玩的2048小游戏的文章就介绍到这了,更多相关HTML5实现2048游戏内容请搜索脚本之家以前的文章或继续浏览下面的相关文章,希望大家以后多多支持脚本之家!

相关文章

  • uniapp在h5页面实现扫码功能(html5-qrcode)

    这篇文章主要介绍了uniapp在h5页面实现扫码功能(html5-qrcode),本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2024-06-11
  • HTML5中的A 标签详解

    a 元素可通过其href属性创建指向其他网页、文件、同一页面内的位置或其他URL的超链接,这篇文章主要介绍了HTML5中的A 标签,需要的朋友可以参考下
    2024-05-28
  • HTML5中的Button 标签示例详解

    button 用于显示一个可点击的按钮,可用在表单或文档的其它地方,button元素是内联双标签,不同浏览器下button样式不同,可以通过CSS修改,这篇文章主要介绍了HTML5 中的Bu
    2024-05-28
  • 关于document.body.clientHeight返回值为0的完美解决方案

    这篇文章主要介绍了关于document.body.clientHeight返回值为0的完美解决方案,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2024-05-16
  • HTML5兼容HEVC视频格式且支持本地绝对路径访问的操作方法

    通过PotPlayer发现该MP4文件的编码格式为HEVC,而video标签不支持该编码格式的视频文件,这篇文章主要介绍了HTML5兼容HEVC视频格式且支持本地绝对路径访问,需要的朋友可以
    2024-05-15
  • HTML5 服务器发送事件(Server-Sent Events)使用详解

    HTML5服务器发送事件(server-sent event)允许网页获得来自服务器的更新,下面通过本文给大家介绍HTML5 服务器发送事件(Server-Sent Events)使用详解,感兴趣的朋友跟随小
    2024-05-15
  • html5 video 标签 controlslist详细使用

    video controlslist 属性可以用于告诉浏览器在视频播放过程中应该显示哪些默认的用户界面控件,下面我们将从几个方面来介绍 video controlslist 的详细使用,感兴趣的朋友跟
    2024-05-15
  • html网页播放多个视频的几种方法

    本文主要介绍了html网页播放多个视频的几种方法,包含iframe标签,VLC插件和一些常见的js插件,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-04
  • HTML5中video标签禁止右键和下载视频的问题解决

    做HTML5的video标签,本身我们有下载功能,由于权限问题,所以本文就来介绍一下HTML5中video标签禁止右键和下载视频的问题解决,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-28
  • html5 video标签controlslist的具体使用

    HTML5 提供了内置的视频播放控件,其中 video controlslist 是其中一个很有用的属性,本文主要介绍了html5 video标签controlslist的具体使用,具有一定的参考价值,感兴趣
    2024-02-27

最新评论