写点什么

鸿蒙元服务实战 - 笑笑五子棋(5)

作者:万少
  • 2025-01-06
    江苏
  • 本文字数:3837 字

    阅读完需:约 13 分钟

鸿蒙元服务实战-笑笑五子棋(5)

鸿蒙元服务实战-笑笑五子棋(5)

来到最后一章了,这一章节讲两个部分。一是笑笑五子棋的卡片制作,二就是发布上架。

卡片介绍

Form Kit(卡片开发框架)提供了一种在桌面、锁屏等系统入口嵌入显示应用信息的开发框架和 API,可以将应用内用户关注的重要


信息或常用操作抽取到服务卡片(以下简称“卡片”)上,通过将卡片添加到桌面上,以达到信息展示、服务直达的便捷体验效果。


新建卡片

卡片类型分为两种:


  1. 静态卡片 功能稍弱

  2. 动态卡片 功能强一些



  1. 选择卡片的属性


  2. 然后你就得到了以下文件


卡片文件解释

EntryFormAbility.ets

entry/src/main/ets/entryformability/EntryFormAbility.ets


该文件可以定义卡片的生命周期,传递数据给卡片等

WidgetCard

entry/src/main/ets/widget/pages/WidgetCard.ets


该文件是卡片的主要展示和业务功能页面。 卡片外观、功能主要由它来提供

form_config.json

entry/src/main/resources/base/profile/form_config.json


该文件是卡片的配置文件,比如卡片的图标、卡片的名字、卡片的种类等等都可以在这配置

获取卡片宽度

卡片的 api 和元服务的 api 稍有区别,所以在开发的需要额外注意


这里在 entry/src/main/ets/entryformability/EntryFormAbility.ets 内,可以设置卡片创建的时获取卡片的宽度


因为卡片有不同的规格尺寸,所以可以动态来获取。


  onAddForm(want: Want) {    let formData: Record<string, number> = {      "canwidth": px2vp((want.parameters?.[formInfo.FormParam.WIDTH_KEY] as number) * 2),    };    return formBindingData.createFormBindingData(formData);  }
复制代码


卡片中是无法使用 AppStorage,所以需要使用 Localstorage 来代替,进行数据传递


卡片中接收


