澳门金冠网站主页set可以取代vector会更好。本标准才针对预计可能引致代码风格有比较生不同的片段作出约定。

       
代码风格请尽量合并,写下来的代码不是和谐的,是浑团队的。说不定某天也使扣押人家的代码,或者某新来之要看咱们的代码。说的不好听,项目时相同长,就见面产出人口流动,如果每个人犹写一个品格,就会杀掉价了。

以方便大家交流暨代码共享,现在此做出一个同之代码风格约定。本标准适用于色C++语言以及其他语言及C++的杂部分。

       
很多问题要么如超前修正,否则后面东西顶多,特殊处理极其多,牵一发而动全身,要费还多之日。

PS:本标准才对预计可能引致代码风格来较充分不同的有些作出约定。

       
一些功能性、业务逻辑上之事物本身不怕无修改了,这样相当给重新写了。只是一味从技术上进行优化,以后有空再重构。

一律、命名规范

于有项目的命名都灵验之正规:

命名是不行主要之,

l  名称表述清楚,使用统一的英文词汇。

l  不下英文简写,除非是局部土生土长之缩略语。

l  单词命名优先表达清楚意思,其次才考虑缩短长度,不过也决不太长。


对于无法用英文表达的命名,使用拼音。每个词看做一个单词,中间不用小写,

例如:

修仙副本 xiuxianCopy

炫阳套装 xuanyangSuit

为汉字太多以来,大写尽多会十分乱。

l  以驼峰命名法,严禁全字母大写并且没有”_”的命名。

l  所有函数、变量、类等,都要要加以注,即使同看即清楚的啊翻一下国语。

l  命名要平等,不同的效应,对于同样之概念,要用相同的称谓。

 

1.当描写配置文件的时刻,尽量用map代替vector,因为找某修配置的当儿,可以减掉运算。有的地方,set可以代替vector会另行好

1.           变量命名规范

l  变量名前匪下外表示项目的前缀。

l  类内部数据成员,以前缀“_”开头;对于公开的多寡成员,可以免采用前缀。

l  变量首字母使用小写。

例如:

2.           函数命名规范

l  函数名叫必须直观,并且能够科学发挥其内在力量。

l  对于函数参数中之援和指针类型视情况为const修饰。

l  对于未改数据成员的切近成员函数,以const修饰。

l  函数曰以略写起来。

    优化前:

3.           类和结构名命名规范

l  类名以C开头,结构以S开头,都归因于大写开头。


接口类的命名沿用上面规则,并先缀“I”开头,例如:IInterfaceMgr,IModule。

bool GameConfigData::CMountConfigManager::getMountConfig(int code, Message::Db::Tables::TMount& tMount)
{
    for (Message::Db::Tables::SeqTMount::iterator iter = _tMounts.begin();
        iter != _mountMap.end();
        iter ++)
    {
        if (iter->code == code)
        {
            tMount == *iter;
            return true;
        }
    }
    return false; 
}

4.           常量与宏命叫作正式

l  尽量不采用宏定义;

l  对于常数定义,尽量采取const修饰或enum定义;

l  对于简易的操作,采用inline函数方式定义;

l  常量称作第一单字母大写。

    优化后:

5.           文件命名规范

l  目录名每个单词首配母大写,不利用另外分隔符;

bool GameConfigData::CMountConfigManager::getMountConfig(int code, Message::Db::Tables::TMount& tMount)
{
    MapTMount::iterator iter = _mountMap.find(code);
    if (iter == _mountMap.end())
    {
        return false;
    }
    tMount = iter->second;
    return true; 
}

6.           typedef类型命名规范

l  typedef std::vector<int> SeqInt; //vector的整整且以前加Seq。

l  typedef ::std::map<int, int>
DictIntInt;//map在cdl中加前缀Dict,在代码中因故Map。

l  必须为大写开头。

得为此set替代vector的地方,set不会见重,而且可就此count函数来拘禁是不是留存,就无须下面是轮回了。

亚、布局规范

应该以IDE的本原的作风也优先。

l  程序体建议为TAB缩进,少用空格缩进。

l  每一个函数(或接近方式)之间起码保留一个空行。

l  以先后体内,具有语义转换时,必须保留一个空行。

l  不修了长的函数代码,如果函数过长应考虑分拆为多独函数。

l  多次用到的代码,尽量减少出来作为一个函数。


除“.”、“→”、“::”外,双目操作符(如:“+”、“*=”等),两侧各留一个空格。

l  单目操作符(如:“++”、“!”)与操作数之间不留空格。

l  逗号分隔符的左边不留给空格,右侧留一个空格。

l  当判断一个指针是否为空时,使用“!ptr”的款式判断。

l  不要以与一行了声明多个变量。


当一个函数的返回值是因针变量或引用变量时,类型和操作符(“*”或“&”)之间不留空格,操作符之后留下一个空格;

