2个月写了一款游戏,然后对底层做了一些修改更符合RPG的游戏吧

首先对UI的部分调整
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//ui部分的修改文件
1.widget的clk的判断方式,move的时候如果已经判定为nohighlight就应该不要再次进入highlight状态
void Widget::onTouchMoved(Touch *touch, Event *unusedEvent)
{

//点击中的状态移动的时候才判断,如果已经点击不中就不要响应后面的
if (_highlight)
setHighlighted(hitTest(_touchMovePosition, _hittedByCamera, nullptr));

}

2.checkbox点击方式修改(如果cancel掉就不应该触发点击,也不应该改变select的状态)
void CheckBox::onTouchEnded(Touch *touch, Event *unusedEvent)
{
if (_highlight)
{
if (_isSelected)
{
setSelected(false);
AbstractCheckButton::onTouchEnded(touch, unusedEvent);
dispatchSelectChangedEvent(false);
}
else
{
setSelected(true);
AbstractCheckButton::onTouchEnded(touch, unusedEvent);
dispatchSelectChangedEvent(true);
}
}
else
{
AbstractCheckButton::onTouchEnded(touch, unusedEvent);
}
}

3.UIScrollView支持fix方式,就是从顶部插入也不会移动特别使用用聊天框锁定(默认是底部插入不移动)
void SetFixInnerPosition(bool bFix){ m_bFixInnerPosition = bFix; }
void ScrollView::setInnerContainerSize(const Size &size)
{

if (!m_bFixInnerPosition)
{
// move children appropriately
{
Size newInnerSize = _innerContainer->getContentSize();
float offsetY = originalInnerSize.height - newInnerSize.height;
float offsetX = 0;
if (_innerContainer->getRightBoundary() <= _contentSize.width)
{
offsetX = originalInnerSize.width - newInnerSize.width;
}
if (offsetX != 0 || offsetY != 0)
{
Vec2 position = _innerContainer->getPosition() + Vec2(offsetX, offsetY);
setInnerContainerPosition(position);
}
}
}

}

4.UIListView改动的最多,这边只列出部分修改,事件增加改变item的消息(主要是解决选中item和非选中item展示的问题),事件增加点击位置
typedef enum
{
LISTVIEW_ONSELECTEDITEM_START,
LISTVIEW_ONSELECTEDITEM_END,
LISTVIEW_ONSELECTEDITEM_CHANGEITEM,
}ListViewEventType;
enum class EventType
{
ON_SELECTED_ITEM_START,
ON_SELECTED_ITEM_END,
ON_SELECTED_ITEM_CHANGE,
};

typedef std::function<void(Ref*, EventType, Touch*)> ccListViewCallback;

void selectedItemEvent(TouchEventType event, Widget sender, Touch pTouch);
void ListView::selectedItemEvent(TouchEventType event, Widget sender, Touch pTouch)
{
this->retain();
switch (event)
{
case TouchEventType::BEGAN:
{
if (_listViewEventListener && _listViewEventSelector)
{
(_listViewEventListener->_listViewEventSelector)(this, LISTVIEW_ONSELECTEDITEM_START);
}
if (_eventCallback) {
_eventCallback(this, EventType::ON_SELECTED_ITEM_START, pTouch);
}
if (_ccEventCallback)
{
_ccEventCallback(this, static_cast(EventType::ON_SELECTED_ITEM_START));
}
}
break;
default:
{
if (_listViewEventListener && _listViewEventSelector)
{
(_listViewEventListener->
_listViewEventSelector)(this, LISTVIEW_ONSELECTEDITEM_END);
}
if (_eventCallback) {
_eventCallback(this, EventType::ON_SELECTED_ITEM_END, pTouch);
}
if (_ccEventCallback)
{
_ccEventCallback(this, static_cast(EventType::ON_SELECTED_ITEM_END));
}
//end发完计算
if (event == TouchEventType::ENDED)
{
//只有ended才选定是哪个,begin只是显示高亮
Widget* parent = sender;

        while (parent)
        {
            if (parent && (parent->getParent() == _innerContainer))
            {
                _curSelectedIndex = getIndex(parent);
                break;
            }
            parent = dynamic_cast<Widget*>(parent->getParent());
        }
    }
    if (_listViewEventListener && _listViewEventSelector)
    {
        (_listViewEventListener->*_listViewEventSelector)(this, LISTVIEW_ONSELECTEDITEM_CHANGEITEM);
    }
    if (_eventCallback) {
        _eventCallback(this, EventType::ON_SELECTED_ITEM_CHANGE, pTouch);
    }
    if (_ccEventCallback)
    {
        _ccEventCallback(this, static_cast<int>(EventType::ON_SELECTED_ITEM_CHANGE));
    }
}
break;
}
this->release();

}
void ListView::interceptTouchEvent(TouchEventType event, Widget sender, Touch touch)
{
ScrollView::interceptTouchEvent(event, sender, touch);
if (!_touchEnabled)
{
return;
}
if (event != TouchEventType::MOVED)
{
if (sender->isHighlighted()) {
selectedItemEvent(event, sender, touch);
}
}
}

