专职C++

不能停止的脚步

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  163 Posts :: 7 Stories :: 135 Comments :: 0 Trackbacks

常用链接

留言簿(28)

我参与的团队

搜索

  •  

最新评论

阅读排行榜

评论排行榜

#

本文地址:http://www.cppblog.com/zdhsoft/archive/2014/07/19/207715.html
笔记汇总:http://www.cppblog.com/zdhsoft/archive/2014/07/15/207659.html
cocos2dx不仅是有框架,还提供了一个编辑器,可以对动画、UI、骨骼动画和场景编辑的功能。
使用这些工具,大大缩短了用cocos2dx开发周期。但总的来说,操作并不是很方便,但是有总比没有强!
下载地址:http://cn.cocos2d-x.org/download/ 现在MAC的版本也出来了。
下图是界面


然后启动,新建一个项目


这样就完成项目的创建。
在编辑之前,需要先给项目提供资源,一种是把资源拖到右边的资源列表或都在资源列表打开选择资源对话框。


插入结果
其它资源依此类推。
项目创建会默认创建一个画布和一个容器panel

在正式编辑UI之前,需要先设置画面大小,这个跟据你项目的要求设置。

下面在画面中,填加一个图片。很不幸,你不能从资源列表直接拖到中间的画布上只,只能在画布或对象列表使用右键,弹出右键菜单,添加图片对象。


然后,用鼠标选这个对象。在画面的右边,会有一个对象的属性面板。

属性面版有尺寸和模式、常规、控件布局、特性。大家可以尝试设置,就知道他的作用了。添加完成后,把具体的图片资源拖到属性面版->特性->文件框内,就可以了。

结果

这样就OK了
在属性面板有一个Tag属性和名子属性要注意一下,我面在加载UI后,可以通过这两个属性取得UI中的这个对象。
可能调整渲染层级达到调整显示次序的效果。
按照上面的步骤,就可以很快的做出UI了。
做完后,就需要导出UI了,cocos2dx是不能直接使用UI工程的,需要使用导出的。


在导出资源这块,要注意一下,使用大图,会把用到的资源拼成一个大图,可以提高效率。使用小图,则把资源的图原样复制过去。这个看你的取舍了。
导出完成后,把导出的目录复制到cocos2dx工程的Resource这个目录下面,就可以在项目中使用了。

最后在需要使用这个UI的场景,增加下面代码

        gui::TouchGroup* ul = gui::TouchGroup::create();
        ul->addWidget(GUIReader::shareReader()->widgetFromJsonFile("NewUi_1/NewUi_1.ExportJson"));
        this->addChild(ul, 2);
如果要访问这个资源,就可以通过tag来操作。 ul->getWidgetByTag(42)。注意不是ui->getChildByTag(42),这个不会遍历所有的子节点。 !这样就完成一个完全的UI操作!
posted @ 2014-07-19 12:28 冬瓜 阅读(5904) | 评论 (0)编辑 收藏

     摘要: 今年7月以来,终于完全投入到cocos2dx手机项目开发了。真是不容易啊。在这之前,做了很多尝试cocos的各种版本。cocos2dx 2.2.2,quick cocos2dx 2.2.4,cocos2dx 2.2.5,cocos2dx.3.0,cocos2dx 3.1,最终,决定还是使用2.2.2这个版本,我的大多数例子也是基于这个版本的,其它的或多或少总有些问题。特别是这次cocos2dx 2.2.5发布,问题也比较大,作者有些随意了。随机项目中进展,我会把项目遇到的问题,会以笔记的方式列出来,为什么:为我以为再次遇到问题可以快速度解决。  阅读全文
posted @ 2014-07-15 23:37 冬瓜 阅读(2509) | 评论 (2)编辑 收藏

cocos2dx有一个编辑器:cocostudio,目前来说,已经是比较好用了,只要加载导出的资源,就可以用上了。省去手动搭建面的麻烦。但是,很多需要事件的地方,操作比较麻烦,所以这里提供一个事件管理器来集中和简化管理事件。对于C++事件委托方面,我这里使用了是FastDelegate(注:一个牛人写的)。下面是具体实现的代理,不多。

