本场景需要集成火山引擎的RTC SDK 以及SUD MGP 互动小游戏接入平台,您需要在 RTC 的控制台开通服务,并下载对应的SUD MGP 的SDK,相应开通指南如下:
详细细节请参见 RTC服务开通指南
/** * Join the RTC room and initialize the parameters * @param token: RTC Token * @param roomID: RTC room id * @param uid: RTC user id **/ - (void)joinChannelWithToken:(NSString *)token roomID:(NSString *)roomID uid:(NSString *)uid { //设置订阅的音视频流回退选项 [self.rtcEngineKit setSubscribeFallbackOption:ByteRTCSubscribeFallbackOptionAudioOnly]; //关闭 本地音频/视频采集 [self.rtcEngineKit stopAudioCapture]; [self.rtcEngineKit stopVideoCapture]; //设置音频路由模式,YES 扬声器/NO 听筒 [self.rtcEngineKit setDefaultAudioRoute:ByteRTCAudioRouteSpeakerphone]; //开启/关闭发言者音量键控 ByteRTCAudioPropertiesConfig *audioPropertiesConfig = [[ByteRTCAudioPropertiesConfig alloc] init]; audioPropertiesConfig.interval = 200; [self.rtcEngineKit enableAudioPropertiesReport:audioPropertiesConfig]; //加入房间,开始连麦,需要申请AppId和Token ByteRTCUserInfo *userInfo = [[ByteRTCUserInfo alloc] init]; userInfo.userId = uid; ByteRTCRoomConfig *config = [[ByteRTCRoomConfig alloc] init]; config.profile = ByteRTCRoomProfileCommunication; config.isAutoPublish = YES; config.isAutoSubscribeAudio = YES; self.rtcRoom = [self.rtcEngineKit createRTCRoom:roomID]; self.rtcRoom.delegate = self; [self.rtcRoom joinRoom:token userInfo:userInfo roomConfig:config]; //设置用户为隐身状态 [self.rtcRoom setUserVisibility:NO]; } /** * 初始化游戏SDK * @param appId: 游戏SDK所需的appId * @param appKey: 游戏SDK所需的appKey * @param callback: 初始化游戏SDK回调 **/ - (void)initSudMGPSDKWithAppId:(NSString *)appId appKey:(NSString *)appKey callback:(void(^)(BOOL success))resultCallback { if (self.isInitSDK) { if (resultCallback) { resultCallback(YES); } return; } __weak __typeof(self) wself = self; [SudMGP initSDK:appId appKey:appKey isTestEnv:YES listener:^(int retCode, const NSString * _Nonnull retMsg) { wself.isInitSDK = retCode == 0; if (resultCallback) { resultCallback(wself.isInitSDK); } }]; } /** * 小游戏游戏界面加载 **/ - (void)initSudMGP { __weak __typeof(self) wself = self; [[GameSudMGPManager shareManager] requestSudMGPCode:NO resultCallback:^(NSString * _Nullable code) { if (!code) { [[ToastComponent shareToastComponent] showWithMessage:@"登录小游戏失败" view:self.view]; return; } [wself.iSudAPP destroyMG]; wself.iSudAPP = nil; wself.iSudAPP = [SudMGP loadMG:[LocalUserComponent userModel].uid roomId:self.roomModel.room_id code:[GameSudMGPManager shareManager].sudMGPCode mgId:self.gameId language:@"zh-CN" fsmMG:self rootView:self.gameRootView]; }]; } /** * 游戏游戏界面UI适配 * @param handle 回调句柄,APP接入方需要调用handle.success或handle.fail * @param dataJson {} */ -(void)onGetGameViewInfo:(id<ISudFSMStateHandle>)handle dataJson:(NSString*)dataJson { CGRect rect = self.gameRootView.frame; CGFloat scale = [[UIScreen mainScreen] nativeScale]; CGFloat height = rect.size.height; CGFloat width = 1.0 / 1.4 * height; //游戏区域宽高比建议1:1.4 width = MIN(width, rect.size.width); CGFloat left = 0.5 * (rect.size.width - width) * scale; NSDictionary *rectDict = [NSDictionary dictionaryWithObjectsAndKeys:@(0), @"top", @(left), @"left", @(0), @"bottom", @(left), @"right", nil]; NSDictionary *viewDict = [NSDictionary dictionaryWithObjectsAndKeys:@(rect.size.width * scale), @"width", @(rect.size.height * scale), @"height", nil]; NSDictionary *dataDict = [NSDictionary dictionaryWithObjectsAndKeys:@(0), @"ret_code", @"return form APP onGetGameViewInfo", @"ret_msg", viewDict, @"view_size", rectDict, @"view_game_rect", nil]; /// 回调 [handle success:[GameUtils dictionaryToJson:dataDict]]; }
/** * tab按钮状态变化回调 * @param itemButton: 点击的button * @param status: button状态 **/ - (void)gameRoomBottomView:(GameRoomBottomView *_Nonnull)gameRoomBottomView itemButton:(GameRoomItemButton *_Nullable)itemButton didSelectStatus:(GameRoomBottomStatus)status { if (status == GameRoomBottomStatusList || status == GameRoomBottomStatusListRed) { __weak __typeof(self) wself = self; [self.userListComponents show:^{ [wself restoreBottomViewMenuStatus]; }]; } else if (status == GameRoomBottomStatusRaiseHand) { //点击举手 __weak __typeof(self) wself = self; [GameRTSManager raiseHandsMicWithBlock:^(RTMACKModel * _Nonnull model) { if (model.result) { [[ToastComponent shareToastComponent] showWithMessage:@"上麦请求已发出,请耐心等待"]; [wself.bottomView updateButtonStatus:GameRoomBottomStatusRaiseHand close:YES]; [wself checkMicrophoneSystemAuthority]; }else { [[ToastComponent shareToastComponent] showWithMessage:@"操作失败,请重试"]; } }]; } else if (status == GameRoomBottomStatusMic) { [SystemAuthority authorizationStatusWithType:AuthorizationTypeAudio block:^(BOOL isAuthorize) { if (itemButton.status == ButtonStatusNone) { //mute [GameRTSManager muteMic]; [[GameRTCManager shareRtc] muteLocalAudioStream:YES]; } else { //unmute [GameRTSManager unmuteMic]; [[GameRTCManager shareRtc] muteLocalAudioStream:NO]; } itemButton.status = itemButton.status == ButtonStatusNone ? ButtonStatusActive : ButtonStatusNone; }]; } else if (status == GameRoomBottomStatusVolume) { [self.volumeComponents show]; } else if (status == GameRoomBottomStatusData) { [self.paramComponents show]; } else if (status == GameRoomBottomStatusDownHand) { //点击下麦 AlertActionModel *alertModel = [[AlertActionModel alloc] init]; alertModel.title = @"确定"; AlertActionModel *cancelModel = [[AlertActionModel alloc] init]; cancelModel.title = @"取消"; __weak __typeof(self) wself = self; [[AlertActionManager shareAlertActionManager] showWithMessage:@"是否确认下麦?" actions:@[cancelModel, alertModel]]; alertModel.alertModelClickBlock = ^(UIAlertAction * _Nonnull action) { if ([action.title isEqualToString:@"确定"]) { [GameRTSManager offSelfMicWithBlock:^(RTMACKModel * _Nonnull model) { if (model.result) { [wself sendDownloadHand]; }else { [[ToastComponent shareToastComponent] showWithMessage:@"操作失败,请重试"]; } }]; } }; } else { } } /** * 房主对观众和嘉宾操作 * @param userModel: 选中user的model * @param dataLists: 对应的用户列表 **/ - (void)updateTableViewWithModel:(GameControlUserModel *)userModel dataLists:(NSArray<GameControlUserModel *> *)dataLists { if (userModel.user_status == 0) { // 邀请上麦 [GameRTSManager inviteMic:userModel.user_id block:^(RTMACKModel * _Nonnull model) { if (!model.result) { [[ToastComponent shareToastComponent] showWithMessage:@"操作失败,请重试"]; } }]; } else if (userModel.user_status == 1) { // 举手 - 同意 __weak __typeof(self)wself = self; [GameRTSManager agreeMic:userModel.user_id block:^(RTMACKModel * _Nonnull model) { if (model.result) { userModel.user_status = 2; [wself updateDataLists:dataLists model:userModel]; } else { [[ToastComponent shareToastComponent] showWithMessage:@"操作失败,请重试"]; } }]; } else if (userModel.user_status == 2) { // 上麦 - 下麦 AlertActionModel *alertModel = [[AlertActionModel alloc] init]; alertModel.title = @"确定"; AlertActionModel *cancelModel = [[AlertActionModel alloc] init]; cancelModel.title = @"取消"; [[AlertActionManager shareAlertActionManager] showWithMessage:@"是否将该用户下麦?" actions:@[cancelModel, alertModel]]; __weak __typeof(self) wself = self; alertModel.alertModelClickBlock = ^(UIAlertAction * _Nonnull action) { if ([action.title isEqualToString:@"确定"]) { [GameRTSManager offMic:userModel.user_id block:^(RTMACKModel * _Nonnull model) { if (model.result) { [wself removeDataLists:dataLists model:userModel]; } else { [[ToastComponent shareToastComponent] showWithMessage:@"操作失败,请重试"]; } }]; } }; } } /** * 房间内观众上麦通知 * @param userModel: 对应user的model **/ - (void)receivedRaiseHandSucceedWithUser:(GameControlUserModel *)userModel { [self.roomView audienceRaisedHandsSuccess:userModel]; [self.userListComponents update]; if ([userModel.user_id isEqualToString:[LocalUserComponent userModel].uid]) { GameControlUserModel *localUser = [self currentLoginuserModel]; localUser.user_status = 2; localUser.is_mic_on = YES; [self.bottomView updateBottomLists:[self getBottomListsWithModel:localUser]]; [[ToastComponent shareToastComponent] showWithMessage:@"您已成功上麦"]; [[GameRTCManager shareRtc] makeCoHost:YES]; [[GameRTCManager shareRtc] muteLocalAudioStream:NO]; [self checkMicrophoneSystemAuthority]; } }
功能点 | API |
---|---|
创建 RTCVideo 对象 | createRTCVideo:delegate:parameters: |
创建 RTCRoom 对象 | createRTCRoom: |
设置用户可见性 | setUserVisibility: |
开启本地音频采集 | startAudioCapture |
加入RTC房间 | joinRoom:userInfo:roomConfig: |
离开房间 | leaveRoom |
关闭内部音频采集 | stopAudioCapture |
销毁 RTCRoom 对象 | destroy |
功能点 | 回调 |
---|---|
本地用户加入 RTC 房间回调 | rtcRoom:onRoomStateChanged:uid:state:extraInfo |
远端可见用户加入房间 | rtcRoom:onUserJoined:elapsed: |