您好,登錄后才能下訂單哦!
這篇“怎么用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進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。