由于最近负面情绪比较多,说以废话比较多。看博客的朋友可以直接跳到下面的==正题==

如果是连博客都不想看的,可以直接看代码(最下方)。

最近的2周感觉被项目给压榨了。连着忙了2周,任务比较赶是一个,其二,是我们程序这边终于有了个管事的了。

上周6下午开会讨论了一下我们工作中的问题。主要有4个。


各个人做的事情没有人确认。所以定了个这样的流程。

通过禅道系统。

  1. 比如,现在有一个任务:背包系统。项目经理把任务会指派给策划。
  2. 策划完成策划案后,交给项目经理确认。
  3. 项目经理在确认之后,再把任务指派给美术和程序,美术和程序此时需要做确认操作(看策划案,理清需求。美术会在这个时候拆分任务,估计时间。程序暂时只是了解一下,等到美术出图再做任务拆分和时间估计)。
  4. 美术绘图拆图完成后,把图片上传到svn的某个位置。交给项目经理确认。
  5. 项目经理确认后,美术把任务指派给程序。程序确认策划案和图片资源后,开工。
  6. 程序完成后,先给美术确认。美术确认后,交给策划确认(策划还负责测试工作)
  7. 策划确认后,项目经理关闭任务。

不知道同事做了什么。

以后要写任务日志了。而且要及时的把已经完成的任务关闭。

通过禅道,每个人都要记录下自己在做某个任务的时候,做了什么,以及耗时,预计剩余时间。

时间粒度最好在0.5小时到2小时之间。比如:背包界面的日志如下:

  • 开始做背包界面 预计剩余耗时: 10小时
  • 界面UI摆放及按钮事件的相应 耗时:2小时 预计剩余耗时: 8小时
  • 背包中单个物品(图标,等级、数量、品质、名字的显示) 耗时: 2小时 预计剩余耗时: 6小时
  • 背包右侧滑块的实现(滑块大小的调整已经位置同步)(滑块用于提示背包滚动的百分比) 耗时:2小时 预计剩余耗时 4小时
  • fix bug : 触摸机制导致点在物品上时不能滑动背包,只有点在物品间空隙位置时才能滑动背包(已解决) 耗时:1小时 预计剩余耗时 4小时
  • 背包中单个物品(装备满级标志,装备碎片标志,已装备的表示的显示) 耗时: 1小时
  • 背包界面以实现,实际耗时8小时

弃用qq,改用rtx(qq太多干扰的信息了,)。虽然通信靠吼是最实时的,但容易打断思路,如果同时正在专注中,用rtx。


测试力度不够,人都是有惰性的。一个迭代是否完成了,需要认真的测试。而不是仅仅看看程序的演示。


ok,上周6下午的讨论大致就是上面4个。

就这样,周一实践了现在。感觉就是,工作效率是蛮高的,气氛也蛮不错。

当然,也有一个负面的情绪。。现在下班后完全不想动脑子了,上班太累了。这个也是自己的问题,以后不要一直坐在那,要多去阳台喝喝水。


说到游戏,我近几个月都在都战斗,所以UI也有点生疏了。之前的UI是用cocosstudio1.6的ui编辑器弄的。我感觉既然需要重新熟悉一遍,还不如就用最新的cocos 2.2.6。

背包系统包括了:

  1. 背包界面(背包里有装备,装备碎片,道具,宝箱,开宝箱的钥匙)
  2. 装备详情,强化,出售
  3. 选择装备界面(用于伙伴选择装备(一个玩家可以有n个伙伴),装备强化也是吃装备的(这个是脑子进水了的))
  4. 装备碎片合成装备
  5. 道具???(突然发现我也不知道道具有那些要做)
  6. 开宝箱(又是一个脑子进水的,要在背包系统里面开宝箱,这明明是宝箱系统的东西)

— 以上写于20150514:周4夜间

周五开会说要在月底之前赶出:商城、新手引导。加上之前的需要重做的背包系统、伙伴系统、主界面、关卡选择。还有那些需要换皮的界面(可以说是所有以前做过的界面、策划说功能没怎么改、可实际情况是、以前的界面都是全屏的、现在是类似弹出的对话框的、都需要重新摆界面)。还有就是暂时被搁置的战斗系统(说是UI太赶,要我先做UI,可,我的战斗系统就没事了吗?)

