【OpenHarmony/HarmonyOS】自定义对战大厅设计:1v1、3v3、队伍槽位与邀请流程
【OpenHarmony/HarmonyOS】自定义对战大厅设计1v1、3v3、队伍槽位与邀请流程多人大厅的难点不在于把六个头像摆成两列而在于“谁有权修改什么”。房主选择模式和地图附近设备收到邀请访客接受后进入房间槽位可能是等待、AI 或关闭最后所有设备必须基于同一份配置同时进入游戏。本篇基于 OpenHarmony/HarmonyOS 项目中的自定义房间原型拆解 ArkUI 大厅的数据结构、P2P 信令和路由参数并明确当前模拟设备、UDP 原型与 3v3 未闭环的边界。一、页面有两个主要阶段CustomTeamPage没有拆成两个路由页而是使用showLobby在设置视图和大厅视图之间切换StateselectedMode:1v1|3v31v1;StatemapSize:small|medium|largemedium;StatemapSizeValue: number 1;StateshowLobby: boolean false;build(): void { Stack() { GalaxyBackground();if(!this.showLobby) {this.SetupView(); }else{this.LobbyView(); } } }阶段用户任务核心状态Setup选择 1v1/3v3、地图小中大、创建房间selectedMode、mapSizeLobby发现设备、邀请、安排槽位、开始游戏玩家数组、slotConfig、P2P 回调这种页面内切换能保留设置数据也避免房间创建前增加一层路由。但showLobby只是布尔值无法表达 Joining、Waiting、Starting、Failed 等网络阶段网络流程复杂后需要显式状态。二、队伍与设备的当前模型页面使用轻量PlayerModelclassPlayerModel{name:string;isHost:boolean;deviceId:string;constructor(name:string, isHost:booleanfalse) {this.name name;this.isHost isHost; } }三个列表分别表达本队、对方和附近设备StateteamAPlayers: PlayerModel[] [ new PlayerModel(我 (本机), true) ];StateteamBPlayers: PlayerModel[] [];StatenearbyDevices: PlayerModel[] [];这个模型适合 UI 原型但不足以支撑真实多人状态。name不是稳定身份deviceId只对发现列表有意义加入队伍后的newPlayer没有保存 peer IP 或 ID断线时难以定位应移除哪个槽位。生产模型至少还需要typePlayerConnectioninvited|joining|connected|disconnected;interfaceLobbyPlayer {playerId:string;displayName:string; deviceId?:string; peerAddress?:string;team:A|B;slotIndex:number;role:host|guest|ai;connection:PlayerConnection;ready:boolean; }这是演进方案。当前代码尚未建立完整玩家身份与准备状态。三、模式与地图选择如何驱动 UI模式按钮接收1v1 | 3v3选中时更新颜色并修改状态。地图使用 0、1、2 的分段控件同时维护字符串值。.onClick(() { animateTo({ duration:200}, () {this.mapSizeValue value;if(value 0)this.mapSize small;elseif(value 1)this.mapSize medium;elsethis.mapSize large; }); })1v1 时每队显示 1 个槽位3v3 时显示 3 个this.TeamSlots(this.selectedMode 1v1?1:3,this.teamAPlayers,#00E5FF);模式状态确实改变了大厅布局但它还没有限制加入人数、验证队伍完整性或改变网络同步协议。所以“UI 可选 3v3”和“支持六人真实对战”是两回事。四、创建房间后才开始发现设备 点击创建房间会清空附近设备并开始扫描createRoom(): void { animateTo({duration: 300 }, () { this.showLobby true; this.nearbyDevices [];P2PConnectionManager.getInstance().startDiscovery(); }); }把扫描放在进入大厅之后能避免用户还在选择配置时持续消耗无线与定时器资源。页面离开时调用stopDiscovery()清除广播 interval 并停止分布式发现。页面显示时先初始化单例 Manager再绑定四类回调发现设备、收到邀请、Peer 连接、房主开始游戏。这形成了一套事件驱动 UIManager 不依赖 ArkUI页面将网络事件转换为列表、Dialog、Toast 与路由。五、设备发现来自两条通道P2PConnectionManager同时尝试分布式设备管理和 UDP 广播flowchartTDA[startDiscovery]--B[Distributed Device Discovery]A-- C[UDP 每 2 秒广播 DISCOVER]A-- D[2 秒后注入模拟设备]B-- E[onDeviceFound]C -- F[收到对端 DISCOVER]F -- E D -- E E -- G[页面去重并加入 nearbyDevices]分布式设备在线事件被转换为统一DiscoveredDeviceUDP 收到DISCOVER后生成lan_ip作为设备 ID。页面按deviceId去重manager.onDeviceFound(device: DiscoveredDevice) {constexists this.nearbyDevices.find(itemitem.deviceId device.deviceId);if(exists)return;constplayer newPlayerModel(device.deviceName); player.deviceId device.deviceId;this.nearbyDevices.push(player); };同一物理设备可能同时通过分布式发现和 UDP 出现两个通道的 ID 不同所以按 deviceId 仍可能显示两次。需要统一身份关联或给通道结果标注来源并合并。六、附近列表中包含明确的模拟设备startDiscovery()两秒后总会调用setTimeout((){ this.mockDeviceFound(dev_001,Mate 60 Pro (模拟)); },2000);邀请dev_*时也不会真正发送网络包而是使用模拟 IP并在一秒后伪造 ACCEPTif(deviceId.startsWith(dev_)) { const targetIp 192.168.1.100;setTimeout((){ this.handleSignal({ type:ACCEPT, name:Mock Player, ip: targetIp }, targetIp); },1000);return; }这对单机演示 UI 很有价值但文章、截图和产品说明必须标注“模拟”。否则读者会以为两台真机发现和握手已经完成。七、邀请握手是怎样完成的真实 LAN 设备 ID 形如lan_ip。房主点击连接后发送{type:INVITE,name:我 (本机)}客端收到后弹出 AlertDialog。接受时发送ACCEPTacceptInvite(from: P2PInviteInfo):void{ manager.acceptInvite(from.ip,我 (本机));this.showLobby true;this.teamAPlayers [newPlayerModel(from.name,true) ];this.teamBPlayers [newPlayerModel(我 (本机),false) ]; }房主收到 ACCEPT 后把 peer 写入peersMap并触发onPeerConnected。页面当前只在 Team B 为空时加入一个玩家manager.onPeerConnected (peer: P2PPeerInfo) {if(this.teamBPlayers.length0) { this.teamBPlayers.push(newPlayerModel(peer.name,false)); }// 当前源码明确保留 3v3 待处理注释};因此握手链路主要覆盖 1v1。第二、第三名玩家、断线重连、队伍切换和房主迁移都没有闭环。八、槽位状态等待、AI、关闭空槽位点击时在三个值间循环StateslotConfig:Mapstring,string newMap();toggleSlotState(index:number,_count:number,isTeamA:boolean):void{constteam isTeamA ?A:B;constkey ${team}_${index};letcurrent this.slotConfig.get(key) ||open;if(current open) current ai;elseif(current ai) current closed;elsecurrent open;this.slotConfig.set(key, current); }值UI 含义GameEngine 当前消费open等待真人加入没有完整真人槽位绑定ai电脑补位Engine 会按 A_/B_ key 生成 AIclosed关闭该槽位不生成 AI页面还保留teamASlotStates、teamBSlotStates两个数组和getSlotState()但实际显示主要读取slotConfigMap。这是原型迭代留下的重复模型应选一个权威来源。Map 原地set()后使用this.mapSizeValue this.mapSizeValue尝试强制刷新不够可靠。更合适的是克隆 Map 后重新赋值。九、房主与访客权限目前没有真正隔离 ⚠️客端接受邀请后进入同一个 LobbyView。源码注释已经提出“Guest shouldnt change settings”但没有实现房主权限判断。开始按钮、槽位按钮和返回设置仍可能对访客可见。多人大厅至少要区分操作房主访客选择模式/地图允许只读修改 AI/关闭槽位允许不允许邀请附近设备允许通常不允许切换自己队伍/准备可按规则允许开始游戏允许且需校验不允许离开房间解散或迁移房主退出自身权限不能只隐藏按钮网络信令接收端也必须验证 sender 是否为房主否则访客可以自行构造 START_GAME。十、START_GAME 配置如何广播房主把 Map 转为普通对象并字符串化constconfigObject:Recordstring,string {};this.slotConfig.forEach((value, key) { configObject[key] value; }); manager.broadcastGameStart({mapSize:this.mapSize,teamMode:this.selectedMode,slotConfig:JSON.stringify(configObject) });Manager 为每个已连接 peer 发送 UDP JSON{type:START_GAME,config: {mapSize:medium,teamMode:3v3,slotConfig:{\A_1\:\ai\}} }客端收到后回调页面并pushUrl到 Index。房主也执行同样路由。这个协议表达了“开始意图”但没有房间 ID、配置版本、随机种子、开始时间和确认 ACK。十一、UDP 信令的可靠性与安全边界当前原型使用固定 8888 端口和 JSON 明文。UDP 不保证送达、顺序或唯一性START_GAME 丢包时可能房主已进入、客端仍留在大厅。重复包则可能重复导航。生产设计至少需要messageId去重roomId隔离同网段不同房间senderId验证消息来源sequence判断新旧配置ACK retry关键命令确认protocolVersion兼容升级身份验证或会话签名阻止任意局域网设备伪造信令长度与字段白名单避免恶意大包和非法 JSON。当前handleSignal(START_GAME)会直接把发送者加入 peers 并触发回调没有确认其此前是否通过邀请成为房主。它适合可信局域网原型不适合作为公网或正式竞技协议。十二、开局参数当前没有在 Index 形成闭环CustomTeamPage 会发送并路由gameModemultiplayer、地图和槽位配置但 Index 的onPageShow()中消费多人参数的代码被注释标注为离线版本移除。GameEngine 确实能解析多人配置并为A_*、B_*的ai槽生成不同队伍 AI但页面路由到startGame(multiplayer, ..., config)的接线当前没有执行。因此准确结论是大厅 UI、设备发现接口、邀请信令和开局配置格式已经存在模拟设备可以演示 1v1 加入效果3v3 真人槽位尚未处理路由接收端当前不会自动启动完整多人局UDP 状态同步属于原型不能宣称正式联机已完成。十三、页面离开时的清理还不完整aboutToDisappear()调用stopDiscovery()能清除广播 interval 和设备发现监听。但页面赋给单例 Manager 的以下回调仍保留onDeviceFoundonReceiveInviteonGameStartonPeerConnected如果页面实例离开后单例收到 UDP 消息回调仍可能修改旧页面状态或执行路由。应在离开时仅当回调仍属于当前页面时置空或由 Manager 返回 unsubscribe 函数。UDP socket 本身也没有在页面离开时关闭因为它属于全局单例。是否保持监听取决于产品如果后台也要接收邀请应由 Ability 生命周期管理如果只在大厅有效应提供disposeSocket()。十四、推荐的大厅状态机stateDiagram-v2 [*] -- Configuring Configuring--Discovering: 房主创建房间 Configuring--Joining: 访客接受邀请 Discovering--Lobby: 扫描启动 Joining--Lobby: 握手确认 Lobby--Starting: 房主点击开始 Starting--Lobby: 有设备未确认/发送失败 Starting--InGame: 所有设备确认同一配置 Lobby--Closed: 房主解散 Lobby--Left: 访客离开主状态之外再保存LobbySnapshot房间 ID、版本、房主、玩家、槽位、地图和模式。每次变更由房主增加 revision 并广播完整快照客端只接受更新版本能比零散地修改数组更容易恢复一致。十五、测试矩阵 场景预期重复发现同一 deviceId附近列表只出现一次分布式与 LAN 发现同设备通过稳定身份合并模拟设备出现UI 明确标“模拟”1v1 接受邀请房主和访客占据正确队伍第二名 peer 加入 1v1拒绝或进入观察不静默丢失3v3 三名访客加入每人有稳定 slotIndex访客点击开始UI 和协议端都拒绝START_GAME 丢包重试并等待 ACKSTART_GAME 重复只导航一次非房主伪造 START_GAME消息被拒绝页面离开后收到消息不再修改旧组件非法 slotConfig JSON保留大厅并提示配置错误Index 参数消费关闭测试明确标记端到端未完成十六、总结 ✨项目已经搭建了一条有价值的自定义大厅原型ArkUI 中选择模式与地图进入大厅后发现设备UDP 发送邀请和接受信令槽位可切换等待、AI、关闭房主广播统一开局配置客端根据回调导航。但“原型可演示”和“多人功能完成”必须严格区分。当前附近列表主动注入模拟设备Peer 加入只完整处理 1v13v3 真人槽位留有待处理注释访客权限没有隔离UDP 没有 ACK、身份验证和去重Index 的开局参数消费也处于注释状态。下一步应先建立权威 LobbySnapshot、房主权限、稳定玩家身份和可靠信令再连接战斗会话。只有配置、网络、页面和引擎四端都消费同一份状态大厅才真正成为多人对战的入口。推荐标签OpenHarmonyHarmonyOSArkTSArkUI局域网UDP多人游戏状态同步P2P

相关新闻

2026北京GEO解决方案服务流程详解:企业配合资料与避坑指南

2026北京GEO解决方案服务流程详解:企业配合资料与避坑指南

随着豆包、DeepSeek等生成式搜索引擎成为用户获取信息的重要渠道,北京企业对品牌在AI回答中曝光度与引用率的关注度持续提升。不少企业在咨询GEO解决方案服务流程相关问题时,既担心遇到流程不规范的机构踩坑,也不清楚自己需要提前准备哪些配合…

2026/7/25 17:33:57 阅读更多 →
【2027最新】基于SpringBoot+Vue的兴顺物流管理系统管理系统源码+MyBatis+MySQL

【2027最新】基于SpringBoot+Vue的兴顺物流管理系统管理系统源码+MyBatis+MySQL

💡实话实说:C有自己的项目库存,不需要找别人拿货再加价。博主介绍:🎓 江南大学计算机科学与技术专业在读研究生 | CSDN博客专家 | Java技术爱好者 在校期间积极参与实验室项目研发,现为CSDN特邀作者、掘金优…

2026/7/24 16:18:47 阅读更多 →
AzurLaneAutoScript终极指南:7×24小时全自动碧蓝航线舰队管理

AzurLaneAutoScript终极指南:7×24小时全自动碧蓝航线舰队管理

AzurLaneAutoScript终极指南:724小时全自动碧蓝航线舰队管理 【免费下载链接】AzurLaneAutoScript Azur Lane bot (CN/EN/JP/TW) 碧蓝航线脚本 | 无缝委托科研,全自动大世界 项目地址: https://gitcode.com/gh_mirrors/az/AzurLaneAutoScript 你是…

2026/7/24 16:18:47 阅读更多 →

最新新闻

腾讯AI Lab用LLM实现视觉编码器突破

腾讯AI Lab用LLM实现视觉编码器突破

1. 项目背景与核心突破最近看到腾讯AI Lab放出一个很有意思的技术成果——他们用纯文本预训练的大语言模型(LLM)作为基础,成功训出了一个视觉编码器(Visual Encoder)。这个模型在图表理解和长视频处理任务上&#xff0…

2026/7/25 17:33:24 阅读更多 →
收藏 | 大模型入门进阶指南:小白程序员必备学习路线图

收藏 | 大模型入门进阶指南:小白程序员必备学习路线图

本文为“大模型入门进阶”系列的第一篇,旨在帮助初学者建立完整的大模型知识体系。文章指出,大模型并非孤立的技术点,而是一个融合多领域的技术体系。学习大模型需遵循特定路线:首先掌握基础编程和数学能力,其次理解机…

2026/7/25 17:33:24 阅读更多 →
终极黑苹果安装指南:3步完成macOS完美配置的完整实战教程

终极黑苹果安装指南:3步完成macOS完美配置的完整实战教程

终极黑苹果安装指南:3步完成macOS完美配置的完整实战教程 【免费下载链接】Hackintosh 国光的黑苹果安装教程:手把手教你配置 OpenCore 项目地址: https://gitcode.com/gh_mirrors/hac/Hackintosh 想在普通PC上体验macOS的流畅与优雅吗&#xff1…

2026/7/25 17:33:24 阅读更多 →
JSON 数据格式

JSON 数据格式

JSON 数据格式:从入门到实战 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人类阅读和编写,也易于机器解析和生成。它基于 JavaScript 的子集,但因其语言无关性,被广泛应用…

2026/7/25 17:33:24 阅读更多 →
解锁Chrome内置AI:本地运行Gemini Nano,零延迟隐私保护

解锁Chrome内置AI:本地运行Gemini Nano,零延迟隐私保护

你是否遇到过这样的场景:在浏览器里打开十几个标签页,每个页面都想用 AI 总结一下,或者快速翻译一段外文,结果要么得手动复制粘贴到某个 AI 工具,要么就得忍受网络延迟和隐私担忧?又或者,你开发的 Web 应用想集成 AI 功能,却苦于服务器成本、网络延迟和用户隐私的平衡难…

2026/7/25 17:33:24 阅读更多 →
Unity游戏实时翻译插件XUnity.AutoTranslator:5分钟部署与深度配置指南

Unity游戏实时翻译插件XUnity.AutoTranslator:5分钟部署与深度配置指南

1. 项目概述:为什么你的Unity游戏需要智能实时翻译?如果你是一名独立游戏开发者,或者正在运营一款面向全球玩家的Unity游戏,那么“语言壁垒”绝对是你最不想面对,却又无法绕开的难题。想象一下,你的游戏在S…

2026/7/25 17:32:24 阅读更多 →

日新闻

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存

突破文档下载限制:kill-doc让你看到的都能保存 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是为了解决您的…

2026/7/25 0:00:35 阅读更多 →
C++ string类模拟实现:从深拷贝到内存管理的完整指南

C++ string类模拟实现:从深拷贝到内存管理的完整指南

1. 项目概述:为什么我们要“手撕”string类?在C的学习道路上,尤其是从C语言过渡到C的“初阶”阶段,string类绝对是一个绕不开的核心。标准库里的std::string用起来太方便了,、find、substr,几个操作符和函数…

2026/7/25 0:00:35 阅读更多 →
三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

三角洲寻宝鼠工具:高效文件搜索与资源管理实战指南

1. 先搞清楚“三角洲寻宝鼠”到底是什么工具从名称来看,“三角洲寻宝鼠”更像是一个资源查找或文件检索类工具,而不是游戏或娱乐软件。这类工具的核心价值在于帮助用户快速定位特定资源,比如文档、图片、压缩包或特定格式的文件。如果你经常需…

2026/7/25 0:00:35 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/25 5:08:22 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/25 5:13:53 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 18:52:18 阅读更多 →

月新闻