更多开源内容请访问:开源基础软件社区https://ost.51cto.com简介小时候,有一个游戏叫俄罗斯方块。大人小孩都喜欢玩。下面就来看看如何使用OpenHarmony来学做俄罗斯方块吧。开发一、HAP应用的建立《#跟着小白一起学鸿蒙#[六]如何编写一个hap应用》我们介绍了简单的Hap应用的开发和基本控件的介绍。这里不再赘述Hap项目的建立过程。下面是基本的Hap页面文件:index.ets。build(){Row(){Column(){Canvas(this.context).width('100%').height('100%').onClick((ev:ClickEvent)=>{console.info("点击!!")this.doClick()}).onReady(()=>{this.context.imageSmoothingEnabled=falsethis.randomType()this.drawwall()})}.width('100%')}。height('100%').backgroundColor("#cccccc")}build是基础页面的构造函数,用于构造界面的元素。其他页面的生命周期函数如下:declareclassCustomComponent{/***自定义弹窗内容构造函数。*@since7*/build():void;/***aboutToAppear方法*@since7*/aboutToAppear?():void;/***aboutToDisappear方法*@since7*/aboutToDisappear?():void;/***onPageShow方法*@since7*/onPageShow?():void;/***onPageHide方法*@since7*/onPageHide?():void;/***onBackPress方法*@since7*/onBackPress?():void;}二、Canvas简介Canvas是一个用于自定义绘制图形的画布组件。具体API页面如下:https://developer.harmonyos.com/cn/docs/documentation/doc-references/ts-components-canvas-canvas-0000001333641081aboutToAppear()函数会在页面显示前调用,这是一个页面生命周期函数。canvas组件初始化后,调用onReady()函数,该函数内部实现了小游戏初始页面的绘制。(1)初始化页面数据drawall(){this.drawBox()this.drawSideBlock()this.drawBoxBlock()this.drawScore()}因为都是画在canvas上,布局有点繁琐,需要几个部分待绘制:中间大方框:方块掉落和堆叠区域。右增强框:下一个块类型。中间块:块移动和堆叠。得分如下:行数得分。(2)绘制大框drawBox(){this.context.lineWidth=4this.context.beginPath()this.context.lineCap='butt'this.context.moveTo(0,100)this.context.lineTo(270,100)this.context.moveTo(270,100)this.context.lineTo(270,690)this.context.moveTo(0,690)this.context.lineTo(270,690)}(3)绘制提示块drawSideBlock(){this.context.fillStyle='rgb(250,0,0)'让bs=this.blockSize让坐标=this.blockShapBasic[this.blockType]让x=this.sideStartX+坐标[0][0]*this.blockSize让y=this.sideStartY+coords[0][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.sideStartX+coords[1][0]*this.blockSizey=this.sideStartY+coords[1][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.sideStartX+坐标[2][0]*this.blockSizey=this.sideStartY+coords[2][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.sideStartX+coords[3][0]*this.blockSizey=this.sideStartY+coords[3][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())this.context.stroke()}(4)绘制运动块drawBoxBlock(){this.setDirection()this.context.fillStyle='rgb(250,0,0)'letbs=this.blockSizeletcoords=this.curBlockShapletstarty=this.slotStartY+this.step*this.blockSizeletx=this.slotStartX+coords[0][0]*this.blockSizelety=starty+coords[0][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.slotStartX+coords[1][0]*this.blockSizey=starty+coords[1][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.slotStartX+coords[2][0]*this.blockSizey=starty+coords[2][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.slotStartX+coords[3][0]*this.blockSizey=starty+coords[3][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())this.context.stroke()this.slotBottomY=y}(5)绘制分数区域drawScore(){this.context.fillStyle='rgb(0,0,0)'this.context.font='80pxsans-serif'this.context.fillText("Score:"+this.score.toString(),20,740)}3.游戏逻辑很简单。小游戏的主要游戏逻辑是:等待开始,开始,结束。点击[click]-->boxdeformationboxdrop-->|falltotheend|-->积累积累-->|堆到最顶层|Entry@ComponentstructIndex{@Statemessage:string='HelloWorld'私有设置:RenderingContextSettings=newRenderingContextSettings(true);私有上下文:CanvasRenderingContext2D=newCanvasRenderingContext2D(this.settings);privateblockType:number=0privatenumberblock=Size:30privateblockShapBasic=[[[0,0],[0,1],[0,2],[0,3]],[[0,0],[0,1],[0,2],[1,2]],[[0,0],[0,1],[1,1],[0,2]],[[0,0],[0,1],[1,1],[1,2]],[[0,0],[0,1],[1,0],[1,1]],]privateblockShap=[[[0,0],[0,1],[0,2],[0,3]],[[0,0],[0,1],[0,2],[1,2]],[[0,0],[0,1],[1,1],[0,2]],[[0,0],[0,1],[1,1],[1,2]],[[0,0],[0,1],[1,0],[1,1]],]privatecurBlockShap=[]privatesideStartX=300;私有端StartY=150;私人slotStartX=120;私人slotStartY=150;;;私人分数=0;私人步骤=0;私人方向=0;aboutToDisappear(){}aboutToAppear(){this.sleep(1000)}asyncsleep(ms:number){returnnewPromise((r)=>{setInterval(()=>{console.log(this.message)这个.drawStep()},ms)})}doClick(){this.direction+=1}drawBox(){this.context.lineWidth=4this.context.beginPath()this.context.lineCap='butt'this.context.moveTo(0,100)this.context.lineTo(270,100)this.context.moveTo(270,100)this.context.lineTo(270,690)this.context.moveTo(0,690)这个.context.lineTo(270,690)}setDirection(){this.curBlockShap=this.blockShap[this.blockType]if(this.direction>0){for(leti=0;i<4;i++){letx=this.curBlockShap[i][0]this.curBlockShap[i][0]=this.curBlockShap[i][1]this.curBlockShap[i][1]=x}this.direction=0}}drawSideBlock(){这个.context.fillStyle='rgb(250,0,0)'letbs=this.blockSizeletcoords=this.blockShapBasic[this.blockType]letx=this.sideStartX+coords[0][0]*this.blockSizelety=this.sideStartY+coords[0][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.sideStartX+coords[1][0]*this.blockSizey=this.sideStartY+coords[1][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.sideStartX+coords[2][0]*this.blockSizey=this.sideStartY+coords[2][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.sideStartX+coords[3][0]*this.blockSizey=this.sideStartY+coords[3][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())this.context.stroke()}drawBoxBlock(){this.setDirection()this.context.fillStyle='rgb(250,0,0)'让bs=this.blockSize让coords=this.curBlockShap让starty=this.slotStartY+this.step*this.blockSize让x=this.slotStartX+coords[0][0]*this.blockSize让y=starty+coords[0][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.slotStartX+coords[1][0]*this.blockSizey=starty+coords[1][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.slotStartX+coords[2][0]*this.blockSizey=starty+coords[2][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())x=this.slotStartX+coords[3][0]*this.blockSizey=starty+coords[3][1]*this.blockSizethis.context.fillRect(x,y,bs,bs)this.context.rect(x,y,bs,bs)console.info("x,y"+x.toString()+":"+y.toString())this.context.stroke()this.slotBottomY=y}drawScore(){this.context.fillStyle='rgb(0,0,0)'this.context.font='80pxsans-serif'this.context.fillText("Score:"+this.score.toString(),20,740)}randomType(){this.blockType=Math.floor(Math.random()*5)控制台。info("blocktype:"+this.blockType.toString())}drawStep(){this.context.clearRect(0,0,this.context.width,this.context.height)this.step+=1这个。drawBox()this.drawSideBlock()this.drawBoxBlock()this.drawScore()if(this.slotBottomY>=660){this.step=0this.randomType()}}drawall(){this.drawBox()这个.drawSideBlock()this.drawBoxBlock()次is.drawScore()}build(){Row(){Column(){Canvas(this.context).width('100%').height('100%').onClick((ev:ClickEvent)=>{console.info("click!!")this.doClick()}).onReady(()=>{this.context.imageSmoothingEnabled=falsethis.randomType()this.drawall()})}.width('100%')}.height('100%').backgroundColor("#cccccc")}}遗留问题:没有实现累计计分(接下来会做),可以实现网络对战(分布式对战)。5.获取源代码等游戏完整发布,会有单机版和网络版两个版本。小结本文主要介绍小游戏的开发和canvas功能的使用。了解更多开源知识,请访问:开源基础软件社区https://ost.51cto.com。
