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自己创建)

Cocos2d-x中配置Protobuf(win32和android)_第1张图片

然后点击Configure按钮

Cocos2d-x中配置Protobuf(win32和android)_第2张图片

这里选2017,其它版本也可以,根据自己电脑装的VS为主。平台选  win32 然后点Finish 

Cocos2d-x中配置Protobuf(win32和android)_第3张图片

会有错误,我们把 BULID_TESTS去掉 然后 点Generate

Cocos2d-x中配置Protobuf(win32和android)_第4张图片

这样就编译成VS项目了

打开目录C:\protobuf-3.12.0-rc2\cmake\vs2017

Cocos2d-x中配置Protobuf(win32和android)_第5张图片

 

用VS2017打开protobuf.sln项目文件:

Cocos2d-x中配置Protobuf(win32和android)_第6张图片

选择release win32平台然后 生成解决方案(之所以先用VS编译,是为了方便以后在VS中调试COCOS项目,最后再移置到Android。)

编译成功后 在 C:\protobuf-3.12.0-rc2\cmake\vs2017\Release 有编译好的库和protoc.exe.

Cocos2d-x中配置Protobuf(win32和android)_第7张图片
我们用记事本创建一个 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,

Cocos2d-x中配置Protobuf(win32和android)_第8张图片

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),

Cocos2d-x中配置Protobuf(win32和android)_第9张图片

 

Cocos2d-x中配置Protobuf(win32和android)_第10张图片

 我把game.pb.cc game.pb.h,这两个文件复制到Classes目录中,再用VS打开 pro.win32目录下的 Game_JJDDZ.sln项目,把这两个文件包含进去,

再打开  game.pb.h文件加入宏定义 :#define PROTOBUF_USE_DLLS,其它错误不用管它。

Cocos2d-x中配置Protobuf(win32和android)_第11张图片

在VS中配置Protobuf,先把 C:\protobuf-3.12.0-rc2\src 中的 google目录复制到Classes目录下,并包含到项目中,还要引用DLL 和 Lib

 

Cocos2d-x中配置Protobuf(win32和android)_第12张图片

 

 

Cocos2d-x中配置Protobuf(win32和android)_第13张图片

 

Cocos2d-x中配置Protobuf(win32和android)_第14张图片

把DLL也引入进来

Cocos2d-x中配置Protobuf(win32和android)_第15张图片

经过上面的操作,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  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 文件,但我测试并不是修改这个文件,并且好像没有用上:

Cocos2d-x中配置Protobuf(win32和android)_第16张图片

我只修改项目目录中的 CMakeLists.txt就可以了:

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

Cocos2d-x中配置Protobuf(win32和android)_第17张图片

 

2.加入所有头文件:

 

Cocos2d-x中配置Protobuf(win32和android)_第18张图片

 

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

Cocos2d-x中配置Protobuf(win32和android)_第19张图片

Cocos2d-x中配置Protobuf(win32和android)_第20张图片

有2处。

还有一项要配置:NinJa

Cocos2d-x中配置Protobuf(win32和android)_第21张图片

下载到c:\ninja-win,并添加环境变量

Cocos2d-x中配置Protobuf(win32和android)_第22张图片

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

添加一个宏:

#ifndef HAVE_PTHREAD
#define HAVE_PTHREAD
#endif

Cocos2d-x中配置Protobuf(win32和android)_第23张图片

经过上面操作后就可以编译APK了,进入CMD 输入命令:

cocos compile -p android

Cocos2d-x中配置Protobuf(win32和android)_第24张图片

经过几分钟等待,当出现下面时表示已编译成功,build successful:

Cocos2d-x中配置Protobuf(win32和android)_第25张图片

以上就把单机斗地主游戏移置为网络游戏的经历,

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处。

如有错误欢迎指导改正。

 

 

 

 

你可能感兴趣的:(protobuf,cocos2d-x,Android)