当前位置: 首页 > Web前端 > vue.js

小小乐游戏vue版(pc-手机均可在线体验,附源码)

时间:2023-03-31 14:49:35 vue.js

游戏名称:酷一侠小小乐技术栈:Vue3+TypeScript+Vite+Element-Plus游戏体验地址(pc/mobile):https://wmuhua.com/games/xxl开源地址:https://github.com/wmuhua/vue...点赞留香,不胜荣幸,谢谢,感谢游戏介绍,先看看吧,我知道界面有点难看→_→主要步骤游戏的功能有:消除、下落、补充、移动,使用三种状态来区分需要删除(remove)、新增(add)、和普通方块(normal)。主要是生成一个小块的列表,立即保存每个块的信息,上下左右,然后判断每个块是上下还是左右相同的类型。它需要被消除。更改块的状态以移除然后更改顶部和左侧以控制下降。同时将被淘汰的职位上移,以填补相应的空缺。如上图,这里特地用了一个矩阵来存储对应的所有网格信息。区分需要消去/补充哪些格子比较简单。由于每个方块都有自己的上、下、左、右信息,所以只需要交换即可。就是这样。有个坑,这是关键。由于diff算法,需要在不重新渲染的情况下保证key的唯一性。比如掉下来重新渲染视觉效果会很奇怪。下面核心代码html是矩阵区域的所有html,就是用一个div做的,根据类型给不同的类名,然后冰淇淋都是一个背景图

