Anchor Battle
Note:
New Battle Arrivals, Limited Time Free Trial Available.
Component Introduction
Battle feature is an intense and entertaining real-time interactive feature designed for anchors and the audience. It allows anchors from different rooms to engage in real-time confrontations, enhancing the competitiveness and entertainment value of live streaming.TUILiveKit's battle feature supports up to 9 anchors participating simultaneously, providing a platform for anchors to showcase their talents and charisma, while offering an exciting viewing experience for the audience. Whether it's a talent competition, knowledge Q&A, or gaming sports, the battle feature creates more interactive opportunities for anchors and the audience, stimulating audience enthusiasm, enhancing the entertainment value and attraction of live streaming, thus bringing more surprises and value to both sides and promoting the diversified development of live streaming content.
In Dual Battle | Dual Battle results | In Multi-player Battle | Multi-player Battle results |
| | | |
Instructions for Use
Note:
Before you initiate or accept a PK, please ensure that you are in a connected state.
Anchor initiates battle
Click the Battle button | Stop Waiting for battle | Exit Battle |
| | |
Anchor receives battle
Anchor receives Battle invitation | Anchor accepts Battle |
| |
Custom Functionality
Custom Battle waiting countdown style
If you need the custom battle waiting countdown style, please refer to the following path for changes:
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/anchor/component/livestreaming/battle/├── BattleCountdownBackView.java // Battle waiting countdown background style└── BattleCountdownView.java // Battle waiting countdown foreground style
// File location: iOS/TUILiveKit/Sources/LiveStream/HostBattle/ViewView├── BattleCountDownBackgroundView.swift // Battle waiting countdown background style└── BattleCountDownView.swift // Battle waiting countdown foreground style
Custom Definition Dual Battle Score Style
If you need the custom Definition Dual battle score style, please refer to the following path for changes:
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/SingleBattleScoreView.javapublic class SingleBattleScoreView extends FrameLayout {...}
// File location: iOS/TUILiveKit/Sources/LiveStream/HostBattle/View/SingleBattleScoreView.swiftclass SingleBattleScoreView: UIView {...func constructViewHierarchy() {// View Hierarchy Construction}func activateConstraints() {// View Layout}}
Custom Definition Multi Battle Score Style
If you need the custom Definition Multi Battle score style, please refer to the following path for changes:
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/BattleMemberInfoView.javapublic class BattleMemberInfoView extends FrameLayout {...}
// File location: iOS/TUILiveKit/Sources/LiveStream/HostBattle/View/BattleMemberInfoView.swiftclass BattleMemberInfoView: UIView {...func constructViewHierarchy() {// View Hierarchy Construction}func activateConstraints() {// View Layout}}
Custom Definition Battle Score Result Style
If you need a Custom Definition Battle Score Result Style, please refer to the following path for changes:
// File location: tuilivekit/src/main/java/com/trtc/uikit/livekit/view/liveroom/view/common/battle/BattleInfoView.javapublic class BattleInfoView extends BasicView {...private void showBattleResult(int type) {// Battle Result Display}}
// File location: iOS/TUILiveKit/Sources/LiveStream/HostBattle/View/BattleInfoView.swiftclass BattleInfoView: UIView {...func showBattleResult(store: LiveStore) {// Battle Result Display}}
Key code
Anchor Battle
TUILiveKit Anchor battle feature is mainly based on
BattleService
. You can obtain the battle management object through store.serviceCenter.battleService
and call the relevant battle API functions to implement the battle feature. For example, in the interaction between Anchor A and B, refer to the diagram below for the specific interaction sequence.
Note:
When inviting multiple participants to the battle, if any invitee accepts the battle, only the battle initiator, the battle invitee who accepted, and the audience in the corresponding rooms will receive the
onBattleStarted
callback.Anchor A initiates Battle
Anchor A initiates a battle by calling
requestBattle
, passing the maximum Battle duration in parameter config
, whether the inviter needs to reply with accept/reject, and passing anchor B's userId in parameter userIdList
, and passing the battle invitation wait duration in parameter timeout
.// File location: 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();}});}
// File location: 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)}}}
Anchor A can receive the request acceptance callback via
onBattleRequestAccept
.Anchor receives a battle request
Anchor B receives the battle request callback via
onBattleRequestReceived
.// File location: 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);}
// File location: iOS/TUILiveKit/Sources/LiveStream/HostBattle/Module/LSBattleManagerObserverfunc onBattleRequestReceived(battleInfo: TUIBattleInfo, inviter: TUIBattleUser, invitee: TUIBattleUser) {manager?.onBattleRequestReceived(battleInfo: battleInfo, inviter: inviter, invitee: invitee)}
Anchor B accepts the battle request by calling
acceptBattle
.// File location: 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) {}});}
// File location: 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)}}}
Anchors A, B, and the audience in the room can receive the battle start callback through
onBattleStarted
.// File location: 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);}
// File location: iOS/TUILiveKit/Sources/LiveStream/HostBattle/Module/LSBattleManagerObserverfunc onBattleStarted(battleInfo: TUIBattleInfo) {manager?.onBattleStarted(battleInfo: battleInfo)}
The anchor exits the battle
For example, when anchor B exits the battle, the interaction sequence can be referenced from the diagram below.
Note:
During multi-anchor Battle:
When a anchor exits the battle, the remaining anchors and corresponding room audience will receive the
onUserExitBattle
callback.When the battle reaches the preset battle time, the anchors and corresponding room audience will receive the
onBattleEnded
callback.When there are two anchors in the battle and one exits, the anchors and corresponding room audience will receive the
onBattleEnded
callback.Anchor B calls
exitBattle
to exit the battle.// File location: 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) {}});}
// File location: 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)}}}
Anchors A, B, and the room audience receive the
onBattleEnded
callback and the battle end notification. // File location: 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);}
// File location: iOS/TUILiveKit/Sources/LiveStream/HostBattle/Module/LSBattleManagerObserverfunc onBattleEnded(battleInfo: TUIBattleInfo, reason: TUIBattleStoppedReason) {manager?.onBattleEnded(battleInfo: battleInfo, reason: reason)}