基于鸿蒙OS开发附近社交游戏平台(一)-项目总览与技术选型

一、NearPlay项目定位与愿景

1.1 我们要做什么

NearPlay是一款运行在HarmonyOS上的附近社交游戏平台。它将"桌游"“附近的人”"语音社交"三个场景融合为一,让用户在物理空间中通过手机就能找到附近的桌游玩伴、加入实时游戏房间、通过语音发言完成游戏流程,最终实现从线上匹配到线下见面交友的完整闭环。

传统的桌游场景存在三个核心痛点:第一,组织成本高——想玩一局狼人杀需要六到十二人,但身边随时凑得出这么多人并不容易;第二,规则学习成本高——每一款新桌游都有一套规则体系,新手往往需要老玩家口述规则、担任法官,入门门槛陡峭;第三,社交连接弱——即便在桌游吧认识了几位有趣的人,游戏结束后各走各路,缺少持续互动的载体。

NearPlay的解法是:用附近匹配引擎解决人数问题——打开App即可看到1-10公里内所有在线玩家,一键发起匹配,系统自动从近到远逐步扩大搜索半径直至凑齐;用内置裁判+流程驱动解决规则问题——每款游戏的阶段推进、倒计时、角色行动判定全部由代码自动完成,无需真人法官;用活动系统+即时聊天+RunAdvisor运动联动解决社交连接问题——游戏结束后可直接进入聊天、报名线下活动,甚至查看对方的运动计划和食谱,找到共同兴趣点。

1.2 目标用户画像

核心用户:18-35岁的都市年轻人,主要覆盖以下细分群体:

  • 桌游爱好者:经常出入桌游吧,但苦于"缺人"或"想玩但不想出门"的用户。他们需要的是随时可匹配的线上桌游替代品。
  • 社交破冰需求者:刚到新城市的大学生、新入职的职场人,希望用"一起玩游戏"这种低压力方式认识附近的人。
  • 运动社交双重需求者:既爱跑步又爱社交的群体,RunAdvisor功能让他们在游戏中发现运动同好。
  • 语音社交偏好者:不喜欢打字、更爱说话表达的用户,语音发言和语音输入让游戏体验更接近真实桌游。

用户的一天可能是这样:下班后打开NearPlay,看到附近800米内有个正在玩狼人杀的房间缺2人,一键加入;游戏中用语音发言辩论,发现自己和另一位玩家都喜欢跑步;游戏结束后查看对方的RunAdvisor运动计划,发现大家都是5公里标准跑爱好者,约了周末一起晨跑。

1.3 竞品分析:桌游小程序 vs NearPlay

当前市场上与NearPlay最接近的产品形态是微信桌游小程序(如"谁是卧底Online""狼人杀官方"等)。我们从七个维度进行对比:

维度微信桌游小程序NearPlay
平台微信小程序,运行在WebView中HarmonyOS原生ArkTS,直接调用系统API
附近发现无,纯线上随机匹配基于位置的附近匹配,1-10km渐扩搜索
游戏驱动依赖真人法官或简化规则内置全自动裁判,阶段推进+倒计时+角色判定
语音交互部分支持语音房,但延迟高原生CoreSpeechKit语音识别+语音发言
社交延续游戏结束即散,无后续聊天+活动系统+RunAdvisor运动联动
内容导入固定题库,不可自定义剧本杀支持外部.txt文件导入自定义剧本
隐私保护无拉黑过滤机制完整BlockModel,拉黑后全App过滤

微信小程序的优势是流量入口和跨平台,但本质上是"线上随机匹配"模式,无法解决"附近真实社交"这个核心需求。NearPlay选择HarmonyOS原生开发,虽然覆盖范围暂时局限于鸿蒙设备,但获得了三样小程序永远无法获得的能力:位置服务深度集成(APPROXIMATELY_LOCATION权限+距离排序)、原生语音识别(CoreSpeechKit回调式引擎)、系统级UI体验(ArkUI声明式渲染,60fps动画)。


二、核心功能全景图

2.1 ASCII功能全景图

┌────────────────────────────────── NearPlay ──────────────────────────────────┐
│                                                                                │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │
│  │   首页Tab    │  │   游戏Tab    │  │   活动Tab    │  │   消息Tab    │  │   我的Tab    │ │
│  │  附近在线    │  │  游戏大厅    │  │  线下活动    │  │  通知+聊天   │  │  个人+黑名单  │ │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘ │
│         │                │                │                │                │        │
│  ┌──────┴──────┐  ┌──────┴──────┐  ┌──────┴──────┐  ┌──────┴──────┐  ┌──────┴──────┐ │
│  │ 附近匹配引擎 │  │ GameRoom    │  │ ActivityPub │  │  ChatPage   │  │ BlockModel  │ │
│  │ MatchEngine │  │ 匹配→路由    │  │ ActivityDet │  │  文字/语音   │  │  拉黑/取消   │ │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └─────────────┘ │
│         │                │                │                │                          │
│  ┌──────┴────────────────┴────────────────┴────────────────┴──────┐                │
│  │                      6 款 桌 游 子 系 统                         │                │
│  │  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐     │                │
│  │  │🐺狼人杀 │ │📜剧本杀 │ │🕵卧底   │ │🎨画猜   │ │💬真心话 │ │🔔反应快 │     │                │
│  │  │6-12人   │ │4-8人    │ │4-10人   │ │2-8人    │ │2-10人   │ │2-6人    │     │                │
│  │  │可导入×  │ │可导入✓  │ │可导入×  │ │可导入×  │ │可导入×  │ │可导入×  │     │                │
│  │  └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘     │                │
│  └───────┼───────────┼───────────┼───────────┼───────────┼───────────┼──────────┘                │
│          │           │           │           │           │           │                            │
│  ┌───────┴───────────┴───────────┴───────────┴───────────┴───────────┴──────────┐                │
│  │                     共 享 基 础 设 施                                         │                │
│  │  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐       │                │
│  │  │GameNetwork│  │VoiceInput│  │GameChat  │  │Permission│  │RunAdvisor│       │                │
│  │  │WebSocket │  │Helper    │  │Panel     │  │Model     │  │Model     │       │                │
│  │  │@NetworkKit│  │CoreSpeech│  │文字+语音  │  │权限引导  │  │运动联动  │       │                │
│  │  └──────────┘  └──────────┘  └──────────┘  └──────────┘  └──────────┘       │                │
│  └───────────────────────────────────────────────────────────────────────────┘                │
│                                                                                │
│  ┌─────────────────────────── Kit 依 赖 层 ───────────────────────────────────┐                │
│  │ @kit.NetworkKit  @kit.CoreSpeechKit  @kit.CoreFileKit  @kit.AbilityKit      │                │
│  │ @kit.BasicServicesKit  @kit.PerformanceAnalysisKit  @kit.ArkUI               │                │
│  └───────────────────────────────────────────────────────────────────────────┘                │
└─────────────────────────────────────────────────────────────────────────────┘

2.2 六款桌游详解

NearPlay内置六款风格各异的桌游,覆盖推理、表演、休闲、社交四大品类。每款游戏均配备自动裁判、阶段倒计时、语音发言集成和完整的流程驱动。

