You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
12 KiB

  1. -- 聊天组件 配合RoomChatView使用
  2. local ChatDefine = require("luaScript.GameChatDefine")
  3. local RoomChatComponentView = class("RoomChatComponentView", cc.UIView)
  4. function RoomChatComponentView:ctor(heads,messageList,faceList)
  5. RoomChatComponentView.super.ctor(self)
  6. --头像节点 viewId 对应下标
  7. -- {
  8. -- [1]= headNode,
  9. -- }
  10. self.heads = heads or {}
  11. --定义处理消息函数
  12. self.handlers = {
  13. [ChatDefine.MessageType.Face] = handler(self,self.onFaceHandler),
  14. [ChatDefine.MessageType.Voice] = handler(self,self.onVoiceHandler),
  15. [ChatDefine.MessageType.Message] = handler(self,self.onMessageHandler),
  16. [ChatDefine.MessageType.Prop] = handler(self,self.onPropHandler),
  17. [ChatDefine.MessageType.Chat] = handler(self,self.onChatHandler),
  18. }
  19. -- 道具播放器
  20. self.propAniPlayer = import("luaScript.Tools.PropAniPlayer"):new(self)
  21. self.messageList = messageList or {
  22. [1] = {oggStandard = "", oggLocal = "", txt = "各位前辈,我要开车了!"},
  23. [2] = {oggStandard = "", oggLocal = "", txt = "今天牌真是太好了!"},
  24. [3] = {oggStandard = "", oggLocal = "", txt = "快点啦!准备开局!"},
  25. [4] = {oggStandard = "", oggLocal = "", txt = "你们打的好,但是我要自摸了"},
  26. [5] = {oggStandard = "", oggLocal = "", txt = "牌神来了,让座让座!"},
  27. [6] = {oggStandard = "", oggLocal = "", txt = "稍等一下,我拉个朋友"},
  28. [7] = {oggStandard = "", oggLocal = "", txt = "时间很宝贵的,快点出牌吧"},
  29. [8] = {oggStandard = "", oggLocal = "", txt = "辛苦十几年,一把回到解放前!!"},
  30. [9] = {oggStandard = "", oggLocal = "", txt = "等下再来一把!"},
  31. }
  32. self.faceList = faceList or ChatDefine.FaceConfigs
  33. --聊天记录
  34. self.chatRecord = {}
  35. --语音是否播放
  36. self.isVoiceEnabled = true
  37. --是否显示道具动画
  38. self.isPropEnabled = true
  39. -- 是否说普通话
  40. self.isStandardLanguage = true
  41. end
  42. -- 设置是否说普通话
  43. function RoomChatComponentView:setLanguage(isStandard)
  44. self.isStandardLanguage = isStandard
  45. end
  46. function RoomChatComponentView:setPropEnabled(enable)
  47. self.isPropEnabled = enable
  48. end
  49. function RoomChatComponentView:setVoiceEnabled(enable)
  50. self.isVoiceEnabled = enable
  51. end
  52. function RoomChatComponentView:onEnter()
  53. RoomChatComponentView.super.onEnter(self)
  54. self:initBindEvent()
  55. end
  56. function RoomChatComponentView:initBindEvent()
  57. -- 监听服务器下发的聊天事件
  58. self:bindEvent(app.user, "onChatMessageResponse", handler(self, self.onChatMessageResponse))
  59. --聊天界面获取聊天记录
  60. self:bindEvent(app.user, GAME_EVENT.CHAT_GET_RECORED, handler(self, self.onGetRecordEvent))
  61. self:bindEvent(app.user, GAME_EVENT.CHAT_PLAY_VOICE, handler(self, self.onPlayVoiceEvent))
  62. self:bindEvent(app.user, GAME_EVENT.CHAT_STOP_VOICE, handler(self, self.onStopVoiceEvent))
  63. end
  64. function RoomChatComponentView:onChatMessageResponse(event)
  65. if not event or not event.response then
  66. return
  67. end
  68. --[[
  69. -- 聊天内容
  70. ChatMessageResponse = defClass("ChatMessageResponse"
  71. -- 用户uid
  72. , defVar("nUserId", VT_Int, 0)
  73. -- //类型 1: 表情 2: 语音 3:聊天
  74. , defVar("type", VT_Short, 0)
  75. -- //内容,客户端自定义格式
  76. , defVar("content", VT_String, "")
  77. )
  78. --]]
  79. local nUserId = event.response.nUserId
  80. local chatType = event.response.type
  81. local content = event.response.content
  82. if not nUserId or not chatType or not content then
  83. return
  84. end
  85. local viewId = app.room:getViewIdByUserId(nUserId)
  86. local data = json.decode(content)
  87. if not data then
  88. return
  89. end
  90. if self.handlers[chatType] then
  91. self.handlers[chatType](nUserId,viewId,data)
  92. end
  93. end
  94. --表情
  95. function RoomChatComponentView:onFaceHandler(nUserId,viewId,data)
  96. local sex = data.sex
  97. local idx = data.chatIdx
  98. local faceConfig = self.faceList[idx]
  99. if not faceConfig or not self.heads[viewId] then
  100. return
  101. end
  102. -- 如果有配语音,还要播放对应的语音
  103. local oggFile;
  104. if self.isStandardLanguage then
  105. oggFile = faceConfig.oggStandard
  106. else
  107. oggFile = faceConfig.oggLocal
  108. end
  109. if oggFile and oggFile ~= "" then
  110. if string.find(oggFile,"%%s") then --如果需要播放男女音效固定2个%s 例如:mj/res/sound/%s/mj_%s_text_7.ogg
  111. oggFile = string.format(oggFile,sex ==1 and "man" or "women",sex)
  112. end
  113. playVoice(oggFile);
  114. end
  115. local headSize = self.heads[viewId]:getContentSize()
  116. if not faceConfig.aniFile then
  117. local nodeFaceImage = cc.ImageView:createNode()
  118. nodeFaceImage:loadTexture(faceConfig.btnPng, cc.TextureResType.plistType)
  119. local action = cc.Sequence:create(cc.DelayTime:create(2),cc.RemoveSelf:create())
  120. nodeFaceImage:runAction(action)
  121. self.heads[viewId]:addChild(nodeFaceImage)
  122. nodeFaceImage:setPosition(headSize.width/2,headSize.height/2)
  123. return
  124. end
  125. -- 加载纹理到内存
  126. loadSpriteFrameFile(faceConfig.aniFile)
  127. -- 加载第一张图片
  128. local sprite = cc.Sprite:createWithSpriteFrameName(string.format("face%d_%d.png",idx,1))
  129. local animation = cc.SpriteAnimation:create()
  130. for i = 1,faceConfig.frameNum do
  131. local frame = cc.SpriteFrameCache:getInstance():getSpriteFrameByName(string.format("face%d_%d.png",idx,i))
  132. animation:addSpriteFrame(frame)
  133. end
  134. animation:setDelayPerUnit(0.1)
  135. sprite:runAction(cc.Sequence:create(cc.SpriteAnimate:create(animation),cc.RemoveSelf:create()))
  136. self.heads[viewId]:addChild(sprite)
  137. sprite:setScale(0.6)
  138. sprite:setPosition(headSize.width/2,headSize.height/2)
  139. end
  140. function RoomChatComponentView:showMessage(viewId,content)
  141. if not self.heads[viewId] then
  142. return
  143. end
  144. local headPos = self.heads[viewId]:getWorldPosition()
  145. local headSize = self.heads[viewId]:getContentSize()
  146. local size = self:getContentSize()
  147. local uiMessageFile = ""
  148. local posMessage = cc.p(0,0)
  149. if headPos.x<size.width/2 then
  150. uiMessageFile = "res/ui/ui_fangjian/ui_fangjian_Message_left.ui"
  151. posMessage = cc.p(headSize.width, 5)
  152. else
  153. uiMessageFile = "res/ui/ui_fangjian/ui_fangjian_Message_right.ui"
  154. posMessage = cc.p(0, 5)
  155. end
  156. local uiMessage = loadUI(uiMessageFile)
  157. uiMessage.Items = getUIItems(uiMessage)
  158. if content then
  159. uiMessage.Items.Text_Chat:setText(content)
  160. end
  161. uiMessage:setPosition(posMessage)
  162. local textSize = uiMessage.Items.Text_Chat:getContentSize()
  163. uiMessage.Items.Layout_Chat:setSize(cc.size(textSize.width+60,textSize.height+44))
  164. local y = headPos.y + uiMessage.Items.Layout_Chat:getContentSize().height/2
  165. if y>size.height then
  166. local offsetY = y-size.height;
  167. uiMessage:setPositionY(-offsetY-5)
  168. end
  169. self.heads[viewId]:addChild(uiMessage)
  170. -- 播放动画,完成后自删
  171. uiMessage.Items.Layout_Chat:playClip("fade", function()
  172. uiMessage:removeFromParent()
  173. end)
  174. end
  175. --短语
  176. function RoomChatComponentView:onMessageHandler(nUserId,viewId,data)
  177. local sex = data.sex
  178. local idx = data.chatIdx
  179. local messageConfig = self.messageList[idx]
  180. if not messageConfig then
  181. return
  182. end
  183. self:showMessage(viewId,messageConfig.txt)
  184. -- 如果有配语音,还要播放对应的语音
  185. local oggFile;
  186. if self.isStandardLanguage then
  187. oggFile = messageConfig.oggStandard
  188. else
  189. oggFile = messageConfig.oggLocal
  190. end
  191. if oggFile and oggFile ~= "" then
  192. if string.find(oggFile,"%%s") then --如果需要播放男女音效固定2个%s 例如:mj/res/sound/%s/mj_%s_text_7.ogg
  193. oggFile = string.format(oggFile,sex ==1 and "man" or "women",sex)
  194. end
  195. playVoice(oggFile);
  196. end
  197. end
  198. --聊天
  199. function RoomChatComponentView:onChatHandler(nUserId,viewId,data)
  200. local content = data.content
  201. if #self.chatRecord>=20 then
  202. table.remove(self.chatRecord,1)
  203. end
  204. table.insert(self.chatRecord,{nUserId=nUserId,content=content})
  205. app.user:dispatchEvent({name = GAME_EVENT.CHAT_PRSPONSE , nUserId = nUserId, content = content})
  206. self:showMessage(viewId,content)
  207. end
  208. function RoomChatComponentView:showVoice(viewId,timelen)
  209. if not self.heads[viewId] then
  210. return
  211. end
  212. local uiHead = self.heads[viewId]
  213. if uiHead.uiVoice and not tolua.isnull(uiHead.uiVoice) then
  214. uiHead.uiVoice:removeFromParent()
  215. uiHead.uiVoice = nil
  216. end
  217. local headPos = uiHead:getWorldPosition()
  218. local headSize = uiHead:getContentSize()
  219. local size = self:getContentSize()
  220. local uiVoiceFile, posAnchorVoice, posVoice
  221. if headPos.x<size.width/2 then
  222. uiVoiceFile = "res/ui/ui_fangjian/ui_fangjian_voice_left.ui"
  223. posAnchorVoice = cc.p(0, 0.5)
  224. posVoice = cc.p(headSize.width, headSize.height / 2)
  225. else
  226. uiVoiceFile = "res/ui/ui_fangjian/ui_fangjian_voice_right.ui"
  227. posAnchorVoice = cc.p(1, 0.5)
  228. posVoice = cc.p(0, headSize.height / 2)
  229. end
  230. local uiVoice = loadUI(uiVoiceFile);
  231. uiVoice.endCallback = endCallback
  232. uiVoice.Items = getUIItems(uiVoice)
  233. uiVoice.Items.ImageView:playClip("speak")
  234. uiVoice.Items.Text:setText(string.format("%d''", timelen))
  235. uiVoice:setAnchorPoint(posAnchorVoice)
  236. uiVoice:setPosition(posVoice)
  237. uiVoice:runDelay(timelen, function()
  238. if uiHead.uiVoice and not tolua.isnull(uiHead.uiVoice) then
  239. uiHead.uiVoice:removeFromParent()
  240. uiHead.uiVoice = nil
  241. end
  242. if uiVoice.endCallback then
  243. uiVoice.endCallback();
  244. end
  245. end)
  246. uiHead.uiVoice = uiVoice;
  247. uiHead:addChild(uiVoice)
  248. end
  249. function RoomChatComponentView:hideVoice(viewId)
  250. if not self.heads[viewId] then
  251. return
  252. end
  253. local uiHead = self.heads[viewId]
  254. if uiHead.uiVoice and not tolua.isnull(uiHead.uiVoice) then
  255. uiHead.uiVoice:removeFromParent()
  256. uiHead.uiVoice = nil
  257. end
  258. end
  259. --语音
  260. function RoomChatComponentView:onVoiceHandler(nUserId,viewId,data)
  261. local recordUrl = tostring(data.recordUrl)
  262. local recordTime = tonumber(data.recordTime)
  263. if nUserId == app.user.loginInfo.uid or not self.isVoiceEnabled then
  264. -- 如果是我自己发送的录音,在发送之前就已经在播放了,现在不需要再播放一次 或者屏蔽播放语音
  265. return
  266. end
  267. app.user:dispatchEvent({name = GAME_EVENT.CHAT_VOICE_RESP ,nUserId = nUserId,viewId = viewId, recordUrl = recordUrl, recordTime = recordTime})
  268. -- self:showVoice(viewId,recordTime)
  269. end
  270. --道具
  271. function RoomChatComponentView:onPropHandler(nUserId,viewId,data)
  272. if not self.isPropEnabled then
  273. return
  274. end
  275. local propId = data.propIdx
  276. local uidSender = data.uidSender
  277. local uidReceiver = data.uidReceiver
  278. local nViewIdBegin = app.room:getViewIdByUserId(uidSender)
  279. local nViewIdEnd = app.room:getViewIdByUserId(uidReceiver)
  280. if not nViewIdBegin or not nViewIdEnd or not propId then
  281. return
  282. end
  283. local posBegin = self.heads[nViewIdBegin]:getWorldPosition()
  284. -- 对自己 == 群发
  285. if uidSender == uidReceiver then
  286. -- 首先要搞清楚,房间里面哪些座位是有人的
  287. -- local viewIds = {}
  288. -- for uid,_ in pairs(self.uids) do
  289. -- local viewId = app.room:getViewIdByUserId(uid)
  290. -- table.insert(viewIds, viewId)
  291. -- end
  292. local isHave = false
  293. for viewId, head in pairs(self.heads) do
  294. if viewId ~= nViewIdBegin then
  295. local uid = app.room:getUserIdByViewId(viewId)--self.headInfos[viewId]
  296. if uid then --如果座位上有人 则播放
  297. isHave = true
  298. local posEnd = head:getWorldPosition()
  299. self.propAniPlayer:playAnimationWithPos(posBegin, posEnd, propId)
  300. end
  301. end
  302. end
  303. if not isHave then
  304. showTooltip("当前没有其他玩家!")
  305. end
  306. else
  307. if self.propAniPlayer and self.heads[nViewIdEnd] then
  308. local posEnd = self.heads[nViewIdEnd]:getWorldPosition()
  309. self.propAniPlayer:playAnimationWithPos(posBegin, posEnd, propId)
  310. end
  311. end
  312. end
  313. --获取聊天记录事件
  314. function RoomChatComponentView:onGetRecordEvent()
  315. app.user:dispatchEvent({name = GAME_EVENT.CHAT_GET_RECORED_RESP , messages = self.chatRecord})
  316. end
  317. function RoomChatComponentView:onPlayVoiceEvent(event)
  318. self:showVoice(event.viewId,event.recordTime)
  319. end
  320. function RoomChatComponentView:onStopVoiceEvent(event)
  321. self:hideVoice(event.viewId)
  322. end
  323. return RoomChatComponentView