/*
    UI触摸事件管理器。
    原有cocos2dx带的触摸事件,每次监听要操作的步骤比较多,为此增加了一个事件管理器,来集中和简化管理
*/
#ifndef _X_TOUCH_EVENT_MANAGER_H_
#define _X_TOUCH_EVENT_MANAGER_H_
#include <cocos2d.h>
#include <cocos-ext.h>
#include <FastDelegate.h>
#include <xmap.h>
#include <xlog.h>
namespace zdh
{
    USING_NS_CC;
    USING_NS_CC_EXT;
    class XTouchEventManager : public CCObject
    {
    public:
        //绑定的事件定义
        typedef fastdelegate::FastDelegate<void(gui::Widget *, gui::TouchEventType)> TTouchEvent;
    
        typedef int TagID_t;
        //一个Tag的触模事件结构,包括了四个事件
        struct STagEvent
        {
            TTouchEvent EventBegin;
            TTouchEvent EventMoved;
            TTouchEvent EventEnded;
            TTouchEvent EventCanceled;

            TTouchEvent * getByType(gui::TouchEventType paramType)
            {
                switch (paramType)
                {
                case gui::TOUCH_EVENT_BEGAN:
                    return &EventBegin;
                case gui::TOUCH_EVENT_MOVED:
                    return &EventMoved;
                case gui::TOUCH_EVENT_ENDED:
                    return &EventEnded;
                case gui::TOUCH_EVENT_CANCELED:
                    return &EventCanceled;
                }
                return nullptr;
            }
            //判断事件是不是都是为空
            bool isAllEmpty() const
            {
                return EventBegin.empty()
                    && EventEnded.empty()
                    && EventMoved.empty()
                    && EventCanceled.empty();
            }
        };
        //Tag事件映射表,可以换用std::map
        typedef XMap<TagID_t, STagEvent> TEventMap;
    public:
        XTouchEventManager()
            :m_UI(nullptr)
        {}

        static XTouchEventManager * create()
        {
            XTouchEventManager * pRet = new XTouchEventManager();
            pRet->autorelease();
            return pRet;
        }
        //property
        void setUI(gui::TouchGroup * paramUI)
        {
            m_UI = paramUI;
        }
        gui::TouchGroup * getUI()
        {
            return m_UI;
        }
        //绑定一个指定Tag和事件类型的事件
        TTouchEvent * Bind(TagID_t paramTagID, gui::TouchEventType paramType)
        {
            if (!(paramType == gui::TOUCH_EVENT_BEGAN
                || paramType == gui::TOUCH_EVENT_CANCELED
                || paramType == gui::TOUCH_EVENT_ENDED
                || paramType == gui::TOUCH_EVENT_MOVED))  return nullptr;

            int iIndex = m_Map.getIndexBykey(paramTagID);
            if (m_Map.isValidIndex(iIndex))
            {
                return m_Map.getValue(iIndex).getByType(paramType);
            }
            else
            {
                gui::Widget * pWidget = GetNodeByTag(paramTagID);
                if (isNULL(pWidget)) return nullptr;
                pWidget->addTouchEventListener(this, gui::SEL_TouchEvent(&XTouchEventManager::OnUITouch));
                return m_Map[paramTagID].getByType(paramType);
            }
        }

        //移除指定Tag和事件类型的侦听
        void RemoveListen(TagID_t paramTagID, gui::TouchEventType paramType)
        {
            if (!(paramType == gui::TOUCH_EVENT_BEGAN
                || paramType == gui::TOUCH_EVENT_CANCELED
                || paramType == gui::TOUCH_EVENT_ENDED
                || paramType == gui::TOUCH_EVENT_MOVED))  return;
            int iIndex = m_Map.getIndexBykey(paramTagID);
            if (m_Map.isValidIndex(iIndex))
            {
                auto pV = m_Map.getValue(iIndex);
                pV.getByType(paramType)->clear();
                if (pV.isAllEmpty())  //如果这个Tag完全没有事件侦听,那么就清除这个Tag的侦听
                {
                    RemoveListen(paramTagID);
                }
            }
        }
        //移除指定Tag的侦听
        void RemoveListen(TagID_t paramTagID)
        {
            gui::Widget * pWidget = GetNodeByTag(paramTagID);
            if (isNotNULL(pWidget))
            {
                pWidget->addTouchEventListener(nullptr, nullptr);
            }
            m_Map.RemoveByKey(paramTagID);
        }