狼人杀(WerewolfGame):经典6-12人推理游戏。支持6种角色(村民/狼人/预言家/女巫/猎人/守卫),11个游戏阶段(角色分配→天黑→狼人行动→预言家查验→女巫用药→守卫守护→天亮→自由讨论→投票放逐→投票结果→胜负判定)。白天讨论阶段采用逐人限时发言制,每人30秒语音发言,轮到当前玩家时VoiceInput组件自动激活,其他玩家处于禁言状态。投票阶段10秒倒计时,超时视为弃权。胜负判定自动执行:狼人全灭→好人胜,狼人数量≥好人数→狼人胜。

剧本杀(ScriptKillGame):4-8人沉浸式推理游戏,最大特色是可导入外部剧本。内置"消失的画家"剧本(4角色+NPC管家+2幕剧情),同时支持通过@kit.CoreFileKit的DocumentViewPicker选择.txt文件导入自定义剧本内容。NPC台词采用模拟TTS朗读(按字数×200ms+1500ms间隔逐句显示),增强沉浸感。流程包括9个阶段:选择剧本→角色分配→幕介绍→NPC发言→自由讨论→线索公开→幕间过渡→最终投票→真相揭晓。

谁是卧底(UndercoverGame):4-10人语言推理游戏。8组词对(火锅/麻辣烫、包子/饺子、咖啡/奶茶等),支持三种角色类型(平民/卧底/白板)。描述阶段每人30秒,投票阶段30秒,淘汰后自动揭示角色身份。平民词和卧底词通过WordPair模型精确区分。

你画我猜(DrawGuessGame):2-8人休闲游戏,使用Canvas绘图。内置12个词库(苹果/太阳/房子/猫/飞机等),60秒/轮倒计时,支持触摸绘图(DrawPoint模型记录坐标+笔画+颜色+线宽)。猜词记录GuessRecord追踪每位玩家的猜测和正确性。

真心话大冒险(TruthOrDareGame):2-10人破冰游戏,独特的众包出题机制:当某位玩家选择真心话或大冒险后,其他玩家有8秒时间提交题目(crowdSource=8s),系统从提交中随机抽取一道。内置6道真心话题("你最近一次说谎是什么时候?"等)和6道大冒险题("给你最近联系的人发’我想你了’"等)作为保底题库。回答阶段20秒/轮。

看谁反应快(QuickReactGame):2-6人手速竞技游戏,改编自桌游"德国心脏病"。5种水果(香蕉/苹果/橙子/葡萄/草莓),5张桌牌,当桌面上某水果总数恰好为5时抢拍。每局自动生成60张洗牌牌组(每种水果12张),reactWindow阶段计时反应速度,误拍惩罚机制。

2.3 活动系统

活动系统是NearPlay将线上社交延伸到线下的核心桥梁。用户可以发布线下活动(ActivityPublish页),填写标题、描述、地点、游戏内容、最大参与人数。已发布的活动在活动Tab展示,显示距离、参与人数、报名状态。活动详情页(ActivityDetail)展示完整信息、已报名参与者列表,如果是发起人还能看到报名管理通知。报名后显示"查看定位"按钮,引导线下见面。

2.4 即时聊天与拉黑过滤

聊天系统(ChatPage)支持三种消息类型:文字消息(ChatMsgType.TEXT)、语音消息(ChatMsgType.VOICE,记录时长)、图片消息(ChatMsgType.IMAGE,通过@kit.CoreFileKit的PhotoViewPicker选择)。聊天页顶部显示对方头像和昵称,右上角"⋯"菜单可触发拉黑确认弹窗。拉黑后输入栏替换为"你已拉黑对方,无法发送消息"提示,并显示"取消拉黑"按钮。

拉黑过滤是全局性的——BlockModel采用模块级let变量+导出函数模式(而非单例类),在Index.ets的aboutToAppear中初始化,拉黑/取消拉黑操作通过syncBlockState()同步到所有数据列表:附近用户列表过滤掉被拉黑者,通知列表过滤掉被拉黑者的通知,聊天会话列表过滤掉被拉黑者的对话。这种设计确保一旦拉黑,用户在全App范围内都不会再看到对方的任何信息。

2.5 附近匹配与MatchEngine

附近匹配卡片

附近匹配是NearPlay的差异化核心。GameRoom.ets实现了渐进式匹配:从1km开始,每1.5秒扩大1km搜索半径,直至找到4名在线玩家或达到10km上限。匹配进度通过Progress组件实时可视化。

匹配完成后进入游戏,GameRoom通过gameRoutes Record路由表分发到正确的游戏页面:

'1' → pages/game/WerewolfGame
'2' → pages/game/ScriptKillGame
'3' → pages/game/UndercoverGame
'4' → pages/game/DrawGuessGame
'5' → pages/game/TruthOrDareGame
'6' → pages/game/QuickReactGame

匹配时还可发起位置共享请求(LocationShareRequest),对方在弹窗中选择同意/拒绝(ShareStatus枚举:PENDING/ACCEPTED/REJECTED),双方同意后共享位置方便线下见面。

MatchEngine计算匹配分数基于两个维度:音乐匹配(同类型音乐+20分)和使用习惯匹配(App使用类别重叠最高80分),总分上限100分。分数映射为标签:≥80→"匹配度·极高",≥60→"匹配度·高",≥40→"匹配度·中",≥20→"匹配度·低",其余不显示。音乐匹配通过MusicModel的classifyGenre函数实现,内置10种音乐类型关键词分类器;使用习惯通过UsageModel的UsageProfile.fromRecords聚合App使用记录,提取top3类别后与对方对比。

2.6 RunAdvisor跨应用联动

RunAdvisor是NearPlay的特色功能,将社交从游戏延伸到运动领域。从附近用户列表点击"🏃"按钮进入UserRunProfilePage,查看对方的运动计划(RunPlan,3种类型:轻松跑/标准跑/耐力跑)和食谱(FoodRecipe,带getCalories()方法计算卡路里)。用户可以对运动计划和食谱点赞(LikeStore模块级likeMap + toggleLike/isLiked/getLikeCount),通过likeRefresh++ @State计数器触发UI刷新。

MockRunAdvisorData预置了8个附近用户的运动档案,每人包含1-2个运动计划和3个食谱,覆盖鸡胸肉/鱼肉/牛肉/虾仁/羊肉/猪瘦肉/三文鱼等蛋白质来源,西兰花/生菜/菠菜/黄瓜等蔬菜,米饭/燕麦/红薯/馒头/土豆等主食,以及各类水果。

2.7 语音识别与VoiceInputHelper

语音识别是NearPlay游戏体验的关键一环。VoiceInputHelper采用plain class(非@Component)设计,封装@kit.CoreSpeechKit的speechRecognizer.createEngine回调式API。初始化参数:language=‘zh-CN’、online=1(在线模式)、recognizerMode=‘short’(短语音识别),音频参数:PCM 16kHz单声道16bit。

VoiceInput组件(@Component UI包装器)通过200ms间隔的refreshTimer轮询VoiceInputHelper的状态(isListening/recognizedText/listenDuration),在UI上实时展示录音状态和识别文本。录音时长上限60秒,超时自动停止。识别完成后通过onVoiceResult回调将文本传回宿主游戏页面。

每款游戏的讨论/发言阶段都集成了VoiceInput:狼人杀在当前发言者是自己时显示、剧本杀在自由讨论时显示、卧底在描述阶段显示。这种"按需激活"设计避免了非发言者的误操作,同时禁言状态通过canSpeak @Prop传递控制。