5.UIListView根据位置获取index的计算方式(我觉得是个bug,上面的修改+这个修改为后续动态加载和显示listview做基础)
static Widget* findClosestItem(const Vec2& targetPosition, const Vector<Widget*>& items, const Vec2& itemAnchorPoint, ssize_t firstIndex, float distanceFromFirst, ssize_t lastIndex, float distanceFromLast)
{
CCASSERT(firstIndex >= 0 && lastIndex < items.size() && firstIndex <= lastIndex, “”);
if (firstIndex == lastIndex)
{
return items.at(firstIndex);
}
if (lastIndex - firstIndex == 1)
{
if (fabs(distanceFromFirst) <= fabs(distanceFromLast))
{
return items.at(firstIndex);
}
else
{
return items.at(lastIndex);
}
}

// Binary search
ssize_t midIndex = (firstIndex + lastIndex) / 2;
Vec2 itemPosition = calculateItemPositionWithAnchor(items.at(midIndex), itemAnchorPoint);
float distanceFromMid = itemPosition.y - targetPosition.y;
if (distanceFromMid > 0)
{
    // Right half
    return findClosestItem(targetPosition, items, itemAnchorPoint, midIndex, distanceFromMid, lastIndex, distanceFromLast);
}
else
{
    // Left half
    return findClosestItem(targetPosition, items, itemAnchorPoint, firstIndex, distanceFromFirst, midIndex, distanceFromMid);
}

}

Widget* ListView::getClosestItemToPosition(const Vec2& targetPosition, const Vec2& itemAnchorPoint) const
{
if (_items.empty())
{
return nullptr;
}

// Find the closest item through binary search
ssize_t firstIndex = 0;
Vec2 firstPosition = calculateItemPositionWithAnchor(_items.at(firstIndex), itemAnchorPoint);
float distanceFromFirst = firstPosition.y - targetPosition.y;

ssize_t lastIndex = _items.size() - 1;
Vec2 lastPosition = calculateItemPositionWithAnchor(_items.at(lastIndex), itemAnchorPoint);
float distanceFromLast = lastPosition.y - targetPosition.y;

return findClosestItem(targetPosition, _items, itemAnchorPoint, firstIndex, distanceFromFirst, lastIndex, distanceFromLast);

}
6.Editbox我这边删除了本身的editbox,是使用现在主流游戏的模式点击之后在键盘的上面增加输入,而不是在实际的显示位置,这个可以查看以前别人的文章

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//2d文件
1.node修改支持绘制的顺序设置和添加userrevert信息
(1)Node.h
virtual void setLocalOrderOfArrive(int nArrived);
void AddContentHeight(float fAddHeight);
virtual void reorderChild(Node * child, int localZOrder, int nOrderOfArrival);
void AddUserRevertData(int nKey, Value& data);
ValueMapIntKey& GetUserRevertData(){ return m_mapRevertData; }
ValueMapIntKey m_mapRevertData;

