存档

2013年6月 的存档

使用CCHttpClient进行cocos2d-x网络编程

2013年6月30日 没有评论

    在我使用的cocos2d-x版本(2.1.2)中,已经将curl融进cocos2d-x框架中。下面动手写个简单的网络程序。

   首先创建一个cocos2d-x项目。

    然后我创建了一个网络连接的类,名叫HttpNetConn。其继承自CCObject,管理网络连接的相应功能。

    

/*
 * 网络连接模块
 * NetConnect.h
 * 
 * Created by fansy [2013-6-30]
 */


#ifndef _NET_CONNECTION_H_
#define _NET_CONNECTION_H_

#include <cocos2d.h>

USING_NS_CC;

class NetConnect: public CCObject
{
public:
	CREATE_FUNC(NetConnect);

	virtual bool init();

	void getData();

	void httpReqFinished(CCNode* node,CCObject* obj);

};


#endif

    其中,getData()是向服务器发请求,httpReqFinished是服务器响应的应答。

    好,接下来,动手实现。

    首先,CCHttpClient在extition中,如果你的包含目录和我一样,没有这个,就要在项目属性->c/c++->附加包含目录中添加:$(SolutionDir)/extensions 此项(具体位置可能和我的有些不一样)。并在其NetConnection.cpp的头文件处加上:

#include "cocos-ext.h"
#include "../extensions/network/HttpClient.h"
#include "../extensions/network/HttpRequest.h"

USING_NS_CC_EXT;

    接下来,写getData函数:

void NetConnect::getData()
{
	CCHttpClient* httpClient = CCHttpClient::getInstance();

	CCHttpRequest* httpReq =new CCHttpRequest();

	httpReq->setRequestType(CCHttpRequest::kHttpGet);
	httpReq->setUrl("http://www.baidu.com");
	httpReq->setResponseCallback(this,callfuncND_selector(NetConnect::httpReqFinished));
	httpReq->setTag("FirstNet");
	httpClient->setTimeoutForConnect(30);
	httpClient->send(httpReq);

	httpReq->release();

}

    觉得逻辑很清晰,就不细解释了。然后是回调函数:

void NetConnect::httpReqFinished( CCNode* node,CCObject* obj )
{
	CCHttpResponse* response = (CCHttpResponse*)obj;
	if (!response->isSucceed())
	{
		CCLog("Receive Error! %s/n",response->getErrorBuffer());
		return ; 
	}

	const char* tag = response->getHttpRequest()->getTag();
	if ( 0 == strcmp("FirstNet",tag))
	{
		std::vector<char> *data = response->getResponseData();
		int data_length =  data->size();
		std::string res;
		for (int i = 0;i<data_length;++i)
		{
			res+=(*data)[i];
		}
		res+='/0';
		CCLog("%s",res.c_str());
	}
}

    ok,F7编译。发现缺少库:

1>  NetConnect.cpp
1>NetConnect.obj : error LNK2019: 无法解析的外部符号 "public: static class cocos2d::extension::CCHttpClient * __cdecl cocos2d::extension::CCHttpClient::getInstance(void)" (?getInstance@CCHttpClient@extension@cocos2d@@SAPAV123@XZ),该符号在函数 "public: void __thiscall NetConnect::getData(void)" (?getData@NetConnect@@QAEXXZ) 中被引用
1>NetConnect.obj : error LNK2019: 无法解析的外部符号 "public: void __thiscall cocos2d::extension::CCHttpClient::send(class cocos2d::extension::CCHttpRequest *)" (?send@CCHttpClient@extension@cocos2d@@QAEXPAVCCHttpRequest@23@@Z),该符号在函数 "public: void __thiscall NetConnect::getData(void)" (?getData@NetConnect@@QAEXXZ) 中被引用
1>D:/Code/UseLess/HelloCSDN/Debug.win32/HelloCSDN.win32.exe : fatal error LNK1120: 2 个无法解析的外部命令

   缺少libExtensions.lib库,加上。在项目属性->链接器->附加依赖项中添加:libExtensions.lib。再编译。

    额…似乎还缺:

1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__pthread_create,该符号在函数 "private: bool __thiscall cocos2d::extension::CCHttpClient::lazyInitThreadSemphore(void)" (?lazyInitThreadSemphore@CCHttpClient@extension@cocos2d@@AAE_NXZ) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__pthread_detach,该符号在函数 "private: bool __thiscall cocos2d::extension::CCHttpClient::lazyInitThreadSemphore(void)" (?lazyInitThreadSemphore@CCHttpClient@extension@cocos2d@@AAE_NXZ) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__pthread_exit,该符号在函数 "void * __cdecl cocos2d::extension::networkThread(void *)" (?networkThread@extension@cocos2d@@YAPAXPAX@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__pthread_mutex_init,该符号在函数 "private: bool __thiscall cocos2d::extension::CCHttpClient::lazyInitThreadSemphore(void)" (?lazyInitThreadSemphore@CCHttpClient@extension@cocos2d@@AAE_NXZ) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__pthread_mutex_destroy,该符号在函数 "void * __cdecl cocos2d::extension::networkThread(void *)" (?networkThread@extension@cocos2d@@YAPAXPAX@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__pthread_mutex_lock,该符号在函数 "private: void __thiscall cocos2d::extension::CCHttpClient::dispatchResponseCallbacks(float)" (?dispatchResponseCallbacks@CCHttpClient@extension@cocos2d@@AAEXM@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__pthread_mutex_unlock,该符号在函数 "private: void __thiscall cocos2d::extension::CCHttpClient::dispatchResponseCallbacks(float)" (?dispatchResponseCallbacks@CCHttpClient@extension@cocos2d@@AAEXM@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__sem_init,该符号在函数 "private: bool __thiscall cocos2d::extension::CCHttpClient::lazyInitThreadSemphore(void)" (?lazyInitThreadSemphore@CCHttpClient@extension@cocos2d@@AAE_NXZ) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__sem_destroy,该符号在函数 "void * __cdecl cocos2d::extension::networkThread(void *)" (?networkThread@extension@cocos2d@@YAPAXPAX@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__sem_wait,该符号在函数 "void * __cdecl cocos2d::extension::networkThread(void *)" (?networkThread@extension@cocos2d@@YAPAXPAX@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__sem_post,该符号在函数 "private: virtual __thiscall cocos2d::extension::CCHttpClient::~CCHttpClient(void)" (??1CCHttpClient@extension@cocos2d@@EAE@XZ) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__curl_slist_append,该符号在函数 "int __cdecl cocos2d::extension::processGetTask(class cocos2d::extension::CCHttpRequest *,unsigned int (__cdecl*)(void *,unsigned int,unsigned int,void *),void *,int *)" (?processGetTask@extension@cocos2d@@YAHPAVCCHttpRequest@12@P6AIPAXII1@Z1PAH@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__curl_slist_free_all,该符号在函数 "int __cdecl cocos2d::extension::processGetTask(class cocos2d::extension::CCHttpRequest *,unsigned int (__cdecl*)(void *,unsigned int,unsigned int,void *),void *,int *)" (?processGetTask@extension@cocos2d@@YAHPAVCCHttpRequest@12@P6AIPAXII1@Z1PAH@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__curl_easy_init,该符号在函数 "int __cdecl cocos2d::extension::processGetTask(class cocos2d::extension::CCHttpRequest *,unsigned int (__cdecl*)(void *,unsigned int,unsigned int,void *),void *,int *)" (?processGetTask@extension@cocos2d@@YAHPAVCCHttpRequest@12@P6AIPAXII1@Z1PAH@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__curl_easy_setopt,该符号在函数 "bool __cdecl cocos2d::extension::configureCURL(void *)" (?configureCURL@extension@cocos2d@@YA_NPAX@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__curl_easy_perform,该符号在函数 "int __cdecl cocos2d::extension::processGetTask(class cocos2d::extension::CCHttpRequest *,unsigned int (__cdecl*)(void *,unsigned int,unsigned int,void *),void *,int *)" (?processGetTask@extension@cocos2d@@YAHPAVCCHttpRequest@12@P6AIPAXII1@Z1PAH@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__curl_easy_cleanup,该符号在函数 "int __cdecl cocos2d::extension::processGetTask(class cocos2d::extension::CCHttpRequest *,unsigned int (__cdecl*)(void *,unsigned int,unsigned int,void *),void *,int *)" (?processGetTask@extension@cocos2d@@YAHPAVCCHttpRequest@12@P6AIPAXII1@Z1PAH@Z) 中被引用
1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__curl_easy_getinfo,该符号在函数 "int __cdecl cocos2d::extension::processGetTask(class cocos2d::extension::CCHttpRequest *,unsigned int (__cdecl*)(void *,unsigned int,unsigned int,void *),void *,int *)" (?processGetTask@extension@cocos2d@@YAHPAVCCHttpRequest@12@P6AIPAXII1@Z1PAH@Z) 中被引用

    再按之前的方法加入:libcurl_imp.lib、pthreadVCE2.lib 这两个库。再编译,走你。

    终于行了。

    接下来把它加到程序中。先在HelloWorldScene中加入NetConnect.h头文件。我更改了右下角的那个CCMenuItem的响应。

void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    // "close" menu item clicked
    //CCDirector::sharedDirector()->end();
	NetConnect* nc = NetConnect::create();
	nc->getData();
}

    运行程序,点击右下角的按钮。看输出日志。打出了我们想要的东西。


本篇博客出自阿修罗道,转载请注明出处:http://blog.csdn.net/fansongy/article/details/9207595
  

    

    

分类: 未分类 标签:

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

2013年6月25日 没有评论

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

游戏的UI界面编程是一个既重要,又麻烦的工具。如何能够更快的完成界面的处理是游戏开发中一个必须要面对的问题。其实现在已经有很多工具能够完成界面的编辑和导出,比如mygui,CEGUI,CocosBuilder等。今天呢?我就向大家隆重自荐一下本人开发的“红孩儿工具箱”,通过一个简单的编辑过程让大家感受一下游戏开发中如何处理界面才更快,效率更高。

 

红孩儿工具箱 0.1.7 版本

下载地址:红孩儿工具箱用户QQ: 20970366及红孩儿Cocos2d-x学习园地QQ群共享

下载后的目录如下:

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

         这里要说明的是Editor.ini:这是工具的配置文件,它里面有

 

[ResDir]

ResDir=IMAGE

         注意:ResDir用于指定资源所在目录。这个很关键,工具所用到的所有图片必须放在这个目录下。

[UIInfo]

PicDir        =IMAGE/UI

         注意:RicDir用于指定资源中UI图片所在目录。这只是为了方便在选图时的默认打开路径。并不是说使用到的图片就必须是在UI目录中。

 

         第一步:我们先将我们的资源放在此目录下。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


         好,我们现在利用这些资源来制做一个游戏动画界面,要求为:

(1)      有不停UV滚动的背景图。

(2)      有一个LOGO面板。

(3)      有一个问号按钮,能够响应按下事件,按下后弹出一个金币或者一朵咬人花.

嘿嘿,有点意思吧?

 

OK,下面运行程序:

 

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


         输入game2z.com论坛注册的账号和密码,点击“登录”进入工具的主界面。

 

         第二步:为了提高渲染的效率,我们需要将一些图片进行合并处理,在拼图界面,选择相应的资源目录,然后点击“立即导出!”,我们就可以进行图片的合并。

         注意:bk这张图是使用纹理UV滚动的,这种情况不能合并进来,另外Cocos2d-x对于这类纹理要求是2的幂次方的宽高。

 

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

         合并完之后:


使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


         第三步:将所用到的动画进行处理:

         打开“动画编辑”界面,然后在左边的树列表中增加一个图片结点,之后对其右键弹出菜单项中点击“创建固定帧间隔的关键帧动画”。在弹出的对话框中选择“拼合图生成”,之后在选图对话框中找到相应的拼合图后确点。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

确定后拉合图会被加载进树列表,点击展开:
使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

         我们先做一下花的序列帧,点击”flower1.png”,然后双击它或者点击“应用此图块”,之后就可以返回到固定关键帧间隔动画的生成对话框:

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


         这里面会自动的将flower系列图块加入进来,我们修改一下间隔时间为500毫秒。点击“确定”后会在动画编辑界面生成相应的动画。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


         点击下方的帧展示面板右边的“播放动画”,即可看到此动画的播放演示。

 

现在我们将其保存为flower.ani.在弹出的动画名称输入框中输入“flower”:

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


点击“导出”后在相应的目录内导出动画:

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


         保存的ani文件是工具编辑使用的文件。导出的gan文件(GAME ANI)即是可以在Cocos2d-x中使用的动画最终文件。

 

这样我们就将咬人花的动画编辑好了。现在我们可以点击“新建动画”,然后创建一个新图片结点,设定其使用图片coin3.png,然后在下面的帧显示区域中第二帧和第三帧的位置右键弹出菜单中新增两个关键帧。我们在第二帧中双击图片结点设定其使用图片coin2.png,并点击选中它之后右键弹出菜单中选中“调整相对位置”。在Y值框里填写-50,将其Y值设为向上抬高50像素。

 

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

        同样的方式,在第三帧我们设定图片结点选用coin1.png并点击选中它之后右键弹出菜单中选中“调整相对位置”。在Y值框里填写-100,将其Y值设为向上抬高100像素。


使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


 

点击“播放动画”我们就可以看到一个向上跳出金币的动画。

 

保存为cion.ani并导出cion.gan文件。

 

现在呢,我们来做一下背景动画。

新建动画,命名为“bk”,然后新建一个图片结点,双击它或者在右边面板的“选择图片”打开选图对话框,然后我们找到这张背景图。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 点击“打开”后这张背景图就会被加进来。选中它后点击“应用此图片”。

注意:如果图片过大我们可以先点击“限制大小”,这样对话框就被限制大小了。更易操作。

 

现在这个图片就被加入动画编辑区域里了,我们把帧间隔调整为30毫秒。然后在下面帧显示条上第50帧处右键,在弹出菜单中点击“加入关键帧”,然后修改右边面板“纹理横向偏移”,输入“1.0”。

 

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

保存,导出为bk.ani和bk.gan。

 

第四步:现在我们要来编辑界面了。点击“界面编辑”,然后在上面一排控件中最左边选择“面板”,在主视窗中拖动创建出一个面板。


使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

 

从左上角到右下角拖动创建好面板后松开鼠标,即可看到一个空白面板产生出来,我们点击选中它,可以在右边的属性编辑区域里输入位置和宽高来调整它,并点击“Normal_Image”对应按钮来选择一张图片或动画。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

         在弹出的选择UI图片对话框里我们点击“加载资源文件”,找到之前做的背景动画bk.ani.

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

选中后点击“应用此动画”,这样面板就应用了这个动画。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

在左边的控件树结点”UICtrl1_Rect”上右键弹出菜单中点击“增加子结点_面板”,新增一个面板并放置中间。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

点击选中子面板,按照上面的方法为其设定标题图片。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

 

这里注意选择ImageShowType属性值为“改变控件”,即按照标题图大小来重设控件大小。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


 

修改好后:

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

下面我们来增加一个按钮控件,在左边的控件树结点”UICtrl1_Rect”上右键弹出菜单中点击“增加子结点_按钮”,新增一个按钮并放置中间靠下位置。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

       然后我们设定其Normal_Image项为UI_Pack_0.png中的ob5_2.png,设定LButtonDown_Image为ob5_0.png。这样我们就成功创建了按钮。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

 

按钮创建成功后,我们再继续为按钮结点”UICtrl3_Button”新增一个面板动画。设定其使用金币动画,放置在按钮所在位置,我们在这里先将它的Visible设为False,留待Cocos2d-x中运行时点击按钮再设为显示。

 

同样做法我们为按钮结点”UICtrl3_Button”新增一个面板动画。设定其使用咬人花动画,放置在按钮上面位置,我们在这里也将它的Visible设为False。

 

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

现在我们保存为mali.xml并导出mali.ui。

 

OK,所有的编辑工作都做完了。现在我们将尝试在Cocos2d-x中运行它。

我们打开编辑器资源目录IMAGE/UI,将所要用到的文件拷到Cocos2d-x的HelloCpp工程中的资源目录中。

 

工具箱资源目录:红色框选的是要拷到Cocos2d-x工程中使用的资源。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

 

然后我们将对应的游戏开发库中的include设置为工程的包含目录。Lib设置为工程的库目录。并将HHRLib_d.lib和HHRLib.lib分别加到工程的debug和release引用库中。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


 

现在我们打开HelloWorldScene.h。为按钮按下时创建一个回调函数:

class HelloWorld : public cocos2d::CCLayer
{
public:
    // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
    virtual bool init();  

    // there's no 'id' in cpp, so we recommend returning the class instance pointer
    static cocos2d::CCScene* scene();
    
    // a selector callback
void menuCloseCallback(CCObject* pSender);


    //设置按钮按下时响应的回调函数
	void OnBtnClicked(CCNode* pSender, void* data);
	//设置动画结束时响应的回调函数
	void OnAniEnd(CCNode* pSender, void* data);
    
    CREATE_FUNC(HelloWorld);
};

 

对应的CPP:

bool HelloWorld::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false;
    }
    
    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

    /////////////////////////////
    // 2. add a menu item with "X" image, which is clicked to quit the program
    //    you may modify it.

    // add a "close" icon to exit the progress. it's an autorelease object
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                                        "CloseNormal.png",
                                        "CloseSelected.png",
                                        this,
                                        menu_selector(HelloWorld::menuCloseCallback));
    
	pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 ,
                                origin.y + pCloseItem->getContentSize().height/2));

    // create menu, it's an autorelease object
    CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
    pMenu->setPosition(CCPointZero);
    this->addChild(pMenu, 1);

    /////////////////////////////
    // 3. add your codes below...

    // add a label shows "Hello World"
    // create and initialize a label
    
    CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", TITLE_FONT_SIZE);
    
    // position the label on the center of the screen
    pLabel->setPosition(ccp(origin.x + visibleSize.width/2,
                            origin.y + visibleSize.height - pLabel->getContentSize().height));

    // add the label as a child to this layer
    this->addChild(pLabel, 1 , 200);



	//加载界面
	CGameUI*		pNewUI = new CGameUI();
	pNewUI->LoadUITree("mali.ui");
	//设置界面的位置
	pNewUI->setOffset(visibleSize.width/2, visibleSize.height/2);
	this->addChild(pNewUI,1,100);
	//取得按钮
	CUICtrl*	pUICtrl = pNewUI->QueryUICtrl("UICtrl3_Button");
	if(pUICtrl)
	{
		CUIButton*	pUIButton = dynamic_cast<CUIButton*>(pUICtrl);
		if(pUIButton)
		{
			//设置在按下时响应的回调函数,可带自定义参数。
			pUIButton->setClickBeginCallFuncND(CCCallFuncND::create(this, callfuncND_selector(HelloWorld::StartCionAni), (void*)0xbebabeba));
		}
	}
	//金币动画面板
	pUICtrl = pNewUI->QueryUICtrl("UICtrl4_Rect");
	if(pUICtrl)
	{
		CUIRect*	pAniRect = 	dynamic_cast<CUIRect*>(pUICtrl);
		if(pAniRect)
		{
			C2DSkinAni*		pSkinAni = pAniRect->getSkinAni();
			if(pSkinAni)
			{
				pSkinAni->SetEndFrameCallFuncND(CCCallFuncND::create(this, callfuncND_selector(HelloWorld::AniEndFrame), (void*)0xbebabeba));
			}
		}
		//咬人花动画面板
pUICtrl = pNewUI->QueryUICtrl("UICtrl5_Rect");
	if(pUICtrl)
	{
		CUIRect*	pAniRect = 	dynamic_cast<CUIRect*>(pUICtrl);
		if(pAniRect)
		{
			C2DSkinAni*		pSkinAni = pAniRect->getSkinAni();
			if(pSkinAni)
			{
				pSkinAni->SetEndFrameCallFuncND(CCCallFuncND::create(this, callfuncND_selector(HelloWorld::OnAniEnd), (void*)0xbebabeba));
			}
		}
	}

	}
    return true;
}

回调函数的处理:

//设置在点击按钮时响应的函数
void HelloWorld::OnBtnClicked(CCNode* pSender, void* data)
{
	CCNode*	pNode = getChildByTag(100);
	if(pNode)
	{
		CGameUI*		pMainUI = 	dynamic_cast<CGameUI*>(pNode);
		if(pMainUI)
		{
			//随机产生金币动画或咬人花动画
			float r = CCRANDOM_0_1();
			if(r > 0.5)
			{
				CUICtrl*		pUICtrl = pMainUI->QueryUICtrl("UICtrl4_Rect");
				if(pUICtrl)
				{
					CUIRect*	pAniRect = 	dynamic_cast<CUIRect*>(pUICtrl);
					if(pAniRect)
					{
						C2DSkinAni*		pSkinAni = pAniRect->getSkinAni();
						if(pSkinAni)
						{

							pSkinAni->Play(1);
							pSkinAni->setVisible(true);
							pAniRect->setVisible(true);
						}
					}
				}
			}
			else
			{
				CUICtrl*		pUICtrl = pMainUI->QueryUICtrl("UICtrl5_Rect");
				if(pUICtrl)
				{
					CUIRect*	pAniRect = 	dynamic_cast<CUIRect*>(pUICtrl);
					if(pAniRect)
					{
						C2DSkinAni*		pSkinAni = pAniRect->getSkinAni();
						if(pSkinAni)
						{

							pSkinAni->Play(1);
							pSkinAni->setVisible(true);
							pAniRect->setVisible(true);
						}
					}
				}
			}
		}
	}

}

//设置在动画结束时响应的函数
void HelloWorld::OnAniEnd(CCNode* pSender, void* data)
{
	CCNode*	pNode = getChildByTag(100);
	if(pNode)
	{
		CGameUI*		pMainUI = 	dynamic_cast<CGameUI*>(pNode);
		if(pMainUI)
		{
			//将金币动画设为不显示
			CUICtrl*		pUICtrl = pMainUI->QueryUICtrl("UICtrl4_Rect");
			if(pUICtrl)
			{
				CUIRect*	pAniRect = dynamic_cast<CUIRect*>(pUICtrl);
				if(pAniRect)
				{
					C2DSkinAni*		pSkinAni = pAniRect->getSkinAni();
					if(pSkinAni)
					{
						pSkinAni->setVisible(false);
					}
				}
			}
			//将咬人花动画设为不显示
pUICtrl = pMainUI->QueryUICtrl("UICtrl5_Rect");
			if(pUICtrl)
			{
				CUIRect*	pAniRect = dynamic_cast<CUIRect*>(pUICtrl);
				if(pAniRect)
				{
					C2DSkinAni*		pSkinAni = pAniRect->getSkinAni();
					if(pSkinAni)
					{
						pSkinAni->setVisible(false);
					}
				}
			}

		}
	}
}

 

好了,现在编译并运行。

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面

或者有时候是出现咬人花

使用红孩儿工具箱完成基于Cocos2d-x的简单游戏动画界面


OK,总实算是完成了~,这样我们就实现了一个完整的动画控制界面。希望大家在这个过程中学到一些动画和界面制做的思想,能够更好的开发出精美的游戏。下次再见!

分类: 未分类 标签:

python xml解析

2013年6月18日 没有评论
first.xml
<info>
<person >
<id>1</id>
<name>fsy</name>
<age >24</age>
</person>
<person>
<id>2</id>
<name>jianjian</name>
<age>24</age>
</person>
<count id ='1'>1000</count>
</info>

from xml.etree import ElementTree as etree

读入
def read_xml(file):
# parse()函数会返回一个能代表整篇文档的对象。这不是根元素。要获得根元素的引用可以调用getroot()方法。
tree = etree.parse(file)
root = tree.getroot()
return root

得到信息
def print_node(node):
'''打印结点基本信息'''
print("node.tag:%s" % node.tag)
print("node.attrib:%s"%node.attrib)
print( "node.text:%s" % node.text)

搜索:
find_all
>>> root = read_xml ('first.xml')    
>>> res = root.findall("person")
[<Element 'person' at 0x00000000033388B8>, <Element 'person' at 0x0000000003413D68>]

注意:findall只查询直接的子节点
>>> r1 = root.findall("id")
>>> r1
[]
>>> r =tree.findall(".//id")
>>> for e in r:
    print( e,e.text)


<Element 'id' at 0x00000000034279F8> 1
<Element 'id' at 0x0000000003427B38> 2
find:

#find()方法用来返回第一个匹配到的元素。当我们认为只会有一个匹配,或者有多个匹配但我们只关心第一个的时候,这个方法是很有用的。
>>> res[0].find("id")
<Element 'id' at 0x0000000003413CC8>
>>> print_node(res[0].find("id"))
node.tag:id
node.attrib:{}
node.text:1

find查找失败:
使用find要注意在布尔上下文中,如果ElementTree元素对象不包含子元素,其值则会被认为是False(即如果len(element)等于0)。这就意味着if element.find(‘…’)并非在测试是否find()方法找到了匹配项;这条语句是在测试匹配到的元素是否包含子元素。想要测试find()方法是否返回了一个元素,则需使用if element.find(‘…’) is not None。
>>> bk = res[0].find("no")
>>> bk
>>> type(bk)
<class 'NoneType'>
>>> res[0].find("id")
<Element 'id' at 0x0000000003413CC8>
>>> if res[0].find("id"):
        print("find")
    else:
        print("not find")
not find
>>> if res[0].find("id") is not None:
        print("find")
    else:
        print("not find")
find

本篇博客出自阿修罗道,转载请注明出处:http://blog.csdn.net/fansongy/article/details/9119661

分类: 未分类 标签:

cocos2d-x 卡牌翻牌效果的实现

2013年6月17日 没有评论

猴子原创,欢迎转载。转载请注明: 转载自Cocos2D开发网–Cocos2Dev.com,谢谢!

原文地址: http://www.cocos2dev.com/?p=428

刚有人问我cocos2dx能否实现卡牌的翻牌效果,其实cocos2dx有个action就是这个效果,晚上随便写了个效果。需要的可以看看。

cocos2d-x 卡牌翻牌效果的实现


上面的效果图是ipad模拟器,所以帧率只有30,实际是60.

这个能实现翻牌的action就是CCOrbitCamera。

static CCOrbitCamera* create(float t, float radius, float deltaRadius, float angleZ, float deltaAngleZ, float angleX, float deltaAngleX);


参数分别为旋转的时间,起始半径,半径差,起始z角,旋转z角差,起始x角,旋转x角差

下面是我封装的cardSprite,

请自己加入自己的工程,

用法:

//创建翻牌sprite, 参数:卡片里面的图,卡片的封面,翻牌所花时间
 
CardSprite* card = CardSprite::create("1.png", "2.png", 2);
 
card->setPosition(ccp(size.width * .5, size.height * .5));
 
addChild(card);
 
card->openCard();//开始翻牌

CardSprite.h

//
//  CardSprite.h
//  Cocos2dev.com
//
//  Created by LiuYanghui on 13-6-17.
//
//

#ifndef __Test__CardSprite__
#define __Test__CardSprite__

#include "cocos2d.h"
USING_NS_CC;

class CardSprite : public CCSprite
{
public:
    CardSprite();
    ~CardSprite();
    static CardSprite* create(const char* inCardImageName, const char* outCardImageName, float duration);
    virtual bool init(const char* inCardImageName, const char* outCardImageName, float duration);
    
private:
    bool m_isOpened;
    CCActionInterval* m_openAnimIn;
    CCActionInterval* m_openAnimOut;
    
    
    void initData(const char* inCardImageName, const char* outCardImageName, float duration);
    
public:
    void openCard();
};

#endif /* defined(__Test__CardSprite__) */

CardSprite.cpp

//
//  CardSprite.cpp
//  Cocos2dev.com
//
//  Created by LiuYanghui on 13-6-17.
//
//

#include "CardSprite.h"

#define kInAngleZ        270 //里面卡牌的起始Z轴角度
#define kInDeltaZ        90  //里面卡牌旋转的Z轴角度差

#define kOutAngleZ       0   //封面卡牌的起始Z轴角度
#define kOutDeltaZ       90  //封面卡牌旋转的Z轴角度差

enum {
    tag_inCard = 1,
    tag_outCard
};

CardSprite::CardSprite()
{
    
}

CardSprite::~CardSprite()
{
    m_openAnimIn->release();
    m_openAnimOut->release();
}

CardSprite* CardSprite::create(const char* inCardImageName, const char* outCardImageName, float duration)
{
    CardSprite *pSprite = new CardSprite();
    if (pSprite && pSprite->init(inCardImageName, outCardImageName, duration))
    {
        pSprite->autorelease();
        return pSprite;
    }
    CC_SAFE_DELETE(pSprite);
    return NULL;
}

bool CardSprite::init(const char* inCardImageName, const char* outCardImageName, float duration)
{
    if (!CCSprite::init())
    {
        return false;
    }
    initData(inCardImageName, outCardImageName, duration);
    return true;
}

#pragma mark - initData
void CardSprite::initData(const char* inCardImageName, const char* outCardImageName, float duration)
{
    m_isOpened = false;
    
    CCSprite* inCard = CCSprite::create(inCardImageName);
    inCard->setPosition(CCPointZero);
    inCard->setVisible(false);
    inCard->setTag(tag_inCard);
    addChild(inCard);
    
    CCSprite* outCard = CCSprite::create(outCardImageName);
    outCard->setPosition(CCPointZero);
    outCard->setTag(tag_outCard);
    addChild(outCard);
    
    m_openAnimIn = (CCActionInterval*)CCSequence::create(CCDelayTime::create(duration * .5),
                                                         CCShow::create(),
                                                         CCOrbitCamera::create(duration * .5, 1, 0, kInAngleZ, kInDeltaZ, 0, 0),
                                                         NULL);
    m_openAnimIn->retain();
    
    m_openAnimOut = (CCActionInterval *)CCSequence::create(CCOrbitCamera::create(duration * .5, 1, 0, kOutAngleZ, kOutDeltaZ, 0, 0),
                                                           CCHide::create(),
                                                           CCDelayTime::create(duration * .5),
                                                           NULL);
    m_openAnimOut->retain();
}

#pragma mark - public func
void CardSprite::openCard()
{
    CCSprite* inCard = (CCSprite*)getChildByTag(tag_inCard);
    CCSprite* outCard = (CCSprite*)getChildByTag(tag_outCard);
    inCard->runAction(m_openAnimIn);
    outCard->runAction(m_openAnimOut);
}


分类: 未分类 标签:

使用boost::python的链接出错

2013年6月16日 没有评论

 

   被这个东西折磨了一个晚上,先是听度娘海扯胡诌,发现各种不靠谱。就自己研究,在几乎要放弃时解决了问题。

   首先是调试库的问题。因为网上下下来的安装版python是没有调试库的,所以调试编不过。居然还有人说直接把.lib改个名就变成调试库了。我去了,这么巧?函数地址都一样??不知编过的兄弟用的是哪个版本。我的是python3.3,这个版本肯定不行。就采用猥琐的办法吧:

#ifdef _DEBUG
 #undef _DEBUG
 #include <boost/python.hpp>
#else
 #include <boost/python.hpp>
#endif

   这样调试库的问题就pass了,接下来当我检查了无数遍。发现接口函数还是没实现。一共就两个库,搞毛线啊。不过我这情况稍微复杂一些,vs2008、vs2012、python2.7、python3.3、boost1.53都有。首先我先把boost那边的编译库研究一通,发现都已经生成了。如果你曾经加载到vs2008项目中进行编译,这些库都有了,不用bjam的,虽然这是我过了很久才意识到。不过库的名字不太对,在前面多了个lib,在/stage文件夹中,改过来就行。当然我用源码引入项目的方式,以及各种方式重新生成了一遍库,还是不行。我开始担心会不会由于2.7和3.3改了不少,接口有变化。最后发现….都不是。因为我不使用boost一样不行! 汗了…


    当确定跟这个boost库没关系之后,我又把目标放到python33.lib这个库上了。去掉所有不可能的,剩下的不管多不可能,都是真相。这话是谁说的,真TM有哲理,我想到了一个也仅剩的一个可能,这个库有问题。官方库也出错?我就上官网去算账去了。最后,一个猥琐的细节引起了我的注意。我机器是64位的。所以我的python装的也是64位的,但是项目是32位的,所以用32位的寻址连接64位的静态库,这不找死呢。我赶紧下了个32位的覆盖安装了,果然…就没问题了。


     坑我一晚上,写个博客祭奠一下我为此无谓浪费的脑细胞,为他们立此墓碑,警醒后人 



本篇博客出自阿修罗道,转载请注明出处:http://blog.csdn.net/fansongy/article/details/9108083


分类: 未分类 标签:

Python 架设网站

2013年6月11日 没有评论

   Python开发一个服务器很方便,模块封装的很好。写了个简易网站。

   说一下大体思路。首先,写个5行的服务器启动,默认打开index.html。在首页中作超链接跳转,到脚本上。在脚本中现将数据打包(也可以理解为将数据从库中提取出来),然后写出网页,并设定好表单等元素。用户点击,进入下一个脚本……

 
    整体来说,通常采用MCV架构:
模型(Module):存储(以及有时处理Web应用数据的代码
视图(View):格式化和显示Web应用用户界面的代码
控制器(Controller):将Web应用”粘合“在一起并提供业务逻辑

M 为数据建模
Web服务器需要一个存储数据的副本。当Web应用启动时,需要把文件中的信息读出来。这里是一个打包好的Pickle,也可能是在程序启动时,搜集相应的文件打的包,因为可能要下发到本地。
小例子没使用数据库,使用pickle即可,注意I/O异常检测。
V 查看界面
使用First Head 书中带的yate.py来生成html。估计应该有其他更NB的PiPy。
C 控制代码
推荐采用以下结构:
WebApp:顶层文件夹是程序的名字,除了子文件夹,还包括web应用的index.html文件,图标,样式表等不适合放在其子文件夹中的内容。
cgi-bin:为Web应用写的所有代码需要放在这里。
data:所有数据在这里
image:如果有必要就创建一个这个文件,将图标、图片放在里面
templates:一些套用的模板

构建服务器必须的信息代码:
from http.server import HTTPServer,CGIHTTPRequestHandler
port = 8080
httpd = HTTPServer(('',port),CGIHTTPRequestHandler) #创建一个服务器
print("Strating simpleHttpd on port: "+str(httpd.server_port))
httpd.serve_forever() #弹出提示并启动服务器

    运行这个文件(命令为 python.exe XXX.py),则在访问相应端口时就会启动本层文件中的index.html。如果没有则显示层级文件。所以运行这几行代码就完成了服务器的架设了。
    操作的跳转则在html中做。例如:超链接<a href="cgi-bin/generate_list.py">timing data</a>
    这样就运行相应的脚本了。

    访问方式大家都知道了:在浏览器中输入:localhost:8080 就行了。

下面是一些能用到的小知识点:

文件操作:glob
查询一个文件列表:data_fales = glob.glob("../data/*.txt")

网页相关的库:cgi
    获取表单数据:数据将作为一个字典返回
    cgi.FieldStorate()
    athlete_name = form_data['which_athlete'].value

开启调试:使用cgitb可以将崩溃问题显示到网页上。

    import cgitb
    cgitb.enable()

将类方法表现为属性:@property
当类中的方法上用@property修饰时,这个类方法表现为一个属性。即使用"."来直接使用,而不用再加括号。


标准库string中包括一个名为Template的类,它支持简单的字符串替换:

with open('../templates/header.html') as headf:
head_text = headf.read()
header = Template(head_text)
return(header.substitute(title=the_title))

代码 http://download.csdn.net/detail/fansongy/5564213

  本篇博客出自阿修罗道,转载请注明出处:http://blog.csdn.net/fansongy/article/details/9076549

分类: 未分类 标签:

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)

2013年6月7日 没有评论

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)

    用冯巩的一句台词:“好久不见,我可想死你们啦!”。红孩儿五月份没有写东西,很对不起大家,红孩儿五月份一直在忙工具箱的事,经过短期发力,工具箱已经可以将动画和界面部分编辑并导出到Cocos2d-x中。另外红孩儿手上的项目进入测试期,就把博客给冷落了。不过大家放心,红孩儿一定会继续坚持把Cocos2d-x的教程进行到底!

 

    好了,书归正传,接上一篇文ClippingNodeTest。我们把后面的部分继续讲完。

第八个实例:RawStencilBufferTest

截图:

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)

说明:

         循环设置模版缓冲各位的值并进行遮罩处理。

原理:

         设置相应的模板缓冲位数据,并通过模板测试比较进行相应区域像素的刷色块与精灵显示。

类代码:

 

class RawStencilBufferTest : public BaseClippingNodeTest
{
public:
	//析构
    ~RawStencilBufferTest();
	//重载基类函数。
    virtual std::string title();
    virtual std::string subtitle();
    virtual void setup();
    virtual void draw();
	//设置遮罩用的模版缓冲
	virtual void setupStencilForClippingOnPlane(GLint plane);
	//设置显示图像用的模板缓冲
	virtual void setupStencilForDrawingOnPlane(GLint plane);

protected:
	//精灵成员
    CCSprite* m_pSprite;
};


对应CPP:
//模板位索引
static GLint _stencilBits = -1;
// ALPHA参考值
static const GLfloat _alphaThreshold = 0.05f;
//面板数量
static const int _planeCount = 8;
//面板颜色
static const ccColor4F _planeColor[] = {
    {0, 0, 0, 0.65f},
    {0.7f, 0, 0, 0.6f},
    {0, 0.7f, 0, 0.55f},
    {0, 0, 0.7f, 0.5f},
    {0.7f, 0.7f, 0, 0.45f},
    {0, 0.7f, 0.7f, 0.4f},
    {0.7f, 0, 0.7f, 0.35f},
    {0.7f, 0.7f, 0.7f, 0.3f},
};
//析构
RawStencilBufferTest::~RawStencilBufferTest()
{
    CC_SAFE_RELEASE(m_pSprite);
}
//标题
std::string RawStencilBufferTest::title()
{
	return "Raw Stencil Tests";
}
//副标题
std::string RawStencilBufferTest::subtitle()
{
	return "1:Default";
}
//初始化
void RawStencilBufferTest::setup()
{
	//OPENGL相应的接口函数取得程序运行在当前设备的模版缓冲区位数。
glGetIntegerv(GL_STENCIL_BITS, &_stencilBits);
//如果小于3,提示模版缓冲不满足当前的OPENGL视窗要求
    if (_stencilBits < 3) {
        CCLOGWARN("Stencil must be enabled for the current CCGLView.");
}
//创建精灵
m_pSprite = CCSprite::create(s_pPathGrossini);
//占用,对其引用计数器加一。
m_pSprite->retain();
//设置锚点横向居中,纵向靠下。就是设置脚部位置为锚点。
m_pSprite->setAnchorPoint(  ccp(0.5, 0) );
//放大2.5倍
m_pSprite->setScale( 2.5f );
//设置开启ALPHA混合。为什么要开启ALPHA混合?好问题!放在后面回答。
    CCDirector::sharedDirector()->setAlphaBlending(true);
}
//绘制函数
void RawStencilBufferTest::draw()
{    
	//取得屏幕右上角位置
    CCPoint winPoint = ccpFromSize(CCDirector::sharedDirector()->getWinSize());
    //根据面板数量取得每个面板的大小。
    CCPoint planeSize = ccpMult(winPoint, 1.0 / _planeCount);
    //开启模板测试。
glEnable(GL_STENCIL_TEST);
//检测是否有运行BUG
    CHECK_GL_ERROR_DEBUG();
    //遍历设置每个面板
    for (int i = 0; i < _planeCount; i++) {
        //计算出每个遮罩区域的右上角位置,这里计算的结果其实就是右边至上而下的平均分位置。
        CCPoint stencilPoint = ccpMult(planeSize, _planeCount - i);
        stencilPoint.x = winPoint.x;
        //计算出精灵的位置。这里计算的结果为精灵在最下方至左向右的平均分位置。
        CCPoint spritePoint = ccpMult(planeSize, i);
        spritePoint.x += planeSize.x / 2;
        spritePoint.y = 0;
        m_pSprite->setPosition( spritePoint );

		 //设置当前面板的遮罩模板缓冲
        this->setupStencilForClippingOnPlane(i);
	 //检测是否有运行BUG
        CHECK_GL_ERROR_DEBUG();
		 //在屏幕上相应遮罩区域绘制色块,写入模板缓冲相应模板值。
        ccDrawSolidRect(CCPointZero, stencilPoint, ccc4f(1, 1, 1, 1));
        //绘制精灵。
		//先保存当前状态下的矩阵。
        kmGLPushMatrix();
		//设置当前节点的矩阵
        this->transform();
		//调用精灵函数绘制精灵。
        m_pSprite->visit();
		//恢复之前状态下的矩阵。
        kmGLPopMatrix();
        //设置显示图形时的模板缓冲。
        this->setupStencilForDrawingOnPlane(i);
		 //检测是否有运行BUG
        CHECK_GL_ERROR_DEBUG();
        //在屏幕上全屏绘制色块,因为有模版遮罩,所以只有遮罩区域才显示。
        ccDrawSolidRect(CCPointZero, winPoint, _planeColor[i]);
        
//再绘制精灵一遍。
        kmGLPushMatrix();
        this->transform();
        m_pSprite->visit();
        kmGLPopMatrix();
    }
    //关闭模版测试
glDisable(GL_STENCIL_TEST);
//检测是否有运行BUG
    CHECK_GL_ERROR_DEBUG();
}
//设置遮罩用的模版缓冲
void RawStencilBufferTest::setupStencilForClippingOnPlane(GLint plane)
{
	//计算相应平面所在的模板位
GLint planeMask = 0x1 << plane;
//设置为模板缓冲掩码
glStencilMask(planeMask);
//先清空当前画面的模板缓冲
glClearStencil(0x0);
    glClear(GL_STENCIL_BUFFER_BIT);
glFlush();
//设置永远不能通过测试。
glStencilFunc(GL_NEVER, planeMask, planeMask);
//如果测试未通过时将相应像素位置的模版缓冲位的值设为1。
    glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
}
//设置显示图像用的模板缓冲
void RawStencilBufferTest::setupStencilForDrawingOnPlane(GLint plane)
{
	//计算相应平面所在的模板位
GLint planeMask = 0x1 << plane;
//取得对应相应模版位的测试参考值,因为之前的位在循环做遮罩时都设为1,故测试参考值应为相应位为1加后面所有位都为1。
GLint equalOrLessPlanesMask = planeMask | (planeMask - 1);
//设置只有像素对应模板位的模板指等于参考值通过测试。即只有缓冲位值为1的像素位置才会显示当前要绘制的精灵像素。
glStencilFunc(GL_EQUAL, equalOrLessPlanesMask, equalOrLessPlanesMask);
//如果测试未通过时保持模版缓冲位的值不变。
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
}

 

 

    这是一个比较难于理解的实例,也许你看的云里雾里,不过放心,红孩儿的教程一定让你深入的理解这里面的玄机。

    这个实例复杂之外其实就是多了一个精灵,为了更好的理解模版缓冲,咱们先把精灵干掉。然后来运行一下。

 

  /*
        kmGLPushMatrix();
        this->transform();
        m_pSprite->visit();
        kmGLPopMatrix();
		*/
        
        this->setupStencilForDrawingOnPlane(i);
        CHECK_GL_ERROR_DEBUG();
        
        ccDrawSolidRect(CCPointZero, winPoint, _planeColor[i]);
        /*
        kmGLPushMatrix();
        this->transform();
        m_pSprite->visit();
        kmGLPopMatrix();
		*/

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)


 

    看,这就是通过循环至上而下设置每个遮罩区域后,对屏幕进行刷色块处理的显示效果。

    再仔细,再仔细,我们以循环两次时的色块截屏来观察:

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)


 

这样,我们可能很好的观察到色块是如何刷的。

    我们在此基础上打开精灵的显示:

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)


 

    我们可以看到精灵被渲染了两次,我用黄线标示了精灵的实际遮罩大小,为什么会是这样的区域呢?在这里我们要重点说明一下,当使用ALPHABLEND和ALPHATEST的区别:

    如果你使用ALPHABLEND,实际它的每个像素仍会写入模版缓冲,即使我们认为它是透明的像素。

    而使用ALPHATEST,它被测试为透明镂空的像素在PS阶段完全被干掉了,不会再对背景缓冲起任何作用,包括颜色缓冲,深度缓冲与模版缓冲。

    下面,我们开启ALPHATEST:

//CCDirector::sharedDirector()->setAlphaBlending(true);
//开启ALPHATEST
	CCGLProgram *alphaTestShader = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColorAlphaTest);
    m_pSprite->setShaderProgram(alphaTestShader);

 

截图显示:

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)


 

    可以看到,与ALPHABLEND时的不同在于黄框中上方的部分区域是镂空的。好好的记住这一点,我们在做很多效果时会用到。

    我们以原来的ALPHABLEND状态再增加一次循环来看一下效果:

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)


 

    可以看到,第三次循染的色块为绿色,精灵我用黄框标示,我们发现在黄框右上角出现一个小区块是没有被涂绿的,这是为什么呢?

    在setupStencilForDrawingOnPlane函数中,我们判定可以通过模版测试的条件是:

    当前像素的模板缓冲值 = 当前循环次数所在缓冲位的数值 | 之前位都为1。

    那右小角的小块呢?它的模板缓冲值是肯定不符合测试条件的。

    它的模板缓冲值为0x100,只是精灵写入了一次。而黄框中其它区域的模板缓冲值为多少呢?0x110.因为与上次循环写入的模板缓冲值0x010做了“或”运算。

如果我们稍稍改动一下:

    把setupStencilForDrawingOnPlane函数中的这句

    GLintequalOrLessPlanesMask = planeMask | (planeMask – 1);

    改为

    GLintequalOrLessPlanesMask = planeMask;