三、技术选型深度论证

3.1 ArkTS vs TypeScript:30+条关键差异

ArkTS是HarmonyOS的专用开发语言,基于TypeScript但施加了大量严格限制以保障运行时性能和类型安全。以下从语法约束、类型系统、运行时差异三个维度列出30余条关键差异:

编号差异项TypeScriptArkTSNearPlay中的应对
1结构体声明class可用任意方式必须用struct + @Component装饰器所有页面组件均用struct
2状态管理无内置响应式@State/@Prop/@Link/@Provide/@ConsumeIndex.ets用@State管理所有列表数据
3UI构建JSX/TSX声明式build() + @Builder所有页面用build()+@Builder模式
4动态属性访问obj[dynamicKey]禁止arkts-no-dynamic-prop-accessgameRoutes用Record<string,string>固定key
5Object.keys()可用禁止arkts-no-obj-keys用已知key数组迭代
6for…in可用禁止arkts-no-for-in改用for循环+已知key数组
7as类型断言宽松严格,仅限兼容类型getParams() as GameRoomParams等
8联合类型广泛支持有限制,建议用enum所有游戏阶段用enum(WerewolfPhase等)
9泛型完整支持受限,部分场景需显式标注ForEach显式标注元素类型
10闭包捕获var/let/均可箭头函数捕获thisonClick用箭头函数
11空值安全可选链?.严格null检查params?.gameId ?? ‘’
12静态方法class staticstatic of()工厂模式所有Model类用static of()构造
13单例模式经典单例不推荐class单例BlockModel用模块级let+导出函数
14模块导出export default建议命名导出所有类/函数用export显式导出
15装饰器实验性一等公民@Component/@Entry每个页面@Entry+@Component
16数组操作任意方法部分受限,建议展开运算this.messages=[…this.messages,msg]
17setTimeout返回number返回numbersetInterval返回timerId
18setInterval返回number返回numberspeakerTimerId: number=-1
19Promise完整支持async/awaitrequestPermission用async
20Map/Set完整受限,建议Record/数组likeMap用Record<string,number>
21JSON.parse返回any必须as指定类型GameMessage.fromJson用Record<string,string
22展开运算对象/数组均可数组展开为主blockedList=[…blockedList,user]
23可选属性interface {x?: T}class {x: T=‘’}所有属性给默认值而非可选
24interface广泛使用受限,建议classRouteParams用interface,ChatPageParams用class
25条件渲染if/else JSXif/else在build()内WerewolfGame用if…else if阶段分发
26列表渲染map()ForEach()所有列表用ForEach+key生成器
27组件传参props@Prop/@LinkVoiceInput用@Prop canSpeak
28事件处理onClick={fn}.onClick(()=>{})所有事件用箭头函数
29样式系统CSS链式调用属性.width(‘100%’).padding(12)
30生命周期useEffect等aboutToAppear/aboutToDisappear初始化在aboutToAppear,清理在aboutToDisappear
31this引用任意struct内thisthis.getUIContext().getRouter()
32全局状态Redux等AppStorage/PersistentStorage当前用@State组件内管理
33导入路径相对/node_modules相对路径+@kitimport from ‘…/model/xxx’
34枚举number/string enum均支持WerewolfRole等用number enum

3.2 HarmonyOS SDK版本选择

NearPlay选择API 24 / SDK 6.1.1 (compileSdkVersion: 60101024),这一决策基于以下考量:

  • API 24是HarmonyOS NEXT的稳定基线:低于此版本的SDK缺少CoreSpeechKit、CoreFileKit等关键Kit的完整支持。
  • speechRecognizer.createEngine的回调式API在API 24中才成熟稳定,低于此版本可能仅支持Promise式创建,与我们的回调式VoiceInputHelper设计不兼容。
  • **abilityAccessCtrl.createAtManager().requestPermissionsFromUser()**在API 24中返回PermissionRequestResult.authResults数组,低版本API结构不同。
  • **@kit.NetworkKit的webSocket.createWebSocket()**在API 24中提供完整的事件回调模型(on(‘open’)/on(‘message’)/on(‘close’)/on(‘error’)),这是GameNetwork自动重连机制的基础。
  • build-profile.json5中compatibleSdkVersion与targetSdkVersion均设为"6.1.1(24)",确保运行时兼容性。

3.3 WebSocket vs 分布式软总线

NearPlay选择WebSocket(@kit.NetworkKit)而非HarmonyOS特有的分布式软总线作为游戏通信方案,原因如下:

分布式软总线的限制:分布式软总线是HarmonyOS设备间近场通信的方案,理论上延迟更低、无需中心服务器。但它要求两端均为HarmonyOS设备且登录同一华为账号,且当前主要面向1对1的设备协同场景(如手机-平板-手表互联),不适合多玩家游戏房间这种N对N广播场景。

WebSocket的优势:WebSocket是互联网标准协议,支持跨平台客户端,可通过中心服务器实现房间管理、消息广播、状态同步。GameNetwork.ets封装了完整的WebSocket生命周期:connect→on(‘open’)→on(‘message’)→on(‘close’)→自动重连(最多5次,每次3秒间隔)。GameMessage模型定义了4种消息类型(ACTION/STATE/SYSTEM/PRIVATE),通过JSON序列化在WebSocket上传输。

当前状态:GameNetwork已完整实现但游戏页面尚未实际调用(使用Mock数据驱动),这为后续接入真实WebSocket服务端预留了干净的接口。

3.4 Mock策略

NearPlay采用深度Mock策略,所有外部数据源均通过Mock类提供静态数据,确保应用可在无后端、无网络的环境下完整运行。Mock设计遵循以下原则:

  • 每个Model文件配套MockData类:MockUserData(8个附近用户)、MockGameData(6款游戏)、MockActivityData(4个活动)、MockChatData(4个会话+6条消息)、MockNotifyData(5条通知)、MockBlockData(1个初始拉黑用户)、MockMusicData(1首当前播放+8首附近播放)、MockUsageData(5条自身记录+8组附近记录)、MockRunAdvisorData(8个运动档案)、MockWerewolfData(8个玩家含6种角色)、MockScriptData(1个完整4人剧本)、MockUndercoverData(8组词对+6个玩家)、MockDrawGuessData(12个词+4个玩家)、MockTruthOrDareData(6+6道题+4个玩家)、MockQuickReactData(动态生成60张洗牌牌组)。

  • 系统API Mock:AVSession(读取当前播放音乐)和usageStatistics(读取应用使用记录)是系统级API,普通应用无法直接调用。NearPlay在PermissionModel中声明了ohos.permission.MANAGE_MEDIA_RESOURCES和ohos.permission.BUNDLE_ACTIVE_INFO权限,但实际数据通过MockMusicData和MockUsageData提供,PermissionPage中的权限请求使用try-catch包裹,失败后静默降级。

  • Mock计时器常量:describe阶段=10s、discuss阶段=30s每人、vote阶段=10s、crowdSource众包出题=8s、round回合=20s。这些常量使游戏流程在模拟器中可完整走完。

3.5 为什么不用React Native/Flutter