可以说是一次完整的换皮加添加新功能。程序这边是从5月7号才开始有事做的。也就是说,在我预计需要6-7周的工作,需要在3周内做完。

不要问为什么需要这么久。我们程序虽然有4个,但客户端包括我只有2个程序。还有1个是服务器端。

还有一个是大牛,30岁左右,之前主要做服务器端,是项目经理以前的同事。因为项目赶,上周加入了我们项目。他的C++是很牛逼的。但由于他对cocos2d-x和cocostudio摆UI不熟悉。他能做的也就是管理进度,然后,叫我们加班(比如周六加班啦,平时延长工作时间啦。)。(其实我火了,他竟然扬言晚上会陪我们程序到最后一个人。呵呵,不知道我离公司就20分钟。其实我习惯在公司待到10点,因为公司网速好。但我不是加班,是在弄自己的事。)

好吧,其实我发现了,我们程序这边算是有个头头了。


呵呵,又写了一大堆废话。有部分原因是赶进度真的是身心疲惫。第二个原因是。策划那边严重的混日子。周五我们有个策划正式离职了(公司11个人,他请了我,和另外两个程序吃饭。4个人吃了三百七十多,够可以的了。如果说同事之间是不传递负面情绪的。那我们4个算是朋友吧,有什么不爽都会说的那种。)。项目经理(兼系统策划)在陪产,他老婆就这几天的预产期(不是昨天就是今天了)。还有一个策划,是老板的堂弟,用他的话说,他的工资只有2k多,天天上班玩玩游戏看看游戏直播的。

老板提的需求的改动,策划那边活活从4月初弄到了5月初,美术那边都没赶玩,我们程序这边就更不好开工了。而且很多的交互也提示对话框都没有考虑到。

好了,说了这么多,都是别人的锅。但结果是,要我们背。呵呵,网络是个好东西,可以发泄负面情绪。


正题

背包界面(背包里有装备,装备碎片,道具,宝箱,开宝箱的钥匙)的实现。


界面摆放

先上图,第一张是美术给的效果图

第二张是摆好后的背包界面

下面说说界面摆放的一些技巧。我的习惯是把美术给的效果图直接放在cocos的最底层,然后就可以很方便的对坐标了。如果有某些图片或者控件挡住了效果图的画,我会把他暂时设置为透明度0%。在位置摆好后,再把透明度设置为100%。

接下来是背包的item

ok,UI摆好后,就可以写代码了。


—以上写于20150518:周日夜间(周一凌晨吧)

根据我的习惯,会把界面中的变量剥离处理,我叫他界面model。游戏项目遗留问题我们项目的UI系统是用C++写的。

好了,先定义界面的模型,也就是界面要显示的内容