l  对于复合语句,如:while, for,
if等,无论复合语句被蕴藏多少个话,一律另起一行,并应用{}括起来;

l  尽量保障头文件被不保证含头文件;

l  对于数据成员还公开之近乎,使用struct关键字来定义,否则用class关键字。

l  对于计数器或迭代器,可利用前++(–)或后++ (–)时,一律采取前++(–)。

 

有异常细致之平整可扣押这里:

http://blog.csdn.net/u012175089/article/details/51078360

 

bool GateApp::CPlayer::isFunctionOpen(std::string functionName)
{
    for (std::vector<std::string>::iterator it = _openFunction.begin(); it != _openFunction.end(); ++it)
    {
        if (functionName == *it)
        {
            return true;
        }
    }
    return false;
}

老三、编码的建议

此间才是部分建议和可能撞的问题。

 

1.尽量管运算提前,能够当起步程序时开展的运算,就无须等到运用的时光才开展。

像对于一些用[xxx,yyy]诸如此类保证在的字符串,应该在初始化的时段就是进展分解,用DictIntInt来保存。而不是历次用的时节拆一下。

与此同时使每一级的习性,在升级后,一个个重复加起来。这是统筹达到之荒谬,在规划布局文件的下,要充分考虑计算量。同时也只要考虑策划的配置量,通常如果配一不善,以后改动很有些之多少就是无欲考虑策划的工作量了。

2.外存中的布局文件,尽量采用map来代替vector。

3.代码里面的code很多,物品、技能、buff、updateCode等等,几乎每个配置都产生一个,最好当动用的时节添加各自的单词,例如:itemCode,skillCode,buffCode等等,不克止写code,难以阅读,而且代码增多后大爱导致混乱。

4.尽量应用集体的工具类函数,一般都位于Common/Public目录下,Util类是太常用的。

5.字符串拼接,一般采用“,”,如果要加多等同层,建议下“;”。使用公用的函数来构建与解释字符串。

6.DataTime转成为int,可以去到2030年过后都未会见出错,使用json保存的下,可以放心使用int,方便于,减少转换,而且减少json的尺寸。

7.智能指针不要互相指引,否则无法自行析构。

8.json尺度达成是因此来保存有比较乱的字段,如果是发出多独字段的组织的屡屡组,可以考虑构建一个新的发明。Json字段通常十分怪,如果是多次组,很爱会超越最老长。而且,很麻烦调试以及查看内存。Json最酷的用是因此来囤和导,不要过度依赖。无法调试的。

9.保留及数据库的数额,尽量用延时保存。

10.绝不写依赖让各个而不用逻辑的代码。

sCodeAttribute.attribute.push_back(attr.attack);  
sCodeAttribute.attribute.push_back(attr.life);  
sCodeAttribute.attribute.push_back(attr.physicalDefense);  
sCodeAttribute.attribute.push_back(attr.magicalDefense);  
sCodeAttribute.attribute.push_back(attr.wreck);  
sCodeAttribute.attribute.push_back(attr.block);  
sCodeAttribute.attribute.push_back(attr.miss);  
sCodeAttribute.attribute.push_back(attr.demiss);  
sCodeAttribute.attribute.push_back(attr.crit);  
sCodeAttribute.attribute.push_back(attr.decrit);  

这般的代码,中间加个字段,就会了混了。

11.推送数据要尽可能压缩,通常一个意义的漫天多少以签到的上推平糟糕,之后更新某个字段才逐个字段推送更新。

12.声称变量的时候顺手初始化一下。

13.循环用底迭代器,如果是背后没有动用及,就应坐循环中。不同循环不要共用迭代器。

14.布置文件或者服务端来规划,策划只是受建议及参照。我们只要充分考虑策划的命名,绝大部分凡是免能够直接使用的,通常口头说之是一个名,写到文档又是一个,等上线后同时是一个命名。如果不精,还会见变动不行频繁。而且,一个名号或者会见改掉,用在其余系统方面。这个时节便老混乱了。

15.假如考虑卡顿的题材。出现卡一般可以分成几种状态:

(1)玩家其实是最好多,现在底行状况,几乎不可能出现了,只有当戏耍后期,很多单服合成一个服才会产出。但是如此的玩家,在线的还是怪少之。所以平时相像不考虑。

(2)功能业务达到统筹来问题,让玩家与一个不胜差的流年段外得召开有项工作。例如设个5分钟的运镖3加倍时间,这个随时一到,所有玩家还当运镖。碰到这种题材,要再接再厉与策划商量,让该认识及或有的景况。这种错误非常酷肯定,可能每日到之时刻段,就会卡壳,也会时有发生为数不少玩家反映。但是修改的对象为异常显著。