维度React NativeFlutterArkTS (NearPlay)
HarmonyOS支持社区实验性适配,无官方Kit社区ohos_flutter,API覆盖不全官方一等公民,完整Kit生态
语音识别需原生桥接需Platform ChannelCoreSpeechKit直接调用
WebSocket第三方库第三方库@kit.NetworkKit内置
权限管理需原生桥接需Platform Channel@kit.AbilityKit直接调用
文件选择需原生桥接需Platform Channel@kit.CoreFileKit直接调用
UI性能JS Bridge瓶颈Skia渲染,60fpsArkUI声明式,原生渲染60fps
声明式UI需JSX+第三方库Widget树build()+@Builder原生支持
状态管理需Redux/MobX需Provider/Riverpod@State/@Prop/@Link原生支持
包体积JS引擎+BridgeSkia引擎≈5MB无额外引擎

结论:NearPlay的核心能力(语音识别、WebSocket、权限管理、文件选择、位置服务)全部深度依赖HarmonyOS Kit,跨平台框架的桥接成本远超收益,且无法保证Kit API的完整覆盖。


四、项目目录树逐文件解读

4.1 完整目录结构

NearPlay/
├── AppScope/
│   └── app.json5                          # 应用级配置(bundleName等)
├── entry/
│   ├── build/                             # 构建产物(自动生成)
│   │   └── default/generated/profile/
│   │       └── default/BuildProfile.ets   # 构建配置生成文件
│   └── src/main/
│       ├── ets/
│       │   ├── entryability/
│       │   │   └── EntryAbility.ets       # 应用入口Ability生命周期
│       │   ├── entrybackupability/
│       │   │   └── EntryBackupAbility.ets # 备份扩展Ability
│       │   ├── components/
│       │   │   ├── VoiceInput.ets         # 语音输入UI组件
│       │   │   └── GameChatPanel.ets      # 游戏内聊天面板组件
│       │   ├── model/
│       │   │   ├── ActivityModel.ets      # 活动数据模型
│       │   │   ├── BlockModel.ets         # 拉黑过滤模型(模块级let+导出函数)
│       │   │   ├── ChatModel.ets          # 聊天会话与消息模型
│       │   │   ├── GameMessage.ets        # 游戏网络消息协议
│       │   │   ├── GameModel.ets          # 游戏项与房间模型
│       │   │   ├── GameNetwork.ets        # WebSocket网络封装
│       │   │   ├── MatchEngine.ets        # 附近匹配分数计算引擎
│       │   │   ├── MusicModel.ets         # 音乐类型分类模型
│       │   │   ├── NotifyModel.ets        # 通知消息模型
│       │   │   ├── PermissionModel.ets    # 权限项定义模型
│       │   │   ├── RouteParams.ets        # 页面路由参数接口
│       │   │   ├── RunAdvisorModel.ets    # 运动计划+食谱+点赞模型
│       │   │   ├── UsageModel.ets         # App使用记录与分类模型
│       │   │   ├── UserModel.ets          # 附近用户与位置共享请求模型
│       │   │   ├── VoiceInputHelper.ets   # 语音识别引擎封装(plain class)
│       │   │   └── game/
│       │   │       ├── DrawGuessModel.ets     # 你画我猜数据模型
│       │   │       ├── QuickReactModel.ets    # 看谁反应快数据模型
│       │   │       ├── ScriptKillModel.ets    # 剧本杀数据模型
│       │   │       ├── TruthOrDareModel.ets   # 真心话大冒险数据模型
│       │   │       ├── UndercoverModel.ets    # 谁是卧底数据模型
│       │   │       └── WerewolfModel.ets      # 狼人杀数据模型
│       │   └── pages/
│       │       ├── Index.ets               # 主页(5-Tab:首页/游戏/活动/消息/我的)
│       │       ├── GameRoom.ets            # 匹配房间页(渐扩匹配+路由分发)
│       │       ├── ChatPage.ets            # 即时聊天页(文字/语音/图片+拉黑)
│       │       ├── ActivityDetail.ets      # 活动详情页
│       │       ├── ActivityPublish.ets     # 活动发布页
│       │       ├── PermissionPage.ets      # 权限引导页(步进式授权)
│       │       ├── UserRunProfilePage.ets  # 运动档案页(RunAdvisor联动)
│       │       └── game/
│       │           ├── WerewolfGame.ets    # 狼人杀游戏页(11阶段+语音发言)
│       │           ├── ScriptKillGame.ets  # 剧本杀游戏页(9阶段+文件导入+TTS)
│       │           ├── UndercoverGame.ets  # 谁是卧底游戏页(5阶段+词对)
│       │           ├── DrawGuessGame.ets   # 你画我猜游戏页(Canvas+4阶段)
│       │           ├── TruthOrDareGame.ets # 真心话大冒险游戏页(众包出题)
│       │           └── QuickReactGame.ets  # 看谁反应快游戏页(水果牌+抢拍)
│       └── resources/
│           └── base/
│               ├── element/
│               │   ├── string.json         # 字符串资源(EntryAbility_label="NearPlay")
│               │   ├── color.json          # 颜色资源
│               │   └── float.json          # 尺寸资源
│               ├── media/
│               │   ├── foreground.png      # 前景图标
│               │   ├── background.png      # 背景图标
│               │   ├── layered_image.json  # 分层图标配置
│               │   └── startIcon.png       # 启动画面图标
│               └── profile/
│                   ├── main_pages.json     # 页面路由注册表(13个页面)
│                   └── backup_config.json  # 备份配置
├── oh-package.json5                        # 依赖声明(@ohos/hypium + @ohos/hamock)
├── build-profile.json5                     # 构建配置(SDK版本+构建模式+模块定义)
├── hvigorfile.ts                           # Hvigor构建脚本入口
├── code-linter.json5                       # 代码检查规则
└── docs/                                   # 项目文档

4.2 非.ets配置文件解读

module.json5:entry模块的核心配置文件。声明模块类型为"entry"(主模块)、设备类型为"phone"、入口Ability为"EntryAbility"、页面列表引用"$profile:main_pages"。requestPermissions数组声明三个运行时权限:ohos.permission.INTERNET(普通权限,自动授予)、ohos.permission.APPROXIMATELY_LOCATION(位置权限,inuse场景)、ohos.permission.MICROPHONE(麦克风权限,inuse场景)。后两个权限需要在PermissionPage中通过abilityAccessCtrl动态请求。

string.json:定义5个字符串资源。最关键的是EntryAbility_label值为"NearPlay"(应用名显示在桌面图标下方)、location_reason和microphone_reason是权限申请时向用户展示的理由文案。

main_pages.json:页面路由注册表,声明了13个页面路径。HarmonyOS只允许跳转到在此注册的页面。顺序决定了页面栈的默认行为,Index.ets作为第一个页面是应用启动页。


五、依赖与Kit引入

5.1 oh-package.json5分析

{
  "modelVersion": "6.1.1",
  "dependencies": {},
  "devDependencies": {
    "@ohos/hypium": "1.0.25",
    "@ohos/hamock": "1.0.0"
  }
}

modelVersion声明SDK模型版本为6.1.1,与build-profile.json5中的targetSdkVersion一致。dependencies为空——NearPlay的所有功能依赖均通过HarmonyOS Kit提供,无需第三方npm包。devDependencies中:

  • @ohos/hypium 1.0.25:HarmonyOS单元测试框架,类似JUnit,支持assertEqual/assertTrue等断言方法。
  • @ohos/hamock 1.0.0:HarmonyOS Mock框架,用于在测试中模拟模块依赖。

