3d Game Walkman

3d图形渲染,网络引擎 — tonykee's Blog
随笔 - 45, 文章 - 0, 评论 - 309, 引用 - 0
数据加载中……

场景编辑器今天有了很好的进展,今天完成了地形塌陷和隆起的编辑,很兴奋

     摘要: 我的大地形的顶点的凹凸都可以用可视化的方式进行编辑了,庆祝一下~!!!  阅读全文

posted @ 2008-03-22 23:24 李侃 阅读(3395) | 评论 (11)编辑 收藏

晚上查了些资料,总算找到了MFC的游戏主循环,并好好研究了一把

网络和流协议,文件打包,读取,等等一工作基本工作总算是完工了,现在人物可以在我的场景中漫游,人物和人物之间通过网络能相互通讯,都已经实现了,但是回头再看看我的场景,实在是汗颜啊,场景十分单调,之前我是把场景对象放入到一个大的XML文件中的,完全手工来编辑XML,因为没有自己的场景编辑器,唉,一直下不了决心去写啊。

从今天开始,我打算自己自作一个场景编辑器,这可是一个大工程啊,不过应该是很值的,如果能完善,那才真就有引擎的架式了
可能你会问,现在也有很多免费的引擎还自己写?
是啊,我的无限大地形是核心,里面溶入了我太多的心血,很多实现和别人的自然“不完全兼容”了,如今是时候了……

进行了简单的设计之后,初步我打算用MDI窗口来制作场景编辑器,工具,参数调节面板在两旁,中间是D3D窗口
可才开始,就碰到问题了,天哪,MFC的主循环在哪里呢?How about Continuous Updating and Rending in MFC ?

不过功夫不负有心人,总算查到了,不过研究了好一会儿,还好有了结果

那么说到正题,怎么在MFC应用程序里面加入主循环呢,MFC的WinMain可是看不到的哦,消息处理都做了高度封装

其实也是有解决方法的,请看下文:

//你需要重写你的应用程序的Run()方法,把原方法里面的代码统统复制过来下面都是copy的CWinApp::Run()的源码

int CMapEditorApp::Run()
{
 //return CWinApp::Run();
 if (m_pMainWnd == NULL && AfxOleGetUserCtrl())
 {
  // Not launched /Embedding or /Automation, but has no main window!
  TRACE(traceAppMsg, 0, "Warning: m_pMainWnd is NULL in CWinApp::Run - quitting application.\n");
  AfxPostQuitMessage(0);
 }


 ASSERT_VALID(this);
 _AFX_THREAD_STATE* pState = AfxGetThreadState();

 // for tracking the idle time state
 BOOL bIdle = TRUE;
 LONG lIdleCount = 0;

 // acquire and dispatch messages until a WM_QUIT message is received.
 for (;;)
 {
 
 //偷看消息队列,如果没有消息的话,就执行游戏的主循环框架完成渲染的Update
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 while(!::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE))
  {
   //这里就可以放游戏的主循环了
   //GameLoop();
   DBWindowWrite("hello \r\n");
  }
//加入上面这段就搞定了,这个方法里面的其他的代码就不要去动他们的了,否则 ^_^!
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

  // phase1: check to see if we can do idle work,处理线程
  while (bIdle &&
   !::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE))
  {
   // call OnIdle while in bIdle state
   if (!OnIdle(lIdleCount++))
    bIdle = FALSE; // assume "no idle" state
  }
       
  // phase2: pump messages while available
  do
  {
   //windows自己的GetMessage消息处理机制,类似于消息泵,有消息就处理消息
   // pump message, but quit on WM_QUIT,
   if (!PumpMessage())
    return ExitInstance();

   // reset "no idle" state after pumping "normal" message
   //if (IsIdleMessage(&m_msgCur))
   if (IsIdleMessage(&(pState->m_msgCur)))
   {
    bIdle = TRUE;
    lIdleCount = 0;
   }

  } while (::PeekMessage(&(pState->m_msgCur), NULL, NULL, NULL, PM_NOREMOVE));
 }
}



这只是一个初步的开始,MFC可不是一个好东西,这到不算什么,地图编辑器才是最麻烦的东西。
唉~~~

无论如何,现在开工吧!

posted @ 2008-03-18 00:42 李侃 阅读(4465) | 评论 (13)编辑 收藏

关于资源包的新的比较完善的想法

     摘要: 关于资源包的新的比较完善的想法,模仿文件或数据库系统内部的数据组织结构,这里只是来谈谈原理和思路,我还没实现  阅读全文

