從零開始使用華為DevEco Studio編寫2048小遊戲

語言: CN / TW / HK

從零開始使用華為DevEco Studio編寫2048小遊戲

寫在前面

本文由我和@WiKiBeta共同完成,也是我們第一次接觸HarmonyOS,對OS瞭解的越多,越覺得開發OS是一件不簡單的事,開發APP只是其中的一部分,背後的工程實在是有點超出想象。這次我們通過對張榮超老師課程(課程連結)的學習,我們對如何使用IDE開發HOS中的APP有了一定的理解,以下是我們學習完成後寫下的筆記,如果有紕漏,希望各位諒解並指出。

概述

本次課程目標是開發能在鴻蒙裝置上執行的經典小遊戲2048,本次學習實現的功能主要有:1.實現頁面佈局 2.在畫布上顯示所有的格子以及格子裡的數字 3. 頁面初始化時隨機選擇兩個格子,並放入2或4。本次課程中,未完整實現的響應滑動事件功能將在以後的學習筆記中進行補充。(課程使用的開發軟體為DevEco Studio, 語言為JS).

準備工作

開發工具

華為HarmonyOS的應用開發工具DevEco Studio下載地址

編寫位置

在這裡插入圖片描述

檔案用途

在這裡插入圖片描述

具體流程

1.	實現頁面佈局

在這裡插入圖片描述 在這裡插入圖片描述 在這裡插入圖片描述

效果如下 在這裡插入圖片描述

  1. 在畫布上顯示所有的格子以及格子裡的數字 在這裡插入圖片描述 在這裡插入圖片描述

效果如下 在這裡插入圖片描述

  1. 頁面初始化時隨機選擇兩個格子,並放入2或4 頁面初始化: 在這裡插入圖片描述 在這裡插入圖片描述

隨機選擇兩個格子,並放入2或4: 在這裡插入圖片描述

效果如下:在這裡插入圖片描述

原始碼(詳解)

                              hml
<div class="container">
    <text class="scores">
        最高分:{{bestScores}}//將bestScores與最高分動態繫結,即bestScores可變
    </text>
    <text class="scores">
        當前分:{{currentScores}}//cunrrentScores與最高分動態繫結,即bestScores可變

    </text>
    <canvas class="canvas" ref="canvas" onswipe="swipeGrids">//定義canvas元件,類為canvas,ref指向canvas物件例項,onswipe指向“滑動”這一事件
    </canvas>
    <input type="button" value="重新開始" class="btn" onclick="restartGame"/>//輸入一個元件input,定義種類為button以顯示一個按鈕,value即按鈕上將顯示的文字,類定義為btn
</div>//以上就定義了我們有哪些元件
                              css 
.container {//整個介面的基本佈局
    flex-direction: column;//將介面中的元件豎向排列
    width: 454px;
    height: 454px;
    justify-content: center;//justify-content 用於設定或檢索彈性盒子元素在主軸(橫軸)方向上的對齊方式,使其中心化
    align-items: center;//align-content 屬性對齊交叉軸上的各項(垂直),這裡使其中心化
}
.scores {
    width: 300px;
    height:20px;
    font-size: 18px;
    text-align: center;
    letter-spacing: 0px;//使類為scores的元素排列的更加緊湊
    margin-top: 10px;//在類為scores的元素周圍設定10px的外邊距
}
.canvas{
    width:305px;
    height:305px;
    background-color: #BBADA0;//背景色,16進位制
}
.btn{
    width:150px;
    height:30px;
    background-color: #AD9D8F;
    font-size: 24px;
    margin-top: 10px;
}
                             js
