跟著小白一起學鴻蒙—一起學做小蜜蜂
作者:王石
本文主要介紹了小游戲的開發,畫布功能的使用,希望能夠幫助到你!
簡介
小時候我們有個熟悉的游戲叫小蜜蜂。本文中引用的圖片資源均來自與Github。
開發
1、HAP應用建立
《#跟著小白一起學鴻蒙#[六]如何編寫一個hap應用》里我們介紹了簡單的Hap應用的開發以及基礎控件的介紹,這里我們就不贅述Hap項目的建立過程,以下就是基礎的Hap的page文件:index.ets。
build() {
Row() {
Column() {
Canvas(this.context)
.width('100%')
.height('100%')
.onClick((ev: ClickEvent) => {
console.info("click!!")
this.doClick()
})
.onReady(() =>{
this.context.imageSmoothingEnabled = false
this.drawall()
})
}
.width('100%')
}
.height('100%')
.backgroundColor("#000000")
}
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;
}
2、Canvas介紹
canvas是畫布組件用于自定義繪制圖形,具體的API頁面如下:
https://developer.harmonyos.com/cn/docs/documentation/doc-references/ts-components-canvas-canvas-0000001333641081
頁面顯示前會調用aboutToAppear()函數,此函數為頁面生命周期函數。
canvas組件初始化完畢后會調用onReady()函數,函數內部實現小游戲的初始頁面的繪制。
(1)初始化頁面數據
drawall() {
this.context.clearRect(0,0,this.context.width,this.context.height)
this.drawFj();
this.drawEn();
this.drawBullet();
this.drawScore();
}
(2)繪制飛機
drawFj() {
this.context.drawImage( this.fjImg, this.fjStartX, this.fjslotY,this.birdH,this.birdW)
}
(3)繪制害蟲
drawEn() {
for (let line=0; line < this.enemylist.length; line++) {
for (let row=0; row < this.enemylist[line].length; row++) {
if (this.enemylist[line][row] == 1) {
if (line == 0) {
this.context.drawImage( this.en1Img, this.en1slotX+row*this.birdW,this.en1slotY-line*this.birdH,this.birdH,this.birdW);
} else if (line == 1) {
this.context.drawImage( this.en2Img, this.en1slotX+row*this.birdW,this.en1slotY-line*this.birdH,this.birdH,this.birdW);
} else if (line == 2) {
this.context.drawImage( this.en3Img, this.en1slotX+row*this.birdW,this.en1slotY-line*this.birdH,this.birdH,this.birdW);
}
}
}
}
}
不同行的害蟲長相不同,分值不同。
3、游戲邏輯
簡單的小游戲主體游戲邏輯為:點擊鼠標移動飛機,飛機發射子彈,命中害蟲,計算分數:
doClick() {
if (this.en1slotX <= 50) {
this.en1slotX += this.birdW
} else {
this.en1slotX -= this.birdW
}
console.log("doclick----")
this.moveFj();
}
4、完整邏輯
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
private blockType: number = 0
private blockSize: number = 30
private en1Img:ImageBitmap = new ImageBitmap("common/images/mf1.png")
private en2Img:ImageBitmap = new ImageBitmap("common/images/mf2.png")
private en3Img:ImageBitmap = new ImageBitmap("common/images/mf3.png")
private fjImg:ImageBitmap = new ImageBitmap("common/images/fj.png")
private startX = 30;
private startY = 100;
private enStartY = 140;
private fjStartX = 50;
private fjStartY = 610;
private fjslotX = 50;
private fjslotY = this.fjStartY;
private en1slotX = 50;
private en1slotY = this.enStartY;
private en2slotX = 50;
private en2slotY = this.enStartY;
private bulletX = 65;
private bulletY = 550;
private birdH = 40;
private birdW = 40;
private score = 0;
private fjDirection = 1;
private enemylist = [
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
]
moveFj() {
this.fjStartX = this.fjStartX + this.fjDirection * this.birdW
if (this.fjStartX >= 210) {
this.fjDirection = -1
} else if (this.fjStartX <= 50) {
this.fjDirection = 1
}
}
drawFj() {
this.context.drawImage( this.fjImg, this.fjStartX, this.fjslotY,this.birdH,this.birdW)
}
drawEn() {
for (let line=0; line < this.enemylist.length; line++) {
for (let row=0; row < this.enemylist[line].length; row++) {
if (this.enemylist[line][row] == 1) {
if (line == 0) {
this.context.drawImage( this.en1Img, this.en1slotX+row*this.birdW,this.en1slotY-line*this.birdH,this.birdH,this.birdW);
} else if (line == 1) {
this.context.drawImage( this.en2Img, this.en1slotX+row*this.birdW,this.en1slotY-line*this.birdH,this.birdH,this.birdW);
} else if (line == 2) {
this.context.drawImage( this.en3Img, this.en1slotX+row*this.birdW,this.en1slotY-line*this.birdH,this.birdH,this.birdW);
}
}
}
}
}
drawBullet() {
let isfind = false
this.context.fillStyle = 'rgb(250,250,250)'
this.context.font = '80px sans-serif'
this.bulletX = this.fjStartX + 20
this.context.fillText(":", this.fjStartX+20, this.bulletY)
for (let line=0; line < this.enemylist.length; line++) {
if (Math.abs(this.bulletY - (this.en1slotY-line*this.birdH)) <= this.birdH) {
console.log("find line: "+line)
for (let row = 0; row < this.enemylist[line].length; row++) {
let matchsize = Math.abs(this.bulletX - (this.en1slotX+row*this.birdW))
// console.log("find szie: "+matchsize.toString()+" row:"+row.toString()+" line:"+line.toString()+" bulletX:"+this.bulletX.toString()+" bulletY:"+
// this.bulletY.toString()+" en1slotX"+this.en1slotX.toString()+" en1slotY"+this.en1slotY.toString())
if (matchsize <= this.birdW) {
if (this.enemylist[line][row] == 1) {
console.log("row:"+row.toString()+" line:"+line.toString()+" bulletX:"+this.bulletX.toString()+" bulletY:"+
this.bulletY.toString()+" en1slotX"+this.en1slotX.toString()+" en1slotY"+this.en1slotY.toString());
this.enemylist[line][row] = 0
isfind = true
switch (line) {
case 0:
this.score += 1;
break;
case 1:
this.score += 2;
break;
case 2:
this.score += 3;
break;
default:
break;
}
//console.log("score: "+this.score.toString())
break
}
}
}
if (isfind) {
break;
}
}
}
if (this.bulletY <= 100 || isfind == true) {
this.bulletY = 550
} else {
this.bulletY -= 50;
}
}
drawScore() {
this.context.fillStyle = 'rgb(250,250,250)'
this.context.font = '80px sans-serif'
this.context.fillText("Score:"+this.score.toString(), 20, 750)
// this.context.fillText(":", 65, 550)
}
drawall() {
this.context.clearRect(0,0,this.context.width,this.context.height)
this.drawFj();
this.drawEn();
this.drawBullet();
this.drawScore();
}
async sleep(ms: number) {
var that = this;
return new Promise((r) => {
setInterval(() => {
if (that.en1slotX <= 50) {
that.en1slotX += that.birdW
} else {
that.en1slotX -= that.birdW
}
console.log(that.en1slotX.toString())
that.drawall()
}, ms)
})
}
doClick() {
if (this.en1slotX <= 50) {
this.en1slotX += this.birdW
} else {
this.en1slotX -= this.birdW
}
console.log("doclick----")
this.moveFj();
}
aboutToAppear() {
this.sleep(1000)
}
build() {
Row() {
Column() {
Canvas(this.context)
.width('100%')
.height('100%')
.onClick((ev: ClickEvent) => {
console.info("click!!")
this.doClick()
})
.onReady(() =>{
this.context.imageSmoothingEnabled = false
this.drawall()
})
}
.width('100%')
}
.height('100%')
.backgroundColor("#000000")
}
}
遺留問題:
- 飛機的子彈可以多發
- 害蟲可以攻擊飛機
- 游戲聲音問題:目前ohos不支持音頻播放資源音頻,看之后版本是否支持
- DevEco用setInterval重繪canvas會導致ide崩潰
5、獲取源碼
見附件:
https://ost.51cto.com/resource/2670。
總結
本文主要介紹了小游戲的開發,畫布功能的使用。
責任編輯:jianghua
來源:
51CTO 開源基礎軟件社區