(3)代码逻辑问题,最容易出现的即是for循环。例如300级的坐骑,如果每级的性能都是单身计算,每次看,升级,甚至走相同步都检测一下。还得循环几百坏,累计起来的计算量会生充分之。这种错误非常隐蔽,多少坏循环才算是有题目?这个无法下定论,但是计算量肯定是共在那里,这个职能累积一下,那个功能累积一下,整个体系便会非常卡。这种卡是时刻,偶尔爆发一下一心动不了,难以找寻,也不知服务端还是客户端的问题。通常都是陪伴在游戏的通生命周期。几乎无法根治,只能于设计及编代码的当儿故意地避免。

16.独立的力量尽量独立管理自己之多少,如果采用了有的描写深的数据,也只要转移化常量。

17.除数得检测是否为0,不管是不是由业务上看起不可能为0.

18.概率的题目,C++随机数最大值是30000大抵。另外,涉及到作战以及性能相关的,统一行使1000,用时量FIGHT_RATING。其他的没什么特殊要求用100哪怕实行了。

19.
在同等截先后中,对于片检测判断,比较轻return或者抛大的,应该置身眼前。变量尽可能放到要就此底时光才声明。

20.
尽量不要管int当bool来行使。代码来改动后非常轻出错,而且即使用int来存放在结果,很多时不时候0不肯定代表错误。

21.同一个职能的部署,建议坐落和一个表里面。当然,东西非常少之多少作用,可以放到t_const里面。但是呢闹无数力量,可能内容非常散,有强布局,而且数据量不是蛮老,可以放同一张表里面。

平凡用这种格式来写,但是要是顾几接触:

   
1.要产生desc字段,写清楚每个字段的意义,上面的还无是格外详细。应该这么:

    type类型value1:阶数,value2:星数,value3:exp,value4:属性id

   
2.当代码里面,要描写自己效力的结构,不可知一直动用value1,value2,value3.在loadConfig函数里面纵使活该转换完成。这种通用表格的情节不应有出现在业务层的代码里面。

 

22.一般景象下,只有接口访问才会直接丢弃大,其他地方弃大会发出题目之,例如登录。

23.
对此一些性能,过了某时刻失效的景况。设个定时器,到了是时间点,就把具备的且断,这是图的思量。我们普通在采取及之早晚检测一下是不是失效了不畏行了。

 

优化后:

bool GateApp::CPlayer::isFunctionOpen(std::string functionName)
{ 
    return _openFunction.find(functionName) != _openFunction.end();
}

2.代码里面的code很多,物品,技能,buff,updateCode。。。。。几乎每个配置都出一个,最好以动的时光增长各自的单词。

例如:itemCode,skillCode,buffCode等等,不要单独写code,难以阅读,而且代码增多后好易造成混乱。

3.建表的上,主键在配备文件里尽量用code,在主库中保存之音讯之所以id。含义:code表示编码,相当给平种植概念;id表示具体的标识,对许正在一个实例。

诸如在布置内部技能的主键是skill_code。在主库里面,我们许多发明底主键是不曾实际意义的,直接写id就尽了。有含义之例如t_player的player_id,t_guild的guild_id。

4.字符串拼接,一般采用“,”,如果一旦多同重合,可以采取“;”。当然,有些配置的地方,使用了“[]”来含有一长长的数,这样可扣押的比清晰。

稍符号是未切合当作分隔符的,例如:“:”

保存和读取,碰到时间CDateTime就会起错了。

//限时皮肤
    {
        std::string timingSkin = "";
        for (std::map<int, cdf::CDateTime>::iterator it = _timingSkin.begin(); it != _timingSkin.end(); it++)
        {
            timingSkin += ToStr(it->first);
            timingSkin += ":";
            timingSkin += it->second.asString();
            timingSkin += ",";
        }
        _playerMountJson[TIMING_MOUNT_KEY] = Json::Value(timingSkin);
    }




   Message::Public::SeqString mountVec;
            cdf::CStrFun::split(mountVec, (*iter).c_str(), ':');
            if (mountVec.size() == 2)
            {
                if (cdf::CStrFun::is_num(mountVec[0].c_str()))
                {
                    int mountCode = cdf::CStrFun::str_to_int32(mountVec[0].c_str());
                    cdf::CDateTime limitDate;
                    limitDate.parse(mountVec[1].c_str(), "YYYY-MM-DD hh:mm:ss");
                    _timingSkin[mountCode] = limitDate;
                }
            }

datetime是的字符串里面凡是包含冒号的,这样分割,就会拧。

5.把日保存到json的时光,使用整形保存秒数,或者字符串都好。经过测算,使用整形来代表时间,因为起1970年初始算从,大概道2030年之后几乎年才见面漫起。所以要想方便,可以采用整形来保存秒数及json中。用int能够省json的长!

6.关于指针的问题,我们使用智能指针,但是智能指针并无是万能的,在星型结构(就是互动指引或者间接互相指引),如果不以为放,可能会见有内存泄露。所以,请尽量保持树形结构。

