Cocos2d-x中配置Protobuf(win32和android)

今天講一下在cocos2d-x-3.17.2項目中配置 protobuf-3.12.0-rc2。

1.下載cocos2d-x-3.17.2:https://www.cocos.com/cocos2dx 解壓到:c:/cocos2d-x-3.17.2

2.下載protobuf-3.12.0-rc2:https://github.com/protocolbuffers/protobuf/releases/,解壓到:c:/protobuf-3.12.0-rc2

要使cocos2d-x-3.17.2能編譯Android 還要配置JDK 、ADK 、 NDK  ,這裏就不介紹。

我們首先用CMAKE把protobuf編譯成VS2017 項目:

 

打開CMAKE,源碼目錄選擇:C:/protobuf-3.12.0-rc2/cmake

編譯目錄選擇:C:/protobuf-3.12.0-rc2/cmake/vs2017(vs2017自己創建)

然後點擊Configure按鈕

這裏選2017,其它版本也可以,根據自己電腦裝的VS爲主。平臺選  win32 然後點Finish 

會有錯誤,我們把 BULID_TESTS去掉 然後 點Generate

這樣就編譯成VS項目了

打開目錄C:\protobuf-3.12.0-rc2\cmake\vs2017

 

用VS2017打開protobuf.sln項目文件:

選擇release win32平臺然後 生成解決方案(之所以先用VS編譯,是爲了方便以後在VS中調試COCOS項目,最後再移置到Android。)

編譯成功後 在 C:\protobuf-3.12.0-rc2\cmake\vs2017\Release 有編譯好的庫和protoc.exe.


我們用記事本創建一個 game.proto文本文件:

syntax = "proto3";
package Game_DDZ;
message Packet{
    int32 id = 1;
    int32 len= 2;
    bytes data= 3;
  repeated bytes datas=4;
}
message Player{    
    int32  desk= 1;  
    int32  seat= 2;   
    bool  ready=3; 
    string  name=4;
    int32 money=5;
    int32 imgnum=6;
    int32 baseScore=7;
}

message PlayerList{
  repeated Player Players= 1;
}

message Cards{
   int32 seat=1;
  repeated int32 card=2;
}

message CardList{
  repeated Cards Card= 1;
}

//一個牌型
message  CardNode {
	int32 cardType=1;
	int32 mainNum=2;
	int32 value=3;
	int32 seralNum=4;
	int32 subNum=5;
	float aggregate=6;
	repeated int32 cards=7;
}

這裏就是一些數據結構和類型,

package Game_DDZ;//這個相當於命名空間

message Packet{ //相當於 Packet結構體
    int32 id = 1;//數字類型
    int32 len= 2;//數字類型
    bytes data= 3;//字節類型(也可以理解爲字符類型)
  repeated bytes datas=4; epeated 相當於類型爲 bytes 的數組,
}//1 2 3 4 代表編號

其實這是個通用結構,可以用來裝所有類型的結構體,數字 字符 數組類型都可以,因爲protobuf中所有的結構體都可以序列爲string , 我們又可以把它裝入 datas中,在網絡傳輸中,知道id是什麼數據包,再爲datas解包爲指定結構。

然後再建一個 game.bat文件內容爲:

protoc --cpp_out=./ game.proto

然後雙擊生成2個文件:game.pb.cc  game.pb.h,

portobuf文件就生成了,下面介紹使用方法:

首先我們用cocos生成一個 cpp項目,當然在這之前,你要安裝好 python2.7  Jdk ADK Ndk,在CMD中輸入下面命令:

cocos new Game_JJDDZ -p com.game.jjddz -l cpp -d d:/app

這句命令的意思爲 新建一個項目名稱爲 Game_JJDDZ ,包名爲:com.game.jjddz 開發語言爲:c++  目錄在 d:/app(後面實例我用的是我自己做好的項目目錄:c:/app),

 

 我把game.pb.cc game.pb.h,這兩個文件複製到Classes目錄中,再用VS打開 pro.win32目錄下的 Game_JJDDZ.sln項目,把這兩個文件包含進去,

再打開  game.pb.h文件加入宏定義 :#define PROTOBUF_USE_DLLS,其它錯誤不用管它。

在VS中配置Protobuf,先把 C:\protobuf-3.12.0-rc2\src 中的 google目錄複製到Classes目錄下,幷包含到項目中,還要引用DLL 和 Lib

 

 

 

 

把DLL也引入進來

經過上面的操作,VS中就可以使用protobuf 了,現在講如何使用,以網絡打牌,C++Socket爲例:

1.封包:

假如程序有一個結構體:

//牌型結構體
//cardType是牌型,只有三種,王炸,單純,連續;
//value 是牌型的值,單純類型爲牌的面值,連續類型爲起始牌的面值,相同牌型以此比較大小;
//mainNum是主牌張數,比如三帶二和飛機裏mainNum=3, 連對時, mainNum=2;
//seralNum是連續張數,seralNum=1是單純牌型,順子時seralNum>=5;
//subNum是副牌數目,三帶一和四帶二時subNum=1,三帶二和四帶兩對時,subNum=2;
//cards是牌型裏包括的牌的牌值,比如三帶一時,可能就是[3, 16, 42, 4], 連對時,可能就是 [3, 16, 4, 17, 5, 18, 6, 19]等等
//aggregate是權重,根據不同的情況求出權重,再按照權重排序所有牌型。可以是本牌型的權重,也可以是手牌裏除了本牌型外剩下所有牌加在一起的權重。

