zoukankan      html  css  js  c++  java
  • cocos2d-x游戏引擎核心之十——网络通信

    一、建立基本的http通信并得到返回信息

    1、创建cocos2dx工程

    2、项目引用外部库

    如果要使用cocos2dx的CCHttpClient来进行网络访问,则需要引入cocos2dx的相关库,详细步骤如下:

    右键单击项目->属性->c/c++->常规,在右边的附件包含目录中添加cocos2dx的extensions目录对应的路径。

    然后,右键单击项目->属性->链接器->输入,在右边的附件依赖项中添加libcurl_imp.lib和libExtensions.lib两个库,用分号隔开。

    如果不引入extensions文件夹,会出现找不到CCHttpClient的错误;如果不引入libcurl_imp.lib和libExtensions.lib两个库,编译项目时也会出现报错。另外注意引入头文件:

    #include "cocos-ext.h"  

    3.添加下载按钮和回调函数

    CCMenuItemImage *pDownloadItem = CCMenuItemImage::create(  
                "bt_blue_light.png",  
                "bt_blue_light.png",  
                this,  
                menu_selector(HelloWorld::menuDownloadCallback)  
            );  
            CC_BREAK_IF(!pDownloadItem);  
            CCSize pWinSize = CCDirector::sharedDirector()->getWinSize();  
          
            CCMenu* pDownloadMenu = CCMenu::create(pDownloadItem, NULL);  
            pDownloadMenu->setPosition(ccp(50  ,50));  
            CC_BREAK_IF(! pDownloadMenu);  
            this->addChild(pDownloadMenu, 1);

    添加按钮的回调函数:

    void HelloWorld::menuDownloadCallback(CCObject* pSender)  
    {  
        cocos2d::extension::CCHttpRequest* request = new cocos2d::extension::CCHttpRequest();  
        request->setUrl("http://www.oschina.net/action/api/news_list");  
        request->setRequestType(cocos2d::extension::CCHttpRequest::kHttpPost);  
        std::vector<std::string> headers;  
        headers.push_back("Content-Type: application/json; charset=utf-8");  
        request->setHeaders(headers);  
        const char* postData = "catalog=2&pageIndex=1&pageSize=5";  
        request->setRequestData(postData ,strlen(postData));  
        request->setResponseCallback(this, callfuncND_selector(HelloWorld::onHttpRequestCompleted));  
        request->setTag("Post_My_Data");  
        cocos2d::extension::CCHttpClient::getInstance()->send(request);  
        request->release();  
    }  

    按钮的回调函数里向服务器发起http请求了,request->setResponseCallback(this, callfuncND_selector(HelloWorld::onHttpRequestCompleted))一行代码,向请求结束时添加了onHttpRequestCompleted回调函数:

    4.为http request 结束增加回调函数并读取网络数据

    void HelloWorld::onHttpRequestCompleted(cocos2d::CCNode *sender ,void *data)  
    {  
        AllocConsole();  
        freopen("CONIN$", "r", stdin);  
        freopen("CONOUT$", "w", stdout);  
        freopen("CONOUT$", "w", stderr);  
        cocos2d::extension::CCHttpResponse *response = (cocos2d::extension::CCHttpResponse*)data;    
         if (!response)    
        {  
            return;    
        }   
         if (0 != strlen(response->getHttpRequest()->getTag()))   
        {  
            CCLog("%s completed", response->getHttpRequest()->getTag());  
        }  
         int statusCode = response->getResponseCode();  
         char statusString[64] = {};  
         sprintf(statusString ,"Http status code:%d ,tag = %s" ,statusCode ,response->getHttpRequest()->getTag());  
         CCLog("response code:%d" ,statusCode);  
         if (!response->isSucceed())  
         {  
             CCLog("response failed");  
             CCLog("error buffer:%s" ,response->getErrorBuffer());  
         }  
         std::vector<char> *buffer = response->getResponseData();  
         printf("Http response,dump data:");  
         std::string result = "";  
         for (unsigned int i = 0; i < buffer->size(); i ++)  
         {  
            printf("%c" ,(*buffer)[i]);  
         }  
    }  

    debug时就能看到reponse中服务器返回的数据了

    :上面操作遇到的问题

    (1) 1>libExtensions.lib(HttpClient.obj) : error LNK2019: 无法解析的外部符号 __imp__pthread_create,该符号在函数 "private: bool __thiscall cocos2d::extension::CCHttpClient::lazyInitThreadSemphore(void)" (?lazyInitThreadSemphore@CCHttpClient@extension@cocos2d@@AAE_NXZ) 中被引用。

    解决方法:刚开始这里我是不理解的,因为我以为lib库只需要添加一个libExtensions.lib就行...其实还需要其他俩个lib库文件,pthreadVCE2.lib,libcurl_imp.lib,添加方法(Vs2012):项目属性->链接器->输入->附加依赖项。

    (2)error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2”

    error:
    vtkCommon.lib(vtkSmartPointerBase.obj) : error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项:值“0”不匹配值“2”(cloudviewer.obj 中)
    1>vtkCommon.lib(vtkGarbageCollector.obj) : error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2”(cloudviewer.obj 中)
    1>vtkCommon.lib(vtkDebugLeaksManager.obj) : error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2”(cloudviewer.obj 中)
     
    错误原因是:Debug使用了Release的库文件。
    即使你连接库里面两个都添加着呢,但是release库文件放在了debug前面,也是出错的。默认按顺序使用库文件。
    类似错误:如release下使用了Debug的库文件,报错类似:
    error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“2”不匹配值“0”.
    解决方法:把Debug模式改为Release模式,编译生成之后,在项目文件夹中运行.exe文件(这里还报了找不到图片资源的错误,把图片资源拷贝到.exe文件同等目录下则可)

     

    #ifndef __HELLOWORLD_SCENE_H__
    #define __HELLOWORLD_SCENE_H__
    
    #include "cocos2d.h"
    
    #include "SimpleAudioEngine.h"
    #include "cocos-ext.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 recommand to return the exactly class pointer
        static cocos2d::CCScene* scene();
        
        // a selector callback
        void menuCloseCallback(CCObject* pSender);
    
        void onHttpRequestCompleted(cocos2d::CCNode *sender ,void *data);
    
    
        // implement the "static node()" method manually
        CREATE_FUNC(HelloWorld);
    };
    
    #endif  // __HELLOWORLD_SCENE_H__
    #include "HelloWorldScene.h"
    
    using namespace cocos2d;
    
    CCScene* HelloWorld::scene()
    {
        CCScene * scene = NULL;
        do 
        {
            // 'scene' is an autorelease object
            scene = CCScene::create();
            CC_BREAK_IF(! scene);
    
            // 'layer' is an autorelease object
            HelloWorld *layer = HelloWorld::create();
            CC_BREAK_IF(! layer);
    
            // add layer as a child to scene
            scene->addChild(layer);
        } while (0);
    
        // return the scene
        return scene;
    }
    
    // on "init" you need to initialize your instance
    bool HelloWorld::init()
    {
        bool bRet = false;
        do 
        {
            //////////////////////////////////////////////////////////////////////////
            // super init first
            //////////////////////////////////////////////////////////////////////////
    
            CC_BREAK_IF(! CCLayer::init());
    
            //////////////////////////////////////////////////////////////////////////
            // add your codes below...
            //////////////////////////////////////////////////////////////////////////
    
            // 1. Add a menu item with "X" image, which is clicked to quit the program.
    
            // Create a "close" menu item with close icon, it's an auto release object.
            CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
                "CloseNormal.png",
                "CloseSelected.png",
                this,
                menu_selector(HelloWorld::menuCloseCallback));
            CC_BREAK_IF(! pCloseItem);
    
            // Place the menu item bottom-right conner.
            pCloseItem->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width - 20, 20));
    
            // Create a menu with the "close" menu item, it's an auto release object.
            CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
            pMenu->setPosition(CCPointZero);
            CC_BREAK_IF(! pMenu);
    
            // Add the menu to HelloWorld layer as a child layer.
            this->addChild(pMenu, 1);
    
            // 2. Add a label shows "Hello World".
    
            // Create a label and initialize with string "Hello World".
            CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
            CC_BREAK_IF(! pLabel);
    
            // Get window size and place the label upper. 
            CCSize size = CCDirector::sharedDirector()->getWinSize();
            pLabel->setPosition(ccp(size.width / 2, size.height - 50));
    
            // Add the label to HelloWorld layer as a child layer.
            this->addChild(pLabel, 1);
    
            // 3. Add add a splash screen, show the cocos2d splash image.
            CCSprite* pSprite = CCSprite::create("HelloWorld.png");
            CC_BREAK_IF(! pSprite);
    
            // Place the sprite on the center of the screen
            pSprite->setPosition(ccp(size.width/2, size.height/2));
    
            // Add the sprite to HelloWorld layer as a child layer.
            this->addChild(pSprite, 0);
    
            bRet = true;
        } while (0);
    
        return bRet;
    }
    
    void HelloWorld::menuCloseCallback(CCObject* pSender)
    {
        // "close" menu item clicked
        //CCDirector::sharedDirector()->end();
        cocos2d::extension::CCHttpRequest* request = new cocos2d::extension::CCHttpRequest();  
        request->setUrl("http://www.oschina.net/action/api/news_list");  
        request->setRequestType(cocos2d::extension::CCHttpRequest::kHttpPost);  
        std::vector<std::string> headers;  
        headers.push_back("Content-Type: application/json; charset=utf-8");  
        request->setHeaders(headers);  
        const char* postData = "catalog=2&pageIndex=1&pageSize=5";  
        request->setRequestData(postData ,strlen(postData));  
        request->setResponseCallback(this, callfuncND_selector(HelloWorld::onHttpRequestCompleted));  
        request->setTag("Post_My_Data");  
        cocos2d::extension::CCHttpClient::getInstance()->send(request);  
        request->release(); 
    
    }
    
    void HelloWorld::onHttpRequestCompleted(cocos2d::CCNode *sender ,void *data)  
    {  
        AllocConsole();  
        freopen("CONIN$", "r", stdin);  
        freopen("CONOUT$", "w", stdout);  
        freopen("CONOUT$", "w", stderr);  
        cocos2d::extension::CCHttpResponse *response = (cocos2d::extension::CCHttpResponse*)data;    
        if (!response)    
        {  
            return;    
        }   
        if (0 != strlen(response->getHttpRequest()->getTag()))   
        {  
            CCLog("%s completed", response->getHttpRequest()->getTag());  
        }  
        int statusCode = response->getResponseCode();  
        char statusString[64] = {};  
        sprintf(statusString ,"Http status code:%d ,tag = %s" ,statusCode ,response->getHttpRequest()->getTag());  
        CCLog("response code:%d" ,statusCode);  
        if (!response->isSucceed())  
        {  
            CCLog("response failed");  
            CCLog("error buffer:%s" ,response->getErrorBuffer());  
        }  
        std::vector<char> *buffer = response->getResponseData();  
        printf("Http response,dump data:");  
        std::string result = "";  
        for (unsigned int i = 0; i < buffer->size(); i ++)  
        {  
            printf("%c" ,(*buffer)[i]);  
        }  
    }  

    二、使用libjson来解析网络json数据

  • 相关阅读:
    2. Add Two Numbers
    1. Two Sum
    leetcode 213. 打家劫舍 II JAVA
    leetcode 48. 旋转图像 java
    leetcode 45. 跳跃游戏 II JAVA
    leetcode 42. 接雨水 JAVA
    40. 组合总和 II leetcode JAVA
    24. 两两交换链表中的节点 leetcode
    1002. 查找常用字符 leecode
    leetcode 23. 合并K个排序链表 JAVA
  • 原文地址:https://www.cnblogs.com/yyxt/p/4092538.html
Copyright © 2011-2022 走看看