    private:
        //当UI被侦听的事件,被触发
        void OnUITouch(CCObject* paramSender, gui::TouchEventType paramType)
        {
            gui::Widget * pUIControl = dynamic_cast<gui::Widget *>(paramSender);
            if (isNULL(pUIControl)) return;

            TagID_t tagID = pUIControl->getTag();
            STREAM_INFO << "Sender Tag=" << tagID << ", paramType=" << paramType;

            int iIndex = m_Map.getIndexBykey(tagID);
            if (m_Map.isValidIndex(iIndex))
            {
                auto pV = m_Map.getValue(iIndex);
                auto pEvent = pV.getByType(paramType);
                if (isNotNULL(pEvent) && (!pEvent->empty()))
                {
                    (*pEvent)(pUIControl, paramType); //调用事件
                }
            }
        }
        //取UI中指定Tag的widget对象
        gui::Widget * GetNodeByTag(TagID_t paramTag)
        {
            if (isNULL(m_UI)) return nullptr;
            return m_UI->getWidgetByTag(paramTag);
        }

    private:
        gui::TouchGroup * m_UI;        //用Cocostudio UI编辑器,然后导入生成的UI对象
        TEventMap m_Map;            //事件侦听映射表
    };
}
#endif

使用例子:在Init函数

m_EventManager = XTouchEventManager::create();  
m_EventManager->retain();  
  
gui::TouchGroup* ul = gui::TouchGroup::create();  
ul->addWidget(GUIReader::shareReader()->widgetFromJsonFile("MainUI_1.ExportJson"));  
this->addChild(ul, 2);  
  
m_EventManager->setUI(m_MainUI);  

最后,事件绑定:

m_EventManager->Bind(ET_BUTTON_EXIT, gui::TOUCH_EVENT_ENDED)->bind(this, &XSceneMain::OnExit);  
m_EventManager->Bind(ET_BUTTON_SAVE, gui::TOUCH_EVENT_ENDED)->bind(this, &XSceneMain::OnSave);  

事件的定义:

void XSceneMain::OnExit(gui::Widget * paramSender, gui::TouchEventType paramType)  
{  
    STREAM_INFO << "OnExit";  
}  
void XSceneMain::OnSave(gui::Widget * paramSender, gui::TouchEventType paramType)  
{  
    STREAM_INFO << "OnSave";  
}  

依赖的代码参考:我的开发代码   

posted @ 2014-07-15 15:58 冬瓜 阅读(2817) | 评论 (0)编辑 收藏

quick-cocos2d-x 的中文站是http://quick.cocoachina.com/?page_id=40,用他们自己的话说:quick-cocos2d-x(后文简称 quick)与 cocos2d-x 的关系,用一句话概括:quick 是 cocos2d-x 针对 Lua 的豪华套装威力加强版。
这里是他的介绍:http://quick.cocoachina.com/?p=1
在我试用2.2.4的时候,2.2.5发布了,目前quick也是非常活跃。
首先、按他们的文章:《设置 quick-cocos2d-x 在 Windows 下的编译环境》 http://quick.cocoachina.com/?p=253 部署好,写的很清楚了,照着做就可以了。
其次、就可以创建项目了,我这里是把quick解压到了G:\cocos2dx\quickx,然在G:\cocos2dx\quickx\bin下面,就可以看到create_project.bat,然后我们在dos命令
提示符下面输入create_project -p com.my.test 然后它就会在G:\cocos2dx\quickx\bin下面创建一个test目录(如果只有包名的情况下,它会以最后一个包名做的项目的名称)
这样我们就创建了一个项目。
第三、用Vs编译
vs的工程在G:\cocos2dx\quickx\bin\test\proj.win32下面,打开test.sln就可以了。
然后编译,就可以显示,如下图所示hello world

第四、用player运行
在G:\cocos2dx\quickx\player\win有一个player
它用可以运行你的lua工程,下如图打开你的工程,



就可以立即看到你的运行结果了。
你可以直接用文本编辑器或其它编辑你的lua文件,保存后,在player按F5就可以立即看到你修改后的运行结果。(不用编译,就是爽)
posted @ 2014-07-12 14:24 冬瓜 阅读(2274) | 评论 (1)编辑 收藏