@Entry@Componentstruct WidgetCard {  @LocalStorageProp("canwidth")  canwidth: number = 0  @LocalStorageProp("canwidth")  canheight: number = 0
复制代码

完成卡片下棋逻辑

因为卡片的下棋逻辑和宿主-元服务本身几乎一致。因此在实际开发中,可以将它们共同的逻辑抽离出来方便管理。这里就 cv 复用了。


@Entry@Componentstruct WidgetCard {  @LocalStorageProp("canwidth")  canwidth: number = 0  @LocalStorageProp("canwidth")  canheight: number = 0  settings: RenderingContextSettings = new RenderingContextSettings(true);  ctx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);  // 棋盘参数  gridSize: number = 15;  cellSize: number = this.canwidth / this.gridSize;  radius: number = this.cellSize / 2 - 5; // 棋子的半径  // 棋盘数据  board: number[][] = []  currentPlayer: number = 1; // 当前玩家 (1: 黑子, 2: 白子)  gameOver: boolean = false;  @State  textContent: string = ""  // 处理玩家落子  handleClick = async (event: ClickEvent) => {    if (this.gameOver) {      return;    }
const x = event.x; const y = event.y;
const col = Math.floor(x / this.cellSize); const row = Math.floor(y / this.cellSize);
if (this.board[row] && this.board[row][col] === 0) { this.board[row][col] = this.currentPlayer; this.drawBoard();
if (this.checkWin(row, col)) { this.textContent = this.currentPlayer === 1 ? '黑子胜利!' : '白子胜利!'; this.gameOver = true; // AlertDialog.show({ message: this.textContent })

} else { this.currentPlayer = this.currentPlayer === 1 ? 2 : 1; this.textContent = this.currentPlayer === 1 ? '轮到黑子落子' : '轮到白子落子'; } } else { // promptAction.showToast({ message: `请点击中棋盘对位位置` }) } }
aboutToAppear(): void {
}
// 绘制棋盘 drawBoard = () => { this.ctx.clearRect(0, 0, this.canwidth, this.canwidth);
// 绘制网格 this.ctx.strokeStyle = "#000"; this.ctx.lineWidth = 1; for (let i = 0; i < this.gridSize; i++) { this.ctx.beginPath(); this.ctx.moveTo(this.cellSize * i, 0); this.ctx.lineTo(this.cellSize * i, this.canwidth); this.ctx.stroke();
this.ctx.beginPath(); this.ctx.moveTo(0, this.cellSize * i); this.ctx.lineTo(this.canwidth, this.cellSize * i); this.ctx.stroke(); }
// 绘制已落的棋子 for (let row = 0; row < this.gridSize; row++) { for (let col = 0; col < this.gridSize; col++) { if (this.board[row][col] !== 0) { this.ctx.beginPath(); this.ctx.arc(col * this.cellSize + this.cellSize / 2, row * this.cellSize + this.cellSize / 2, this.radius, 0, 2 * Math.PI); this.ctx.fillStyle = this.board[row][col] === 1 ? 'black' : 'white'; this.ctx.fill(); this.ctx.stroke(); } } } } // 判断是否有五子连珠 checkWin = (row: number, col: number) => { interface abc { dr: number dc: number }
const directions: abc[] = [ { dr: 0, dc: 1 }, // 水平 { dr: 1, dc: 0 }, // 垂直 { dr: 1, dc: 1 }, // 主对角线 { dr: 1, dc: -1 }// 副对角线 ];
for (let i = 0; i < directions.length; i++) { const dr = directions[i].dr const dc = directions[i].dc let count = 1;
// 向一个方向检查 for (let i = 1; i < 5; i++) { let r = row + dr * i; let c = col + dc * i; if (r >= 0 && r < this.gridSize && c >= 0 && c < this.gridSize && this.board[r][c] === this.currentPlayer) { count++; } else { break; } }
// 向另一个方向检查 for (let i = 1; i < 5; i++) { let r = row - dr * i; let c = col - dc * i; if (r >= 0 && r < this.gridSize && c >= 0 && c < this.gridSize && this.board[r][c] === this.currentPlayer) { count++; } else { break; } }
// 如果连续五个相同的棋子,则胜利 if (count >= 5) { return true; } }
return false; } // 初始化游戏 initGame = () => { this.board = [] for (let index = 0; index < this.gridSize; index++) { const arr: number[] = [] for (let index2 = 0; index2 < this.gridSize; index2++) { arr.push(0)
} this.board.push(arr)
} this.currentPlayer = 1; this.gameOver = false; this.textContent = '轮到黑子落子'; this.drawBoard(); }
build() { Stack({ alignContent: Alignment.TopStart }) { Canvas(this.ctx) .width(this.canwidth) .height(this.canwidth) .backgroundColor(Color.Orange) .onReady(() => { this.cellSize = this.canwidth / this.gridSize; this.radius = this.cellSize / 2 - 5; // 棋子的半径 this.initGame() }) .onClick( this.handleClick )
Text(this.textContent) .fontSize(14) .padding(5) .fontColor(Color.White) .fontWeight(700)
} .width("100%") .height("100%") }}
复制代码

调整卡片的图标和名字

主要业务开发完毕了,可以调整卡片的展示信息



这部分信息在 entry/src/main/resources/base/profile/form_config.json中配置:


  1. displayName 标题

  2. description 简介


{  "forms": [    {      "name": "widget",      "displayName": "$string:widget_display_name",      "description": "$string:widget_desc",      "src": "./ets/widget/pages/WidgetCard.ets",      "uiSyntax": "arkts",      "window": {        "designWidth": 720,        "autoDesignWidth": true      },      "colorMode": "auto",      "isDynamic": true,      "isDefault": true,      "updateEnabled": false,      "scheduledUpdateTime": "10:30",      "updateDuration": 1,      "defaultDimension": "4*4",      "supportDimensions": [        "2*2",        "4*4"      ]    }  ]}
复制代码

发布上架

最后,如果要将卡片发布上架,还需要做一些小处理


  1. 设置你的元服务的展示图标

  2. 配置证书

  3. 打包成 Hap

  4. 在 AGC 平台上发布上架等等

  5. 具体流程可以参考底部的文章

参考链接

  1. 卡片开发

  2. HarmonyOS Next 实战卡片开发 01

  3. HarmonyOS Next 实战卡片开发 02

  4. HarmonyOS Next 实战卡片开发 03

  5. HarmonyOS Next 最新 元服务新建到上架全流程

代码仓库

https://gitee.com/ukSir/laughing-at-gomoku
复制代码

总结

至此,笑笑五子棋的开发上架流程已经完毕。


如果你兴趣想要了解更多的鸿蒙应用开发细节和最新资讯,欢迎在评论区留言或者私信或者看我个人信息,可以加入技术交流群。


发布于: 刚刚阅读数: 4
用户头像

万少

关注

还未添加个人签名 2021-12-02 加入

还未添加个人简介

评论

发布
暂无评论
鸿蒙元服务实战-笑笑五子棋(5)_鸿蒙_万少_InfoQ写作社区