再运行看看:

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)

    右上角就被填充了,因为黄框中所有模板缓冲值为0x100,而测试条件只测第三位,所以与0x110运算是可以通过测试的。

    瞧,这么一个小程序,里面也是处处玄机。你是否领悟了真正的引擎开发:的乐趣呢?

后面的RawStencilBufferTest2~ RawStencilBufferTest6是一堆由此实例派生的各种测试实例,分别代表的意义为:

    RawStencilBufferTest2:关闭写入深度缓冲。

    RawStencilBufferTest3:关闭写入深度缓冲,并关闭深度测试。这样会按照渲染的先后顺序来做Z排序,而非深度缓冲。

    RawStencilBufferTest4: RawStencilBufferTest2基础上使用ALPHATEST而非混合。

    RawStencilBufferTest5: RawStencilBufferTest3基础上使用ALPHATEST而非混合。

    RawStencilBufferTest6:这个是取像素的模版缓冲。简单说一下:

//取得幅标题。
std::string RawStencilBufferTest6::subtitle()
{
	return "6:ManualClear,AlphaTest:ENABLE";
}

//初始化
void RawStencilBufferTest6::setup()
{
	//判断所处平台支持
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
	//取得窗口大小
    CCPoint winPoint = ccpFromSize(CCDirector::sharedDirector()->getWinSize());
	//清空模板缓冲值为0
    unsigned char bits = 0;
    glStencilMask(~0);
    glClearStencil(0);
    glClear(GL_STENCIL_BUFFER_BIT);
    glFlush();
	//取得0,0点的像素的模板缓冲值
    glReadPixels(0, 0, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, &bits);
	//创建文字标签来显示模板缓冲值。
    CCLabelTTF *clearToZeroLabel = CCLabelTTF::create(CCString::createWithFormat("00=%02x", bits)->getCString(), "Arial", 20);
    clearToZeroLabel->setPosition( ccp((winPoint.x / 3) * 1, winPoint.y - 10) );
    this->addChild(clearToZeroLabel);
	//清空模板缓冲值为0xAA
    glStencilMask(0x0F);
    glClearStencil(0xAA);
    glClear(GL_STENCIL_BUFFER_BIT);
    glFlush();
	//取得0,0点的像素的模板缓冲值
    glReadPixels(0, 0, 1, 1, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, &bits);
//创建文字标签来显示模板缓冲值。
    CCLabelTTF *clearToMaskLabel = CCLabelTTF::create(CCString::createWithFormat("0a=%02x", bits)->getCString(), "Arial", 20);
    clearToMaskLabel->setPosition( ccp((winPoint.x / 3) * 2, winPoint.y - 10) );
    this->addChild(clearToMaskLabel);
#endif
	//设置遮罩掩码为0xfffffffff
    glStencilMask(~0);
	//调用基类的相应函数。
    RawStencilBufferTest::setup();
}