(2)Node.cpp
void Node::setLocalOrderOfArrive(int nArrived)
{
if (_parent)
{
_parent->reorderChild(this, _localZOrder, nArrived);
}
_eventDispatcher->setDirtyForNode(this);
}
void Node::reorderChild(Node child, int zOrder)
{
reorderChild(child, zOrder, s_globalOrderOfArrival++);
}
void Node::reorderChild(Node * child, int zOrder, int nOrderOfArrival)
{
CCASSERT(child != nullptr, “Child must be non-nil”);
_reorderChildDirty = true;
child->setOrderOfArrival(nOrderOfArrival);
child->_localZOrder = zOrder;
}
void Node::AddUserRevertData(int nKey, const char
pData)
{
m_mapRevertData = pData;
}
void Node::AddUserRevertData(int nKey, Value& data)
{
m_mapRevertData = data;
}

2.spriteframecache支持永不释放
CCSpriteFrameCache.h
struct SpriteFrameValue
{
bool m_bInit;
std::string m_strTextureName;
cocos2d::Vector<SpriteFrame*> m_vtFrame;
SpriteFrameValue()
{
m_bInit = false;
}
//判断是否已经初始化
bool IsInit(){ return m_bInit; }
void Init(std::string& strTextureName, cocos2d::Vector<SpriteFrame*>& vtFrame)
{
m_bInit = true;
m_strTextureName = strTextureName;
m_vtFrame = vtFrame;
}
};

class SpriteFrameCacheAlwaysCachePList
{
public:
SpriteFrameCacheAlwaysCachePList();
virtual ~SpriteFrameCacheAlwaysCachePList();

//保存这些节点
SpriteFrameValue* GetSpriteFrameByListName(const std::string& strList);

protected:
std::map<std::string, SpriteFrameValue*> m_mapCache;
};

Texture2D* addSpriteFramesWithFile(const std::string& plist, bool bNoRelease);
CCSpriteFrameCache.cpp
SpriteFrameCacheAlwaysCachePList::SpriteFrameCacheAlwaysCachePList()
{

}

SpriteFrameCacheAlwaysCachePList::~SpriteFrameCacheAlwaysCachePList()
{
for (auto cacheData : m_mapCache)
{
delete cacheData.second;
}
m_mapCache.clear();
}
//保存这些节点
SpriteFrameValue* SpriteFrameCacheAlwaysCachePList::GetSpriteFrameByListName(const std::string& strList)
{
std::map<std::string, SpriteFrameValue*>::iterator iter = m_mapCache.find(strList);
if (iter == m_mapCache.end())
{
SpriteFrameValue* pNewData = new SpriteFrameValue();
m_mapCache = pNewData;
return pNewData;
}
return iter->second;
}

void SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist)
{
addSpriteFramesWithFile(plist, false);
}
Texture2D* SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist, bool bNoRelease)
{

{

if (texture)
{
addSpriteFramesWithDictionary(dict, texture);
_loadedFileNames->insert(plist);

        cocos2d::Vector<SpriteFrame*> vtFrame;
        if (bNoRelease)
        {
            ValueMap& framesDict = dict"frames"].asValueMap();
            for (auto iter = framesDict.begin(); iter != framesDict.end(); ++iter)
            {
                std::string spriteFrameName = iter->first;
                SpriteFrame* pSpriteFrame = getSpriteFrameByName(spriteFrameName);
                if (pSpriteFrame)
                {
                    vtFrame.pushBack(pSpriteFrame);
                }
                else
                {
                    assert(0);
                }
            }
        }
        pCacheFrameValue->Init(texturePath, vtFrame);
        return texture;
    }
    else
    {
        CCLOG("cocos2d: SpriteFrameCache: Couldn't load texture");
    }
}
else
{
    if (pCacheFrameValue->IsInit())
    {
        return Director::getInstance()->getTextureCache()->addImage(pCacheFrameValue->m_strTextureName.c_str());
    }
    else
    {
        assert(0);
    }
}
return NULL;

}

3.FastTMXTiledMap支持从plist加载资源,并且支持45度角的tmx文件
CCFastTMXTiledMap.h
CCFastTMXTiledMap.cpp
CCFastTMXLayer.h
CCFastTMXLayer.cpp
TMXXMLParse.h
TMXXMLParse.cpp
这块有时间我单独开一个

