做中國(guó)供應(yīng)商免費(fèi)網(wǎng)站有作用嗎怎么自己創(chuàng)建網(wǎng)址
介紹
本篇Codelab是基于TS擴(kuò)展的聲明式開發(fā)范式編程語(yǔ)言,以及OpenHarmony的分布式能力實(shí)現(xiàn)的一個(gè)手柄游戲。
說(shuō)明: 本示例涉及使用系統(tǒng)接口,需要手動(dòng)替換Full SDK才能編譯通過(guò)。
完成本篇Codelab需要兩臺(tái)開發(fā)板,一臺(tái)開發(fā)板作為游戲端,一臺(tái)開發(fā)板作為手柄端,實(shí)現(xiàn)如下功能:
- 游戲端呈現(xiàn)飛機(jī)移動(dòng)、發(fā)射子彈等效果。
- 游戲端分布式拉起手柄端FA。
- 手柄端與游戲端建立連接,發(fā)送指令給游戲端,比如移動(dòng)飛機(jī),發(fā)射子彈和釋放技能等。
最終效果圖如下:
搭建OpenHarmony環(huán)境
完成本篇Codelab我們首先要完成開發(fā)環(huán)境的搭建,本示例以RK3568開發(fā)板為例,參照以下步驟進(jìn)行:
- 獲取OpenHarmony系統(tǒng)版本:標(biāo)準(zhǔn)系統(tǒng)解決方案(二進(jìn)制)。
? ? ? 以3.1版本為例:
2.搭建燒錄環(huán)境。
- 完成DevEco Device Tool的安裝
- 完成RK3568開發(fā)板的燒錄
3.搭建開發(fā)環(huán)境。
- 開始前請(qǐng)參考工具準(zhǔn)備,完成DevEco Studio的安裝和開發(fā)環(huán)境配置。
- 開發(fā)環(huán)境配置完成后,請(qǐng)參考使用工程向?qū)?chuàng)建工程(模板選擇“Empty Ability”),選擇JS或者eTS語(yǔ)言開發(fā)。
- 工程創(chuàng)建完成后,選擇使用真機(jī)進(jìn)行調(diào)測(cè)。
分布式組網(wǎng)
本章節(jié)以系統(tǒng)自帶的音樂播放器為例(具體以實(shí)際的應(yīng)用為準(zhǔn)),介紹如何完成兩臺(tái)設(shè)備的分布式組網(wǎng)。
- 硬件準(zhǔn)備:準(zhǔn)備兩臺(tái)燒錄相同的版本系統(tǒng)的RK3568開發(fā)板A、B。
- 開發(fā)板A、B連接同一個(gè)WiFi網(wǎng)絡(luò)。
打開設(shè)置-->WLAN-->點(diǎn)擊右側(cè)WiFi開關(guān)-->點(diǎn)擊目標(biāo)WiFi并輸入密碼。
3.將設(shè)備A,B設(shè)置為互相信任的設(shè)備。
- 找到系統(tǒng)應(yīng)用“音樂”。
- 設(shè)備A打開音樂,點(diǎn)擊左下角流轉(zhuǎn)按鈕,彈出列表框,在列表中會(huì)展示遠(yuǎn)端設(shè)備的id。
- 選擇遠(yuǎn)端設(shè)備B的id,另一臺(tái)開發(fā)板(設(shè)備B)會(huì)彈出驗(yàn)證的選項(xiàng)框。
- 設(shè)備B點(diǎn)擊允許,設(shè)備B將會(huì)彈出隨機(jī)PIN碼,將設(shè)備B的PIN碼輸入到設(shè)備A的PIN碼填入框中。
- 配網(wǎng)完畢。
代碼結(jié)構(gòu)解讀
- HandleEtsOpenHarmony
- GameEtsOpenHarmony
本篇Codelab只對(duì)核心代碼進(jìn)行講解,首先介紹一下整個(gè)工程的代碼結(jié)構(gòu):
└── HandleGameApplication│── GameEtsOpenHarmony│ └── HandleEtsOpenHarmony
其中HandleEtsOpenHarmony為手柄端工程代碼,GameEtsOpenHarmony為游戲端工程代碼。
HandleEtsOpenHarmony
- MainAbility:存放應(yīng)用主頁(yè)面。
- pages/index.ets:應(yīng)用主頁(yè)面。
- common/images:存放圖片資源的目錄。
- ServiceAbility:存放ServiceAbility相關(guān)文件。
- service.ts:service服務(wù),用于跨設(shè)備連接后通訊。
GameEtsOpenHarmony
- MainAbility:存放應(yīng)用主頁(yè)面。
- pages/index.ets:應(yīng)用主頁(yè)面。
- common/images:存放圖片資源。
- model:存放獲取組網(wǎng)內(nèi)的設(shè)備列表相關(guān)文件。
- RemoteDeviceModel.ets:獲取組網(wǎng)內(nèi)的設(shè)備列表。
- GameElement.ets:游戲端界面元素的實(shí)體類,用于封裝子彈、飛機(jī)等元素的屬性。
- ServiceAbility:存放ServiceAbility相關(guān)文件。
- service.ts:service服務(wù),用于跨設(shè)備連接后通訊。
實(shí)現(xiàn)手柄端功能
- 實(shí)現(xiàn)布局和樣式。
手柄端有兩個(gè)功能:向游戲端發(fā)送指令和實(shí)時(shí)獲取游戲端得分?jǐn)?shù)據(jù)。界面上有三個(gè)功能組件:藍(lán)色圖形組件用于控制游戲端飛機(jī)移動(dòng)方向,黃色圖形組件用于發(fā)射子彈,綠色圖形組件用于釋放技能,效果圖如下:
主要代碼如下:
@Entry
@Component
struct Index {
...build() {Stack() {...Text('score:' + this.score)...Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.SpaceBetween }) {Stack() {Image('/common/images/bigcircle.png').width(300).height(300)Image('/common/images/smallcircle.png').width(140).height(140).position({ x: this.smallPosX, y: this.smallPosY }) // 30+75-35}...Row() {Image('/common/images/a.png').width(160).height(160).margin({ right: 20, bottom: 80 })Image('/common/images/b.png').width(200).height(200)}.alignItems(VerticalAlign.Bottom)...}}
}
2.實(shí)現(xiàn)搖桿功能。
給搖桿(藍(lán)色小圓圖形)添加TouchEvent,動(dòng)態(tài)改變搖桿position屬性使搖桿跟隨手指移動(dòng),主要代碼如下:
onTouchEvent(event: TouchEvent) {switch (event.type) {case TouchType.Down:this.startX = event.touches[0].screenX;this.startY = event.touches[0].screenY;break;case TouchType.Move:this.curX = event.touches[0].screenX;this.curY = event.touches[0].screenY;this.getSmallCurrentPos(this.curX - this.smallR - 60, this.curY - this.smallR - 60)angle = Math.round(this.calculateAngle());break;default:break;}
}
3.計(jì)算搖桿偏移角度。
主要代碼如下:
calculateAngle() {var angle = 0var degree = Math.atan(this.getDisAbsY() / this.getDisAbsX()) * 180 / Math.PIvar quadrant = this.quadrant();switch (quadrant) {case this.QUADRANT_1:// 向右上移動(dòng)angle = degree;break;case this.QUADRANT_2:// 向左上移動(dòng)angle = 180 - degree;break;case this.QUADRANT_3:// 向左下移動(dòng)angle = -180 + degree;break;case this.QUADRANT_4:// 向右下移動(dòng)angle = -degree;break;default:angle = 0;break;}return angle;
}
4.連接游戲端Service。
當(dāng)手柄端被游戲端拉起時(shí),獲取游戲端傳遞的數(shù)據(jù):游戲端deviceId和分?jǐn)?shù)score。然后通過(guò)deviceId連接游戲端Service,主要代碼如下:
aboutToAppear() {// 當(dāng)被拉起時(shí),通過(guò)want傳遞的參數(shù)同步對(duì)端界面UIawait featureAbility.getWant((error, want) => {// 遠(yuǎn)端被拉起后,連接游戲端的serviceif (want.parameters.deviceId) {let remoteDeviceId = want.parameters.deviceIdconnectRemoteService(remoteDeviceId)}});
}async function connectRemoteService(deviceId) {
...await featureAbility.connectAbility({'deviceId': deviceId,'bundleName': "com.huawei.cookbook",'abilityName': "com.huawei.cookbook.ServiceAbility",},{onConnect: onConnectCallback,onDisconnect: onDisconnectCallback,onFailed: onFailedCallback,},);
}
5.通過(guò)RPC發(fā)送數(shù)據(jù)到游戲端。
連接游戲端Service之后,搖桿角度angle和操作類型actionType(1為發(fā)射子彈,2為釋放技能)發(fā)送給游戲端,主要代碼如下:
async function sendMessageToRemoteService() {
...let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();data.writeInt(actionType);data.writeInt(angle);await mRemote.sendRequest(1, data, reply, option);
}
實(shí)現(xiàn)游戲端功能
- 實(shí)現(xiàn)布局和樣式。
游戲界面主要由玩家飛機(jī)、敵機(jī)、子彈和道具(降落傘)等組成,由于敵機(jī)和子彈都是多個(gè)的,所以使用ForEach來(lái)實(shí)現(xiàn),主要代碼如下:
@Entry
@Component
struct Index {build() {Stack() {... ForEach(this.bullets, item => {Image(item.imgSrc).width(item.imgWidth).height(item.imgHeight).position({ x: item.positionX, y: item.positionY })}, item => item.timestamp.toString())ForEach(this.enemyPlanes, item => {Image(item.imgSrc).width(item.imgWidth).height(item.imgHeight).position({ x: item.positionX, y: item.positionY })}, item => item.timestamp.toString())Image('/common/images/planeOne.png').width(this.planeSize).height(this.planeSize).position({ x: this.planePosX, y: this.planePosY }).onTouch((event: TouchEvent) => {this.onTouchEvent(event)})Image('/common/images/props.png').width(this.propsSize).height(this.propsSize).position({ x: this.propsPosX, y: this.propsPosY })...}.height('100%').width('100%')}
}
2.實(shí)現(xiàn)游戲端元素動(dòng)畫效果。
飛機(jī)、子彈和道具等元素的移動(dòng)是通過(guò)動(dòng)態(tài)改變Image的position屬性來(lái)實(shí)現(xiàn)的。使用定時(shí)器setInterval每隔16ms重新設(shè)置界面元素position屬性的值,主要實(shí)現(xiàn)代碼如下:
startGame() {var that = thissetInterval(function () { // 每60*16ms創(chuàng)建一個(gè)敵機(jī)if (that.num % 60 == 0) {that.createEnemyPlane()}// 移動(dòng)子彈var bulletsTemp: GameElement[] = []for (var i = 0; i < that.bullets.length; i++) {var bullet = that.bullets[i]bullet.positionY -= 8// 當(dāng)子彈移除屏幕外的時(shí)候,釋放掉if (bullet.positionY > 0) {bulletsTemp.push(bullet)}}that.bullets = bulletsTemp// 移動(dòng)飛機(jī)var enemyPlanesTemp: GameElement[] = []for (var j = 0; j < that.enemyPlanes.length; j++) {var enemyPlane = that.enemyPlanes[j]enemyPlane.positionY += 6// 當(dāng)飛機(jī)移除屏幕外的時(shí)候,釋放掉if (enemyPlane.positionY < that.screenHeight) {enemyPlanesTemp.push(enemyPlane)}}that.enemyPlanes = enemyPlanesTemp// 每隔 500*16ms顯示降落傘if (that.num % 500 == 0) {that.getPropsFlag = truethat.propsPosY = -that.propsSizethat.propsPosX = Math.round((Math.random() * (that.screenWidth - that.propsSize)))}// 刷新道具位置if (that.propsPosY < that.screenHeight) {that.propsPosY += 6}that.checkCollision()}, 16);}
3.判斷元素是否發(fā)生碰撞。
在setInterval中改變?cè)匚恢玫臅r(shí)候同時(shí)檢測(cè)元素之間是否發(fā)生碰撞,子彈和敵機(jī)發(fā)生碰撞則分?jǐn)?shù)值改變(摧毀小飛機(jī)加50分,摧毀大飛機(jī)加100分),玩家飛機(jī)和道具發(fā)生碰撞則道具加1,主要實(shí)現(xiàn)代碼如下:
checkCollision() {...for (var i = 0; i < this.enemyPlanes.length; i++) {var enemy = this.enemyPlanes[i];for (var j = 0; j < this.bullets.length; j++) {var bullet = this.bullets[j];var inside = this.isInside(bullet, enemy);// 發(fā)生碰撞if (inside) {enemy.imgSrc = '/common/images/boom.png'if (enemy.flag == 1) {this.score += 50sendMessageToRemoteService(that.score)} else if (enemy.flag == 2) {this.score += 100sendMessageToRemoteService(that.score)}// 清除子彈this.enemyPlanes.splice(i, 1);i--;enemy.flag = 3// 清除被子彈打中敵機(jī)that.bullets.splice(j, 1);j--;}}}// 飛機(jī)和降落傘是否發(fā)生碰撞var isGetProps = this.isInside(myPlane, props);if (isGetProps && this.getPropsFlag) {this.getPropsFlag = falsethis.bombNum++this.propsPosY = 2000}}
4.獲取設(shè)備列表。
點(diǎn)擊界面右上角的“電腦”圖標(biāo),調(diào)用registerDeviceListCallback()發(fā)現(xiàn)設(shè)備列表,并彈出設(shè)備列表選擇框DeviceListDialog ,選擇設(shè)備后拉起遠(yuǎn)端FA。DeviceListDialog 主要代碼如下:
@CustomDialog
export struct DeviceListDialog {controller: CustomDialogControllerbuild() {Column() {Text("選擇設(shè)備").fontWeight(FontWeight.Bold).fontSize(20).margin({ top: 20, bottom: 10 })List() {ForEach(deviceList, item => {ListItem() {Stack() {Text(item).fontSize(12).margin({ top: 10 })}.onClick(() => {startRemoteAbility(item)this.controller.close();}).padding({ left: 30, right: 30 })}}, item => item.toString())}.height("30%").align(Alignment.TopStart)
...}}
}
5.拉起手柄端FA。
點(diǎn)擊設(shè)備列表獲取遠(yuǎn)程設(shè)備id后,拉起手柄端FA,代碼如下:
function startRemoteAbility(deviceId) {var params = {deviceId: localDeviceId}var wantValue = {bundleName: 'com.huawei.cookbook',abilityName: 'com.huawei.cookbook.MainAbility',deviceId: deviceId,parameters: params};featureAbility.startAbility({want: wantValue}).then((data) => {console.info('[game] featureAbility.startAbility finished, localDeviceId=' + localDeviceId + '----deviceId:' + deviceId);// 拉起遠(yuǎn)端后,連接遠(yuǎn)端serviceconnectRemoteService(deviceId)});
}
6.連接手柄端Service。
拉起手柄端FA后,連接手柄端Service,代碼如下:
async function connectRemoteService(deviceId) {// 連接成功的回調(diào)async function onConnectCallback(element, remote) {mRemote = remote;}
...if (remoteDeviceModel.deviceList.length === 0) {return;}await featureAbility.connectAbility({'deviceId': deviceId,'bundleName': "com.huawei.cookbook",'abilityName': "com.huawei.cookbook.ServiceAbility",},{onConnect: onConnectCallback,onDisconnect: onDisconnectCallback,onFailed: onFailedCallback,},);
}
7.通過(guò)RPC發(fā)送數(shù)據(jù)到手柄端。
通過(guò)RPC將游戲分?jǐn)?shù)發(fā)送給手柄端,主要代碼如下:
async function sendMessageToRemoteService(score) {console.log('[game]connectRemoteService sendMessageToRemoteService:')if (mRemote == null) {return;}let option = new rpc.MessageOption();let data = new rpc.MessageParcel();let reply = new rpc.MessageParcel();data.writeInt(score);await mRemote.sendRequest(1, data, reply, option);
}
8.Service發(fā)布公共事件。
通過(guò)Service接收手柄端數(shù)據(jù),然后使用CommonEvent模塊將數(shù)據(jù)發(fā)送給FA,主要代碼如下:
class GameServiceAbilityStub extends rpc.RemoteObject {
...onRemoteRequest(code, data, reply, option) {console.log('[game]Service onRemoteRequest');var publishCallBack;if (code === 1) {// 讀取手柄端發(fā)送的數(shù)據(jù)let actionType = data.readInt();let angle = data.readInt();reply.writeInt(100);var params = {actionType: actionType,angle: angle,}var options = {code: 1,data: 'init data',isOrdered: true,bundleName: 'com.huawei.cookbook',parameters: params}publishCallBack = function () {}// 發(fā)布公共事件commonEvent.publish("publish_action", options, publishCallBack);} return true;}
}
9.FA訂閱公共事件。
訂閱公共事件,接收從Service發(fā)送的公共事件數(shù)據(jù),actionType 為操作類型(1表示發(fā)送子彈指令,2表示釋放技能指令),angle 為飛機(jī)移動(dòng)的角度。接收到數(shù)據(jù)后執(zhí)行手柄端發(fā)送的指令:移動(dòng)玩家飛機(jī)、發(fā)射子彈和釋放技能摧毀所有敵機(jī),主要代碼如下:
subscribeEvent() {
...// 訂閱公共事件回調(diào)function SubscribeCallBack(err, data) {let msgData = data.data;let code = data.code;
...// 處理接收到的數(shù)據(jù)datathat.actionType = data.parameters.actionType;that.angle = data.parameters.angle;if (that.actionType == 1) {that.createBullet()}if (that.actionType == 2) {if (that.bombNum > 0) {that.bombNum--that.destroyAllEnemy()}}if (that.angle != 0) {that.movePlaneByHandle()}}//創(chuàng)建訂閱者回調(diào)function CreateSubscriberCallBack(err, data) {subscriber = data;//訂閱公共事件commonEvent.subscribe(subscriber, SubscribeCallBack);}//創(chuàng)建訂閱者commonEvent.createSubscriber(subscribeInfo, CreateSubscriberCallBack);
}
恭喜您
通過(guò)本篇Codelab,您可以學(xué)到:
如何跨設(shè)備拉起遠(yuǎn)程FA。
如何連接遠(yuǎn)程Service。
使用RPC實(shí)現(xiàn)本地FA和遠(yuǎn)程Servcice通信。
通過(guò)CommonEvent發(fā)布與訂閱實(shí)現(xiàn)Service和FA之間通信。
為了幫助大家更深入有效的學(xué)習(xí)到鴻蒙開發(fā)知識(shí)點(diǎn),小編特意給大家準(zhǔn)備了一份全套最新版的HarmonyOS NEXT學(xué)習(xí)資源,獲取完整版方式請(qǐng)點(diǎn)擊→《HarmonyOS教學(xué)視頻》
HarmonyOS教學(xué)視頻
鴻蒙語(yǔ)法ArkTS、TypeScript、ArkUI等.....視頻教程
鴻蒙生態(tài)應(yīng)用開發(fā)白皮書V2.0PDF:
獲取白皮書完整版方式請(qǐng)點(diǎn)擊→《鴻蒙生態(tài)應(yīng)用開發(fā)白皮書V2.0PDF》
鴻蒙 (Harmony OS)開發(fā)學(xué)習(xí)手冊(cè)
一、入門必看
- 應(yīng)用開發(fā)導(dǎo)讀(ArkTS)
- ……
二、HarmonyOS 概念
- 系統(tǒng)定義
- 技術(shù)架構(gòu)
- 技術(shù)特性
- 系統(tǒng)安全
- ........
三、如何快速入門?《做鴻蒙應(yīng)用開發(fā)到底學(xué)習(xí)些啥?》
- 基本概念
- 構(gòu)建第一個(gè)ArkTS應(yīng)用
- ……
四、開發(fā)基礎(chǔ)知識(shí)
- 應(yīng)用基礎(chǔ)知識(shí)
- 配置文件
- 應(yīng)用數(shù)據(jù)管理
- 應(yīng)用安全管理
- 應(yīng)用隱私保護(hù)
- 三方應(yīng)用調(diào)用管控機(jī)制
- 資源分類與訪問
- 學(xué)習(xí)ArkTS語(yǔ)言
- ……
五、基于ArkTS 開發(fā)
- Ability開發(fā)
- UI開發(fā)
- 公共事件與通知
- 窗口管理
- 媒體
- 安全
- 網(wǎng)絡(luò)與鏈接
- 電話服務(wù)
- 數(shù)據(jù)管理
- 后臺(tái)任務(wù)(Background Task)管理
- 設(shè)備管理
- 設(shè)備使用信息統(tǒng)計(jì)
- DFX
- 國(guó)際化開發(fā)
- 折疊屏系列
- ……
更多了解更多鴻蒙開發(fā)的相關(guān)知識(shí)可以參考:《鴻蒙 (Harmony OS)開發(fā)學(xué)習(xí)手冊(cè)》