当前位置:首页 >焦点 >跟着小白一起学鸿蒙—一起学做小蜜蜂 画布功能的起学起学使用

跟着小白一起学鸿蒙—一起学做小蜜蜂 画布功能的起学起学使用

2024-06-28 21:34:54 [百科] 来源:避面尹邢网

跟着小白一起学鸿蒙—一起学做小蜜蜂

作者:王石 系统 OpenHarmony 本文主要介绍了小游戏的小白开发,画布功能的起学起学使用,希望能够帮助到你!鸿蒙

​​想了解更多关于开源的蜜蜂内容,请访问:​​

跟着小白一起学鸿蒙—一起学做小蜜蜂 画布功能的起学起学使用

​​51CTO 开源基础软件社区​​

跟着小白一起学鸿蒙—一起学做小蜜蜂 画布功能的起学起学使用

​​https://ost.51cto.com​​

跟着小白一起学鸿蒙—一起学做小蜜蜂 画布功能的起学起学使用

简介

小时候我们有个熟悉的小白游戏叫小蜜蜂。本文中引用的起学起学图片资源均来自与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")
}
}

遗留问题:

  1. 飞机的子弹可以多发
  2. 害虫可以攻击飞机
  3. 游戏声音问题:目前ohos不支持音频播放资源音频,看之后版本是否支持
  4. DevEco用setInterval重绘canvas会导致ide崩溃

5、获取源码

见附件:

https://ost.51cto.com/resource/2670。

总结

本文主要介绍了小游戏的开发,画布功能的使用。

​​想了解更多关于开源的内容,请访问:​​

​​51CTO 开源基础软件社区​​

​​https://ost.51cto.com​​

责任编辑:jianghua 来源: 51CTO 开源基础软件社区 小游戏开发画布功能

(责任编辑:娱乐)

    推荐文章
    热点阅读