5.2 五个核心@kit.*引入详解

Kit名称引入位置核心API引入原因
@kit.NetworkKitGameNetwork.etswebSocket.createWebSocket()WebSocket通信,支持游戏房间实时消息传输。注意:使用@kit.NetworkKit而非@kit.InternetKit,因为WebSocket API在NetworkKit中
@kit.CoreSpeechKitVoiceInputHelper.etsspeechRecognizer.createEngine()语音识别引擎,回调式创建,支持zh-CN在线短语音识别。同一Kit还提供TTS能力(ScriptKillGame中使用)
@kit.CoreFileKitChatPage.ets, ScriptKillGame.etspicker.PhotoViewPicker(), picker.DocumentViewPicker(), fileIoChatPage用PhotoViewPicker选择图片发送,ScriptKillGame用DocumentViewPicker+fileIo导入外部剧本.txt文件
@kit.AbilityKitEntryAbility.ets, PermissionPage.ets, ChatPage.etsUIAbility, abilityAccessCtrl.createAtManager(), common.UIAbilityContext应用入口生命周期管理、运行时权限请求、获取UIAbilityContext
@kit.BasicServicesKitVoiceInputHelper.ets, GameNetwork.etsBusinessError错误类型定义,WebSocket和语音识别的回调参数使用BusinessError

此外还有两个辅助Kit:

  • @kit.PerformanceAnalysisKit(EntryAbility.ets):hilog日志输出,DOMAIN=0x0000,标签’testTag’。
  • @kit.ArkUI(EntryAbility.ets, DrawGuessGame.ets, QuickReactGame.ets):window窗口管理、display屏幕信息获取、CanvasRenderingContext2D绑画布绘图。

六、构建体系

6.1 hvigor构建系统

HarmonyOS使用hvigor作为构建工具,替代了传统的Gradle。hvigor基于TypeScript实现,配置文件为hvigorfile.ts。核心命令:

  • hvigorw assembleHap:构建HAP包(HarmonyOS Ability Package),相当于Android的APK。
  • hvigorw clean:清理构建产物,删除entry/build目录。
  • hvigorw --mode module -p module=entry@default assembleHap:指定模块和target构建,用于增量编译。

6.2 build-profile.json5结构解析

build-profile.json5
├── app
│   ├── signingConfigs: []           # 签名配置(调试时为空)
│   ├── products
│   │   └── default
│   │       ├── name: "default"
│   │       ├── signingConfig: "default"
│   │       ├── targetSdkVersion: "6.1.1(24)"
│   │       ├── compatibleSdkVersion: "6.1.1(24)"
│   │       ├── runtimeOS: "HarmonyOS"
│   │       └── buildOption
│   │           └── strictMode
│   │               ├── caseSensitiveCheck: true
│   │               └── useNormalizedOHMUrl: true
│   └── buildModeSet
│       ├── { name: "debug" }
│       └── { name: "release" }
└── modules
    └── entry
        ├── name: "entry"
        ├── srcPath: "./entry"
        └── targets
            └── default
                ├── name: "default"
                └── applyToProducts: ["default"]

关键配置解读

  • strictMode.caseSensitiveCheck: true:启用大小写敏感检查,防止Windows/macOS路径大小写不一致导致的跨平台问题。这意味着import路径必须与文件系统实际大小写完全一致。
  • strictMode.useNormalizedOHMUrl: true:使用标准化的OHM URL格式,确保模块引用路径统一。
  • targetSdkVersion与compatibleSdkVersion相同:当前仅支持API 24+设备,不做低版本兼容。如果需要兼容更低版本,应将compatibleSdkVersion设为更低的API编号。
  • buildModeSet:定义debug和release两种构建模式。debug模式不混淆、保留调试符号;release模式启用代码混淆和优化。

6.3 debug vs release

特性debugrelease
代码混淆是(ProGuard规则)
调试符号保留剥离
SourceMap生成不生成
日志输出hilog全部输出hilog.warn及以上
性能优化内联/死代码消除
HAP体积较大较小
签名调试证书发布证书

七、开发环境

7.1 DevEco Studio

NearPlay使用DevEco Studio作为IDE,这是HarmonyOS官方集成开发环境,基于IntelliJ IDEA。核心功能包括:

  • ArkTS语言服务:实时代码检查、自动补全、arkts-*规则静态分析。
  • 预览器(Previewer):实时预览ArkUI组件渲染效果,支持热重载。
  • 模拟器管理:内置远程模拟器和本地模拟器管理界面。
  • hvigor集成:菜单栏Build→Build Hap(s)/APP(s)直接触发hvigor构建。
  • hdc工具集成:终端可直接使用hdc命令与设备交互。

7.2 SDK路径配置

HarmonyOS SDK安装路径需在DevEco Studio的File→Settings→HarmonyOS SDK中配置。SDK目录结构:

HarmonyOS SDK/
├── openharmony/          # OpenHarmony SDK(开源部分)
│   └── 24/              # API 24
│       ├── ets/         # ArkTS声明文件
│       └── native/      # Native开发头文件和库
└── harmonyos/           # HarmonyOS SDK(闭源部分)
    └── 6.1.1/           # 版本6.1.1
        ├── ets/         # @kit.*声明文件
        └── toolchains/  # 编译工具链

7.3 模拟器选择:Pura 90 vs Mate X7

NearPlay在两款模拟器上进行了测试验证:

Pura 90(推荐):正常启动,页面渲染流畅,WebSocket模拟连接成功,语音识别引擎创建成功(回调触发)。连接地址127.0.0.1:5555。此为日常开发推荐模拟器。

Mate X7:出现启动超时问题,疑似与模拟器GPU渲染模式或系统镜像版本有关。在Mate X7上测试时,App启动后停留在白屏阶段超过30秒,hilog显示Ability onCreate已执行但loadContent回调未触发。建议降级到Pura 90或使用真机调试。

hdc连接命令

hdc tconn 127.0.0.1:5555     # 连接远程模拟器
hdc install entry-debug.hap  # 安装HAP
hdc shell aa start -a EntryAbility -b com.example.nearplay  # 启动应用
hdc shell hilog -t testTag   # 查看应用日志

八、版本演进史

NearPlay从一个空白的HarmonyOS模板项目,经过10个主要迭代阶段,逐步演进为功能完整的附近社交游戏平台。以下是commit级别的版本叙事:

v0.1 — 空项目脚手架

初始创建HarmonyOS ArkTS项目,bundleName注册为com.example.nearplay。此时项目仅包含EntryAbility.ets(空白UIAbility)、Index.ets(空页面)、module.json5(基础配置,仅INTERNET权限)、oh-package.json5(空依赖)。build-profile.json5设定targetSdkVersion=“6.1.1(24)”。项目可编译通过但没有任何业务功能,只是DevEco Studio生成的标准模板。

v0.2 — 5-Tab主框架

在Index.ets中搭建Tabs容器,barPosition设为BarPosition.End(底部Tab栏),创建5个TabContent:首页、游戏、活动、消息、我的。每个Tab先用占位Text显示Tab名称。@State currentTab记录当前选中Tab,Tabs.onChange回调更新currentTab。这是整个应用的骨架,后续所有功能都在这5个Tab上生长。