//设置遮罩用的模版缓冲
void RawStencilBufferTest6::setupStencilForClippingOnPlane(GLint plane)
{
	//取得相应循环对应的位
    GLint planeMask = 0x1 << plane;
	//设置模版缓冲的掩码值。
    glStencilMask(planeMask);
	//设置永远不通过测试
    glStencilFunc(GL_NEVER, 0, planeMask);
	//设置如果不通过测试,就设置相应位的值为1.
    glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
	//全屏绘制白色,写入模板缓冲值。
    ccDrawSolidRect(CCPointZero, ccpFromSize(CCDirector::sharedDirector()->getWinSize()), ccc4f(1, 1, 1, 1));
	//设置永远不通过测试
    glStencilFunc(GL_NEVER, planeMask, planeMask);
	//设置如果不通过测试,就设置相应位的值为1.
    glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
	//关闭深度测试。
    glDisable(GL_DEPTH_TEST);
	//关闭写入深度。
    glDepthMask(GL_FALSE);
	//开始ALPHA测试。
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
    glEnable(GL_ALPHA_TEST);
    glAlphaFunc(GL_GREATER, _alphaThreshold);
#else
    CCGLProgram *program = CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionTextureColorAlphaTest);
    GLint alphaValueLocation = glGetUniformLocation(program->getProgram(), kCCUniformAlphaTestValue);
    program->setUniformLocationWith1f(alphaValueLocation, _alphaThreshold);
    m_pSprite->setShaderProgram(program);
