-- 主界面 -- 加载界面时,分别在五个玩家门前放置5张牌,但并不显示 -- 更新玩家手牌列表时,按需显示 local ZiPaiRoomMessageView = class("ZiPaiRoomMessageView", cc.UIView) function ZiPaiRoomMessageView:ctor(ui) ZiPaiRoomMessageView.super.ctor(self); -- 玩家节点 self.nodes = {} self.recording = false; -- 是否正在录音 --是否关闭点击信息 self.m_isClose = true -- 记录每个玩家的最后一条语音 self.playerVoice = {} --系统的音效状态 self.soundState = app.systemSetting.info.sound --[[ self.playerVoice = { [1] = {url = url, filePath = filePath, recordTime = recordTime}, [2] = {url = url, filePath = filePath, recordTime = recordTime}, [3] = {url = url, filePath = filePath, recordTime = recordTime}, [4] = {url = url, filePath = filePath, recordTime = recordTime}, [5] = {url = url, filePath = filePath, recordTime = recordTime}, } --]] -- 最后一条音效 self.lastSound = nil -- 正在说话的椅子号(同一时刻只允许一个玩家说话) self.lastSpeakingSeatId = false end function ZiPaiRoomMessageView:onEnter() ZiPaiRoomMessageView.super.onEnter(self) local ui = loadUI("zipai/res/ui/ui_fangjian/zipai_ui_shengyin.ui"); self.ui = ui; self:addChild(ui); -- 语音按钮 self.ui.Items.Button_Record:registerClick(handler(self , self.stopRecord), handler(self , self.beginRecord), handler(self , self.cancelRecord)); -- 如果没有语音插件,则不显示语音按钮 if not app.plugin.pluginVoice then self.ui.Items.Button_Record:setVisible(false) end -- 表情按钮 self.ui.Items.Button_Face:registerClick(handler(self , self.onClickFace)) -- 录音中 self.ui.Items.Layout_luyinzhong:setVisible(false) -- 初始化玩家的各种节点 self:initNodes() -- 监听事件 self:initEvents() end function ZiPaiRoomMessageView:initNodes() self.myViewId = ZiPai_GAME_CONST.GAME_CONST_ME_VIEW_ID for i = 1, ZiPai_GAME_CONST.ZiPai_GAME_CONST_PLAYER do self.nodes[i] = {} local nodes = self.nodes[i]; -- 说话的语音 local nameSpeak = string.format("Layout_speak_%d",i) local nodeSpeak = self.ui.Items[nameSpeak] nodeSpeak:setVisible(false) nodes.nodeSpeak = nodeSpeak; -- 玩家头像信息 local nameHeadInfo = string.format("Layout_wanjiaxinxi_%d",i) local nodeHeadInfo = self.ui.Items[nameHeadInfo] nodeHeadInfo:setVisible(false) nodes.nodeHeadInfo = nodeHeadInfo; --表情 local nameFaceBG = string.format("Layout_face_%d",i); local nodeFaceBG = self.ui.Items[nameFaceBG] nodeFaceBG:setVisible(false) nodes.nodeFaceBG = nodeFaceBG; --表情图片 local nameFaceImage = string.format("ImageView_face_%d",i); local nodeFaceImage = self.ui.Items[nameFaceImage] nodeFaceImage:setVisible(false) nodes.nodeFaceImage = nodeFaceImage; --聊天文字 local nameChatText = string.format("Text_Chat_%d",i); local nodeChatText = self.ui.Items[nameChatText] nodes.nodeChatText = nodeChatText; end end function ZiPaiRoomMessageView:initEvents() -- 玩家语音 self:bindEvent(app.user , "onChatMessageResponse" , handler(self , self.onChatMessageResponse)); -- 回调語音播放 self:bindEvent(app , "recordCallback" , handler(self , self.recordCallback)); end function ZiPaiRoomMessageView:onClickBG() -- 隐藏头像 for i = 1, ZiPai_GAME_CONST.ZiPai_GAME_CONST_PLAYER do self.nodes[i].nodeHeadInfo:setVisible(false) self.nodes[i].nodeHeadInfo:removeAllChildren() end self.m_isClose = true end -- 显示屏幕中间滑动手指取消录音的提示 function ZiPaiRoomMessageView:showSpeaking() self.ui.Items.Layout_luyinzhong:setVisible(true) self.ui.Items.Layout_luyinzhong:playClip("speaking") end -- 隐藏屏幕中间滑动手指取消录音的提示 function ZiPaiRoomMessageView:hideSpeaking() self.ui.Items.Layout_luyinzhong:setVisible(false) self.ui.Items.Layout_luyinzhong:stopClip("speaking") end function ZiPaiRoomMessageView:beginRecord() if not app.user:canSendChatMessage(2) then showTooltip("您发送语音信息的间隔时间太短,请稍后再发!") return end -- 停止所有的表情声音 if self.lastSound then stopVoice(self.lastSound) end --为了不影响录制的过程,还可以听到音效,关闭所有的音效 app.systemSetting.info.sound = false --暂停音乐 cc.AudioController:getInstance():pause(); --暂停音效 --cc.AudioController:getInstance():setPlaySound(false) -- 停止所有的玩家语音 app.plugin:stopPlayRecord() -- 如果有玩家正在说话 if self.lastSpeakingSeatId then self.nodes[self.lastSpeakingSeatId].nodeSpeak:setVisible(false) end self.recording = true; --showTooltip("开始录音") self:showSpeaking() app.plugin:startRecord() end function ZiPaiRoomMessageView:cancelRecord() if not self.recording then return end --继续音乐 cc.AudioController:getInstance():resume(); --恢复音效 --cc.AudioController:getInstance():setPlaySound(app.systemSetting.info.sound) app.systemSetting.info.sound = self.soundState --showTooltip("取消录音") self.recording = false; self:hideSpeaking(); app.plugin:cancelRecord() end function ZiPaiRoomMessageView:stopRecord() if not self.recording then return end --showTooltip("结束录音") self.recording = false; self:hideSpeaking(); app.systemSetting.info.sound = self.soundState --继续音乐 cc.AudioController:getInstance():resume(); --恢复音效 --cc.AudioController:getInstance():setPlaySound(app.systemSetting.info.sound) if cc.Application:getInstance():getTargetPlatform() == 0 then local jsonData = { recordUrl = "recordUrl", recordTime = 10, } local content = json.encode(jsonData) if app.user:sendChatMessage(2, content) then -- 记录我发送过的语音 self.playerVoice[self.myViewId] = {} self.playerVoice[self.myViewId].filePath = "" self.playerVoice[self.myViewId].recordUrl = jsonData.recordUrl self.playerVoice[self.myViewId].recordTime = jsonData.recordTime; --播放录音时先停止背景音乐 --cc.AudioController:getInstance():pause(); -- 播放我的语音 self:replayRecord(self.myViewId) -- 播放我的语音 self:showSpeakClip(self.myViewId) self.ui.Items.Layout_1:runDelay(jsonData.recordTime, function() --播放背景音乐 --cc.AudioController:getInstance():resume(); end ) end return end app.plugin:stopRecord() end -- 播放回调函数 function ZiPaiRoomMessageView:recordCallback(event) --恢复音乐 if app.systemSetting.info.music then cc.AudioController:getInstance():resume(); end if not event then return end local filePath, recordUrl, recordTime = event.filePath, event.recordUrl, event.recordTime log("log_event", filePath, recordUrl, recordTime) if not filePath then return end if not recordUrl then return end if not recordTime then return end recordTime = math.ceil(recordTime / 1000); if recordTime <= 1 then showTooltip("录音时间过短!") return end local jsonData = { recordUrl = recordUrl, recordTime = recordTime, } local content = json.encode(jsonData); if app.user:sendChatMessage(2, content) then -- 记录我发送过的语音 self.playerVoice[self.myViewId] = {} self.playerVoice[self.myViewId].filePath = filePath; self.playerVoice[self.myViewId].recordUrl = recordUrl; self.playerVoice[self.myViewId].recordTime = recordTime; --播放录音时先停止背景音乐 --cc.AudioController:getInstance():pause(); -- 播放我的语音 self:replayRecord(self.myViewId) -- 播放我的语音 self:showSpeakClip(self.myViewId) --[[self.ui.Items.Layout_1:runDelay(recordTime, function() --播放背景音乐 cc.AudioController:getInstance():resume(); end)--]] end end -- 重新播放某个玩家之前说的话 function ZiPaiRoomMessageView:replayRecord(nSeatShowId) log("ZiPaiRoomMessageView:replayRecord() nSeatShowId = ", nSeatShowId); log("ZiPaiRoomMessageView:replayRecord() self.playerVoice = ", table.tostring(self.playerVoice)); local data = self.playerVoice[nSeatShowId] if data and data.filePath then app.plugin:playRecord(data.filePath) local recordTime = data.recordTime self.lastSpeakingSeatId = nSeatShowId self.ui.Items.Layout_1:runDelay(recordTime, function() self.lastSpeakingSeatId = nil end ) end end -- 创建一个用户头像 function ZiPaiRoomMessageView:createHeadInfo(nSeatShowId) local nUserId = app.room:getUserIdByViewId(nSeatShowId); local memberInfo = app.room.roomInfo.memberList[nUserId] if not memberInfo then return end local userInfo = json.decode(memberInfo.userInfo) local ui = loadUI("res/ui/ui_fangjian/ui_fangjian_wanjiaxinxi.ui") --隐藏滑动条 ui.Items.ScrollView:hideAllBar() --头像显示 --先设置默认头像 local nodeHead = ui.Items.ImageView_head self.headSize = {} self.headSize.width = nodeHead:getContentSize().width self.headSize.height = nodeHead:getContentSize().height if nSeatShowId == self.myViewId then ui.Items.ImageView_my:setVisible(true) ui.Items.ImageView_other:setVisible(false) else ui.Items.ImageView_my:setVisible(false) ui.Items.ImageView_other:setVisible(true) end setPlayerHeadImage(memberInfo.nUserId, userInfo.headimgurl, nodeHead) --男1女2 local sexNum = userInfo.sex or 1 if tonumber(sexNum) == 1 then ui.Items.ImageView:loadTexture("userInfo_boy.png",cc.TextureResType.plistType) else ui.Items.ImageView:loadTexture("userInfo_girl.png",cc.TextureResType.plistType) end --注册时间 local registerTime = tonumber(loadUserInfo("userRegisterTime")) or 0 local time = os.date("%Y/%m/%d",registerTime) ui.Items.Text_registerTime:setText(tostring(time)) -- 如果显示宽度大于10个英文字符宽度,则展示8个英文字符加省略号 local nickname = getSubStringNickname(userInfo.nickname,ui.Items.Text_mingzi) ui.Items.Text_mingzi:setText(nickname) local id = tonumber(nUserId) or 0 ui.Items.Text_id:setText(string.format("%06d", id)) ui.Items.Text_2:setVisible(false) if self.playerVoice[nSeatShowId] then local recordTime = self.playerVoice[nSeatShowId].recordTime or 0 ui.Items.Text_2:setText(tostring(recordTime).."''") -- 点击播放语音 ui.Items.ImageView_5:setTouchEnabled(true) ui.Items.ImageView_5:registerClick(function() --停止播放背景音乐 cc.AudioController:getInstance():pause(); app.systemSetting.info.sound = false --停止播放音效 --cc.AudioController:getInstance():setPlaySound(false) -- 播放语音 self:replayRecord(nSeatShowId) --必须用全局的 local seq = cc.Sequence:create(cc.DelayTime:create(recordTime),cc.CallFunc:create(function () app.systemSetting.info.sound = self.soundState cc.AudioController:getInstance():resume(); --恢复音效 --cc.AudioController:getInstance():setPlaySound(app.systemSetting.info.sound) end)) cc.Director:getInstance():getRunningScene():runAction(seq) --播放动画 ui.Items.Layout_2:playClip("say") ui.Items.Layout_2:runDelay(recordTime, function() ui.Items.Layout_2:stopClip("say") end ) end ) else ui.Items.ImageView_5:setTouchEnabled(true) ui.Items.ImageView_5:registerClick(function() if nSeatShowId == self.myViewId then showTooltip("请先录音哦") else showTooltip("该玩家还没说过话呢") end end ) end --道具ID, 消息类型 local function SendPropMessage(uidStarId,uidEndId,propId,mType,isQunFa) self:onClickBG() if not app.user:canSendChatMessage(1) then showTooltip("您发送聊天信息的间隔时间太短,请稍后再发!") return end local sexId = 0 local memberInfo = app.room.roomInfo.memberList[app.user.loginInfo.uid] if memberInfo then local userInfo = json.decode(memberInfo.userInfo) if not userInfo then return end --男1女2,默认是男生 sexId = tonumber(userInfo.sex) or 1 end local tt = json.decode(app.user.userInfo) local data = { uidStarId = uidStarId, uidEndId = uidEndId, propId = propId, isQunFa = isQunFa, areano = tt.areano, } -- 发送消息到服务器 --1: 表情 2: 语音 3:聊天 local str = json.encode(data) local isSendSuccess = app.user:sendChatMessage(mType, str); --[[if isSendSuccess == true then if mType == 4 then self:showProp(uidStarId, uidEndId,propId,isQunFa) end end--]] end self.lastPropTouchTime = tonumber(loadUserInfo("lastPropTouchTime")) or 0 saveUserInfo("lastPropTouchTime",self.lastPropTouchTime) ui.Items.Button_5:setVisible(false) ui.Items.Button_7:setVisible(false) ui.Items.ScrollView:requestDoLayout() ui.Items.ScrollView:doLayout() --道具实现 for i = 1 ,10 do local name = string.format("Button_%d",i - 1) ui.Items[name]:registerClick(function () playBtnEffect() if app.room.isOnLooker then showTooltip("旁观不允许发送道具") return end if table.nums(app.room.roomInfo.memberList) == 1 then showTooltip("桌子上没有其他人可以发哦") return end local curTime = os.time() local distance = curTime - self.lastPropTouchTime local disbandTime = 12 if distance <= disbandTime then showTooltip(string.format("您操作太快,请%d秒后再试!",disbandTime - distance + 1)) return end self.lastPropTouchTime = curTime saveUserInfo("lastPropTouchTime",self.lastPropTouchTime) if nSeatShowId == self.myViewId then --群发道具 --根据在线人数发送道具 local propID = i local targetUid = app.room:getUserIdByViewId(nSeatShowId) SendPropMessage(app.user.loginInfo.uid,targetUid,propID,4,1) else local propID = i local targetUid = app.room:getUserIdByViewId(nSeatShowId) if not targetUid then showTooltip("道具:目标ID不存在") return end SendPropMessage(app.user.loginInfo.uid,targetUid,propID,4,0) end end) end return ui end -- 显示玩家的头像信息 function ZiPaiRoomMessageView:showHeadInfo(nSeatShowId) if not self.nodes[nSeatShowId] or not self.nodes[nSeatShowId].nodeHeadInfo then return end self:onClickBG() local layoutHeadInfo = self.nodes[nSeatShowId].nodeHeadInfo layoutHeadInfo:removeAllChildren() self.m_isClose = nil local ui = self:createHeadInfo(nSeatShowId) if not ui then return end layoutHeadInfo:addChild(ui); layoutHeadInfo:setVisible(true) end -- 播放某个玩家说话的动画 function ZiPaiRoomMessageView:showSpeakClip(nSeatShowId) if not self.playerVoice[nSeatShowId] then return end local recordTime = self.playerVoice[nSeatShowId].recordTime or 1 local uiFile = "" if nSeatShowId == 1 or nSeatShowId == 2 then uiFile = "res/ui/ui_fangjian/ui_fangjian_speak_4.ui" else uiFile = "res/ui/ui_fangjian/ui_fangjian_speak_2.ui" end local ui = loadUI(uiFile) ui.Items.Text:setText(tostring(recordTime).."''"); ui.Items.ImageView:playClip("speak"); local nodeSpeak = self.nodes[nSeatShowId].nodeSpeak; nodeSpeak:removeAllChildren() nodeSpeak:addChild(ui); nodeSpeak:setVisible(true) --播放录音时先停止背景音乐 cc.AudioController:getInstance():pause(); app.systemSetting.info.sound = false nodeSpeak:runDelay(recordTime, function() nodeSpeak:setVisible(false) nodeSpeak:removeAllChildren() --播放背景音乐 cc.AudioController:getInstance():resume(); app.systemSetting.info.sound = self.soundState end ) -- 记录语音正在播放中 self.lastSpeakingSeatId = nSeatShowId self.ui:runDelay(recordTime, function() self.lastSpeakingSeatId = nil end ) end --点击表情按钮显示表情界面 function ZiPaiRoomMessageView:onClickFace() local function SendChatMessage(chatId,mType) if not app.user:canSendChatMessage(1) then showTooltip("您发送聊天信息的间隔时间太短,请稍后再发!") return end local sexId = 0 local memberInfo = app.room.roomInfo.memberList[app.user.loginInfo.uid] if memberInfo then local userInfo = json.decode(memberInfo.userInfo) if not userInfo then return end --男1女2,默认是男生 sexId = tonumber(userInfo.sex) or 1 end local data = { Id = chatId, sexId = sexId, } -- 发送消息到服务器 --1: 表情 2: 语音 3:聊天 local str = json.encode(data) local isSendSuccess = app.user:sendChatMessage(mType, str); if isSendSuccess == true then -- 本地播放表情和音效 if mType == 1 then --self:showFace(self.myViewId, chatId); elseif mType == 3 then --self:showChat(self.myViewId, chatId,sexId); end end end playBtnEffect() local function mesCallBack(idx) playBtnEffect() SendChatMessage(idx,3) end local function faceCallBack(idx) playBtnEffect() SendChatMessage(idx,1) end local faceUI = import("Views.Room.ChatFaceView"):new(ZiPai_GAME_CHAT_TXT,mesCallBack,faceCallBack) self.ui:addChild(faceUI); end --显示快捷语 function ZiPaiRoomMessageView:showChat(nSeatShowId, Id,sexId) local voiceFile = "" if sexId == 1 then voiceFile = string.format("zipai/res/sound/chat/ZiPai_%s_%d.ogg","male",Id) else voiceFile = string.format("zipai/res/sound/chat/ZiPai_%s_%d.ogg","female",Id) end --播放音效 self:playFaceVoice(voiceFile); --展示话筒 self.nodes[nSeatShowId].nodeChatText:setText(ZiPai_GAME_CHAT_TXT[Id]) self.nodes[nSeatShowId].nodeFaceBG:setScale(0,0,0) self.nodes[nSeatShowId].nodeFaceBG:setOpacity(255) self.nodes[nSeatShowId].nodeFaceBG:setVisible(true) self.nodes[nSeatShowId].nodeFaceBG:stopAllActions() self.nodes[nSeatShowId].nodeFaceBG:runAction(cc.Sequence:create(cc.ScaleTo:create(0.2,1,1,1), cc.DelayTime:create(4.0),cc.FadeOut:create(0.3),cc.CallFunc:create(function () self.nodes[nSeatShowId].nodeFaceBG:setVisible(false) self.nodes[nSeatShowId].nodeFaceBG:setOpacity(255) end))) end --显示表情 function ZiPaiRoomMessageView:showFace(nSeatShowId, Id) --播放动画 self:playFaceAnimation(nSeatShowId,Id) end function ZiPaiRoomMessageView:playFaceAnimation(nSeatShowId,Id) --判断纹理是否存在 local name = string.format("face%d_%d.png",Id,1) local cache = cc.SpriteFrameCache:getInstance() local spriteFrame = cache:getSpriteFrameByName(name); if tolua.isnull(spriteFrame) then print("spriteFrame is not in cache") return end local nodeFaceImage = self.nodes[nSeatShowId].nodeFaceImage nodeFaceImage:setScale(0.6) local indexFace = 0; --[1-10] local maxList = {10,10,10,10,10,10,10,24,10,12,11,10} --每隔多少秒切换一张图片 local everyFrame = 0.1 local seq = cc.Sequence:create(cc.DelayTime:create(everyFrame),cc.CallFunc:create(function () indexFace = indexFace + 1 if 0 < indexFace and indexFace <= maxList[Id] then local name = string.format("face%d_%d.png",Id,indexFace) if not tolua.isnull(nodeFaceImage) then nodeFaceImage:loadTexture(name, cc.TextureResType.plistType) end else self.nodes[nSeatShowId].nodeFaceImage:setVisible(false) end end)) if not maxList[Id] then return end local act = cc.Repeat:create(seq,maxList[Id] + 2) nodeFaceImage:stopAllActions() nodeFaceImage:runAction(act) nodeFaceImage:setVisible(true) end --播放表情音效 function ZiPaiRoomMessageView:playFaceVoice(musicFilePath) -- 如果正在播放语音,则不处理 if self.lastSpeakingSeatId then return end -- 如果正在播放音效,则停止音效 if self.lastSound then stopVoice(self.lastSound) self.lastSound = nil end -- 记录当前的音效 self.lastSound = playVoice(musicFilePath) end -- //////////////////////// //////////////////////// -- function ZiPaiRoomMessageView:onChatMessageResponse(event) if not event or not event.response then return end -- 用户ID local nUserId = event.response.nUserId local nSeatShowId = app.room:getViewIdByUserId(nUserId); if not nSeatShowId then print("ZiPaiRoomMessageView:onChatMessageResponse() nSeatShowId = ", nSeatShowId); return end -- //类型 1: 表情 2: 语音 3:聊天 if event.response.type == 1 then -- 表情 local data = json.decode(event.response.content) local Id = data.Id or 1 self:showFace(nSeatShowId, Id); elseif event.response.type == 2 then -- 语音 local jsonData = json.decode(event.response.content) local recordUrl = tostring(jsonData.recordUrl) local recordTime = tonumber(jsonData.recordTime) --[[if self.recording then return end--]] -- 下载玩家的语音文件并播放 -- 下载完成后返回该文件在本地存储的路径 app.plugin:downloadRecord(nUserId, recordUrl, function(recordTag, filePath) local userId = tonumber(recordTag) local seatShowId = app.room:getViewIdByUserId(userId) if not seatShowId then print("ZiPaiRoomMessageView:onChatMessageResponse() seatShowId = ", seatShowId); return end self.playerVoice[seatShowId].filePath = filePath end); -- 记录该玩家的语音文件,重播要用 self.playerVoice[nSeatShowId] = {} self.playerVoice[nSeatShowId].recordUrl = recordUrl; self.playerVoice[nSeatShowId].recordTime = recordTime; -- 该玩家头像上播放说话的效果 self:showSpeakClip(nSeatShowId) elseif event.response.type == 3 then -- 聊天 local data = json.decode(event.response.content) local Id = data.Id local sexId = data.sexId self:showChat(nSeatShowId, Id,sexId); elseif event.response.type == 4 then -- 道具 local data = json.decode(event.response.content) local uidStarId = data.uidStarId local uidEndId = data.uidEndId local propId = data.propId local isQunFa = data.isQunFa self:showProp(uidStarId, uidEndId,propId,isQunFa) else -- 未知的 end end --发送道具 function ZiPaiRoomMessageView:showProp(uidStarId, uidEndId,propId,isQunFa) response = {} response.uidStarId = uidStarId response.uidEndId = uidEndId response.propId = propId response.isQunFa = isQunFa app.room:dispatchEvent({name = "showProp",response = response}); end return ZiPaiRoomMessageView;