PK Battles
PK (Player Kill) battles allow two hosts to compete in a split-screen view. Each host's audience can see both streams side by side.
PK Architecture
┌──────────────────────────────────────────────────────┐
│ PK BATTLE VIEW │
├─────────────────────────┬────────────────────────────┤
│ │ │
│ HOST A (LEFT) │ HOST B (RIGHT) │
│ (Your Room) │ (Opponent Room) │
│ │ │
├─────────────────────────┴────────────────────────────┤
│ Points: 1,500 VS Points: 1,200 │
└──────────────────────────────────────────────────────┘
How It Works
- Each host is in their own room with their audience
- When PK starts, each host joins the opponent's room as subscriber
- UI switches to split-screen showing both hosts
- Audience in each room sees both hosts
Start PK Battle
// 1. Get opponent's room info from your backend
String opponentUrl = pkData.getOpponentServerUrl();
String opponentToken = pkData.getOpponentToken();
String opponentChannel = pkData.getOpponentChannelName();
// 2. Switch UI to PK layout
pkLayout.setVisibility(View.VISIBLE);
normalLayout.setVisibility(View.GONE);
// 3. Initialize PK renderers
initPkRenderers();
// 4. Attach local video to LEFT side
videoHelper.attachLocalVideoToPkView(pkLeftRenderer);
// 5. Join opponent's room
videoHelper.joinPkOpponentRoom(opponentUrl, opponentToken, opponentChannel);
// 6. Set up callback for opponent video
videoHelper.setPkOpponentCallback(new PkOpponentCallback() {
@Override
public void onPkOpponentVideoReceived(VideoTrack track) {
runOnUiThread(() -> {
track.addRenderer(pkRightRenderer);
});
}
@Override
public void onPkOpponentOffline(String name) {
showOpponentOffline(name);
}
});
// 7. Attach opponent video to RIGHT side
videoHelper.attachPkRemoteVideoToView(pkRightRenderer);
End PK Battle
// 1. Leave opponent's room
videoHelper.leavePkOpponentRoom();
// 2. Cleanup PK renderers
videoHelper.cleanupPkRenderers();
// 3. Switch back to normal layout
pkLayout.setVisibility(View.GONE);
normalLayout.setVisibility(View.VISIBLE);
// 4. Re-attach local video to normal view
videoHelper.attachLocalVideoToView(localVideoView);
PK Layout XML
<LinearLayout
android:id="@+id/pk_layout"
android:orientation="horizontal"
android:visibility="gone">
<!-- Left: Local host -->
<FrameLayout
android:layout_weight="1">
<io.conostream.webrtc.TextureViewRenderer
android:id="@+id/pk_left" />
</FrameLayout>
<!-- Divider -->
<View android:layout_width="2dp" android:background="#FFF" />
<!-- Right: Opponent -->
<FrameLayout
android:layout_weight="1">
<io.conostream.webrtc.TextureViewRenderer
android:id="@+id/pk_right" />
<TextView
android:id="@+id/pk_opponent_offline"
android:text="Opponent Offline"
android:visibility="gone" />
</FrameLayout>
</LinearLayout>
Handle Opponent Offline
videoHelper.setPkOpponentCallback(new PkOpponentCallback() {
@Override
public void onPkOpponentOffline(String name) {
runOnUiThread(() -> {
pkOpponentOfflineText.setText(name + " offline");
pkOpponentOfflineText.setVisibility(View.VISIBLE);
});
}
@Override
public void onPkOpponentReconnected() {
runOnUiThread(() -> {
pkOpponentOfflineText.setVisibility(View.GONE);
});
}
});
ℹ️
PK scoring, timers, and winner determination are handled by your backend/app logic. ConoStream only handles the video streams.