#endif
	//立即刷新缓冲。
    glFlush();
}
//设置显示图像用的模板缓冲
void RawStencilBufferTest6::setupStencilForDrawingOnPlane(GLint plane)
{
	//关闭ALPHATEST
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) || (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX) || (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
    glDisable(GL_ALPHA_TEST);
#endif
	//打开写入深度缓冲。
    glDepthMask(GL_TRUE);
	//打开深度测试。
    glEnable(GL_DEPTH_TEST);
	//调用基类的相应函数。
    RawStencilBufferTest::setupStencilForDrawingOnPlane(plane);
	//立即刷新缓冲。
    glFlush();
}

运行截图:

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)

讲了这么多,那倒底用遮罩能做什么效果呢?为了更好的理解,我用“红孩儿工具箱”来展示遮罩的功能:

一.红孩儿工具箱之遮罩动画1-【遮罩显示】

http://v.qq.com/boke/page/t/h/v/t0407iwbmhv.html

 

这个演示是使用模板缓冲来实现图片相应区域的显示。

 

二.红孩儿工具箱之遮罩动画2-【遮罩隐藏】
http://v.qq.com/boke/page/y/c/m/y0407t6szcm.html

这个演示是使用模板缓冲来实现图片相应区域的隐藏。

Cocos2d-x2.1.1-ClippingNodeTest深入分析(二)


 

    我只使用了简单的三张图,就实现了需要大量序列帧才能实现的效果,大大的节省了游戏对内存的需求。所以,这种技法很有用。

 

    衷心的希望大家能有所收获,把游戏做的更漂亮。下节课再见!

 

