凡人修真3D(2)神兵
来源:互联网 发布:js闭包坏处 编辑:程序博客网 时间:2024/06/02 10:27
1.命名很重要,不知道上面有么有提过,不过发现了还是写下来吧。命名的时候,要看看这个单词在其他系统中,是否已经被使用了,已经具有特别的意义。
例如:整个游戏里面,表示魔法的都是用magical这个词,现在神兵也用了这个词,很容易造成误解。而且,神兵怎么翻译,好像都翻译不出magical吧。
2.读取TAttribute表的时候,还是要判断一下是否有这个数据的。
bool GameConfigData::CAttributeConfigManager::getAttribute( int attrId,Message::Db::Tables::TAttribute& attr ){MapTAttribute::iterator iter = _attrMap.find(attrId);if (iter != _attrMap.end()){attr = iter->second;return true;}else{return false;}}因为没有数据的时候,附加上去是没有意义的。而且tAttribute的__init()函数好长,所以传进来是没有初始化的。如果在外面没初始化,可能附加了一个随机数,甚至变负。
3.在for循环的初始化语句的地方,很多人为了缩减语句长度,把第一句抽出来。实际上换行就好了,放进for循环中,就相当于一个局部的属性,这个for循环用完了,这个属性就没有了。如果抽了出来,就会一直存在,下面的for循环必须有一个不同的名字,而且如果类型一样,可能会造成混用,编译器也检查不出来。所以如果不是特殊的需要,请把内容放到for循环中去。
int GameConfigData::CMagicalConfigManager::getStarNum(int promoteLevel, int starLevel){MapMapCStarConfigPtr::const_iterator it = _mapMapStarConfig.begin();//我说的是这句!!!!!要放进for循环中去。int starNum = 0;for (; it != _mapMapStarConfig.end(); ++it){if (promoteLevel > it->first){continue;}starNum += it->second.size();}starNum += starLevel;return starNum;}
4.这个不算是bug,算是一个建议把。在写代码的时候,在一个函数里面,可能一层一层下来,if、switch之类一堆,就会出现很多层。到下面的层就一个屏幕都无法显示出来了。我一般是把一些if语句抽出来,早点return掉,下面的继续执行。说的不是很清楚,看代码吧。
if (needItemCount < promoteConfig->_tMagicalPromote.itemNum ){//数量不足if (autoBuy){ //xxxx这里还有一堆代码,省略了。这部分代码很长很长}else{// 升阶石不足CErrorCodeManager::throwException("ErrorGate_MagicalPromoteStoneNotEnough");}}
一般我会这样写的:
if (needItemCount < promoteConfig->_tMagicalPromote.itemNum ){//数量不足if (!autoBuy){ // 升阶石不足 CErrorCodeManager::throwException("ErrorGate_MagicalPromoteStoneNotEnough");} //继续执行自动购买的代码。}这样能尽量减少{}的嵌套。只是个小小建议,我也不知道这样算不算好。
5.代码里面尽量不要写死,对于一些用处比较多的数字,可以用一个常量表示。
int price = 0;int shopCode = 10003;//商店类型CShopPtr shop = CShopConfigManager::instance()->getShop(shopCode);if (shop){这里面的自动购买商店在CShopConfigManager里面有定义
CShopPtr shop = CShopConfigManager::instance()->getShop(SHOP_CODE_AUTO_BUY);一开始写代码的时候可能大家都不知道有这种东西存在,不过大家要保持这种意识,留意和多看别人的代码。
6.这个好像提过,不过碰到了就写一下吧。读取商店配置的时候,要用上价格单位和数量。单独的数量是无意义的,而且万一改了货币单位呢!
int price = 0; CShopPtr shop = CShopConfigManager::instance()->getShop(SHOP_CODE_AUTO_BUY);if (shop){CShopSellPtr shopSell = shop->getShopSell(promoteConfig->_tMagicalPromote.itemCode);if (shopSell){price = shopSell->_tShopSell.price;}}//检测是否有钱player->enoughMoneyException(EPriceUnitEMoney, price * promoteConfig->_tMagicalPromote.itemNum, updateCode);7.除数必须检测是否为0.
例如:
if (tPlayerMagical.blessingValue + tPlayerMagical.limitBlessingValue + addExp >= promoteConfig->_tMagicalPromote.needBlessing)
8.对于配置在t_const里面的复杂的字符串,如果有自己功能的Config管理类,应该在GameCofnigData里面先分解。
// 成功率 = 取祝福值百分比区间的成功率.int successRate = 0;std::string successRateStr = CConstConfigManager::instance()->getConstValueStr("MagicalPromoteSuccessRate");std::vector<std::string> successRateTemp;cdf::CStrFun::split_ex(successRateTemp, successRateStr.c_str(), "[]");for (std::vector<std::string>::iterator iter = successRateTemp.begin(); iter != successRateTemp.end(); ++iter){std::vector<std::string> successRateTemp1;cdf::CStrFun::split(successRateTemp1, (*iter).c_str(), ',');if (successRateTemp1.size() != 2){continue;}if (atoi(successRateTemp1[0].c_str()) < blessingPercent){successRate = atoi(successRateTemp1[1].c_str());}}
像这样的,应该先分解,然后封装在管理类里面了。
std::string successRateStr = CConstConfigManager::instance()->getConstValueStr("MagicalPromoteSuccessRate");CUtil::changBracketsStrToMap(_promoteSuccessRate, successRateStr);
bool GameConfigData::CMagicalConfigManager::isPromoteSuccess(int blessingPercent){int rate = 0;for (DictIntInt::iterator iter = _promoteSuccessRate.begin(); iter != _promoteSuccessRate.end(); ++iter){if (blessingPercent < iter->first){break;}else{rate = iter->second;}}int rand = ::Common::CUtil::myRand(1, 10000);return rand < rate;}内容会清晰和简单很多。
9.关于概率计算的问题,C++中的随机数最大值大概是30000多,不能更大了。另外,一般情况下,设计到战斗和属性之类的,总概率都是10000,用常量FIGHT_RATING。其他的概率一般是100.这个不做要求,但是用到的时候要注意,不要搞错。
bool GameConfigData::CMagicalConfigManager::isPromoteSuccess(int blessingPercent){int rate = 0;for (DictIntInt::iterator iter = _promoteSuccessRate.begin(); iter != _promoteSuccessRate.end(); ++iter){if (blessingPercent < iter->first){break;}else{rate = iter->second;}}int rand = ::Common::CUtil::myRand(1, 10000);//这里总概率是10000,但是上面的配置的总概率是100.return rand < rate;}
10.在一段程序里面,对于一些检测判断,比较容易return或者抛异常的,应该放在前面。变量尽可能放到要用的时候才声明。
这个例子可能不算很经典
void::Message::Game::IMagicalImpl::magicalStar_async(const ::Message::Game::AMD_IMagical_magicalStarPtr& magicalStarCB,int autoBuy,const ::cde::CContext& context){ int succeed = 0;//这两个变量根本没用到,应该放在后面 int exp = 0;CGateEntityPtr gateEntity;CPlayerPtr player;CGateHelper::getPlayerAndEntity(context, gateEntity, player);//一般来说,接口都是这两个比较靠前,因为要取出来用CMagicalManagerPtr magicalManager = CMagicalManagerPtr::dynamicCast(gateEntity->getComponent(ECOMPONENT_TYPE_MAGICAL_MANAGER));// 神兵数据if (!magicalManager->getTPlayerMagical().activate){//神兵还没激活CErrorCodeManager::throwException("ErrorGate_MagicalNotActivate");}
11.尽量不要把int当bool来使用。代码有变动之后很容易出错,而且就算用int来存放结果,很多时候0不一定代表错误。在java中,返回0通常表示成功的。
if (!magicalManager->getTPlayerMagical().activate){//神兵还没激活CErrorCodeManager::throwException("ErrorGate_MagicalNotActivate");}
if (autoBuy){int price = 0;int shopCode = 10003;//商店类型
12.代码换行之后,该缩进的时候要缩进一下。这个我也不知道什么标准了,不过一般都是按编译器换行后的缩进。
std::string skinStr = "";for (MapSMagicalSkinInfo::iterator iter = _magicalSkin.begin();iter != _magicalSkin.end();//for循环中间的应该缩进吧iter++){//大括号中间的内容应该缩进skinStr += "[";skinStr += ToStr(iter->second.skinCode);skinStr += ",";skinStr += ToStr(iter->second.skinGradeLevel);skinStr += ",";skinStr += ToStr(iter->second.skinStarLevel);skinStr += ",";skinStr += ToStr(iter->second.isLimitTime);skinStr += ",";skinStr += ToStr(iter->second.skinLimitTime);skinStr += "]";}
13.对于一些复杂的内容,要保存到字符串,在放到数据库中。一般都是登陆的时候将字符串分解。保存到数据库的时候才将东西转成字符串。
void GateApp::CMagicalManager::setMagicalPromoteReturnReward(SPromoteReturnRewardInfo sPromoteReturnRewardInfo){_magicalPromoteReturnReward[sPromoteReturnRewardInfo.promoteLevel] = sPromoteReturnRewardInfo; std::string promoteReturnRewardStr = "";for (std::map<int, SPromoteReturnRewardInfo>::iterator iter = _magicalPromoteReturnReward.begin();iter != _magicalPromoteReturnReward.end();iter++){promoteReturnRewardStr += "[";promoteReturnRewardStr += ToStr(iter->second.promoteLevel);promoteReturnRewardStr += ",";promoteReturnRewardStr += ToStr(iter->second.consumeNum);promoteReturnRewardStr += ",";promoteReturnRewardStr += ToStr(iter->second.isGet);promoteReturnRewardStr += "]";}_tPlayerMagical.promoteReturnReward = promoteReturnRewardStr;}
这个每次变化都转一次,是没必要的。在save函数中执行,save函数在隔五分钟才会保存一次,不会过多执行。
void GateApp::CMagicalManager::save(bool logOut){cdf::CDateTime now;SSaveInfo& saveInfo = getSaveInfo(EMPlayerMagical);if (!saveInfo.needToSave(logOut, now)){return;}std::string skinStr = "";for (MapSMagicalSkinInfo::iterator iter = _magicalSkin.begin();iter != _magicalSkin.end();iter++){skinStr += "[";skinStr += ToStr(iter->second.skinCode);skinStr += ",";skinStr += ToStr(iter->second.skinGradeLevel);skinStr += ",";skinStr += ToStr(iter->second.skinStarLevel);skinStr += ",";skinStr += ToStr(iter->second.isLimitTime);skinStr += ",";skinStr += ToStr(iter->second.skinLimitTime);skinStr += "]";}_tPlayerMagical.skinStr = skinStr;std::string promoteReturnRewardStr = "";for (MapSPromoteReturnRewardInfo::iterator iter = _magicalPromoteReturnReward.begin();iter != _magicalPromoteReturnReward.end();iter++){skinStr += "[";skinStr += ToStr(iter->second.promoteLevel);skinStr += ",";skinStr += ToStr(iter->second.consumeNum);skinStr += ",";skinStr += ToStr(iter->second.isGet);skinStr += "]";}_tPlayerMagical.promoteReturnReward = promoteReturnRewardStr;saveInfo.reset(now);Message::Db::IMagicalDbPrx prx = Message::Db::IMagicalDbPrx::dynamicCast(Common::CCoreChannelManager::instance()->getProxy(Common::ECHANNEL_TYPE_DB_CACHE, Common::IMagicalDb));prx->updatePlayerMagical_async(NULL, _tPlayerMagical);}14.一般来说一个功能一个configManager,除非很大,代码太多才会分开。
MagicalConfigManager
MagicalSkinConfigManager
MagicalAwakenConfigManager
这三个内容都不多,是在没多大必要。
- 凡人修真3D(2)神兵
- 凡人修真3D(3)神翼
- 凡人修真3D(1)坐骑
- 凡人修真3D(6)背包
- 《凡人修真2》 架设
- 凡人修真2宠物攻略独家大全
- 《凡人修真2》攻略:教你如何选择宠物
- 凡人
- 凡人!
- 2013年北邮网研院上机真题(D)
- 凡人修真传-程序员的十个等级
- 作团队感悟(2)----凡人心态
- 作团队感悟(2)----凡人心态
- 作团队感悟(2)----凡人心态
- 作团队感悟(2)----凡人心态
- Android神兵利器之黄油刀(ButterKnife)
- 软件测试江湖(二)神兵利器篇
- Android 神兵利器Dagger2使用详解(一)基础使用
- C#简易访问sqlserver
- [Extjs6] 页面电话号码点击后进入打电话界面
- 制作3D旋转视频展示区
- MDX多维查询
- Mysql远程连接配置
- 凡人修真3D(2)神兵
- linux系统中安装ntopng的坎坷路
- js学习笔记:事件——事件流、事件处理程序、事件对象
- docker whenever部署时设置环境
- 导入时如何定制spring-boot依赖项的版本
- 使用WebView时的一些坑(图片拼接、不显示、shouldOverrideUrlLoading正确用法)
- Dijkstra(迪杰斯特拉)算法-js实现
- 用微笑面对一切令你烦恼的人或事,不久之后,你会发现令你微笑的人或事变得越来越多了。
- 便捷的数据同步机制,在同一类型数据库服务器上