基于cocos2dx 2.2.2版本。这几天使用了cocostudio实现了,动画,骨骼动画,UI编辑,粒子效果,虽然有些不足,但已经算是非常好了。今天尝试用lua,这个非常简单,创建的时候,设置语言为lua,那就可以创建lua工程。
在cocos2d-x-2.2.2\tools\project-creator下运行:
python create_project.py -project test_lua -package com.android.zdhsoft -language lua
xcopy ..\..\cocos2dx\platform\android\java\src\* ..\..\projects\test_lua\proj.android\src /E
就可以创建test_lua,就可以顺利跑起来。
但是我有些代码是C++的,想到在lua下用,感觉得用cocos2dx自带的tolua++,会影响现有的Cocos2dx框架,也可能带来潜在的风险。(除了,bug,我一般不乐意修改框架的东西)。而且需要手动绑定的也不多。于是找了几个开源的绑定框架。有luabind,luatinker,ELuna,luabridge,等。luabind需要boost库,这个太头痛了,luatinker,eluna在试用过程都有些问题(有一个不支持派生类和模板),虽然这两个是最简单的,但是功能也弱了些。最后,用luabridge顺利解决,使用起来也非常简单。
下面是下载地址:https://github.com/vinniefalco/LuaBridge
个版本已经支持lua 5.1.5,不过不支持C++0x11,例子很丰富。这里有很多例子,http://vinniefalco.com/LuaBridge/Manual.html
载后,直接解压,把LuaBridge.h,RefCountedObject.h,RefCountedPtr.h和detail下的所有头文件,全部复制到classes目录,然后在AppDelegate包含luabrigde.h就可以了。
下面是一个用于测试的类
class testA
{
public:
    testA()
    {

    }
    int getValue()
    {
        return 100;
    }
};
下面是绑定代码
    luabridge::getGlobalNamespace(pEngine->getLuaStack()->getLuaState())
        .beginClass<testA>("testA")
        .addConstructor<void(*) ()>()
        .addFunction("getValue", &testA::getValue)
        .endClass();
然后,就可以在你的lua代码使用这个类了。
    local testa = testA ()
    cclog("testa=%d", testa:getValue()) 
现在cocos2dx上面,现在出现了两个重要的lua分支, 一个是quickx,一个cocos-code-ide。quickx提供了一个非常强大的lua框架,让你写lua省心省力。而cocos ide则基于eclipse提供了一个x-man的编辑器,支持lua和js调试。这让C++情何以堪啊!
posted @ 2014-07-09 20:06 冬瓜 阅读(1853) | 评论 (0)编辑 收藏

cocos2dx框架已经提供了很多场景切换的类,但是一些自定义的场景切换,只有自己实现了。下面是实现的类。这里设计的分辨率是750*500.请根据实际的要求调整。
头文件
#ifndef _TRANSITION_GAME_H_
#define _TRANSITION_GAME_H_
#include <cocos2d.h>
namespace cocos2d 
{
    class CCTransitionGame : public CCTransitionScene
    {
    public:
        CCTransitionGame();
        virtual ~CCTransitionGame();
        void onEnter();
        static CCTransitionGame * create(float t, CCScene *scene);
    private:
        void LRFinish(void);
        void OnFirstActionFinish(void);
    private:
        int m_FinishCnt;
    };
}
#endif
源文件
#include "TransitionGame.h"
#include "xlog.h"
#include <xstring.h>
namespace cocos2d
{
    using namespace zdh;
    CCTransitionGame * CCTransitionGame::create(float t, CCScene *scene)
    {
        CCTransitionGame * pScene = new CCTransitionGame();
        if (pScene && pScene->initWithDuration(t, scene))
        {
            pScene->autorelease();
            return pScene;
        }
        CC_SAFE_DELETE(pScene);
        return NULL;
    }

    CCTransitionGame::CCTransitionGame()
    {
        m_FinishCnt = 0;
    }

    CCTransitionGame::~CCTransitionGame()
    {
    }