posted @ 2008-03-12 11:58 李侃 阅读(1487) | 评论 (4)编辑 收藏

上午写了两个类,实现了自定义资源文件,数据流的存取,一个字爽

     摘要:   阅读全文

posted @ 2008-03-08 15:02 李侃 阅读(3054) | 评论 (6)编辑 收藏

这段时间加入了网络序列化的功能

前面的文章也提到了,看了一些服务器的大师级的代码,SmartStruct和自定义序列化的方式都有,如果单单只用C结构体作为语意数据载体固然可以,但很多网友也提出了很多质疑,最大的缺陷就是灵活性欠佳,诚然如此。

这段时间沉下了心,好好写了一些类主要有:

ObjectStream
StreamBuffer
SerializeMap
PacketStruct
...

等等,有了前人的经验,似乎也算比较顺利,一个个从基本的数字,
到数组,到char[] (很多资料也称之为:raw 二进制序列)
再到STL 的一系列容器的序列化工作都实现了

其中大量使用了模版类的泛型设计,不必要求一个可序列化的类必须继承某某基类,只需要具备以下:

 SerializeTag ComputeTag();
 bool Read(ObjectStream& stream);
 bool Write(ObjectStream& stream);
 DWORD GetLength(ObjectStream& stream);
 bool operator==(const PacketHeader &other) const;

五个方法就可以了,如果随意给你一个事先定义好的类,可以实现序列化吗?当然可以,只需要写出该类的
Wrapped Proxy,再添加这5个方法,就能通过 ObjectStream 和 StreamBuffer 实现该类的序列化了

这些是写完成了,回头看看自己已经写好的网络逻辑模块,犯愁了。
唉……,加入序列化,相当于高层次的通讯协议全都变了,包结构要改,所有的业务逻辑通讯代码随之要改。

之前的工作…… 又要写大量的重构代码了。

重构真是件痛苦的事情。
最坏的打算把之前的一些逻辑东西按现有思路重写一遍嘛,二次加工也许能应祸得福,把破旧看不过眼的地方重整理的更漂亮,好比重新装修升级一样

现在,只能告诉自己一件事,沉下心,沉注气。

posted @ 2008-03-01 17:15 李侃 阅读(1769) | 评论 (4)编辑 收藏

返璞归真,网络传输——结构体还是序列化?

虽然,网络编程里面的数据传送推荐用序列化,但我不用,还是选择结构体(返璞归真),有以下几点理由:
1.跨平台问题:
  序列化确实可以很好的跨语言平台,可大多数网络游戏不需要跨语言平台

2.别以为有了序列化就不需要结构体
  表面上序列化代码量小,按顺序读和写char int short LPCSTR ... 就好,逻辑对象写不写都无所谓,那就是大错而特错了
  待序列化的对象发送前的结构还是不可省略的序列化的过程就是 object->(按一定顺序拆分)write->bytes->(按拆分顺序组装)read->object的过程
 其实object还是不能省略,很多人写网络程序不注重逻辑对象结构,收到的一堆bytes按一定顺序读和写就完事了,这样虽然灵活,但缺乏结构,容易造成混乱,调试起来是灾难
   所以结构体(或类)还是省略不了的,所以:别以为有了序列化,就不需要结构体了。

3.结构体存在内存对齐和CPU不兼容的问题,可以避免
  的确结构体是有内存对齐的问题,存在兼容性问题,我可以选择pack(1)把内存对齐给关闭掉,避免兼容性问题,既然选择了iocp就不打算跨平台了,可以避免结构体平台兼容的问题

4.结构体调试起来方便很多,减少内存拷贝,效率高
  不用序列化可write和read的过程就不需要过多考虑(少写太多代码了),read write 就好像现代社会每个人每天都要穿衣服和脱衣服一样,原始社会需要吗?其实人类进化到原始裸奔状态才是最爽快的:)
  但还是要说句公道话:有人说序列化编码解码read write 需要耗费资源, 诚然这个过程基本等于赋值和内存拷贝,那点效率损失主要还在内存拷贝上,这点效率损失很小,不能作为序列化的缺点,当然如果涉及到数据加密那将是另外一个话题

5.结构体貌似呆板,发送数据限制多,发送变长数据就不方便,数据组织起来也不灵活
  我想这是很多人抛弃结构体,选择用序列化方式发送和接受数据的一个很重要的原因
  但:其实对于变长结构(子结构也是变长)的问题,用结构体来实现的确很麻烦,但并不代表不能实现
  我已经实现了,而且读和写变长子结构体嵌套任意多层都不成问题,可以存储复杂变长的数据结构,
  数据就如同能自动序列化一样方便,这个应该是技术难点,但细心去做是可以实现的