struct CardNode {
	int32_t cardType;
	int32_t mainNum;
	int32_t value;
	int32_t seralNum;
	int32_t subNum;
	float aggregate;
	std::vector<int>  cards;
};

game.proto中的定義:

syntax = "proto3";
package Game_DDZ;
message Packet{
    int32 id = 1;
    int32 len= 2;
    bytes data= 3;
  repeated bytes datas=4;
}

//一個牌型
message  CardNode {
	int32 cardType=1;
	int32 mainNum=2;
	int32 value=3;
	int32 seralNum=4;
	int32 subNum=5;
	float aggregate=6;
	repeated int32 cards=7;
}

現在用戶打出了一個牌型爲  mCardNode:

    Game_DDZ::Packet gamePacket;
	gamePacket.set_id(7);//7爲出牌
	gamePacket.set_len(mCardGame->seatId);//mCardGame->seatId 爲打牌人的位置
	Game_DDZ::CardNode gameCardNode;
	gameCardNode.set_cardtype(mCardNode.cardType);
	gameCardNode.set_mainnum(mCardNode.mainNum);
	gameCardNode.set_value(mCardNode.value);
	gameCardNode.set_seralnum(mCardNode.seralNum);
	gameCardNode.set_subnum(mCardNode.subNum);
	gameCardNode.set_aggregate(mCardNode.aggregate);
    for (int value : mCardNode.cards)
	{
		gameCardNode.add_cards(value);
    }
    string cardData;
	gameCardNode.SerializePartialToString(&cardData);//把Game_DDZ::CardNode序列化爲要要string
	gamePacket.set_data(cardData);//裝入 bytes(data)中 如果mCardNode爲數組 就一個一個裝入:datas中(用 add_datas())。
	string packetData;
	gamePacket.SerializeToString(&packetData);
	mTcpSocket->SendMsg((void *)packetData.c_str(), gamePacket.ByteSize());
	mTcpSocket->Flush();

這樣一個包就封好了,並通過Socket發送走了,下面看解包:

2.解包:

    char buffer[_MAX_MSGSIZE] = { 0 };
	int inlen = recv(mTcpSocket->GetSocket(), buffer, _MAX_MSGSIZE, 0);
	if (inlen > 0)
	{
		Game_DDZ::Packet gamePacket;
		gamePacket.ParseFromArray(buffer, inlen);
		int cmd = gamePacket.id();
		//0 一般信息
		//1準備信息

		switch (cmd)
		{
        case 7://接收出的牌
		{

			Game_DDZ::CardNode gameCardNode;
			gameCardNode.ParseFromString(gamePacket.data());
			CardNode mycard;
			mycard.cardType = gameCardNode.cardtype();
			mycard.mainNum = gameCardNode.mainnum();
			mycard.value = gameCardNode.value();
			mycard.seralNum = gameCardNode.seralnum();
			mycard.subNum = gameCardNode.subnum();
			mycard.aggregate = gameCardNode.aggregate();

			for (int card : gameCardNode.cards())
			{
				mycard.cards.push_back(card);
			}
        }
        break;
        ...
        ...
        ...
        }
}

這樣一個傳輸協議就形成了。

下面講如何移置到Android中,確保安裝了 JDK NDK ADK並設置好環境變量:

網上說的要修改 android.mk 文件,但我測試並不是修改這個文件,並且好像沒有用上:

我只修改項目目錄中的 CMakeLists.txt就可以了:

1.加入項目中所有源文件:

 

2.加入所有頭文件:

 

 

protobuf要加哪些文件可以到 C:\protobuf-3.12.0-rc2\src\Makefile.am中查看找到 libprotobuf_lite_la_SOURCES標記:

有2處。

還有一項要配置:NinJa

下載到c:\ninja-win,並添加環境變量

另外還要修改一個protobuf文件,C:\app\Game_JJDDZ\Classes\google\protobuf\stubs\common.h

添加一個宏:

#ifndef HAVE_PTHREAD
#define HAVE_PTHREAD
#endif

經過上面操作後就可以編譯APK了,進入CMD 輸入命令:

cocos compile -p android

經過幾分鐘等待,當出現下面時表示已編譯成功,build successful:

以上就把單機鬥地主遊戲移置爲網絡遊戲的經歷,

Window版本:Win10 64位

VS版本:2017 Enterprise

cocos2d-x版本:cocos2d-x-3.17.2

Protobuf版本:protobuf-3.12.0-rc2

Android SDK版本:android-18

Android NDK版本:android-ndk-r13b

JDK版本:jdk1.8.0_131

ninj版本:ninj-win

以上一個都不能少,在編譯中也許會有錯誤,我們要注意以下幾點:

1.代碼中不能有除C++11 cocos2d-x以外的數據類型,如VS的大部分數據類型(INT32 CString ...)

2. JDK ADK NDK環境變量要配置好,還有ninja。

3.項目中的所有文件都要包含到時項目根目錄文件CMakeLists.txt中,頭文件也包含進去,protobuf可根據Makefile.am中 libprotobuf_lite_la_SOURCES標記,有2處。

如有錯誤歡迎指導改正。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章