    void CCTransitionGame::onEnter()
    {
        CCTransitionScene::onEnter();
        CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();


        CCPoint stLeftBegin, stLeftEnd, stRightBegin, stRightEnd;
        //设置左边的起点和终点
        stLeftBegin.setPoint(-436.0f, -60);
        stLeftEnd.setPoint(visibleSize.width / 2.0f + stLeftBegin.x, -60.0f);
        //设置右边的起点和终点
        stRightBegin.setPoint(visibleSize.width, -60.0f);
        stRightEnd.setPoint(visibleSize.width / 2.0f, -60.0f);
        //加载动画序列
        CCSpriteFrameCache* pCache = CCSpriteFrameCache::sharedSpriteFrameCache();
        pCache->addSpriteFramesWithFile("middle_ani_1.plist");
        pCache->addSpriteFramesWithFile("middle_ani_2.plist");
        //生成画动图片列表和动画对象
        CCArray* pAnimFrames = CCArray::createWithCapacity(69);
        XAnsiString strAniName;
        for (int i = 1; i < 70; i++)
        {
            strAniName.printf("light%04d.png", i);
            pAnimFrames->addObject(pCache->spriteFrameByName(strAniName.c_str()));
        }
        CCAnimation* animation = CCAnimation::createWithSpriteFrames(pAnimFrames, this->m_fDuration * 2.0f/3.0f/69.0f );
        

        CCNode * pNode = CCNode::create(); //这个有两个子节点,一个是左边交换图片,一个是中间的动画,用于一起做移动的Action
        CCSprite* pLeft = CCSprite::createWithSpriteFrameName("swap_left.png");
        pLeft->setAnchorPoint(CCPointZero);
        pNode->addChild(pLeft);

        CCSprite * pMiddle = CCSprite::create();  //显示动画
        pMiddle->setAnchorPoint(CCPointZero);
        pMiddle->setPosition(ccp(436.0f - 69.0f, 250.0f + 60.0f - 72.0f));
        pMiddle->runAction(CCAnimate::create(animation));
        pNode->addChild(pMiddle);

        pNode->setAnchorPoint(ccp(0,0));
        pNode->setPosition(stLeftBegin);
        this->addChild(pNode,1);

        //右边的交换图片
        CCSprite* pRight = CCSprite::createWithSpriteFrameName("swap_right.png");
        pRight->setPosition(stRightBegin);
        pRight->setAnchorPoint(CCPointZero);
        this->addChild(pRight, 0);

        //定义动作
        
//左边的向右移动活动
        CCMoveTo* pActionLeft = CCMoveTo::create(m_fDuration / 3, stLeftEnd);
        //右边的向左移动活动
        CCMoveTo * pActionRight = CCMoveTo::create(m_fDuration / 3, stRightEnd);
        //原地不动
        CCMoveTo* pActionLeft1 = CCMoveTo::create(m_fDuration / 3, stLeftEnd);
        CCMoveTo * pActionRight1 = CCMoveTo::create(m_fDuration / 3, stRightEnd);
        
        CCMoveTo* pActionLeft2 = CCMoveTo::create(m_fDuration / 3, stLeftBegin);
        CCMoveTo * pActionRight2 = CCMoveTo::create(m_fDuration / 3, stRightBegin);

        m_FinishCnt = 0;
        pNode->runAction(CCSequence::create(pActionLeft, CCCallFunc::create(this, callfunc_selector(CCTransitionGame::OnFirstActionFinish)), pActionLeft1, pActionLeft2, CCCallFunc::create(this, callfunc_selector(CCTransitionGame::LRFinish)), NULL));
        pRight->runAction(CCSequence::create(pActionRight, pActionRight1,pActionRight2, CCCallFunc::create(this, callfunc_selector(CCTransitionGame::LRFinish)), NULL));
    }

    void CCTransitionGame::LRFinish(void)
    {
        //所以的活动完成后,要执行场行的Finish
        m_FinishCnt++;
        if (m_FinishCnt >= 2)
        {
            CCTransitionScene::finish();
        }
    }