6.关于结构体指针
  游戏里面要发送的数据内存事先分配好的,不存在指针,深度复制更不用考虑,所以内存拷贝不会出错
  如果用到指针即使用序列化来实现也会面临同样的问题也占不了多少便宜,由于C++这们语言的特点,
  不象java那样有个标准实现,对于序列化本身没有一个统一的标准,所以可想而知,有人说:boost有它的序列化的实现
  其实那个实现不见得就合适你自己,如果真要做序列化,编码和解码的仿照那个过程自己写才最为牢靠,
  哪些指针对应的内存需要序列化那些不需要序列化,是个逻辑结构,需要自己说了算才好(好像扯远了点)
  说回游戏数据,既然不用需要他用到指针,结构体用来发送数据也没问题的

7 平台扩充问题
  退一万步的说:换了语言就基本上换了客户端,客户端的数据组织形式都要重写
  实在不行还可以考虑用xml json 编码等等一些跨平台的解决方案,现在所写的结构体是可以用来做数据接收的,只是发送的不再是结构体而已

8.综上所述
  如果需要跨语言平台,不用序列化(二进制流或xml, json文本等等)根本无法实现
  序列化的优点还是非常多的.如果主要是跨平台和语言自定义读写规则,根据需要读写对象的某一部分数据,
  空间浪费少,不存在内存对齐问题等诸多优点,缺点就是拐弯抹角,代码量大,调试不方便


权衡了良久
  数据如果能组织的合理,而且没有跨语言平台的要求,用结构体也未尝不可,毕竟数据发送直来直去还是方便些,减少内存拷贝,效率也高了很多
  特别是调试起来容易太多了,衡量利弊我还是放弃了序列化,选择了原始的结构体,只是难在数据的组织(好在基本已经克服了)

我知道:序列化很好很强大,很多网络程序高手根本不屑于直接发一个逻辑结构体,用这种方式就好象是旁门左道,狗肉上不了大雅之堂一样,狗肉还是很多人喜欢吃的嘛,:)。

我还是返璞归真选择了结构体

一句话:物尽其用,用的恰当,够用就好。

如果有什么不对,敬请拍砖,莫要客气

posted @ 2008-02-17 12:53 李侃 阅读(8200) | 评论 (30)编辑 收藏

这两天改正了过去遗留的两个BUG,畅快啊

过去的老代码库里隐藏很深的臭虫,被我逐个抓了出来,一共三个用了我足足两天的时间,虽然两天才找了3个bug但自我感觉很值得。
程序运行起来不会象过去那样不稳定了。
还是很畅快的,这下我好集中精力攻克后面的内容

这次带给我的经验是,当程序框架越来越大的时候
一个错误可能是由几个模块的任何一个模块导致的,测试任何一个大的模块都是伤精动骨的事
一个桩模块可能对应N个驱动模块,测起来很不容易。
一开始做好单元测试的工作太重要了。

新的问题总是会不断的出现,也得要一个个的扫除之~!!!!!

posted @ 2008-01-29 18:01 李侃 阅读(540) | 评论 (0)编辑 收藏

今天做了一个Struct结构,作为游戏里面的包容器来使用,可以一次发送多个逻辑结构信息了,爽啊!!!

     摘要: 做了个包容器,一次可以发多个变长逻辑结构了体了,爽啊。  阅读全文

posted @ 2008-01-24 00:21 李侃 阅读(2035) | 评论 (2)编辑 收藏

今天完成了下线通知功能

过去用户断开,其他用户不知道,也就出现了鬼影,现在刚有时间完善了这块,某人一下线,周围的人立马就知道了,另外人物移动和周围的人物通讯,已经基本实现,只是有些细节部分还不完善。这是个细致活。还要继续加油啊~!!!

posted @ 2008-01-17 13:13 李侃 阅读(704) | 评论 (5)编辑 收藏

对于线程资源竞争的改进

     摘要: 对于线程资源共用问题,实际上也没有一个最完美的解决方案,没有最适合的,只有根据情况来分析,找合适的方法,我最近在做角色之间的位置信息交换,已经实现了一部分了。感觉很爽  阅读全文

posted @ 2008-01-10 20:36 李侃 阅读(880) | 评论 (1)编辑 收藏

仅列出标题
共5页: 1 2 3 4 5