#ifndef DialogBagModel_h__
#define DialogBagModel_h__#include <vector>
#include <string>
#include <stdint.h>
#include "NodeBagItemModel.h"//背包界面的model
struct DialogBagModel
{//背包列表std::vector<NodeBagItemModel> item_list;//背包上限int capacity_limit;//创建测试数据void createTestData(){capacity_limit = 90;for (int i = 0; i < 20; i++){NodeBagItemModel a;a.gridModel.grid_bg_color = i % 5 + 1;a.gridModel.icon_id = 10001 + i;a.gridModel.level = i+1;a.gridModel.type = NodeBagGridModel::Equip;a.name = "zhuang bei";item_list.push_back(a);}}//从模型层获取数据void crateFromModel();};#endif // DialogBagModel_h__

代码很简单,一个列表,一个上限。还有1个函数用于生成测试数据。

由于项目需要联网获取用户信息,其实是一件比较不利于快速调试的事情。所以,自己生成界面会用到的数据,而不是依赖网络,是一个好的做法。

这样做可以确保如果有问题,可以很容易的分辨是显示的问题还是服务器端数据的问题。


#ifndef DialogBag_h__
#define DialogBag_h__#include "cocos2d.h"
#include "ui/CocosGUI.h"
#include "cocostudio/CocoStudio.h"
USING_NS_CC;
using namespace ui;
using namespace cocostudio;#include <vector>
#include <string>
#include "NodeBagItem.h"
#include "DialogBagModel.h"//背包界面
class DialogBag : public Layer{
public://创建界面CREATE_FUNC(DialogBag);//界面初始化virtual bool init();virtual void onEnter();virtual void onExit();//设置界面显示内容void setupDialogBag(DialogBagModel* model);//绑定cocos文件到程序控件void bindingNode(cocos2d::Node* dialog);void onBtnCallback(Ref *object, Widget::TouchEventType type);//ScrollView滚动事件的回调void onSVCallback(Ref*, ui::ScrollView::EventType type);//ScrollView触摸事件的回调void onSVTouch(Ref *object, Widget::TouchEventType type);//背包中某一个item被点击void onItemClick(int sno, int id);//该函数响应背包内容更新的事件void doUpdateViewEvent(EventCustom* event);virtual ~DialogBag();DialogBag();
private:Button* btn_close;//关闭按钮Button* btn_back;//返回按钮ui::ScrollView* sv;//滚动层ImageView* slider_base;//滑块底部ImageView* slider_bar;//滑块Text* bg_capacity_label;//显示背包容量的文字Vector<NodeBagItem*> item_list;//背包item的列表
private:float slider_bar_min_pos_y;//用于控制滑块的位置float slider_bar_area;//滑块y轴可移动的距离的范围DialogBagModel* model_;EventListenerCustom* bag_updateEventListener;//用于监听背包内容更新
};#endif // DialogBag_h__

上面的头文件就是背包界面的Layer。其实可以把这个界面看成是一个模态对话框,因为他屏蔽了下层的触摸事件。

当然,触摸的屏蔽依靠的是Layout,在cocos中添加一个和屏幕一样大的Layout在界面最底部,就好了。

接下来让我们看看界面初始化。其实没什么内容,就是加载csb文件。

bool DialogBag::init()
{Layer::init();//初始化字段slider_bar_min_pos_y = 0;slider_bar_area = 0;//csb文件位于KouDaiCE D:\temp\ui2\KouDaiCEauto dialog = CSLoader::createNode("DialogBag.csb");bindingNode(dialog);this->addChild(dialog); return true;
}

我在注释中写出类cocos项目的路径,其实是因为我还没有把这个工程放入svn中去。把所有的东西都做好版本管理,是一个好习惯。


void DialogBag::bindingNode(cocos2d::Node* dialog)
{//按钮btn_close = (Button*)dialog->getChildByName("Button_3");btn_back = (Button*)dialog->getChildByName("Button_1");btn_close->addTouchEventListener(CC_CALLBACK_2(DialogBag::onBtnCallback, this));btn_back->addTouchEventListener(CC_CALLBACK_2(DialogBag::onBtnCallback, this));bg_capacity_label = (Text*)dialog->getChildByName("Text_1_0");//滚动层sv = (ScrollView*)dialog->getChildByName("ScrollView_1");sv->addEventListener(CC_CALLBACK_2(DialogBag::onSVCallback, this));sv->addTouchEventListener(CC_CALLBACK_2(DialogBag::onSVTouch, this));//滑块slider_base = (ImageView*)dialog->getChildByName("Image_1");slider_bar = (ImageView*)slider_base->getChildByName("Image_2");
}

绑定控件,这里只需要对你感兴趣的控件进行绑定。最后是在cocos中给控件取一个好名字,而不是"Text_1_0""Button_3"。当然,有时候觉得getChildByName不够智能(有时会把控件放在很深的树形节点中),可以使用Helper::seekWidgetByName,不过,前题是跟节点得是Widget而不是Node。当然,你可以自己写一个seekNodeByName

ok,下面是正题。通过界面model设置界面。这里可能写的比较乱,model_是类的成员函数。由于是个指针,所以需要手动控制他的释放。其实直接传入结构体而不是结构体指针也是可以的,而且会更方便(但是要特别注意,如果一个指针释放了。我可以保证他为NULL,但结构体的话,就会看到一堆乱七八糟的值。所以我还是选择用指针。)

void DialogBag::setupDialogBag(DialogBagModel* model)
{CC_SAFE_DELETE(model_);model_ = model;//设置背包容量的文字---------------------------------------------------------------int capacity = model_->capacity_limit;int size = model_->item_list.size();bg_capacity_label->setString(StringUtils::format("%d/%d", size, capacity));//根据item的数量动态设置其在背包中的位置,已经滚动区域的大小------------------------int width = 792;//滚动层的宽int height = 352;//滚动层的高int padding = 6;//只是为了对坐标,并不是真正的内边距int count_per_row = 6;//每行的个数float row_width = 127+padding;//127是图片btn_daojudibang.pngfloat column_heigth = height / 2;//因为空格子也要显示int max = (capacity > size) ? capacity : size;//计算列数float total_column = ((max - 1) / count_per_row + 1);//计算内容区的高度int container_hight = total_column*column_heigth;container_hight = (container_hight > height) ? container_hight : height;sv->setInnerContainerSize(Size(width, container_hight));//更新item-------------------------------------------------------------------------int old_item_list_size = item_list.size();//默认为0//如果有多余的Item,删除多余的itemif (old_item_list_size>max){for (int idx = old_item_list_size; idx < max;idx--)//倒着删{auto item = item_list.at(idx-1);item->removeFromParent();item_list.popBack();}}//更新或者创建itemfor (int idx = 0; idx < max; idx++){int row = idx % count_per_row;int column = idx / count_per_row;NodeBagItem* item;if (old_item_list_size>idx){//复用这个itemitem = item_list.at(idx);}else{//不够就创建item = NodeBagItem::create();sv->addChild(item);item_list.pushBack(item);}if (idx < size){NodeBagItemModel data = model_->item_list[idx];item->setupNodeBagItem(data);}else if (idx < capacity) //空格子{NodeBagItemModel data;data.createGridNothing();item->setupNodeBagItem(data);}//计算并设置位置int x = padding/2 + row_width * row;int y = padding / 2 + container_hight - (column + 1)*(column_heigth);item->setPosition(x, y);}//计算滑块的大小和位置-------------------------------------------------------------float slider_orign_height = slider_base->getContentSize().height;float slider_bar_height = slider_orign_height*(2.0 / total_column);slider_bar->setContentSize(Size(11, slider_bar_height));this->slider_bar_min_pos_y = slider_bar_height;this->slider_bar_area = slider_orign_height - slider_bar_height;if (slider_bar->getPositionY() < slider_bar_min_pos_y){slider_bar->setPositionY(slider_bar_min_pos_y);}
}

由于考虑到背包的更新(比如装备强化后(装备吃装备然后升等级),其实这个时候背包页面也是存在的,所以需要更新背包内容)。在更新item的时候,如果item存在,则修改显示内容。如果不存在,则创建一个新的。当然,如果有多余,就删了。

还有就要注意cocos2dx的坐标系的原点在左下角。如果想让添加到ScrollViewInnerContainer里的东西显示在最顶端,就要反过来。或者,把他想成是最高的位置。int y = padding / 2 + container_hight - (column + 1)*(column_heigth);

厄,发现贴了好多代码了。其实我最讨厌在网页里看代码,但是,还是继续吧。已经贴了50%了。

//ScrollView滚动事件的回调
void DialogBag::onSVCallback(Ref*, ScrollView::EventType type)
{if (type == ScrollView::EventType::SCROLLING){//根据InnerContainer的滚动更新滑块的位置float current_pos = -sv->getInnerContainer()->getPositionY();float pos_area = sv->getInnerContainerSize().height - sv->getContentSize().height;//由于ScrollView开启了回弹效果,所以他的位置会超出范围,所以需要修正if (current_pos<0){current_pos = 0;}else if (current_pos>pos_area){current_pos = pos_area;}float percent = current_pos / pos_area;//设置滑块的位置if (slider_bar_area != 0){slider_bar->setPositionY(slider_bar_min_pos_y + slider_bar_area*percent);}}
}//ScrollView触摸事件的回调
void DialogBag::onSVTouch(Ref *object, Widget::TouchEventType type)
{//由于按钮的点击事件会屏蔽ScrollView的滚动事件。即点击在按钮上的时候是不能拖动滚动层的。//所以背包中的item并不是button。而是自己实现的点击判定//处理背包中item的点击,模拟按钮的点击效果。if (type == Widget::TouchEventType::ENDED){auto pos = sv->getTouchEndPosition();CCLOG("ended x = %f , y = %f", pos.x, pos.y);auto pos_began = sv->getTouchBeganPosition();float dis = pos.distance(pos_began);for (auto item : item_list){auto btn = item->getBtn();btn->loadTexture("bag/btn_daojudibang.png");//设置所有item为非选中状态if (dis < 10 && btn->hitTest(pos)){//如果移动距离小于10,判断为1次点击操作CCLOG("on click item : sno = %lld , id = %d", item->get_sno(), item->get_id());onItemClick(item->get_sno(), item->get_id());}}}if (type == Widget::TouchEventType::BEGAN){auto pos = sv->getTouchBeganPosition();CCLOG("began x = %f , y = %f", pos.x, pos.y);for (auto item : item_list){auto btn = item->getBtn();if (btn->hitTest(pos)){//设置点中的item为点中状态btn->loadTexture("bag/pressed_daojudibang.png");}}}if (type==Widget::TouchEventType::MOVED){auto pos = sv->getTouchMovePosition();CCLOG("moved x = %f , y = %f", pos.x, pos.y);}
}

ok。一个完整的背包界面就搞定了。

—以上写于20150518:夜间


没想到被cn.cocos2d-x.org给转载了。happy!

其实一个完整的背包还有一大堆肮脏的代码。就一并贴出来吧。首先是和背包项有关的2个类,一个是界面模型,一个是界面。

NodeBagItemModel.h


#ifndef NodeBagItemModel_h__
#define NodeBagItemModel_h__#include <string>
#include <stdint.h>
#include "NodeBagGrid.h"class ModelEquipment;
class ModelProp;//背包中的item的model
struct NodeBagItemModel
{int64_t sno;//装备有唯一序列号,道具为0std::string name;bool is_suipian;bool yi_zhuang_bei;bool isSelect;//用于装备选择界面,理论上应该移到子类中去。NodeBagGridModel gridModel;void createGridNothing();//创建一个空的itemvoid createFromEquipModel(ModelEquipment* item);//根据装备的相关数据创建界面model,从数据model填充界面modelvoid createFromPropModel(ModelProp* item);//根据道具的相关数据创建界面model,从数据model填充界面model//肮脏的代码,由于装备碎片的icon_id是合成后的装备的icon_id,再在左上角加一个碎片的碎。//所以添加了一个多余的字段,用于获取其原始idint debris_id;
};#endif // NodeBagItemModel_h__

哈哈,代码中其实已经有肮脏的使用了拼音的变量了。bool is_碎片bool 已装备。还有bool isSelect,这个变量是用于装备选择界面(而不是背包界面的,背包选择界面中的item会有选中的效果)的。但由于偷懒就没有拆分成2个类。

NodeBagItemModel.cpp


#include "NodeBagItemModel.h"
#include "ModelEquipment.h"
#include "ModelProp.h"void NodeBagItemModel::createGridNothing()
{this->sno = 0;this->name = "";this->isSelect = false;this->yi_zhuang_bei = false;this->is_suipian = false;gridModel.icon_id = -1;gridModel.level = -1;gridModel.grid_bg_color = 1;gridModel.num = 0;gridModel.is_max_level = false;
}void NodeBagItemModel::createFromEquipModel(ModelEquipment* item)
{this->gridModel.type = NodeBagGridModel::Equip;this->gridModel.grid_bg_color = item->getColor();this->gridModel.icon_id = item->getId();this->gridModel.level = item->getLevel();this->sno = item->getSno();this->name = item->getName();if (item->getLevelLimit() == item->getLevel()){this->gridModel.is_max_level = true;}else{this->gridModel.is_max_level = false;}this->yi_zhuang_bei = false;if (item->getEquipPartnerId() > 0){this->yi_zhuang_bei = true;}this->is_suipian = false;
}void NodeBagItemModel::createFromPropModel(ModelProp* item)
{this->gridModel.type = NodeBagGridModel::Other;this->gridModel.grid_bg_color = 1;this->gridModel.icon_id = item->getId();this->gridModel.level = -1;this->sno = 0;this->gridModel.num = item->getNum();this->name = item->getName();this->gridModel.is_max_level = false;this->yi_zhuang_bei = false;this->is_suipian = false;if (item->getType() == ModelProp::EQUIPMENT_DEBRIS){this->is_suipian = true;ModelEquipmentDebrisProp* debris_item = ((ModelEquipmentDebrisProp*)item);this->gridModel.icon_id = debris_item->getTargetId();this->debris_id = item->getId();}
}

cpp中的3个函数都是用于初始化结构体的。第一个是什么都没有的空item(由于有背包上限,所以空格子也要显示。这是策划要求的,但目前背包界面还没有做筛选标签(在筛选标签页里,这些空格子估计是不会显示的)。第二个是装备,第三个是道具(其实我一直不知道道具在程序中怎么说,prop?item?dao_ju?没有一个是没有歧义、让我满意的)。


NodeBagItem就没什么好说的了,根据model设置显示内容。页面是通过CSLoader::createNode("NodeBagItem.csb");加载的。但里面的NodeBagGrid是手动创建的。

NodeBagItem.h


#ifndef NodeBagItem_h__
#define NodeBagItem_h__#include "cocos2d.h"
#include "ui/CocosGUI.h"
#include "cocostudio/CocoStudio.h"
#include "NodeBagGrid.h"
#include "NodeBagItemModel.h"
USING_NS_CC;
using namespace ui;
using namespace cocostudio;//背包中的物品item(长方形),包含NodeBagGrid以及一些额外信息(名字,是否已装备等)
class NodeBagItem : public Node{
public:CREATE_FUNC(NodeBagItem);virtual bool init();void setupNodeBagItem(NodeBagItemModel model);void setSelected(bool isSelected);bool isSelected(){ return isSelected_; }ImageView* getBtn(){ return btn; }int64_t get_sno();int get_id();private:ImageView* btn;NodeBagGrid* grid;Text* name_label;bool isSelected_;Sprite* isSelected_sp;Sprite* sp_debris;Sprite* already_use;
private:NodeBagItemModel view_model;
};#endif // NodeBagItem_h__

NodeBagItem.cpp

include “NodeBagItem.h”

static const std::string text1 = “\xE7\xA9\xBA”;//空

bool NodeBagItem::init()
{
Node::init();

Node* node = CSLoader::createNode("NodeBagItem.csb");this->addChild(node);btn = (ImageView*)node->getChildByName("Image_2");auto center_x = btn->getContentSize().width / 2;
auto center_y = btn->getContentSize().height / 2;grid = NodeBagGrid::create();
btn->addChild(grid);grid->setPosition(Vec2(center_x, center_y + 20));auto position_y_name = 20;name_label = (Text*)node->getChildByName("Text_1");isSelected_sp = Sprite::create("bag/img_xuanzhong.png");
isSelected_sp->setPosition(center_x, center_y);this->addChild(isSelected_sp);setSelected(false);sp_debris = (Sprite*)node->getChildByName("img_flag_suipian_1");
already_use = (Sprite*)node->getChildByName("img_yizhuangbei_2");return true;

}

void NodeBagItem::setupNodeBagItem(NodeBagItemModel model)
{

view_model = model;grid->setupNodeBagGrid(model.gridModel);if (model.name != "")
{name_label->setString(model.name);
}
else{name_label->setString(text1);
}sp_debris->setVisible(model.is_suipian);
already_use->setVisible(model.yi_zhuang_bei);

}

void NodeBagItem::setSelected(bool isSelected)
{
this->isSelected_ = isSelected;

isSelected_sp->setVisible(isSelected);

}

int64_t NodeBagItem::get_sno()
{
return view_model.sno;
}

int NodeBagItem::get_id()
{
int id = view_model.gridModel.icon_id;

//肮脏的代码,由于碎片的icon_id是合成后的装备的icon_id。
//所以添加了一个多余的字段,用于获取其原始id
if (view_model.is_suipian == true)
{id = view_model.debris_id;
}return id;

}


最后给出图标的显示节点代码实现。

NodeBagGrid.h(里面包含了NodeBagGridModel和NodeBagGrid两个类)


#ifndef NodeBagGrid_h__
#define NodeBagGrid_h__#include "cocos2d.h"
#include "ui/CocosGUI.h"
#include "cocostudio/CocoStudio.h"
USING_NS_CC;
using namespace ui;
using namespace cocostudio;struct NodeBagGridModel
{enum ItemType{Equip,//装备,需要显示等级,Other,//包括道具、宝箱和钥匙,需要显示数量};ItemType type;//物品的类型int icon_id;//道具的id,id和图片资源一一对应int level;//如果是装备,显示等级int grid_bg_color;//装备的稀有度通过框框的背景色表示//bool has_jiahao;bool is_max_level;//装备有等级上限,满级会显示max标志int num;//其他类型的物品需要显示数量
};//物品节点(正方形的格子),对应一件道具或装备
class NodeBagGrid : public Node{
public:CREATE_FUNC(NodeBagGrid);virtual bool init();void setupNodeBagGrid(NodeBagGridModel model);protected://Sprite* btn_jia;ImageView* btn;Sprite* equip_icon;Sprite* lv_flag;TextAtlas* lable_level;Sprite* lv_max_flag;
};#endif // NodeBagGrid_h__

NodeBagGridModel是item中的一部分,也在其他的很多界面里用到了,其实这里的命名有问题,他其实更像是一个icon(道具icon,装备icon),而不是叫什么背包格子。

NodeBagGrid.cpp


#include "NodeBagGrid.h"void NodeBagGrid::setupNodeBagGrid(NodeBagGridModel model)
{//如果是装备,装备的品质通过底板背景表示switch (model.grid_bg_color){case 1:btn->loadTexture("common/img_zhuangbeikuang.png");break;case 2:btn->loadTexture("common/img_huang.png");break;case 3:btn->loadTexture("common/img_lv.png");break;case 4:btn->loadTexture("common/img_lang.png");break;case 5:btn->loadTexture("common/img_zi.png");break;default:break;}//默认不显示满级标识lv_max_flag->setVisible(false);if (model.icon_id != -1)//有id说明不是空格子{//设置图标iconauto equip_icon_path = StringUtils::format("icon/big_icon/%d.png", model.icon_id);equip_icon->setTexture(equip_icon_path);if (model.type == NodeBagGridModel::Equip)//装备{//设置等级或者满级标识lv_flag->setVisible(true);lable_level->setVisible(true);lable_level->setString(StringUtils::format("%d", model.level));lv_flag->setPosition(lable_level->getPositionX() - lable_level->getContentSize().width - 15, lable_level->getPositionY());lv_max_flag->setVisible(model.is_max_level);if (model.is_max_level)//注意:满级会设置等级文字为不可见,装备id为-1也会设置为不可见{lv_flag->setVisible(false);lable_level->setVisible(false);}else{lv_flag->setVisible(true);lable_level->setVisible(true);}}else{//道具需要显示数量lv_flag->setVisible(false);lable_level->setVisible(true);lable_level->setString(StringUtils::format("%d", model.num));}}else{//-1为空格子equip_icon->setTexture(nullptr);equip_icon->setTextureRect(Rect::ZERO);lv_flag->setVisible(false);lable_level->setVisible(false);}}bool NodeBagGrid::init()
{Node::init();btn = ImageView::create("common/img_zhuangbeikuang.png");this->addChild(btn);equip_icon = Sprite::create();btn->addChild(equip_icon);equip_icon->setPosition(Vec2(btn->getContentSize().width / 2, btn->getContentSize().height / 2));lv_flag = Sprite::create("bag/img_lv.png");btn->addChild(lv_flag);lv_flag->setPosition(88 + 15, 10 + 5);lable_level = TextAtlas::create("1234567890", "common/img_shuzi01.png", 225 / 15, 19, "+");btn->addChild(lable_level);lable_level->setPosition(Vec2(88 + 15, 10 + 5));lable_level->setAnchorPoint(Vec2(1, 0.5));lv_max_flag = Sprite::create("common/img_Max.png");lv_max_flag->setPosition(lable_level->getPosition());lv_max_flag->setAnchorPoint(Vec2(1, 0.5));btn->addChild(lv_max_flag);return true;
}

— 以上写于20150521:8点


cocos2dx 背包界面的实现相关推荐

  1. Unity MVC设计模式与UI背包界面制作

    Unity MVC设计模式与UI背包界面制作 MVC设计模式非常适合UI的架构,UI界面相当于View,UI转换控制相当于Controller,UI上面的数据变换相当于Model.MVC设计模式在软件 ...

  2. MC仿JAVA版背包界面_我的世界背包编辑器教程

    转自:MCBBS 我的世界背包编辑器MOD教程,希望对大家有所帮助. 教程① 那么我先给大家来一个基本教程 1.如何修改物品名字 修改这个非常容易 你只要修改Item Name:下面这一项就可以了 比 ...

  3. MC仿JAVA版背包界面_Minecraft背包编辑器mod下载大全(1.5.2-1.7.10)

    详细介绍: All--U--Want 让新手们更好地了解一下这个Mod的神奇之处 Mod功能 可以设置某物品无限耐久 调节某物品攻击力 调节物品附魔属性,级别不限 附魔书的修改 药水效果设置 头颅制作 ...

  4. 【HIMI转载推荐之三】基于Cocos2dx引擎UI扩展引擎包[cocos2d-x-3c]

    [前言点评] 此篇主要作者:jason-lee-lijunlin  基于Cocos2d-x引擎进行封装的UI框架的扩展包. 此文章Himi已经仔细看过,总体来说是篇很好的文章,是给使用-x引擎的童鞋们 ...

  5. cocos2dx 讲解

    Cocos2d-x 优点:高效稳定.易用(引擎本身).开源.跨平台 缺点:缺少稳定及功能全面的工具链.上手难 出于对Cocos2d-x引擎的热爱,作者也需要来稍加点评,在优点上不想多做评论,正是因为它 ...

  6. 一个cocos2dx的扩展库

    版本管理及下载列表 Download CocosBase-2.2beta-3c.zip     http://pan.baidu.com/s/1kTfXoWJ CocosBase-2.2.1beta- ...

  7. VS2010下安装Cocos2dx完整教程(原)

    一.本人所使用的Cocos2dx版本(cocos2d-2.1rc0-x-2.1.3),下载地址:http://code.google.com/p/cocos2d-x/downloads/list 当前 ...

  8. 拆解任天堂教科书般的界面动效设计

    我们今天来说一说游戏<集合啦!动物森友会>里的动效. 一般来说,一款游戏的界面动效的根本存在意义主要是这几个方面: 第一,反馈.指的是玩家对界面进行操作之后,界面的反应.简单到一个按钮的点 ...

  9. 2022年小游戏----游戏背包系统之自定义填充背包和切换背包页面

    文章目录 蓝图展示 UI_Main_Bag蓝图 UI_Main_Bag_Item蓝图 创建数据结构和数据表 创建数据结构 引用结构创建数据表 编辑UI_Main_Bag_Item图表 使用标签获取数据 ...

最新文章

  1. python读取大文件csv内存溢出_Python,内存错误,csv文件太大
  2. html 内嵌xml数据库,在SQLite数据库中存储XML/HTML文件 - 可能吗?
  3. LAMP构架概述及相关服务的搭建(附带搭建论坛实验)
  4. 周长相等的正方形面积一定相等_万萍:画图研究图形与几何问题—怎样围面积更大(四下)...
  5. where嵌套select_Select子查询:Select Zoo
  6. vs2010 “最近使用的项目”为空?解决办法!
  7. html图片下方会有一像素,div里嵌套了img底部会有白块问题和图片一像素问题解决 - Macchiato...
  8. 稀疏矩阵的加,减,乘,转置
  9. 绕开“陷阱“,阿里专家带你深入理解C++对象模型的特殊之处
  10. 【Lintcode】541. Zigzag Iterator II
  11. OpenBmc开发9:dts简介与使用
  12. 怎么把qlv格式转成mp4
  13. matlab 如何使用虚数,编程高手帮我解决下怎么用matlab解含有虚数的微分方程组...
  14. 零基础如何学习SEO网站优化
  15. Eclipse官网查找历史版本Eclipse
  16. kali 中 MongoDB安装
  17. java 这么获取农历_用JAVA查询中国农历年
  18. oracle_sql性能优化
  19. Parallels Desktop2023最新版免费虚拟机软件
  20. 模板第一次总结--语法

热门文章

  1. 两数之和Ⅳ - 输入 BST
  2. 奥比中光 Astra pro 深度相机在ROS Melodic的调试
  3. Exception获取getMessage()为空
  4. ceph kernel rbd (一): 简介
  5. WORD注脚短横线的删除方法
  6. 生物大分子的计算机模拟就业,生物大分子体系结合自由能及构象变化的计算机模拟...
  7. vue项目在ie9中碰到的问题——axios请求拒绝访问
  8. OSChina 周二乱弹 ——找老婆身材重要还是脸蛋重要
  9. 终端报错PTY allocation request failed on channel 0
  10. 防洪决策指挥系统(Axure高保真原型)