    void CCTransitionGame::OnFirstActionFinish(void)
    {
        //打开门之前,关闭显示第一个场景,显示第二个场景
        m_pInScene->setVisible(true);
        m_pOutScene->setVisible(false);
    }

}
用到的资源
/Files/zdhsoft/plist.zip 效果图:
posted @ 2014-07-01 20:12 冬瓜 阅读(2124) | 评论 (0)编辑 收藏

     摘要: 在cocos2dx 2.2.2版本中,cocos使用的是CLOG写入日期,其格式是C的Printf方式生成日志。现在也有很多C++流式日志,类似于cout这样的操作。我看了也有很多,log4cxx,等。但是个人移动有些大。我就在我原来的日志中增加了对流式的支持。并顺利移植到cocos2dx环境中使用  阅读全文
posted @ 2014-06-30 15:16 冬瓜 阅读(1189) | 评论 (0)编辑 收藏

     摘要: 在用vs开发cocos2dx过程中,要显示的中文,要求是UTF-8格式的才能正常显示出来,但VS一般是ANSI格式保存,这样,在代码中写入的中文字符串,运行后,显示的就是乱码。
为了正确显示中文,或支持多语言,我这里定义一个简单的字符串管理类,来满足上述要求。  阅读全文
posted @ 2014-06-30 14:59 冬瓜 阅读(1255) | 评论 (0)编辑 收藏

之前我的代码是放到code.google.com上面的,但是最近老有些问题,前些天又发现发现csdn搞了一个git服务器,于是就把代码迁移到这上面来了。地址如下,有喜欢的朋友,可以看看,这些代码,已经在我的很多项目中使用了,当然,还会有不少问题。
下载地址是:https://code.csdn.net/zdhsoft/commonlib/tree/master,git地址是:git@code.csdn.net:zdhsoft/commonlib.git
对于windows的客户端,荐举使用TortoiseGit,为什么用它,因为我之前用的是TortoiseSVN,习惯了。
附:
Git下载地址:https://github.com/msysgit/msysgit/releases/download/Git-1.9.4-preview20140611/Git-1.9.4-preview20140611.exe
TortoiseGit下载地址:http://wzgj.newhua.com/down/TortoiseGit-1.8.9.0-32bit.zip
安装配置过程,大家都知道,我就不说了,很简单。
posted @ 2014-06-27 11:26 冬瓜 阅读(1594) | 评论 (1)编辑 收藏

下面代码是我常用VA的Snippet的片断,做记录,防止丢失
命令函数通用代码
Title:Command Common! 
Shortcut:dwr
    TAnswer & stAns = getAnswer();  
    TRequest & stReq = getRequest();
    error_code_t iRet = ERR_OK;
    CPlayer * pPlayer = gPlayerMaster->getPlayer(getUID());
    do
    {
          if (isNULL(pPlayer))                
           {                                   
               iRet = ERR_LOGIC_PLAYER_IS_NULL;
               break;                          
           }     
           pPlayer->PropertyBeginChange();
        $end$

    }while(false);
    stAns.Result = iRet;          
    gCtrl.AnswerClientCmd(this);  
    if (isNotNULL(pPlayer))               
    {                             
        pPlayer->PropertyEndChange();
    }                             
    return ERR_OK;
通用bool属性代码
Title:is Boolean Property
Shortcut:isb
//-------------------------------------------------------------------------
//property $PropertyName$
bool is$PropertyName$() const
{
    return this->m_$PropertyName$;
}
//--------
void set$PropertyName$(bool param$PropertyName$)
{
    this->m_$PropertyName$ = param$PropertyName$;
}
通用基本数据属性代码
Title:base data property
Shortcut:bp
//-------------------------------------------------------------------------
//property $PropertyName$
$PropertyType$ get$PropertyName$() const
{
    return this->m_$PropertyName$;
}
//--------
void set$PropertyName$($PropertyType$ param$PropertyName$)
{
    this->m_$PropertyName$ = param$PropertyName$;
}
通用对象属性代码
Title:object data property
Shortcut:op
//-------------------------------------------------------------------------
//property $PropertyName$
const $PropertyType$ & get$PropertyName$() const
{
    return this->m_$PropertyName$;
}
//--------
void set$PropertyName$(const $PropertyType$ & param$PropertyName$)
{
    this->m_$PropertyName$ = param$PropertyName$;
}
posted @ 2014-06-27 10:09 冬瓜 阅读(1657) | 评论 (0)编辑 收藏

仅列出标题
共17页: First 4 5 6 7 8 9 10 11 12 Last