//主要是修正bug
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//3d文件
1.如果3d动画帧数不够就设置为0,不要存在负数导致整个动作永远结束不了
bool Animate3D::init(Animation3D* animation, float fromTime, float duration)
{
float fullDuration = animation->getDuration();
if (duration > fullDuration - fromTime)
duration = fullDuration - fromTime;
if (duration < 0.0f)
duration = 0.0f;
_start = fromTime / fullDuration;
_last = duration / fullDuration;
setDuration(duration);
setOriginInterval(duration);
_animation = animation;
animation->retain();
setQuality(Configuration::getInstance()->getAnimate3DQuality());
return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//base文件
1.custom支持添加到节点上面,这样释放的时候能够统一释放
CCEventDispatcher.h
EventListenerCustom* addCustomEventListenerWithNode(const std::string &eventName, const std::function<void(EventCustom*)>& callback, Node* node);
CCEventDispatcher.cpp
EventListenerCustom* EventDispatcher::addCustomEventListenerWithNode(const std::string &eventName, const std::function<void(EventCustom*)>& callback, Node* node)
{
EventListenerCustom listener = EventListenerCustom::create(eventName, callback);
addEventListenerWithSceneGraphPriority(listener, node);
return listener;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//ActionTimeline文件
1.动作加载的时候必须clone不然无法达到服用的目的
CSLoader.cpp:1035
if (classname == “ProjectNode”)
{

cocostudio::timeline::ActionTimeline
pBindAction = action->clone();
pBindAction->setTimeSpeed(projectNodeOptions->innerActionSpeed());
node->runAction(pBindAction);
pBindAction->gotoFrameAndPause(0);
}
2.csload支持从内存中获取数据
CSLoader.h
//提供绑定函数
void bindFileLoadCacheFunc(const std::function<Data*(const std::string&)>& func);
//提供绑定函数是否从缓存中获取
ccNodeLoadCacheFunc m_func;
CSLoader.cpp
//提供绑定函数
void CSLoader::bindFileLoadCacheFunc(const std::function<Data*(const std::string&)>& func)
{
m_func = func;
}
953行
//首先从func里面获取是否存在
Data* pFindCache = NULL;
Data buf;
if (m_func != nullptr)
{
pFindCache = m_func(fullPath);
}
if (pFindCache)
{
buf = *pFindCache;
}
else
{
CC_ASSERT(FileUtils::getInstance()->isFileExist(fullPath));

buf = FileUtils::getInstance()->getDataFromFile(fullPath);

}
1037行
Data* pTmpBuf = NULL;
Data buf;
if (m_func != NULL)
{
pTmpBuf = m_func(filePath);
}
if (pTmpBuf)
{
buf = *pTmpBuf;
}
else
{
buf = FileUtils::getInstance()->getDataFromFile(filePath);
}

ios的点击问题,主要是用了editbox(我的是在键盘上面显示输入框,如果本身的输入框在底部,弹起的时候有可能子panel在父panel外面,ios下这样子panel是收不到消息的,因此做了修改)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//platform文件
1.ios子panel在父panel外部也支持点击
CCEAGLView-ios.mm:898

  • (UIView*)hitTest : (CGPoint)point withEvent : (UIEvent )event
    {
    UIView
    pView = ;
    if (pView == nil)
    {
    for (UIView* pSubView in self.subviews)
    {
    if (pSubView.userInteractionEnabled)
    {
    CGPoint tp = ;
    if (CGRectContainsPoint(pSubView.bounds, tp))
    {
    pView = ;
    break;
    }
    }
    }
    }
    return pView;
    }

cocos的引擎开发感觉没有和cocos2dx的开发配合起来,比如component的使用,cocos里面应该是用不到update模式的component,但是现在每个节点都要scheduleupdate,导致节点一多效率非常的低

建议在Node.h里面增加ComponentContainer *_componentContainerNoUpdate;///< Dictionary of components
目前cocos里面不管是layout,name还是audio都只是作为容器存在