分类: cocos2d 标签:

Physics Material slow down the game

2013年6月5日 没有评论

I have developed game something like coin dozer. And for the smooth movement of coin i have add one Physics Material to each coin but my game is very slow after doing that . Is there any alternative of that or how can i make coin movement smooth without use of Physics material . So can anybody help me to come out from this situation.

So the problem is physics calculation.

DO NOT use the mesh of the graphic as the collider to calculate coin’s moving, especially when there are lots of triangles and verts on the mesh. You should choose a simpler collider, maybe something like prism would behavior similar as a coin and reduce a lot of calculation. You can use another simple prism mesh exported from 3d software and make a new game object with that mesh. Stripe off everything related to physics(rigid body, collider and physics material) from the origin coin. Then organize the visible coin without physics and the new added object(which handle all physics) to the same parent. Less triangles in a mesh collider means less calculation. Control the collider mesh triangles as few as possible. I suggest to use a box collider as a start point to check if the performance improves.

Another thing might help is changing the Solver Iteration Count in the Physics Setting. You can try to change it to a lower value (maybe 3 or 4 is enough for a coin game) from the default.

Limit the frame rate to a lower value alse can help, but it is the last way you should go.

You can add physics to the coins with delay. I mean add physics when coin is near to fall. Also you need to destroy every coin body when you are removing the coin out of the scene. If you are removing only sprite the there will be too many bodies on the scene.