jsjs部分主要封装了一个类,方便统一管理和操作:number//方块大小typeCount=7//方块类型数matrix:Array=[]//方块矩阵,用于每次消除后根据矩阵规则生成新的游戏盘data:Array=[]//在渲染页面使用isHandle=false//游戏是否被淘汰/掉落/添加isSelect=false//是否有选择score=0//scoretarget1:any={active:false}//selectedsquaretarget2:any={}constructor(x:number,y:number,size:number){this.x=xthis.y=ythis.size=sizethis.getMatrix()//生成矩阵this.init(true)//生成用于渲染的数据}getMatrix(){}init(){}//循环gameLoop(){}//点击click(){}//换位swap(){}//删除remove(){}//下拉(){}//补充add(){}}gamestart/loop//等待动画结束,所以使用awaitasyncgameLoop(bool:boolean=false){//游戏结束时将分数清零并重新开始if(bool)this.score=0//游戏状态变为正在执行,动画执行期间不能点击和交换控件this.isHandle=true//找到需要删除的awaitthis.remove()//用于检测点击后交换,判断是否需要删除,如果没有,再改回来letstatus=this.data.some((item)=>item.status==="remove")//只要有删除的东西,就执行上面的去向和补充,然后循环查找supplementNothingtoremovewhile(this.data.some((item)=>item.status==="remove")){awaitthis.down()awaitthis.add()awaitthis.remove()}//删除所有可以删除的东西后,更改状态,然后可以点击this.isHandle=falsereturnstatus}删除。注意remove的状态并不是真的删除了,只是在页面上看不到而已。补充的时候会删掉。remove//清除remove(){returnnewPromise((resolve,reject)=>{const{data}=thisdata.forEach((item)=>{const{left,right,top,bottom,type}=item//如果self+self的左右类型相同,则status变为deleteif(left?.type==type&&right?.type==type){left.status="remove"item.status="remove"right.status="remove"}//如果self+self的top和bottom类型相同,状态变为deleteif(top?.type==type&&bottom?.type==type){top.status="remove"item.status="remove"bottom.status="remove"}})setTimeout(()=>{//执行删除动画,页面不可见,统计分数,但是数据还没有被删除forEach((item,index)=>{if(item.status==="remove"){item.scale=0this.score+=1}})//延迟100毫秒这里是第一次进入页面的时候,首先看grid里面有东西,不然就是空的},100)//动画时长是500毫秒,css定义的,所以延时500毫秒setTimeout(()=>{resolve(true)},500)})}行踪有一个坑,除了把行踪放到删除的格子上,还需要把行踪放在删除的(状态是删除,不可见page)grid到上面的空白区域,否则,新添加的Grid会从下面弹出//falldown(){returnnewPromise((resolve,reject)=>{const{data,size,x,y}=thisdata.forEach((item,index)=>{让distance=0//移动的格子个数if(item.status==="remove"){//将删除的位置上移,调整新增格子的位置lettop=item.top//需要移动的统计向上多少步while(top){if(top.状态!=="移除"){distance+=1}top=top.top}//向上移动if(distance){item.y-=distanceitem.positionTop=item.positionTop-size*distance}}else{letbottom=item.bottom//计算需要下降多少步while(bottom){if(bottom.status==="remove"){distance+=1}bottom=bottom.bottom}//下降if(distance){item.y+=distanceitem.positionTop=item.positionTop+size*distance}}})setTimeout(()=>{resolve(true)},500)})}add可以想象,drop执行后,矩阵中页面,它存在于所有的grid中,但是看似空的grid其实是删除的grid占据在那里,然后只要按照顺序重新生成matrix,每个非removegrid的状态为保留,移除时重新生成,达到替换补充的效果//addadd(){returnnewPromise((resolve,reject)=>{const{size,matrix}=this//重置矩阵为空this.getMatrix()//把当前所有的网格信息保存对于矩阵this.matrix=matrix.map((row,rowIndex)=>row.map((col:any,colIndex:number)=>{returnthis.data.find((item)=>{returncolIndex==item.x&&rowIndex==item.y})}))//根据需要清除的矩阵的位置替换新的方块this.init()setTimeout(()=>{//新的添加的网格执行动画this.data.forEach((item)=>{if(item.status==="add"){item.scale=1item.status="normal"}})},100)//animationendsetTimeout(()=>{resolve(true)},500)})}下面的逻辑比较简单,没什么好说的,都写在注释里了Generatematrix/data//GenerateallemptymatricesgetMatrix(){const{x,y}=thisconstrow=newArray(x).fill(undefined)constmatrix=newArray(y).fill(undefined).map((item)=>row)this.matrix=matrix}//生成小方块init(bool:boolean=false){const{x,y,typeCount,matrix,size}=thisconstdata:Array=[]//这里我们使用两个指针而不是嵌套循环来降低复杂度let_x=0let_y=0for(leti=0,len=Math.pow(x,2);i{square.left=data.find((item)=>item.x==square.x-1&&item.y==square.y)square.right=data.find((item)=>item.x==square.x+1&&item.y==square.y)square.top=data.find((item)=>item.x==square.x&&item.y==square.y-1)square.bottom=data.find((item)=>item.x==square.x&&item.y==square.y+1)})this.data=data}点击//点击小方块click(target:any){//处理游戏动画时,不给点击if(this.isHandle)return//console.log(target)const{isSelect}=this//Ifnotselectedif(!isSelect){//选择第一个target.active=truethis.target1=targetthis.isSelect=true}else{//选择第二个if(this.target1===target)returnthis.target1.active=false//如果相邻if(["left","top","bottom","right"].some((item)=>this.target1[item]==target)){this.target2=target;(async()=>{//switchpositionawaitthis.swap()//将返回消息Deleted状态letres=awaitthis.gameLoop()//如果不是,再次改变位置并恢复if(!res){awaitthis.swap()}})()this.isSelect=false}else{//如果是不相邻target.active=truethis.target1=targetthis.isSelect=true}}}改变位置这里的逻辑主要是交换两个方块的位置信息,然后重新生成上下左右,就可以了//改变位置y:y1}=target1const{positionLeft:pl2,positionTop:pt2,x:x2,y:y2}=target2setTimeout(()=>{target1.positionLeft=pl2target1.positionTop=pt2target1.x=x2target1。y=y2target2.positionLeft=pl1target2.positionTop=pt1target2.x=x1target2.y=y1data.forEach((square)=>{square.left=data.find((item)=>item.x==square.x-1&&item.y==square.y)square.right=data.find((item)=>item.x==square.x+1&&item.y==square.y)square.top=data.find((item)=>item.x==square.x&&item.y==square.y-1)square.bottom=data.find((item)=>item.x==square.x&&项目.y==square.y+1)})},0)setTimeout(()=>{resolve(true)},500)})}结语游戏名称:清凉一夏和消消乐技术栈:Vue3+TypeScript+Vite+Element-Plus游戏体验地址(pc端和手机端):https://wmuhua.com/games/xxl开源地址:https://github.com/wmuhua/vue...点赞留香,我很荣幸,谢谢,谢谢