var grids;//設定變數grids
var context;//使context作為全域性變數,因為使用頻率較高
const colors={//設定常量colors,用於填充字型顏色和網格背景色
    "0": "#CDC1B4",
    "2": "#EEE4DA",
    "4": "#EDE0C8",
    "8": "#F2B179",
    "16": "#F59563",
    "32": "#F67C5F",
    "64": "#F65E3B",
    "128": "#EDCF72",
    "256": "#EDCC61",
    "512": "#99CC00",
    "1024": "#83AF9B",
    "2048": "#0099CC",
    "2or4": "#645B52",
    "others": "#FFFFFF"
}
const MARGIN =5;//定義常量MARGIN,為girds中grid與grid的間距
const SIDELEN=70;//grid的邊長
export default {//export default命令,為模組指定預設輸出
    data: {
        currentScores: 0,//預設值為0
        bestScores: 9818
    },
    onInit(){//初始化遊戲介面:
        this.initGrids();//呼叫initGrids,使所有網格的填充色為字元0元素的背景色,而字元0本身沒有顏色,從而使介面看起來像清空
        this.addTwoOrFourToGrids();//在grids中任意指定一個grid使其為2or4
        this.addTwoOrFourToGrids();
    },
    onReady(){//首次顯示頁面,頁面初次渲染完成,會觸發onReady方法,渲染頁面元素和樣式,一個頁面只會呼叫一次,代表頁面已經準備妥當,可以和檢視層進行互動(用於渲染)
        context=this.$refs.canvas.getContext("2d");//獲得canvas對應的2d繪製引擎,並將其賦值給全域性變數context
    },
    onShow(){//頁面載入後觸發onShow方法,顯示頁面。每次開啟頁面都會呼叫一次(用於顯示)
        this.drawGrids();
    },
    initGrids(){//使所有網格的填充色為字元0元素的背景色,而字元0本身沒有顏色,從而使介面看起來像清空
        grids=[[0,0,0,0],
               [0,0,0,0],
               [0,0,0,0],
               [0,0,0,0]];
    },
    drawGrids() {//繪製grids
        for (let row = 0; row < 4; row++) {
            for (let column = 0; column < 4; column++) {//遍歷所有grid
                let gridStr = grids[row][column].toString();//將grid上的數字轉化為字串

                context.fillStyle = colors[gridStr];//網格的填充色,根據字串來定,以context繪圖實現
                let leftTopX = column * (MARGIN + SIDELEN) + MARGIN;//grid左上角的橫座標
                let leftTopY = row * (MARGIN + SIDELEN) + MARGIN;//grid左上角的縱座標
                context.fillRect(leftTopX, leftTopY, SIDELEN, SIDELEN);//定義繪製的範圍,四個引數

                context.font = "24px HYQiHei-65S";//繪製的字型形式
                if (gridStr != "0") {//“0”不用繪製
                    if (gridStr == "2" || gridStr == "4") {
                        context.fillStyle = colors["2or4"];
                    } else {
                        context.fillStyle = colors["others"];
                    }

                    let offsetX = (4 - gridStr.length) * (SIDELEN / 8);//str左上角與gridX方向上的間距,四個字元佔的長度=SIDELEN
                    let offsetY = (SIDELEN - 24) / 2;////str左上角與gridY方向上的間距

                    context.fillText(gridStr, leftTopX + offsetX, leftTopY + offsetY);//接受gird上的字串以及STR左上角的橫座標以及縱座標並將其進行繪製
                }
            }
        }
    },
    addTwoOrFourToGrids(){//在初始化或restart時選中兩個grid作為最開始時出現的grid,其值為2or4
        let array=[];
        for(let row =0;row<4;row++){
            for(let column=0;column<4;column++){
                if(grids[row][column]==0){
                    array.push([row,column]);//遍歷並存儲網格上數字為0的網格位置
                }
            }
        }
        let randomIndes=Math.floor(Math.random()*array.length);//取[0,array.length-1]之間的任意一個整數
        let row=array[randomIndes][0];//索引中陣列為0的元素為行索引
        let column=array[randomIndes][1];//索引中陣列為1的元素為列索引
        if(Math.random()<0.8){//使出現2的概率大於4,選定一個grid,使其的值為2or4
            grids[row][column]=2;
        }else{
            grids[row][column]=4;
        }
    },
// swipeGrids(event){//未完成的滑動操作
//        let newGrids;
//        if(newGrids.toString()!=grids.toString()){
//            grids=newGrids;
//            this.addTwoOrFourToGrids();
//            this.drawGrids();
//        }
//    }
    restartGame(){//相應點選按鈕這一事件,重新開始遊戲
        this.initGrids();
        this.addTwoOrFourToGrids();
        this.addTwoOrFourToGrids();
        this.drawGrids();
    }

}

寫在後面

由於張老師的課程時間限制的原因,還未實現所有的功能,在張老師推出完整教程後我們可能會寫出完整的版本。以上就是我們的學習筆記,希望大家看完能有所收穫,謝謝。在這裡感謝張榮超老師精彩細緻的講解,讓我們這些小白也能有所體會,同時也感謝ojs師兄,lcz老師,和wbh老師帶領我們進入這個領域,讓我們有幸接觸到HarmonyOS,最後,希望我們能和大家一起進步,將來寫出更好的程式碼。