例如:在GateApp中,

                           GateEntity

Player       Role         Bag       Mount 。。。。。

这些还是悬挂在GateEntity中,缺了啊,就由GateEntity中取得出来。

像这样:

/*
* 获取背包中坐骑卡数量
* return 坐骑卡数量返回
* @param cardCode 坐骑卡Code
*/
int GateApp::CMountManager::getMountCardCount(int cardCode) const
{
    assert(_bag);
    return _bag->getItemCount(cardCode);
}

当Mount下面又挂一下Bag,实在是发出格外充分隐患的。

7.决不觉得大简短的代码,不按标准没所谓,如果是小事的饶终于了,如果是在比顶层的功用中,一定要严按标准。我们的需要是常常转移的。一个职能可能变动十几二十不好,现在比少见,如果上线之后,效果不好,就见面时碰到了。

8.部分结构的typedef在CdlPublic中,另外,Common/Public/ComPublic.h写了部分cdl里面没的,方便大家用。

例如:

   //set
    typedef std::set<int> SetInt;  
    typedef std::set<long64_t> SetLong64;
    typedef std::set<std::string> SetString;
    //map
    typedef std::map<int, SeqInt> MapSeqInt;
    typedef std::map<long64_t, int> MapLongInt;
    typedef std::map<int, long64_t> MapIntLong;
    typedef std::map<int, MapIntLong> MapMapIntLong;

9.关于json,有便宜也产生弊,json可以省大量字段,但是调试之时节,如果要是看内存的值,非常困难,而且用json的计算量肯定会比较充分的。

例如:

/*
* 检测玩家是否已拥有该坐骑
* return true为已拥有,false为未拥有
* @param mountCode 坐骑Code
*/
bool GateApp::CMountManager::isMountExist(int mountCode) const
{
    for (Json::Value::const_iterator citer = _playerMountJson[ALL_MOUNT_KEY].begin();
        citer != _playerMountJson[ALL_MOUNT_KEY].end(); ++citer)
    {
        if ((*citer).isInt())
        {
            if ((*citer).asInt() == mountCode)
            {
                return true;
            }
        }
    }

    return false;
}

马上里面的始末基本上是力不从心查看的。

据此一般景象下,建议json只是保存某些数据,用来节省字段。另外用一个结构来保证存在内存,保存数据库的时刻再换一下。

10.有作用的检测、登陆特殊处理,必须等整体数据初始化之后才能够以。

