Anchor Battle
说明:
PK 上新,限时免费体验。
功能介绍
PK 功能是一种激烈而富有趣味的实时互动方式,专为主播和观众设计。它允许来自不同房间的主播进行实时对抗,增加了直播的竞争性和观赏性。TUILiveKit 的 PK 功能支持多达9位主播同时参与对战,为主播提供了一个展示才华、比拼魅力的平台,同时也为观众带来了紧张刺激的观看体验。无论是才艺比拼、知识问答还是游戏竞技,PK 功能都能为主播和观众创造更多的互动机会,激发观众的参与热情,提升直播的趣味性和吸引力,从而为双方带来更多的惊喜和价值,推动直播内容的多样化发展。
双人 PK 中 | 双人 PK 结果 | 多人 PK 中 | 多人 PK 结果 |
| | | |
使用说明
说明:
在您准备发起 PK 或接受 PK 前,请确保您处于连线状态中。
主播发起 PK
点击 PK 按钮 | 停止 PK 等待 | 断开 PK |
| | |
主播接收 PK
主播收到 PK 邀请 | 主播接受 PK |
| |
功能定制
自定义 PK 等待倒计时样式
如您需要自定义 PK 等待倒计时样式 ,请参考以下路径更改:
// 文件位置:tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/anchor/component/livestreaming/battle/├── BattleCountdownBackView.java // PK 等待倒计时背景样式└── BattleCountdownView.java // PK 等待倒计时前景样式
// 文件位置:iOS/TUILiveKit/Sources/LiveStream/HostBattle/ViewView├── BattleCountDownBackgroundView.swift // PK 等待倒计时背景样式└── BattleCountDownView.swift // PK 等待倒计时前景样式
自定义双人 PK 比分样式
如您需要自定义双人 PK 比分样式 ,请参考以下路径更改:
// 文件位置:tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/SingleBattleScoreView.javapublic class SingleBattleScoreView extends FrameLayout {...}
// 文件位置:iOS/TUILiveKit/Sources/LiveStream/HostBattle/View/SingleBattleScoreView.swiftclass SingleBattleScoreView: UIView {...func constructViewHierarchy() {// 视图层级构建}func activateConstraints() {// 视图layout布局}}
自定义多人 PK 比分样式
如您需要自定义多人 PK 比分样式 ,请参考以下路径更改:
// 文件位置:tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/BattleMemberInfoView.javapublic class BattleMemberInfoView extends FrameLayout {...}
// 文件位置:iOS/TUILiveKit/Sources/LiveStream/HostBattle/View/BattleMemberInfoView.swiftclass BattleMemberInfoView: UIView {...func constructViewHierarchy() {// 视图层级构建}func activateConstraints() {// 视图layout布局}}
自定义 PK 比分结果样式
如您需要自定义 PK 比分结果样式 ,请参考以下路径更改:
// 文件位置:tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/BattleInfoView.javapublic class BattleInfoView extends BasicView {...private void showBattleResult(int type) {// PK结果展示}}
// 文件位置:iOS/TUILiveKit/Sources/LiveStream/HostBattle/View/BattleInfoView.swiftclass BattleInfoView: UIView {...func showBattleResult(store: LiveStore) {// PK结果展示}}
关键代码
主播 PK
TUILiveKit 主播 PK 功能主要是基于
LiveService
实现的,在LiveService
中,您可通过 mTUIRoomEngine.getLiveBattleManager()
获取到 PK 管理类对象,进而调用 PK 相关 API 函数,实现 PK 功能。以主播 A 和主播 B 的 PK 为例,具体交互时序可参考下图。
说明:
邀请多人参加 PK 时,若被邀请方中有人接受了 PK,则仅 PK 发起方和 PK 邀请接受方和对应房间内观众会收到
onBattleStarted
回调。主播 A 发起 PK
主播 A 通过调用
requestBattle
发起 PK,在参数 config
中传入 PK 最大时长、是否需要邀请方回复同意/拒绝,在参数 userIdList
中传入主播 B 的 userId,在参数 timeout
中传入 PK 邀请等待时长。// 文件位置:tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/controller/BattleController.javapublic void requestBattle(List<String> roomIdList, int timeout) {TUILiveBattleManager.BattleConfig config = new TUILiveBattleManager.BattleConfig();config.duration = BattleState.BATTLE_DURATION;config.needResponse = mBattleState.mNeedResponse;config.extensionInfo = "";mLiveService.requestBattle(config, roomIdList, timeout, new TUILiveBattleManager.BattleRequestCallback() {@Overridepublic void onSuccess(TUILiveBattleManager.BattleInfo battleInfo,Map<String, TUILiveBattleManager.BattleCode> map) {mBattleState.mBattleId = battleInfo.battleId;mBattleState.mBattleConfig.copy(config);List<BattleState.BattleUser> sendRequests = mBattleState.mSentBattleRequests.get();for (Map.Entry<String, TUILiveBattleManager.BattleCode> entry : map.entrySet()) {String key = entry.getKey();TUILiveBattleManager.BattleCode code = entry.getValue();if (code == TUILiveBattleManager.BattleCode.SUCCESS) {for (ConnectionState.ConnectionUser user : mConnectionState.connectedUsers.get()) {if (TextUtils.equals(user.userId, key)) {sendRequests.add(new BattleState.BattleUser(user));break;}}} else {notifyToast(convertCodeToString(entry.getValue()));}}mBattleState.mSentBattleRequests.set(sendRequests);}@Overridepublic void onError(TUICommonDefine.Error error, String s) {ErrorHandler.onError(error);mBattleState.mSentBattleRequests.clear();}});}
// 文件位置:iOS/TUILiveKit/Sources/LiveStream/HostBattle/API/LSBattleService.swiftfunc requestBattle(config: TUIBattleConfig, userIdList: [String], timeout: TimeInterval) async throws -> (battleInfo: TUIBattleInfo, resultMap: [String : TUIBattleCode]) {return try await withCheckedThrowingContinuation { [weak self] continuation inguard let self = self else { return }battleManager.requestBattle(config: config, userIdList: userIdList, timeout: timeout) { battleInfo, resultMap invar battleResult: [String: TUIBattleCode] = [:]resultMap.forEach { (key: String, value: NSNumber) inbattleResult[key] = TUIBattleCode(rawValue: value.intValue) ?? .unknown}continuation.resume(returning: (battleInfo, battleResult))} onError: { err, message inlet error = InternalError(error: err, message: message)continuation.resume(throwing: error)}}}
主播 A 可通过
onBattleRequestAccept
接收请求同意回调。主播收到 PK 请求
主播 B 通过
onBattleRequestReceived
接收 PK 请求回调。// 文件位置:tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/observer/LiveBattleManagerObserver.java@Overridepublic void onBattleRequestReceived(BattleInfo battleInfo, BattleUser inviter, BattleUser invitee) {LiveKitLog.info(mTag + " onBattleRequestReceived:[battleInfo:" + new Gson().toJson(battleInfo)+ ", inviter:" + new Gson().toJson(inviter) + ", invitee:" + new Gson().toJson(invitee) + "]");mBattleController.onBattleRequestReceived(battleInfo, inviter);}
// 文件位置:iOS/TUILiveKit/Sources/LiveStream/HostBattle/Module/LSBattleManagerObserverfunc onBattleRequestReceived(battleInfo: TUIBattleInfo, inviter: TUIBattleUser, invitee: TUIBattleUser) {manager?.onBattleRequestReceived(battleInfo: battleInfo, inviter: inviter, invitee: invitee)}
主播 B 通过调用
accept
接受 PK 请求。// 文件位置:tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/controller/BattleController.javapublic void accept() {mLiveService.acceptBattle(mBattleState.mBattleId, new TUIRoomDefine.ActionCallback() {@Overridepublic void onSuccess() {}@Overridepublic void onError(TUICommonDefine.Error error, String s) {}});}
// 文件位置:iOS/TUILiveKit/Sources/LiveStream/HostBattle/API/LSBattleService.swiftfunc acceptBattle(battleId: String) async throws {return try await withCheckedThrowingContinuation { [weak self] continuation inguard let self = self else { return }battleManager.acceptBattle(battleId: battleId) {continuation.resume()} onError: { err, message inlet error = InternalError(error: err, message: message)continuation.resume(throwing: error)}}}
主播 A,B 以及房间内观众可通过
onBattleStarted
接收 PK 开始回调。// 文件位置:tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/observer/LiveBattleManagerObserver.java@Overridepublic void onBattleStarted(BattleInfo battleInfo) {LiveKitLog.info(mTag + " onBattleStarted:[battleInfo:" + new Gson().toJson(battleInfo) + "]");mBattleController.onBattleStarted(battleInfo);}
// 文件位置:iOS/TUILiveKit/Sources/LiveStream/HostBattle/Module/LSBattleManagerObserverfunc onBattleStarted(battleInfo: TUIBattleInfo) {manager?.onBattleStarted(battleInfo: battleInfo)}
主播退出 PK
以主播 B 退出 PK 为例,交互时序可参考下图。
说明:
多人PK 时:
当有主播退出 PK,则其余 PK 中主播和对应房间内观众会收到
onUserExitBattle
回调。当 PK 到达预设 PK 时间,则 PK 中主播和对应房间内观众会收到
onBattleEnded
回调。当 PK 中主播人数为2,且有主播退出 PK 时, PK 中主播和对应房间内观众会收到
onBattleEnded
回调。主播 B 调用
exitBattle
退出 PK。// 文件位置:tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/controller/BattleController.javapublic void exitBattle() {mLiveService.exitBattle(mBattleState.mBattleId, new TUIRoomDefine.ActionCallback() {@Overridepublic void onSuccess() {mBattleState.mSentBattleRequests.clear();mBattleState.mBattledUsers.clear();removeBattleRequestReceived();}@Overridepublic void onError(TUICommonDefine.Error error, String s) {}});}
// 文件位置:iOS/TUILiveKit/Sources/LiveStream/HostBattle/API/LSBattleService.swiftfunc exitBattle(battleId: String) async throws {return try await withCheckedThrowingContinuation { [weak self] continuation inguard let self = self else { return }battleManager.exitBattle(battleId: battleId) {continuation.resume()} onError: { err, message inlet error = InternalError(error: err, message: message)continuation.resume(throwing: error)}}}
主播 A,B 以及房间内观众收到
onBattleEnded
回调,收到 PK 结束通知。// 文件位置:tuilivekit/src/main/java/com/trtc/uikit/livekit/manager/observer/LiveBattleManagerObserver.java@Overridepublic void onBattleEnded(BattleInfo battleInfo, BattleStoppedReason reason) {LiveKitLog.info(mTag + " onBattleEnded:[battleInfo:"+ new Gson().toJson(battleInfo) + ", reason:" + reason + "]");mBattleController.onBattleEnded(battleInfo);}
// 文件位置:iOS/TUILiveKit/Sources/LiveStream/HostBattle/Module/LSBattleManagerObserverfunc onBattleEnded(battleInfo: TUIBattleInfo, reason: TUIBattleStoppedReason) {manager?.onBattleEnded(battleInfo: battleInfo, reason: reason)}