v0.3 — 6款游戏模型与大厅

创建GameModel.ets,定义GameItem(id/name/icon/description/playerMin/playerMax/type/canImportContent)和GameType枚举(PARTY/WEREWOLF/SCRIPT/CASUAL)。MockGameData.getGames()返回6款游戏数据。游戏Tab的GameContent用List+GameDetailCard展示游戏列表,首页Tab的HomeContent用Grid+GameQuickCard展示热门游戏快捷入口。点击游戏卡片创建GameRoomParams参数对象,通过router.pushUrl跳转到GameRoom页。

同时创建6款游戏的基础Model文件:WerewolfModel(角色/阶段/夜晚行动/投票结果)、ScriptKillModel(剧本/角色/NPC/幕/台词)、UndercoverModel(玩家/角色类型/词对/阶段)、DrawGuessModel(玩家/绘图点/猜测记录)、TruthOrDareModel(玩家/选择类型/问题提交/阶段)、QuickReactModel(玩家/水果牌/水果类型/阶段)。每款游戏对应一个MockData类提供测试数据。

v0.4 — 游戏页面实现

逐一实现6款游戏页面。每款游戏页面遵循相同模式:@Entry+@Component装饰、@State管理阶段和玩家状态、aboutToAppear初始化数据、build()用if-else分发不同阶段的UI、GameChatPanel作为底部聊天组件。

WerewolfGame.ets实现了完整的11阶段流程,包括角色分配时点击查看身份、狼人选择击杀目标、预言家查验并显示结果、女巫使用解药/毒药、守卫选择守护对象、天亮显示死亡信息、白天逐人30秒发言、投票10秒倒计时、胜负判定。VoiceInput组件在当前发言者是自己时激活。

ScriptKillGame.ets实现了9阶段流程,包括选择剧本(内置+文件导入)、角色分配展示秘密、幕介绍、NPC台词模拟朗读、自由讨论、线索公开、幕间过渡、最终投票、真相揭晓。文件导入使用@kit.CoreFileKit的DocumentViewPicker + fileIo.readTextSync。

UndercoverGame.ets实现了5阶段流程:词语分配→描述(30s/人)→投票(30s)→淘汰揭示→最终揭示。8组词对覆盖火锅/麻辣烫等热门词组。

DrawGuessGame.ets实现了Canvas绘图+4阶段流程:回合开始→绘图(60s)→回合结果→游戏结束。DrawPoint模型记录触摸轨迹,CanvasRenderingContext2D渲染绘图。

TruthOrDareGame.ets实现了众包出题机制:选类型→其他玩家8s内提交题目→随机抽取→20s回答。6+6道保底题库。

QuickReactGame.ets实现了5种水果牌+5张桌牌+抢拍机制。60张洗牌牌组动态生成,误拍惩罚。

v0.5 — 即时聊天系统

创建ChatModel.ets,定义ChatConversation(id/type/name/avatar/targetId/lastMessage/unreadCount)、ChatMsg(工厂方法text/voice/image)、ChatType枚举(PRIVATE/GAME/ACTIVITY)、ChatMsgType枚举(TEXT/VOICE/IMAGE)。MockChatData提供4个会话和6条消息(含文字、语音、图片三种类型)。