void CPlayer::setTPlayerExtend2( const Message::Db::Tables::TPlayerExtend2& tPlayerExtend2 )
{ 
    _tPlayerExtend2 = tPlayerExtend2;
    _playerExtend2Json.parse(_tPlayerExtend2.jsStr);
    if (!isFunctionOpen("OfflineHour"))//这里还没初始化!!!
    {
        _tPlayerExtend2.offlineHour = 0;
    }
    else
    {

11.有关保存数据库的题材,很多功效,如果没有特殊要求,都是延时保存的。服务端最老的下压力之地方。

使一旦立马保存,可以这么写,

getSaveInfo(ETPlayerMount).immediatelyUpdate= true;

然而及时是匪推荐的。所有GateEntity的component里面,都是默认300秒的延时保留之。

因而一般还这么形容:

mountManager->getSaveInfo( ETPlayerMount ).changeFlag= true;
mountManager->save(false);//记得加上这个,否则没保存的

可看一下此的代码:

logout是底线的时节调用的,time是时工夫,intervalSeconds是延时保存之工夫间隔

bool SSaveInfo::needToSave( bool logOut, const cdf::CDateTime& time, int intervalSeconds )
{
    if ( immediatelyUpdate )//一些特殊的,非常非常重要的东西才立刻保存,用这个属性
    {
        return true;
    }
    if ( ! changeFlag )//一般情况下用这个属性。
    {
        return false;
    }
    if ( logOut )
    {
        return true;
    }

#ifdef _DEBUG
    {
        intervalSeconds = 10;
    }
#endif

    if ( ( time - lastUpdateTime ).getTotalSeconds() > intervalSeconds )
    {
        return true;
    }
    return false;
}

记调用save函数,否则不见面沾保存之。

12.虽说代码顺序一般是不克更改,但是也应保障独立性,尽量做到包。

例如:

Message::Game::SCodeAttribute GateApp::CMountManager::getMountAttribute(int code)
{
    Message::Game::SCodeAttribute sCodeAttribute;
    Message::Db::Tables::TMount tMount;
    if (CMountConfigManager::instance()->getMountConfig(code, tMount))
    {
        Message::Db::Tables::TAttribute attr;
        CAttributeConfigManager::instance()->getAttribute(tMount.attributeId, attr);

        //攻击、生命、物防、法防、穿透、格挡、命中、闪避、暴击、韧性
        sCodeAttribute.attribute.push_back(attr.attack);
        sCodeAttribute.attribute.push_back(attr.life);
        sCodeAttribute.attribute.push_back(attr.physicalDefense);
        sCodeAttribute.attribute.push_back(attr.magicalDefense);
        sCodeAttribute.attribute.push_back(attr.wreck);
        sCodeAttribute.attribute.push_back(attr.block);
        sCodeAttribute.attribute.push_back(attr.miss);
        sCodeAttribute.attribute.push_back(attr.demiss);
        sCodeAttribute.attribute.push_back(attr.crit);
        sCodeAttribute.attribute.push_back(attr.decrit);
    }
    sCodeAttribute.code = code;
    return sCodeAttribute;
}

这种以顺序把这么多个属性在一个数组里面,如果中不小心插入或者去一个,就会见没救了。

vector是因此来存放同样的东西,这个同样的东西,不是独自数据类型上面,同样的整形,而是借助工作逻辑上,同样的内容。这其中是八只不同之属性。调试起来为无能为力关押了。

13.每当干到客户端的cdl定义之时光,尽量考虑扩展性,因为我们温馨改变好代码容易,让客户端改一下还是老大烦的。

14.像之一意义的战斗力,这种服务端完全没意义,不用保存,只是显示作用的,如果客户端能够获得数据,应该让客户端去举行,而休是服务端计算好才传过去。用于展示的事物,应该是客户端做的,这是展现层的职能,而休应有服务端做了。而且服务端应该尽量减少计算,以降低负荷,这是发出实际意义的。另外做的上或得看沟通,有时候如果实在无影响性,是可适度分担一下客户端的出工作的。不过本质上,应该客户端去分担服务端的计算量是勿转移的。

15.其他输入还是勿可信之。对于一个函数来说,输入的参数是免可信的,需要检测,当然,都是劳动端的代码,大部分之当儿不是那严峻。但是于cdl定义的接口,客户端传过来的始末,是绝不可信的,需要严格检测其合法性。这并无是说咱俩的客户端程序员的水平非常,而是因为市场上设有大气免费之外挂,不免费的或者啊几乎块钱,用来刷我们的纰漏。被刷的尾巴,轻的震慑是刷的要命厉害,被其他玩家或者运营发现,我们修改回去。中度的震慑是发现了问题,我们怎么为招来不顶是怎么刷的。更要紧的凡我们平素不清楚让刷了。

        所以要大跌出错的也许,cdl定义的接口,可以尽可能减少传输的情节。

16.来早晚以方便,将片数码配在t_const表里面,每次用的时段还取得出来。但是只要加大上的是一窜数字,最好还是在启动服务端的早晚取得下,整理成适宜的格式。

例如:

在因为骑培养的时利用这,其实代码没有啊好的问题,就是每次都因此字符串解释成数字,多累啊。

/*
* 坐骑培养暴击经验
* @return 暴击经验返回
*/
int GateApp::CMountManager::getFosterCritExp()
{
    int mountCritExp = 0;
    int haveRate = 0;
    int oldRate = 0;
    int randRate = ::Common::CUtil::myRand(1, 10000);

    std::string critStr = CConstConfigManager::instance()->getConstValueStr("MountPropCritFoster");
    int wakanFosterLv = CConstConfigManager::instance()->getConstValue("MountWakanFosterLevel");
    if (wakanFosterLv > _tPlayerMount.fosterLevel)
    {
        critStr = CConstConfigManager::instance()->getConstValueStr("MountWakanCritFoster"); 
    }

    std::vector<std::string> critTemp;
    cdf::CStrFun::split_ex(critTemp, critStr.c_str(), "[]");//每次都要转化,多麻烦啊
    for (std::vector<std::string>::iterator iter = critTemp.begin(); iter != critTemp.end(); ++iter)
    {
        std::vector<std::string> critTemp1;
        cdf::CStrFun::split(critTemp1, (*iter).c_str(), ',');
        if (critTemp1.size() == 2)
        {
            oldRate = haveRate;
            haveRate += atoi(critTemp1[1].c_str());
            if (oldRate < randRate && randRate <= haveRate)
            {
                mountCritExp = atoi(critTemp1[0].c_str());//这里已经获得了,还不跳出循环,后面的运算都是多余的。
            }
        }
    }
    return mountCritExp;
}

修改一下:

//在load坐骑的时候,顺便转一下这些字符串
    const std::string& pStr = CConstConfigManager::instance()->getConstValueStr("MountPropCritFoster");
    Common::CUtil::changBracketsStrToMap(_propFosterExpMap, pStr);//使用道具的配置,使用这个函数可以把[]的格式的字符串转成map
    const std::string& wStr = CConstConfigManager::instance()->getConstValueStr("MountWakanCritFoster");
    Common::CUtil::changBracketsStrToMap(_wakanFosterExpMap, wStr);//使用灵力
    _wakanFosterLevel = CConstConfigManager::instance()->getConstValue("MountWakanFosterLevel");

下一场每次点击培养的时刻,运行一下沾更值,这里仅配置的运算,可以放开配置的管理类里面。

int GameConfigData::CMountConfigManager::computeFosterExp(int fosterLevel)
{
    int randRate = ::Common::CUtil::myRand(1, 10000);
    Message::Public::DictIntInt expMap;
    if (_wakanFosterLevel >= fosterLevel)
    {
        expMap = _wakanFosterExpMap;//使用灵力培养的配置
    }
    else
    {
        expMap = _propFosterExpMap;//使用道具培养的配置
    }

    for (DictIntInt::iterator iter = expMap.begin(); iter != expMap.end(); ++iter)
    {
        if (randRate <= iter->second)
        {
            return iter->first;//已经获得就直接返回
        }
        else
        {
            randRate -= iter->second;
        }
    }
    return 1;
}

17.推送数据如果尽量减少,一个大局的数,在登陆的时段推平赖就是执行了。之后产生创新的时节,一般而言,只推送更新的数额。而未是历次都推全部的多寡。

   Message::Game::SPlayerMount_Ptr clientMountMsg = new Message::Game::SPlayerMount();
    mountManager->makeClientMountInfo(gateEntity, *clientMountMsg);
    gateEntity->messageToClient(ECmdGateMountInfo, clientMountMsg);

此地的为骑信息多,没有必要每次都推送,这样增大了推送的数据量,增大了产出网络丢包之概率。客户端收到数量以后,又比方全局初始化,双方都要算是更多。

18.对部分提升的功用,每一级都产生性加,例如坐骑,如果每级的特性都是直配,以后每次计算的时段,都设加以起来。看起没什么。但是因骑900个阶段,每次变更一下属性将再计算一下。。。。。。应该每一个时号都是一个总和,升级后,直接用新的attribute_id就行了。

void GameConfigData::CMountConfigManager::getMountFosterConfigAttribute(int transTimes, int curFosterLevel, int& totalExp,
    Message::Db::Tables::TAttribute& configAttribute)
{
    MapSubType2MountConfig fosterConfig = _mapMountFosterConfig[transTimes];

    //1.[0, curFosterLevel)经验,attribute属性
    int toFosterLv = curFosterLevel;
    if (curFosterLevel == _maxFosterLevel)
    {
        toFosterLv = _maxFosterLevel - 1;
    }

    for (int fosLv = 0; fosLv <= toFosterLv; fosLv++)//在这里,如果到10级就要循环10次了。
    {
        if (!fosterConfig[fosLv])
        {
            assert(false);
            break;
        }
        //total experience
        totalExp += fosterConfig[fosLv]->_tMountFoster.maxExp;

        //[0, toFosterLv]的所有attributeId属性
        Message::Db::Tables::TAttribute tempAttr;
        CAttributeConfigManager::instance()->getAttribute(fosterConfig[fosLv]->_tMountFoster.attributeId, tempAttr);
        configAttribute.attack          += tempAttr.attack;
        configAttribute.physicalDefense += tempAttr.physicalDefense;
        configAttribute.magicalDefense  += tempAttr.magicalDefense;
        configAttribute.life            += tempAttr.life;
        configAttribute.crit            += tempAttr.crit;
        configAttribute.block           += tempAttr.block;
        configAttribute.demiss          += tempAttr.demiss;
        configAttribute.miss            += tempAttr.miss;
        configAttribute.decrit          += tempAttr.decrit;
        configAttribute.wreck           += tempAttr.wreck;
        configAttribute.moveSpeed += tempAttr.moveSpeed;
    }

19.价,是当指定了钱单位之后才有含义的。从商店中获取下的物品,就设遵照部署的标价,不克盖自己明白现在是某种价格,就描写很了某种价格。

比如说:这个函数,只回了急需之币数据,没有回货币价格,调用的时段是摹写好了。

/*
* 道具不足,获取培养所需的费用
* return 道具费用返回
* @param propCode 道具Code
* @param propNum 道具数量
*/
int GateApp::CMountManager::getFosterPropPrice(const CGateEntityPtr& gateEntity,
    const CPlayerPtr& player,
    int propCode,
    int propNum)
{
    int price = 0; 
    CShopPtr shop = CShopConfigManager::instance()->getShop(SHOP_CODE_AUTO_BUY);
    if (shop)
    {
        CShopSellPtr shopSell = shop->getShopSell(propCode);
        if (shopSell)
        {
            price = shopSell->_tShopSell.price;
        }
    }

    if (price == 0)
    {
        CErrorCodeManager::throwException("ErrorGate_MountItemNotOnSale");
    }

    return price * propNum;
}


costMoney = mountManager->getFosterPropPrice(gateEntity, player, propCode, config->_tMountFoster.propNum2 - ownPropNum);
player->enoughMoneyException(EPriceUnitPoint, costMoney, updateCode);

如此这般就是限制大了使EPriceUnitPoint了,万一策划改了是免会见通知你的。急在,策划就是像家一样,是形成的。
20.对有==0之检测,如果无见面生出负数,最好改化≤0。

   if (moneyAmount == 0)
    {
        CErrorCodeManager::throwException("ErrorGate_MountItemNotOnSale");
    }

如这请商品,如果有地方串或者溢起了成为负数,这里就是检测不下了。

除此以外,很多极致可怜价值的检测也是改变成为≥比较好。

21.声明变量的上,顺手初始化一下,要养成习惯。

int flushNum;
int leftSeconds;
mountManager->getPotentialLeftSeconds(flushNum, leftSeconds);

22.对某些经常利用的“[]”结构的字符串,例如有布局,最好当GameConfigData中,启动的时即便进行解释。不要老是用的上才说。其他的情状为相应如此处理。写代码的时段,要把好当做一台电脑,怎样才能让好计算更不见使上平等的目的。东西不多,估计优化的效力啊不深,但是所有娱乐,所有机能,所有代码都这样,肯定会发题目之。

例如:坐骑计算皮肤属性的时段,每次都要诠释这个字符串。

void GateApp::CMountManager::calSkinAttribute(
    int mountCode, 
    Message::Public::DictIntInt& specSkinAdd, 
    Message::Public::DictIntInt& specWeaponAdd, 
    Message::Db::Tables::TPlayerRoleFightInfo& playerFightInfo)
{
    Message::Db::Tables::TMount tMountConfig;
    if (! CMountConfigManager::instance()->getMountConfig(mountCode, tMountConfig))
    {
        return;
    }

    SeqString vecTemp;
    cdf::CStrFun::split_ex(vecTemp, tMountConfig.specialAddition.c_str(), "[]");
    for (std::vector<std::string>::iterator iter = vecTemp.begin(); iter != vecTemp.end(); ++iter)
    {
        std::vector<std::string> vecAddition;
        cdf::CStrFun::split(vecAddition, (*iter).c_str(), ',');
        if (vecAddition.size() == 3)
        {
            //1跟2区分坐骑装备加成还是皮肤某一属性加成
            if (atoi(vecAddition[0].c_str()) == 1)
            {
                specWeaponAdd[atoi(vecAddition[1].c_str())] = atoi(vecAddition[2].c_str());
            }
            else
            {
                specSkinAdd[atoi(vecAddition[1].c_str())] = atoi(vecAddition[2].c_str());
            }
        }
    }

修改一下,放到MountConfigManager::loadCofngi()中失去。

//TMount
    Message::Db::Tables::SeqTMount mounts;
    Message::Db::Tables::Loader::loadFile(mountConfigFile, mounts);
    for (Message::Db::Tables::SeqTMount::iterator iter = mounts.begin();
        iter != mounts.end();
        iter ++)
    {
        CMountConfigPtr m = new CMountConfig();
        m->_tMount = *iter;
        SeqString vecTemp;
        cdf::CStrFun::split_ex(vecTemp, iter->specialAddition.c_str(), "[]");
        for (SeqString::iterator iter2 = vecTemp.begin(); iter2 != vecTemp.end(); ++iter2)
        {
            SeqString vecAddition;
            cdf::CStrFun::split(vecAddition, iter2->c_str(), ',');
            if (vecAddition.size() == 3)
            {
                CMountSpecialAdd sa;
                sa.type = atoi(vecAddition[0].c_str());
                sa.attrType = atoi(vecAddition[1].c_str());
                sa.addPercent = atoi(vecAddition[2].c_str());
                m->_specialAdds.push_back(sa);
            }
        }
        _mountMap[iter->code] = m;
    }

23.组成部分字段的命名的题目。这是单很蛋疼的问题,一方面我们如果命名得硬着头皮与策划写的文档尽量相同,但是不少汉语无法翻译到相应的英文的。另外,策划是形成的,更何况这些名,一到上线的早晚,就会转移得又快。所以如果和谐把握,不要一直按策划定义之号来做。

像:坐骑的部署表,按照策划写的来开,其实怎么看还扣留不懂得。因为于咱们的代码里面,type、subType好多都是种、小类来定义了。贸然按照策划的命名,尤其是策动定义之英文,很有或是跟我们片常用的翻译,甚至是C++里面的主要字相悖。对代码阅读造成大不便。

1) 星配置:坐骑共有0-14改动(0-9),每变动生10等级(1阶0星星-10阶0星星),每阶有5星球(10等没有5星球,而是使转生),因此各级改得配置45星,t_mount_foster的type是转,sub_type是星级,config_type=1凡造就进阶,config_type=2是转生

Type=0,sub_type=0,是0转1阶0星

Type=0,sub_type=1,是0转1阶1星

Type=0,sub_type=2,是0转1阶2星

Type=0,sub_type=3,是0转1阶3星

Type=0,sub_type=4,是0转1阶4星

Type=0,sub_type=5,是0转2阶0星球(1阶5星体满则升1品级,变为2阶0星,所以1阶5星=2阶0星星)

盖此类推……

对了,顺便说一样句,配置文件或者我们协调计划吧,策划为的单是建议及参照。

24.有关Map的一部分命名,直接上例子好了:

typedef std::map<int, CMountFosterConfigPtr> MapSubType2MountConfig;

以此别名,加了个subType,但是任何地方一样可以就此到,可能key值不是subtype。

因而自己之提议是

typedef std::map<int, CMountFosterConfigPtr> MapCMountFosterConfigPtr;
typedef std::map<int, MapCMountFosterConfigPtr> MapMapCMountFosterConfigPtr; 

于typedef的命名,脱离现实效果。在运用的下,注释上实际的key和value

MapCMountFosterConfigPtr _mapMountTransConfig;     //坐骑转生配置[转生次数,config]
MapMapCMountFosterConfigPtr _mapMountFosterConfig;  //坐骑培养配置[阶[星,config]]

25.坐骑配置疏散的问题,会招后面高级的时刻发生某些生成就会见促成循环几百次于。对于这种状况,要由零星个角度来考虑。

       
(1)在极短时间内,例如那1秒钟内,会不见面招计算量暴增,通常有限时间之功能,例如答题、帮派战等,将满服之玩家堆积在同,大家还对服务器发送相似之请。计算量肯定会暴增的,这个上也许会见卡壳。这个现象会非常引人注目,玩家肯定会投诉,但是发生强烈修改方向,往往对优化一下,就会克缓解问题。

       
(2)在一个于长之年月段中间,例如一整天,累积下来的究竟的时间量会无见面十分挺。坐骑配置的题目即是是,可能未见面造成服务器卡,甚至开始之时光了无会见在问题。但是越往后面,服务器会愈发卡,让您寻找问题吗查找不至,玩起来就觉得卡,想优化,发现优化一个地方吧未会见生鲜明效益。这是慢性毒药,通常发现问题之早晚就是是病入膏肓,做什么还回天无力的感到。

所以卡的问题,要发发现地避免。

void GameConfigData::CMountConfigManager::initFosterExpAndAttribute()
{
    //计算每个培养等级的总属性以及总经验。
    int lastExp = 0;//之前的所有等级的经验。
    Message::Db::Tables::TAttribute lastAttr;//之前所有等级获得的属性
    lastAttr.__init();
    Message::Db::Tables::TAttribute thisAttr;//当前这条属性
    for (MapCMountFosterConfigPtr::iterator iter = _transMap.begin();
        iter != _transMap.end();
        iter++)
    {
        MapCMountFosterConfigPtr& curFosterMap = _fosterMap[iter->first];//当前转的培养配置。
        for (MapCMountFosterConfigPtr::iterator iter2 = curFosterMap.begin();
            iter2 != curFosterMap.end();
            iter2++)
        {

            //经验值
            lastExp += iter2->second->_tMountFoster.maxExp;//
            iter2->second->_currentMaxExp = lastExp;
            //属性 
            if (!CAttributeConfigManager::instance()->getAttribute(iter2->second->_tMountFoster.attributeId, thisAttr))
            {  
                continue;//当前配置没有属性
            }  
            Common::CFightAlgorithm::addAttribute(lastAttr, thisAttr);//当前的加上之前的属性
            iter2->second->_currentAttribute = lastAttr;//当前的总属性
        }
        //这是培养满了,没有转生的情况
        //经验值
        lastExp += iter->second->_tMountFoster.maxExp;
        iter->second->_currentMaxExp = lastExp;
        //转生前的总属性  
        if (!CAttributeConfigManager::instance()->getAttribute(iter->second->_tMountFoster.attributeId, thisAttr))
        {
            continue;//当前配置没有属性
        }
        Common::CFightAlgorithm::addAttribute(lastAttr, thisAttr);//当前的加上之前的属性
        iter->second->_currentAttribute = lastAttr;//当前的总属性 
    }
}

及时是坐骑属性的解决办法。本来真正的解决办法,是改变配置的法门,让策划把东西到底好。但是今效益曾做扫尾,客户端也是故到是布局。这种干到客户端的题目,可能就是较难沟通。自己立即无想吓的事物,要人家背锅,而且,你切莫知晓客户端要改至啊程度。所以一般以力量就了,再失优化,我们会召开的转业鲜,往往要挑选妥协的主意,最好要以开干之前就是考虑当下上头的题材。这次的解决办法是当起步的时刻,把持有等级的塑造属性都算是一周。

澳门金冠网站主页 1

相关文章