乱稿:PNG的数据结构和传统的数据结构

随手涂鸦的:

 

// HellowTest2008.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "CLock.h"

	/*
		V1表示旧的数据,V2表示扩充的数据
		旧数据nVersion表示为0, 扩充数据nVersion表示为1
	*/
struct Role1
{
	int V1n1;
	int V2n1;
};

struct Role2
{
	int V2n1;
	int V1n1;
};

class CRole
{
public:

private:

public:
	int V1n1;
	Role1 V1Role1;
	Role2 V1Role2;

	int V2n1;
	int V2n2;
	int V2n3;

private:

};

struct ChunkHead
{
	int nLen;
};

struct Chunk
{
	int nLen;
	int ChunkType;
	char Buffer;
	int CRC;
};

/*
	CSave表示一个已经从介质里读取出来的数据
*/
class CSave
{
public:
	CSave();
	void V1Read(CRole *pRole);
	void V1Write(CRole *pRole);

	void V2Read(CRole *pRole);
	

private:

public:
	/*
		V1
	*/
	int nVersion;
	char Buffer[1024];

	/*
		V2
	*/
	char V2Buffer[1024];   //这段的组成规则是ChunkHead|Chunk|Chunk|Chunk


private:

};

CSave::CSave()
{
	nVersion = 0;
}

void CSave::V1Read(CRole *pRole)
{
	/*
		BufferXXX表示产出一个最终结果值,这里我们不关心
	*/
	if(0==nVersion)
	{
		pRole->V1n1 = BufferXXX;
		/*
			每个结构是否有自己的序列化函数,这都不重要.关心的是一个写值的动作
		*/
		pRole->V1Role1.V1n1 = BufferXXX;
		pRole->V1Role1.V1n1 = BufferXXX;
	}

	/*
		扩充后,根据版本号来读取。
		这里的扩充一般会有两种情况,
		1.先扩充存储介质(比如数据库)
		2.先扩充代码,根据写入时来自动扩充数据库
		3.两边一起扩充

		如果是第一种,或许不要版本号,只要代码扩充好,然后把介质中新加的字段一个初始值,
		最后再精心修改下0==nVersion中的代码,算好介质中各种新加入的偏移值。这明显是最差的,把同介质之间的接口作用放大。

		如果是第二种(大多数下是),首先在读的时候仍然按照旧版本读(这个时候介质还没扩充),写入时按照
		新版本的写,然后修改版本号。

		如果是第三种,其实跟第一种类似,把同介质之间的接口作用放大。还要需要修改数据库代码。而数据库,更倾向看成是一个
		read,write的东西。只要关心数据和长度这两个参数即可.如果你想要查看,我觉得单独做个读取工具更好。而且这段读取的
		代码和你真正工程里读取数据的代码区别不大。

		下面代码给出第二种方法
	*/
	if(1==nVersion)
	{
		//先调用0==nVersion的函数读一遍
		pRole->V1Role1.V2n1 = BufferXXX;
		pRole->V2n1 = BufferXXX;
		//......
	}
	if( 2==nVersion )
	{
		//掉调用1==nVersion的。。
		//......
	}

	/*
		    这种用版本号的方法可以解决兼容的问题。但是不好的地方是让第二个版本的数据知道了第一个版本的数据,在
		数据的意义上它们是等同的,但是处理方法却变成了一种兼容的方式。同时,BufferXXX获取的接口中,也要从一个
		大数据里面取出对应的第二个版本数据。这些都明显增加了二次开发和扩充的代价。我以前一次工作中,数据库的设计
		是针对每个角色都有特别大的空间,防止以后扩充不够。结果每次增加新东西时,总要奔赴在修改各种旧的代码之间,
		即使你不用动它,它们也总是在你调试的时候跳来跳去。更可恶的是数据库的字段名,一开始只是简单的叫d1,d2,d3...dn,
		在核对各个字段上又浪费了不少时间。结果在扩充一些大功能的时候,另外建立了单独的空间,终于让它们享受一样的
		待遇了。
		    于是就想,为什么不把扩充的数据也当成一个全新的数据,只是让他们最终流向的Role结构不一样而已。完全可以
		让它们在新旧版本上的数据流程都一样,就像新写了一遍。
	*/
}

void CSave::V2Read(CRole *pRole)
{
	/*
		每个新加的数据只要按Chunk块排好,读、写总的函数完全不用变,每个人关心自己的
		HandleChunkType()即可。
	*/
	int nHasLen = 0;
	while(ChunkHead.nLen>nHasLen)
	{
		switch(Chunk.ChunkType)
		{
			HandleChunkType();
		}

		nHasLen += Chunk.nLen;
	}
}

void CSave::V1Write(CRole *pRole)
{
	/*
		写这里相对简单, 因为得到的都是最后一组、最新的数据。不做更多的阐述
	*/
}

int _tmain(int argc, _TCHAR* argv[])
{


	return 0;
}
 

但是,结合PNG的这种格式,仍然可以在游戏中做点事情。比如可以在扩充字段时,旧的方案需要修改2-3个点,完全可以改为只要修改一个点就够了。

修改的2-3个点包括,对数据库字段,SQL语句,变量的读取。如果有一些中间件变化得可能更多。

用一些小技巧,可以把这些修改点都集中到一个函数上。所以PNG还是有很大启发的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值