ChatPage.ets实现完整聊天界面:顶部导航栏显示对方头像和昵称、消息气泡区分自己(绿色#DCF8C6)和对方(白色)、输入栏支持文字+语音录音+图片选择+更多面板。语音录音使用setInterval计时,最长60秒自动停止。图片选择使用@kit.CoreFileKit的PhotoViewPicker。消息发送后通过数组展开运算追加到messages列表。

消息Tab在Index.ets中分为通知区和聊天区:通知区显示NotifyItem(报名/系统/游戏邀请三种类型),未读通知用黄色背景#FFF8E1高亮+红点标记;聊天区显示会话列表,未读消息数用红色圆形徽标显示。

v0.6 — 拉黑过滤系统

创建BlockModel.ets,采用模块级let变量blockedList + 导出函数模式(而非单例class),这是ArkTS限制下的最佳实践。提供5个导出函数:initBlockList初始化、isUserBlocked判断、blockUser拉黑(去重检查+数组展开添加)、unblockUser取消(filter过滤)、getBlockedUsers返回副本。

在Index.ets中,aboutToAppear调用initBlockList初始化拉黑列表,refreshFilteredData在三个维度过滤:nearbyUsers过滤掉被拉黑者、notifications过滤掉被拉黑者的通知、chatConversations过滤掉被拉黑者的会话。doBlockUser和doUnblockUser操作后调用syncBlockState重新同步。

首页附近用户卡片的"🚫"按钮触发doBlockUser,ProfileContent的"黑名单管理"展开BlockListPanel显示完整拉黑列表,支持"取消拉黑"操作。ChatPage.ets中右上角菜单触发BlockConfirmDialog确认弹窗,拉黑后输入栏替换为BlockedBar提示。

v0.7 — 附近匹配与GameRoom

创建GameRoom.ets,实现渐进式匹配算法:startMatching将matchRadius设为1km,doMatchStep每1.5秒执行一次,filter出在matchRadius内的在线玩家,追加到matchedUsers。找到4人后停止,否则radius+1继续,最大10km。匹配进度通过Progress组件可视化(value=matchRadius, total=10)。

匹配完成后点击"进入游戏",enterGame通过gameRoutes Record路由表分发:键为gameId(‘1’-‘6’),值为对应游戏页面路径。这是ArkTS中替代switch-case的惯用模式,Record<string,string>类型安全且无需动态属性访问。

GameRoom还实现了位置共享请求机制(LocationShareRequest + ShareStatus枚举),匹配成功的玩家可"申请定位",对方在弹窗中选择同意/拒绝,实现双向位置共享。

v0.8 — 权限引导系统

创建PermissionModel.ets,定义3个权限项:ohos.permission.MANAGE_MEDIA_RESOURCES(读取正在播放音乐,可选)、ohos.permission.BUNDLE_ACTIVE_INFO(读取应用使用记录,可选)、ohos.permission.APPROXIMATELY_LOCATION(获取位置,必需)。

PermissionPage.ets实现步进式权限引导: currentIndex追踪当前权限项,grantAndNext调用abilityAccessCtrl.createAtManager().requestPermissionsFromUser(context, [permName])异步请求权限,返回PermissionRequestResult.authResults[0]===0表示授权成功。必需权限不允许跳过(不显示"暂不允许"按钮),可选权限允许跳过。全部完成后显示CompleteUI汇总所有权限状态,点击"进入NearPlay"用replaceUrl跳转到Index首页。

值得注意的是,MANAGE_MEDIA_RESOURCES和BUNDLE_ACTIVE_INFO是系统级API权限,普通应用通常无法获得授权,因此PermissionModel的权限请求使用try-catch包裹,失败后静默降级到Mock数据。

v0.9 — MatchEngine与RunAdvisor联动

创建MatchEngine.ets,实现computeMatch匹配分数计算。音乐匹配:computeMusicMatch比较双方NowPlayingSong的genre,同类型返回true+20分。使用习惯匹配:computeUsageMatch比较双方UsageProfile的topCategories,双top1命中+40分、单侧top1命中+25分、双方top2命中+20分、其他交叉+10分,上限80分。总分=使用习惯分数+音乐匹配分数,上限100分。

创建MusicModel.ets,定义MusicGenre枚举(10种类型+UNKNOWN)、NowPlayingSong模型、classifyGenre关键词分类器(10组关键词,每组5-6个中英文关键词)、getGenreIcon图标映射。MockMusicData提供1首当前播放(晴天-周杰伦-流行)和8首附近播放。

创建UsageModel.ets,定义AppCategory枚举(10种类别)、AppUsageRecord模型、classifyApp分类器(19个已知bundleName映射)、UsageProfile.fromRecords聚合器(按类别汇总使用时长→排序→取top3)。MockUsageData提供5条自身记录和8组附近记录。

创建RunAdvisorModel.ets,定义RunPlan(3种类型:轻松跑3km/标准跑5km/耐力跑10km)、FoodRecipe(带getCalories()方法=caloriesPer100g×defaultGrams/100取整)、UserRunProfile、LikeStore(模块级likeMap + toggleLike/isLiked/getLikeCount/initLikes)。MockRunAdvisorData预置8个附近用户运动档案。

UserRunProfilePage.ets展示运动计划和食谱,支持点赞(toggleLike触发likeRefresh++ @State计数器刷新UI),从Index.ets首页附近用户卡片的"🏃"按钮跳转,携带UserRunProfileParams参数。

v0.10 — 语音输入与VoiceInputHelper重构

初始版本中,语音输入逻辑直接散落在各游戏页面的aboutToAppear中,导致代码重复和难以维护。本次重构将语音识别逻辑提取为独立的VoiceInputHelper(plain class)和VoiceInput(@Component UI包装器)两层架构。

VoiceInputHelper.ets封装@kit.CoreSpeechKit的speechRecognizer.createEngine回调式API:startListening接收onResult回调,内部创建engine(zh-CN/online/short模式),设置RecognitionListener(onStart/onEvent/onResult/onComplete/onError),onResult中更新recognizedText并在isLast时自动stopListening,stopListening中调用engine.finish+engine.shutdown,recognizedText非空时触发onResultCallback。同时维护durationTimer(1秒间隔计时,60秒上限自动停止),destroy方法清理timer和engine。

VoiceInput.ets作为@Component UI包装器,持有VoiceInputHelper实例,通过200ms间隔的refreshTimer轮询helper状态更新@State变量(isListening/recognizedText/listenDuration)。build()渲染两种状态:录音中(显示"语音输入中"+时长+停止按钮)和待机(显示麦克风按钮+识别结果文本+禁言提示)。onVoiceResult回调将识别文本传回宿主游戏。

重构后所有6款游戏统一使用VoiceInput组件(讨论/发言阶段),VoiceInputHelper实例由各游戏页面持有,aboutToDisappear中调用helper.destroy()清理资源。这消除了6处重复的引擎创建/销毁代码,也确保了录音资源不会泄漏。


附录:关键数据流图

用户启动App
    │
    ▼
EntryAbility.onCreate ─── setColorMode ─── hilog.info
    │
    ▼
EntryAbility.onWindowStageCreate ─── windowStage.loadContent('pages/Index')
    │
    ▼
Index.aboutToAppear
    ├── initBlockList(MockBlockData.getInitialBlocked())
    ├── games = MockGameData.getGames()
    ├── activities = MockActivityData.getActivities()
    └── refreshFilteredData()
         ├── nearbyUsers = enrichUsersWithMatch(rawUsers)
         │    ├── MockMusicData.getMyNowPlaying()
         │    ├── UsageProfile.fromRecords(MockUsageData.getMyUsage())
         │    ├── for each user: computeMatch(mySong, otherSong, myUsage, otherUsage)
         │    └── user.matchScore / matchLabel / musicGenreLabel
         ├── notifications = filter(!blocked)
         └── chatConversations = filter(!blocked)
用户点击游戏卡片
    │
    ▼
router.pushUrl({url: 'pages/GameRoom', params: GameRoomParams})
    │
    ▼
GameRoom.aboutToAppear
    ├── gameId / gameName from params
    └── nearbyOnlineUsers = filter(online)
    
用户点击"开始匹配"
    │
    ▼
startMatching() → doMatchStep() loop (1.5s interval)
    ├── radius 1→2→3→...→10 km
    ├── matchedUsers accumulates
    └── ≥4 players → "匹配完成"

用户点击"进入游戏"
    │
    ▼
enterGame() → gameRoutes[gameId] → router.pushUrl(targetPage)
    │
    ▼
WerewolfGame / ScriptKillGame / ... aboutToAppear
    ├── MockXxxData初始化
    └── 开始游戏流程(自动阶段推进)
语音发言流程
    │
    ▼
VoiceInput.onClick → helper.startListening(onResult)
    │
    ▼
speechRecognizer.createEngine(params, callback)
    ├── 成功 → engine.setListener → engine.startListening
    │    ├── onResult → recognizedText = result.result
    │    ├── isLast → stopListening()
    │    └── onError → stopListening()
    └── 失败 → isListening = false

stopListening()
    ├── clearInterval(durationTimer)
    ├── engine.finish(sessionId) + engine.shutdown()
    ├── onResultCallback(recognizedText)
    └── isListening = false

VoiceInput.refreshTimer (200ms)
    ├── isListening = helper.isListening
    ├── recognizedText = helper.recognizedText
    └── listenDuration = helper.listenDuration

九、6种游戏的社交功能定位

9.1 狼人杀——信息博弈型社交

狼人杀是NearPlay中最具深度社交博弈的游戏。8名玩家分为好人和狼人阵营,通过白天的讨论和投票、夜晚的行动和特殊技能进行信息博弈。社交价值体现在:

推理暴露性格:玩家的发言逻辑、投票选择、犹豫程度都会暴露其思维方式和性格特征。一个总是急于指认他人的玩家可能是冲动型人格,而一个谨慎观察再发言的玩家可能更理性。这种"通过游戏行为观察性格"的机制比直接聊天更真实。

语音社交体验:狼人杀的讨论阶段使用VoiceInputHelper语音发言,玩家的语气、停顿、语速都成为社交信号。相比纯文字聊天,语音沟通传递的信息量更大、情感更真实。

信任博弈:狼人需要伪装成好人,好人需要识别狼人。这种"谁在说谎"的信任博弈是极好的破冰场景——在游戏中被欺骗不会造成真实伤害,但可以快速建立"这个人是否值得信任"的初步判断。

9.2 剧本杀——角色扮演型社交

剧本杀让玩家扮演剧本中的角色,通过朗读台词、搜索线索、讨论推理来还原故事真相。社交价值体现在:

角色代入降低社交压力:玩家不是以"自己"的身份发言,而是以"剧本角色"的身份发言。这种角色代入极大地降低了社交焦虑——说错话是角色的错,不是自己的错。

NPC-TTS技术增强沉浸感:系统NPC台词通过textToSpeech引擎朗读,营造"现场有非玩家角色"的氛围。即使只有5名真人玩家,配合TTS播报也能感受到完整的多人互动场景。

剧本文件导入:支持从外部.txt文件导入自定义剧本,玩家可以创作自己的故事。这种UGC模式让游戏内容无限扩展,也为"编剧→分享→一起玩"的社交链条提供了可能。

9.3 谁是卧底——语言表达型社交

谁是卧底考验的是语言表达能力——如何在不说出词语本身的情况下描述它的特征。社交价值体现在:

描述风格反映思维:有人从功能描述(“可以用来喝水”),有人从场景描述(“办公室桌上都有”),有人从情感描述(“让人感到温暖”)。不同的描述风格反映不同的思维方式,是了解他人的窗口。

投票讨论中的推理:谁是卧底?谁的描述最不像正常词语?这些推理过程需要分析他人的表达逻辑,是另一种形式的社交观察。

10秒描述时间压力:短时间内的表达最能暴露一个人的思维特征——从容不迫说明准备充分、紧张犹豫说明缺乏安全感、滔滔不绝说明表达欲强。

9.4 你画我猜——非语言沟通型社交

你画我猜是最具创意互动性的游戏,画者只能绘图不能写字,猜者通过画面猜测答案。社交价值体现在:

非语言沟通:绘画是一种完全不同于文字的表达方式。画得歪歪扭扭反而更有趣,误解和搞笑猜测是天然的社交话题。这种"你说东我猜西"的沟通失败比成功更有社交价值。

创意展示:擅长绘画的玩家可以展示才华,不擅长绘画的玩家的"灵魂画作"同样引人注目。无论画技如何,都能获得社交关注。

语音猜词:VoiceInputHelper语音识别让猜词更自然,说话代替打字更接近真实桌游的喊答案体验。

9.5 真心话大冒险——隐私披露型社交

真心话大冒险直接触及个人隐私和勇气边界,是破冰效率最高的游戏。社交价值体现在:

众包出题的针对性:其他玩家了解被问者,可以出针对性的问题。"你最近一次说谎是什么时候"这种问题,陌生人出和好朋友出,答案的深度完全不同。

选择揭示性格:选真心话还是大冒险,本身就是性格的体现——选真心话的人可能更坦诚(或更有秘密),选大冒险的人可能更爱冒险(或更有不想说的秘密)。

语音回答的真实感:说话时的犹豫、停顿、笑声都是社交信息。文字回答可以精心措辞,语音回答更难掩饰真实情感。

9.6 看谁反应快——竞技娱乐型社交

看谁反应快是最轻量级的社交游戏——5张水果卡上出现5个相同水果就抢拍。社交价值体现在:

低门槛高刺激:规则极简,任何人都能立刻参与。但反应速度的竞争带来强烈的刺激感和即时反馈。

语音抢拍创新:喊"拍/抢/有"即可抢拍,结合VoiceInputHelper语音识别,让抢拍比点击按钮更自然(也更吵——这正是桌游的乐趣所在)。

误抢惩罚的社交趣味:判断失误时的-1惩罚不是惩罚,而是笑点。“怎么还没五个你就抢了哈哈哈”——这种善意的嘲笑是最好的社交粘合剂。

十、技术选型深度论证

10.1 为什么选ArkTS而非React Native/Flutter

React Native:JavaScript桥接层导致性能损耗,WebView渲染无法达到60fps流畅动画。更重要的是,React Native无法调用HarmonyOS系统级API(CoreSpeechKit、AVSession等),丧失了NearPlay最核心的差异化能力——原生语音识别和位置服务。

Flutter:虽然渲染性能优秀,但Flutter的Dart语言与HarmonyOS生态割裂。Flutter for HarmonyOS(ohos_flutter)仍处于实验阶段,不支持CoreSpeechKit等关键API。Flutter的自绘引擎也与ArkUI的声明式范式冲突,两套渲染体系并存会导致内存和性能问题。

ArkTS:HarmonyOS第一方开发语言,直接调用所有系统API,ArkUI声明式UI框架提供60fps原生渲染。虽然ArkTS有严格模式限制(禁止any/unknown/for…in等),但这些限制恰恰保证了代码质量和运行时安全性。选择ArkTS意味着选择平台原生能力而非跨平台兼容性——这是NearPlay"深度集成HarmonyOS"战略的正确决策。

10.2 为什么选WebSocket而非分布式软总线

HarmonyOS的分布式软总线(Distributed Soft Bus)可以在同一华为账号的设备间建立低延迟通信通道。但NearPlay的目标场景是"附近的陌生人"——他们使用不同的华为账号,无法建立分布式软总线连接。

WebSocket是互联网标准的全双工通信协议,不依赖特定账号体系,任何人都可以连接。代价是需要中心化服务器做中转(Host-adjudicator模式),但这也带来了裁判公正性的保证——服务器是游戏规则的权威执行者,客户端无法作弊。

10.3 为什么选Mock数据而非真实API

NearPlay的六种游戏、五个Tab页面、匹配引擎、聊天系统等都需要数据支撑。在最小可行产品阶段选择Mock数据而非真实后端接口,原因有三:第一是开发效率——Mock数据让前端开发完全独立于后端,无需等待接口设计、开发、联调,一个前端工程师可以在一天内完成整个游戏页面的开发和测试;第二是演示友好——Mock数据保证每次演示都有一致的体验,固定的附近用户列表、固定的游戏对局、固定的匹配结果,真实接口的数据可能因为在线人数少而导致空列表或匹配超时;第三是降级兼容——所有系统接口调用都使用异常捕获包裹,失败时自动降级到Mock数据,确保应用在任何设备上都能正常运行。

Mock数据的代价是数据不真实——匹配分数基于假设的偏好而非真实的使用习惯,聊天消息是本地生成的而非对方发送的。但这在原型验证阶段是可接受的——我们验证的是功能完整性和交互设计,不是数据准确性。当产品验证成功后,只需启动后端服务、修改连接地址即可切换到真实数据。

10.3 为什么选Mock数据而非真实API

NearPlay的6种游戏、5个Tab页面、匹配引擎、聊天系统等都需要数据支撑。在MVP阶段选择Mock数据而非真实后端API,原因有三:

开发效率:Mock数据让前端开发完全独立于后端,无需等待API设计、开发、联调。一个前端工程师可以在1天内完成整个游戏页面的开发和测试。

演示友好:Mock数据保证每次演示都有一致的体验——固定的附近用户列表、固定的游戏对局、固定的匹配结果。真实API的数据可能因为在线人数少而导致空列表或匹配超时。

降级兼容:所有系统API调用(AVSession、usageStatistics等)都使用try-catch包裹,失败时自动降级到Mock数据。这确保了应用在任何设备上都能正常运行,不受权限和API可用性限制。

十一、产品闭环:从线上到线下

11.1 完整用户旅程

打开App → 发现附近同好 → 匹配进入游戏 → 语音互动破冰 
→ 游戏结束添加好友 → 聊天深化关系 → 报名线下活动 → 线下见面
→ RunAdvisor运动联动 → 持续互动 → 回到App发现更多同好

11.2 每个功能的闭环贡献

功能闭环环节贡献
附近匹配发现→连接解决"附近有谁"问题
6种游戏连接→互动解决"一起做什么"问题
语音发言互动→信任解决"如何真实交流"问题
聊天系统互动→关系解决"游戏后如何继续"问题
活动系统关系→线下解决"如何线下见面"问题
RunAdvisor线下→持续解决"见面后如何持续互动"问题
拉黑系统全程安全解决"不想见的人如何屏蔽"问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值