这篇“怎么用git实现羊了个羊游戏”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“怎么用git实现羊了个羊游戏”文章吧。
以下就是基础的Hap的page文件:index.ets
build() { Row() { Column() { Canvas(this.context) .width('100%') .height('100%') .onClick((ev: ClickEvent) => { console.log("screen.xy:"+ev.screenX+":"+ev.screenY) console.log("xy:"+ev.x+":"+ev.y) }) .onReady(() =>{ this.context.imageSmoothingEnabled = false this.drawBlock() }) } .height("80%") .width("100%") } .height('100%') .width('100%') .backgroundImage($r("app.media.grass")) .backgroundImageSize(ImageSize.Cover) }
build是基础页面的构造函数,用于界面的元素构造,其他的页面的生命周期函数如下:
declare class CustomComponent { /** * Customize the pop-up content constructor. * @since 7 */ build(): void; /** * aboutToAppear Method * @since 7 */ aboutToAppear?(): void; /** * aboutToDisappear Method * @since 7 */ aboutToDisappear?(): void; /** * onPageShow Method * @since 7 */ onPageShow?(): void; /** * onPageHide Method * @since 7 */ onPageHide?(): void; /** * onBackPress Method * @since 7 */ onBackPress?(): void; }
canvas是画布组件用于自定义绘制图形
页面显示前会调用aboutToAppear()函数,此函数为页面生命周期函数
canvas组件初始化完毕后会调用onReady()函数,函数内部实现小游戏的初始页面的绘制
initBlocks() { for (let i=0;i<this.avaliableCnt;i++) { let lineCn = Math.floor(i/3) let rowCn = Math.floor(i%3) if (lineCn == 0) { this.blockList[i] = { img: "censer", isShow: true, x: this.startX+rowCn*30, y: this.startY, w: 55, h: 53, } } else if (lineCn == 1) { this.blockList[i] = { img: "cloud", isShow: true, x: this.startX+rowCn*30, y: this.startY+lineCn*90, w: 55, h: 53, } } else if (lineCn == 2) { this.blockList[i] = { img: "knif", isShow: true, x: this.startX+rowCn*30, y: this.startY+lineCn*90, w: 55, h: 53, } } } }
小游戏的每个卡片都是用canvas绘制的图片资源,用于进行排列以及点击判断所以在此设计了个数据结构
{ img: 卡片资源类型,用于图片渲染和相似图片消除 isShow: 卡片是否显示标志,用于渲染的时候进行判断 x:卡片渲染左上角横坐标 y:卡片渲染左上角纵坐标 w:卡片渲染宽度 h: 卡片渲染高度 }
现在制作的是用固定方法初始化卡片的方法即渲染3行,每行3个图片,之后改进可以改成明确一个区域,然后采用随机算法进行位置和卡片类型生成。
drawBlock() { //初始化消除区域的卡片 this.blockList.forEach((block)=>{ if (block.isShow) { let imgItem:ImageBitmap = null switch(block.img) { case "censer": imgItem = this.censerImg break case "cloud": imgItem = this.cloudImg break case "knif": imgItem = this.knifImg break default: imgItem = this.censerImg break } this.context.drawImage( this.cardImg,block.x,block.y,this.blockw,this.blockh) this.context.drawImage( imgItem,block.x+5,block.y+5,block.w,block.h) } }) //初始化选择卡片区域 this.context.drawImage( this.slotImg,this.slotX,this.slotY,300,39) let pos = 0 for (let i=0;i<5;i++) { this.context.drawImage( this.cardImg,this.slotX + pos,this.slotY+40,61,69) if (i < this.emptyList.length) { let emptyText = this.emptyList[i] let pItem = null; switch (emptyText) { case "censer": pItem = this.censerImg; break; case "cloud": pItem = this.cloudImg; break; case "knif": pItem = this.knifImg; break; default: break; } if (pItem) { this.context.drawImage(pItem,this.slotX + pos + 3,this.slotY+40,55,59) } } pos += 60 } }
整个绘制区域分两个区域:
消除区域:绘制卡片背景和卡片类型,利用初始化的卡片数据进行卡片绘制;
选择区域:绘制栏杆,卡片背景,以及选择的卡片
简单的小游戏主体游戏逻辑为:初始化(之前的章节已经介绍),点击(选中,选不中,消除,选择区域满,消除区域空)流程图如下:
graph LR init[初始化] --> click[点击] click[点击] --> isSelect{是否点中} isSelect -->|点中| yes[点中] isSelect -->|没点中| no[没点中] yes --> isEmpty{是否选择区域满} isEmpty -->|满| full[无法消除] isEmpty -->|不满| notfull[加入选择区域] notfull --> canClear{有3个相同} canClear -->|能消除| clear[消除] canClear -->|不能消除| append[进入选择区域] append --> 重绘
.onClick((ev: ClickEvent) => { if (this.needRestart) { this.needRestart = false this.emptyList.splice(0, this.emptyList.length) this.blockList.splice(0, this.blockList.length) this.emptyCnt = 5 this.avaliableCnt = 9 this.initBlocks() this.context.clearRect(0,0,this.context.width,this.context.height) this.drawBlock() return } console.log("screen.xy:"+ev.screenX+":"+ev.screenY) console.log("xy:"+ev.x+":"+ev.y) //判断是否点中方块 let flag = this.isSelect(ev.x, ev.y) console.info("flag:"+flag) if (flag == 1) { //如果可以移动或消除则清空重填 this.context.clearRect(0,0,this.context.width,this.context.height) this.drawBlock(); } else if (flag == 2) { //如果清空显示胜利画面 this.context.drawImage( this.blackImg,0,0,this.context.width,this.context.height) this.context.drawImage( this.winImg,this.slotX+50,this.slotY-300,200,200) this.context.font="100px bold" this.context.fillText("欢迎你加入羊群", this.slotX+50,this.slotY-350,500) this.needRestart = true } else if (flag == 3) { this.context.clearRect(0,0,this.context.width,this.context.height) this.drawBlock(); this.context.drawImage( this.blackImg,0,0,this.context.width,this.context.height) this.context.drawImage( this.ylgyImg,this.slotX+50,this.slotY-300,200,100) this.context.font="100px bold" this.context.fillText("加入羊群失败", this.slotX+50,this.slotY-350,500) this.needRestart = true } })
@Entry @Component struct Index { @State message: string = 'Hello World' @State _translate: TranslateOptions = { x: 0, y: 0, z: 0 } @State _scale: ScaleOptions = { x: 1, y: 1, z: 1 } private settings: RenderingContextSettings = new RenderingContextSettings(true); private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private cardImg:ImageBitmap = new ImageBitmap("common/images/iback.png") private slotImg:ImageBitmap = new ImageBitmap("common/images/lan.png") private ylgyImg:ImageBitmap = new ImageBitmap("common/images/ylgy.png") private blackImg:ImageBitmap = new ImageBitmap("common/images/black.png") private censerImg:ImageBitmap = new ImageBitmap("common/images/censer.png") private cloudImg:ImageBitmap = new ImageBitmap("common/images/cloud.png") private knifImg:ImageBitmap = new ImageBitmap("common/images/knif.png") private winImg:ImageBitmap = new ImageBitmap("common/images/win.png") private startX = 50; private startY = 10; private slotX = 20; private slotY = 450; private blockw = 62; private blockh = 69; private blockList = [] private emptyList = [] private emptyCnt = 5; private avaliableCnt = 9; private clearLen = 3; private needRestart = false; animationStep(value: AnimateParam, event: () => void) { return () => { return new Promise((resolve) => { let onFinish = value.onFinish value.onFinish = () => { if(onFinish) onFinish() resolve(true) } animateTo(value, event) }) } } async pulse(time) { // 0% - 50% let step1 = this.animationStep({ duration: time * 0.5, // 动画时长 tempo: 0.5, // 播放速率 curve: Curve.EaseInOut, // 动画曲线 delay: 0, // 动画延迟 iterations: 1, // 播放次数 playMode: PlayMode.Normal, // 动画模式 }, () => { this._scale = { x: 1.05, y: 1.05, z: 1.05 } }) // 50% - 100% let step2 = this.animationStep({ duration: time * 0.5, // 动画时长 tempo: 0.5, // 播放速率 curve: Curve.EaseInOut, // 动画曲线 delay: 0, // 动画延迟 iterations: 1, // 播放次数 playMode: PlayMode.Normal, // 动画模式 }, () => { this._scale = { x: 1, y: 1, z: 1 } }) await step1() await step2() } initBlocks() { for (let i=0;i<this.avaliableCnt;i++) { let lineCn = Math.floor(i/3) let rowCn = Math.floor(i%3) if (lineCn == 0) { this.blockList[i] = { img: "censer", isShow: true, x: this.startX+rowCn*30, y: this.startY, w: 55, h: 53, } } else if (lineCn == 1) { this.blockList[i] = { img: "cloud", isShow: true, x: this.startX+rowCn*30, y: this.startY+lineCn*90, w: 55, h: 53, } } else if (lineCn == 2) { this.blockList[i] = { img: "knif", isShow: true, x: this.startX+rowCn*30, y: this.startY+lineCn*90, w: 55, h: 53, } } } } aboutToAppear() { this.initBlocks() let audioPlayer = media.createAudioPlayer(); audioPlayer.on('dataLoad', () => { //设置'dataLoad'事件回调,src属性设置成功后,触发此回调 console.info('audio set source success'); audioPlayer.play(); //开始播放,并触发'play'事件回调 }); // audioPlayer.src = $r("app.media.background") } clearEmpty() { let emptyMap:Map<string, number> = new Map() console.info("emptylen:"+this.emptyList.length) for (let i=0;i<this.emptyList.length;i++) { let txt = this.emptyList[i] if (emptyMap[txt]) { let num = emptyMap[txt] emptyMap[txt] = num + 1 if (emptyMap[txt] == 3) { for (let j=0;j<3;j++) { this.emptyList.splice(this.emptyList.indexOf(txt), 1) } this.emptyCnt += 3 console.info("key:"+txt+" n:"+this.emptyList.length) } } else { emptyMap[txt] = 1 } } } isSelect(x, y) : number { let noshowCnt = 0 let nofind = 0 for (let i=0;i<this.blockList.length;i++) { // this.blockList.forEach((block)=>{ let block = this.blockList[i] noshowCnt += 1 x = Math.ceil(x) y = Math.ceil(y) // console.info("x:"+x+"y:"+y) // console.info("blockx:"+block.x+"block.y:"+block.y) let endx = block.x+this.blockw let endy = block.y+this.blockh if ((block.x <= x && endx >= x) && (block.y <= y && endy >= y)) { console.info("isFind") if (block.isShow == true && this.emptyCnt > 0) { block.isShow = false; this.emptyCnt -= 1; this.avaliableCnt -= 1; this.emptyList.push(block.img) this.clearEmpty() //找到block if (this.avaliableCnt == 0) { return 2 } else { if (this.emptyList.length == 5) { return 3 } else { return 1 } } } else if (this.emptyCnt == 0) { //没有空闲空间 return 3 } else if (block.isShow == false) { nofind += 1 } } else { console.info("noFind") nofind += 1 } } if (nofind == this.blockList.length) { //没有点中 return 0 } if (noshowCnt == this.blockList.length) { //没有block return 2 } } drawBlock() { this.blockList.forEach((block)=>{ if (block.isShow) { let imgItem:ImageBitmap = null switch(block.img) { case "censer": imgItem = this.censerImg break case "cloud": imgItem = this.cloudImg break case "knif": imgItem = this.knifImg break default: imgItem = this.censerImg break } this.context.drawImage( this.cardImg,block.x,block.y,this.blockw,this.blockh) this.context.drawImage( imgItem,block.x+5,block.y+5,block.w,block.h) } }) this.context.drawImage( this.slotImg,this.slotX,this.slotY,300,39) let pos = 0 for (let i=0;i<5;i++) { this.context.drawImage( this.cardImg,this.slotX + pos,this.slotY+40,61,69) if (i < this.emptyList.length) { let emptyText = this.emptyList[i] let pItem = null; switch (emptyText) { case "censer": pItem = this.censerImg; break; case "cloud": pItem = this.cloudImg; break; case "knif": pItem = this.knifImg; break; default: break; } if (pItem) { this.context.drawImage(pItem,this.slotX + pos + 3,this.slotY+40,55,59) } } pos += 60 } } build() { Row() { Column() { Canvas(this.context) .width('100%') .height('100%') .onClick((ev: ClickEvent) => { if (this.needRestart) { this.needRestart = false this.emptyList.splice(0, this.emptyList.length) this.blockList.splice(0, this.blockList.length) this.emptyCnt = 5 this.avaliableCnt = 9 this.initBlocks() this.context.clearRect(0,0,this.context.width,this.context.height) this.drawBlock() return } console.log("screen.xy:"+ev.screenX+":"+ev.screenY) console.log("xy:"+ev.x+":"+ev.y) //判断是否点中方块 let flag = this.isSelect(ev.x, ev.y) console.info("flag:"+flag) if (flag == 1) { //如果可以移动或消除则清空充填 this.context.clearRect(0,0,this.context.width,this.context.height) this.drawBlock(); } else if (flag == 2) { //如果清空显示胜利画面 this.context.drawImage( this.blackImg,0,0,this.context.width,this.context.height) this.context.drawImage( this.winImg,this.slotX+50,this.slotY-300,200,200) this.context.font="100px bold" this.context.fillText("欢迎你加入羊群", this.slotX+50,this.slotY-350,500) this.needRestart = true } else if (flag == 3) { this.context.clearRect(0,0,this.context.width,this.context.height) this.drawBlock(); this.context.drawImage( this.blackImg,0,0,this.context.width,this.context.height) this.context.drawImage( this.ylgyImg,this.slotX+50,this.slotY-300,200,100) this.context.font="100px bold" this.context.fillText("加入羊群失败", this.slotX+50,this.slotY-350,500) this.needRestart = true } }) .onReady(() =>{ this.context.imageSmoothingEnabled = false this.drawBlock() }) } .height("80%") .width("100%") } .height('100%') .width('100%') .backgroundImage($r("app.media.grass")) .backgroundImageSize(ImageSize.Cover) } }
遗留问题:
点击选择没有判断图层:可以在卡片数据结构里增加图层标识,最下面的卡片为图层标识为1,上面的多一层加1,点中选择的时候可以判断,增加是否可以选中的逻辑;
消除区域布局可灵活配置:增加布局配置逻辑,使用数据结构设定布局逻辑,可规定卡片种类,数量,布局行数,列数以及层级
游戏声音问题:目前ohos不支持音频播放资源音频,看之后版本是否支持
以上就是关于“怎么用git实现羊了个羊游戏”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。