分类: stackoverflow精选, unity3d 标签:

使用boost读取XML文件

2013年6月4日 没有评论

    boost中提供了对配置文件读取的支持,它就是:property_tree。

    basic_ptree 是property_tree的核心基础。其接口像std::list。可以执行很多基本的元素操作,比如使用begin()、end()等。

    此外还加入了操作属性树的get()、get_child()、get_value()、data()等额外的操作。

    basic_ptree有两个重要的内部定义self_type和value_type。self_type是basic_ptree模板实例化后自身的类型,它也是子节点的类型。value_type是节点的数据结构,它是一个std::pair,它含有属性名(first)和节点自身(second)。

    通常不使用basic_ptree,而是使用预定义的typedef。ptree、wptree、iptree、wiptree。前缀i表示忽略大小写,前缀w表示支持宽字符。

例如:
config.xml
<?xml version="1.0" encoding="utf-8"?>
<con>
  <id>1</id>
  <name>fansy</name>
  <urls>
    <url>http://blog.csdn.net//fansongy</url>
    <url>http://weibo.com//fansongy</url>
  </urls>
</con> 

我要读取它的数据:

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/typeof/typeof.hpp>  
using namespace std;
using namespace boost::property_tree;
int  main()
{
    ptree pt;
    read_xml("conf.xml",pt);     //读入一个xml文件
    cout<<"ID is "<<pt.get<int>("con.id")<<endl;  //读取节点中的信息
    cout<<"Try Default"<<pt.get<int>("con.no_prop",100)<<endl;  //如果取不到,则使用默认值
    ptree child = pt.get_child("con");    //取一个子节点
    cout<<"name is :"<<child.get<string>("name")<<endl;    //对子节点操作,其实跟上面的操作一样
    
    child = pt.get_child("con.urls");
    for(BOOST_AUTO(pos,child.begin());pos != child.end();++pos)  //boost中的auto
     {
         cout<<"/t"+pos->second.data()<<endl;
     }
    pt.put("con.name","Sword");    //更改某个键值
    pt.add("con.urls.url",http://www.baidu.com); //增加某个键值
    write_xml("conf.xml",pt);    //写入XML
    getchar();
    return 0;
}

运行的显示为:
ID is 1
Try Default100
name is :fansy

http://blog.csdn.net//fansongy


http://weibo.com//fansongy

config.xml为:
<?xml version="1.0" encoding="utf-8"?>
<con>
  <id>1</id>
  <name>Sword</name>
<urls>
     <url>http://blog.csdn.net//fansongy</url>
     <url>http://weibo.com//fansongy</url>
     <url>http://www.baidu.com</url>
</urls>
</con> 

本篇博客出自阿修罗道,转载请注明出处:http://blog.csdn.net/fansongy/article/details/9026407

分类: 未分类 标签:

使用BitmapFont打包字体文件、在cocos2d-x中使用 CCLabelBMFont

2013年6月2日 没有评论


通常情况下,字尤其是数字都不是写上去的,是“贴”上去的,这样效果更好。

怎么弄呢?这里就用到了图片打包的技术。

1、先下载一个BMFont。

2、运行程序,单击鼠标左键点亮相应位置的字母,比如:0、1、2、/ 等。

3、选择 Edit->Open Image Manager。弹出一个“Image Manager" 对话框。

4、点击Image->import Image.在弹出的对话框中选择对应的图片路径。

5、然后指定对应的id。此id就是要替换的字符的标识。可以将鼠标悬停在对应的格子上,右下角的“48:30"中的第一项即是Id号。

6、设定x,y的偏移量(看需求)

7、点ok并逐一添加相应的字体。

8、点击Option->Export options,在弹出的对话框中选择 Bit depth:32

9、点击Option->Save bitmap font as…

10、输入相应的保存名。例如"abc"。则会生成abc.fnt和abc_0.fnt两个文件。

11、在程序中这样使用即可:

CCLabelBMFont* pLabel = CCLabelBMFont::create("01234a6789", "abc.fnt"); 

本篇博客出自阿修罗道,转载请注明出处:http://blog.csdn.net/fansongy/article/details/9006677

分类: 未分类 标签: