【Lua】手游聊天系统客户端完成总结

网上很多例子,我是参考这篇文章:http://www.myexception.cn/operating-system/1591495.html

1.聊天系统难题一:消息需要支持插入表情和换行。

一开始我打算借鉴上面文章中的方法自己用label和image拼接实现自己的富文本,后来同事建议我使用cocos2dx自带的富文本空间RichText,网上找了一些例子学习,在代码中使用发现效果还不错,可以插入图片,也支持自动换行(通过setContentSize(cc.size(width,height))来设置空间的宽高之后,超过宽度的内容就可以自动换行)

RichText使用方法:

  local rt = ccui.RichText:create();

  rt:ignoreContentAdaptWithSize(false);

  rt:setContentSize(cc.size(550,120));

  --第一个参数是Tag

  local re1 = ccui.RichElementText:create(1,cc.c3b(255, 255,255), 255,"地瓜与土豆的小清新","Marker Felt",24);  --文本

    local re2 = ccui.RichElementImage:create(3,cc.c3b(255, 255, 255), 255, "equip/test_icon.png");  --图片

    local sp = cc.Sprite:create("equip/test_icon1.png");

  local re3 = ccui.RichElementCustomNode:create(4,cc.c3b(255,255,255),255,sp);  --自定义

  rt:pushBackElement(re1);

  rt:pushBackElement(re2);

  rt:pushBackElement(re2);

  --最后把rt加入到容器中,这里我使用的是listview

  list:pushBackCustomItem(rt);
View Code

2.聊天系统难题二:对消息的格式化处理。

需要对消息字符串进行拆分解析,才能正常提取出消息中的文字和图片。

下面是几个我使用到的字符串处理函数:

 

--判断字符是否为0到9的数字

function cu:is_number(char) --这里传入的char是通过函数string.byte(字符串,下标)取出的对应字符的整数形式


    if char >= 48 and char <= 57 then


        print("char==number:"..str);


        return true;


    end


    return false;


end
View Code

--获取字符串的真实长度处理

function cu:getRealStringLength(str)

    local i = 1;

    local len = string.len(str);

    local r = 0;

    while i<=len do

        if (self:is_zh_ch(string.byte(str, i))==1) then  --这里使用了is_zh_ch()判断是否为中文

            r=r+1;

            i=i+3;

        else

            r=r+1;

            i=i+1;

        end

    end

    return r;

end
View Code

--判断是否是中文

function cu:is_zh_ch(p)

    if p < 127 then

        return 0;

    else

        return 1;

    end

end
View Code

--截取字符,避免乱码的处理;

function cu:subString(str,start,ends)

    if string.len(str)>0  then

    

        local len = string.len(str);

        local tmp = "";

        

        --先把str里的汉字和英文分开

        local dump = {};

        local i = 1;

        while i<=len do

            if (cu:is_zh_ch(string.byte(str, i))==1) then

                table.insert(dump,table.getn(dump)+1,string.sub(str,i,i+2));

                i=i+3;

            else

                table.insert(dump,table.getn(dump)+1,string.sub(str,i,i));

                i=i+1;

            end

        end

        

        local iDumpSize = table.getn(dump);

        if ends > 0 then

        ends = ends;

        else

            ends = iDumpSize;

        end

      

        if(start<0 or start>ends) then

            return "";

         end

         

        for i = start, ends, 1 do  

            if dump[i]~=nil then

                tmp = tmp..dump[i];

            end    

        end

      

        return tmp;

    else

        print("str is not string
");

        return "";

    end

end
View Code

--解析消息字符串,将解析后的内容放入RichText返回

function cu:changeToRichText(str)

    local richtext_ = ccui.RichText:create();

    richtext_:ignoreContentAdaptWithSize(false);

    if cu:getRealStringLength(str) > 25 then

        richtext_:setContentSize(cc.size(500,60));

    else

        richtext_:setContentSize(cc.size(500,30));

    end

    

    local iMsgEnd = 1;

    local iMsgStart = 1;

    local r = "";

    local iRealLength = cu:getRealStringLength(str);

    local continue = false;

    

    while (cu:subString(str,iMsgStart,iMsgEnd) ~= "") do

        r = cu:subString(str,iMsgStart,iMsgEnd);

        continue = false;

        --先判断当前读取的字符内容是否是表情

        if(string.sub(r,string.len(r),string.len(r))=='[') then

            print("有表情");

            local tmp = cu:subString(str,iMsgEnd,iMsgEnd+3);

            print("string.sub(tmp,2,2):"..string.sub(tmp,2,2));

            print("string.sub(tmp,3,3):"..string.sub(tmp,3,3));

            print("string.sub(tmp,4,4):"..string.sub(tmp,4,4));

     

            if(string.sub(tmp,4,4)==']' and cu:is_number(string.byte(tmp,2)) and cu:is_number(string.byte(tmp,3))) then --face

                --表情前面若有内容的处理

                print("有表情1");

                if(iMsgEnd-iMsgStart>0) then

--                    textView->setString(r.substr(0,r.length()-1).c_str());

                    local txt_1 = string.sub(r,1,string.len(r)-1);

                    local temp_re_txt = ccui.RichElementText:create(1,cc.c3b(255, 255,255), 255,txt_1,"Marker Felt",24);

                    richtext_:pushBackElement(temp_re_txt);

                    print("字符串1:"..txt_1); 

                end

    

                --如果有表情的处理

                local temp = {0};

                if(string.sub(tmp,2,2)-'0' == 0) then

                    temp = "equip/test_icon"..(string.sub(tmp,3,3)-'0')..".png";

                else

                    temp = "equip/test_icon"..(string.sub(tmp,2,2)-'0')..(string.sub(tmp,3,3)-'0')..".png";

                end

                

                local temp_re_image = ccui.RichElementImage:create(2,cc.c3b(255, 255, 255), 255, "equip/test_icon.png");

--                local temp_re_image = ccui.RichElementImage:create(2,cc.c3b(255, 255, 255), 255, temp);

                richtext_:pushBackElement(temp_re_image);

                

                iMsgEnd = iMsgEnd + 4;

                iMsgStart = iMsgEnd;

                

                if(iMsgEnd>iRealLength) then

                    break;

                end

--                goto next  

                continue = true;

           end

        end    

--        local txt_2 = r; 

        if not continue then

            if(iMsgEnd>=iRealLength) then

                break;

            end

            iMsgEnd = iMsgEnd+1; 

        end

--        iMsgStart=iMsgEnd;

          

--        ::next::

     end 

    local txt_2  = cu:subString(str,iMsgStart,iMsgEnd);

    local temp_re_txt = ccui.RichElementText:create(1,cc.c3b(255, 255,255), 255,txt_2,"Marker Felt",24);

    richtext_:pushBackElement(temp_re_txt);

    print("字符串2:"..txt_2);

    

    return richtext_;

end
View Code

tip:对哪种格式的文本是图片完全根据个人喜好制定,不好用常用的聊天符号就行,这里我使用的是[xx](x为0~9的数字)

 

3.聊天系统难题三:控制发送消息的时间间隔。

需要使用定时器:

  --定时器控制发送消息的频率 (参数1是定时器函数 参数2是定时器的循环时间间隔 参数3表示是否循环)

  self.ScriptFuncId = CCDirector:sharedDirector():getScheduler():scheduleScriptFunc(self.send_message_scheduler,send_time_interval,false);

  --控制发送消息频率定时器函数

  function cu:send_message_scheduler()

      if_send = true; --在定时器中把标记设置为真,每次发送消息后将标记重新设置回false,通过此标记控制是否可以发送消息

  end

 

 

原文地址:https://www.cnblogs.com/Liyang1992/p/4015799.html