Profil de Duo一心天堂PhotosBlogListes Outils Aide

Duo Maxwell

Occupation
Centres d'intérêt 
年轻的心给我热情,成熟的思考让我变的冷漠,一张高中生般的脸上洋溢的永远是我不屑的微笑
Photo 1 sur 1

Flux

Le propriétaire n'a spécifié aucun flux pour ce module.

Lecteur Windows Media

一心天堂

用心去实现一个天堂

月历

Chargement...
17 novembre

关于使用lib

      周末打算把数据解析和属性修改的内容做完的,不过一如既往的,还是没有完成目标T_T,发现涉及的XML库的调用挺麻烦,所以权衡再三,决定对这个库做小部分的重构,因此,周末的时间就在重构上用完了。写了有些时间的东西,要重构起来就有点回忆不清,这次重构完,有必要留一套比较全的UML设计文档了。

      另外在编译,和重新启动单元测试程序后,对库的链接出了点问题。

      一。是一定要慎用#pragma comment来加载库,因为这东西的路径是相对与自己的,一旦是link多个库,代码里的这个路径很容易出问题。

      二。使用库的时候一定要注意 ,编译时的/MTD /MD选项要一致,否则容易报LNK2005很莫名的错误。我花了一个晚上检查代码,最终也还是没有查出LNK2005的重定义从何而来,最后才发现时项目中的一个设置在版本控制时被覆盖了,结果造成一个库用的/MTD,一个/MD,改成一致后,莫名的LNK2005就解决了。

11 novembre

数据解析

      昨天开始抽空写了数据解析程序,原本的XML系统中的数据节点的设计部太适合我目前想做的关于自解析和填充数据的用法。其实这个问题早在设计游戏内的数据结构时我就发现了,也想好怎么改了,只是一直没有进入数据结构加载阶段,也就没动这块程序。昨天把XML系统中的设计修改了,把rpg引擎里的基类结构写完。用了一种pump的推动方式来自动加载数据对象中所有数据。今天想把从游戏初始化到加载数据的部分都做完。不知道晚上我的笔记本床上桌到了没,否则就可以在床上写程序了。

      另外研究了下位移贴图,和细分曲面,不错,长知识了。发现自己对曲面的计算几何还是不行,完全看不懂论文里的计算,要补习下

9 novembre

泄漏解决

    把泄漏搞定,发现文件系统中有一个不太方便的接口调用,修改了下,下午开始写数据导出结构,为XML系统的加入做准备……
7 novembre

泄漏,泄漏!

    哦,又是内存泄露。昨天今天,在发布能编辑文档后,突然发现了5个内存泄露,其中三个是因为我有意暂时不加释放程序,造成的。还是习惯不好啊。后面两个就诡异了。一个是在DLL内部调用的。其诡异表现在一个丝毫没有被执行到的new,造成了泄漏。百思不得其解,和riger前辈交流了一下午,没有结果,最后认为是编译器bug。今天早上还是不死心,心里总有个疙瘩。抱着再试一次的想法,我依旧使用_CrtSetbreakAlloc试图定位。(昨天试过,结果没断下来)。经过一个早上的折腾,最后发现没定位下来的原因,是其内存分配的ID早于我的CRT调试函数,提醒我了,所以在构造APP的时候调用,结果定位,最后发现造成泄漏的是我给静态变量来了个new,而恰好没有调用相应的释放函数。而两个内存泄露,一个是因为我包含了含该变量的cpp文件,而在DLL内因为再次调用,但不在同一地址空间,因为两次执行。最后还是自己粗心了。不过编译器的报告确实存在误导,它根本没有检查出静态变量的泄露,而是报我成员函数内new的泄露,这算编译器一个警告的不完善的bug吧。
     哎,不过还是有内存泄露,今天后来去拿笔记本了,明天还得把电脑修修,估计晚上才有时间改这两个bug吧,我实在很讨厌内存泄露啊。
6 novembre

XML显示

    旅游归来,一切照旧,公司里忙着解决音效的问题,回到家电脑坏了,工作不得。加上有点心事,在周四开始稍微空点后,才开始写了点东西。调整了下加载游戏逻辑的DLL加载结构,然后将文本内容显示出来,同志们,你们可以编辑XML了。
29 octobre

windbg+vmware单机调试内核

    最近玩debug有点走火入魔了,这两天一直在搞内核调试,希望对内核的分析可以帮助找到应用崩溃的线索。试了下用windbg+vmvare虚拟机调试内核,一开始windbg怎么都连不上vmware,最后发现vmware虚拟的串口要设成The end is server,我设成client了,T_T

windbg内核调试

    windbg进行内核调试,一般要双机,很多时候是用来调试驱动,或是操作系统内核的。但是最近查了很多网上资料,本机内核调试应用程序的dmp文件的话,能提供非常多的有用信息。双机调试环境毕竟有点困难,要么用windbg+vware。但windbg非常奇怪,切换到kenerl mode后不能attach process也算了(这是user mode)。但居然连dmp都不让打开。所以如果用windbg进行本机内核调试,要使用.opendump命令,手动加载dmp文件。
26 octobre

光环3真是不错

    光环3真的出乎我的意料,尽然这么好玩,感觉超越了战争机器。有载具使用,玩起来感觉就是不一样。除了丰富的武器,战场上随意可以抢夺敌方的战斗载具,小到摩托,大到飞机坦克,只有你能遇见的,都可以强行借来一用。同时BOSS战都是巨大的敌方作战机动兵器,非常过瘾。我最喜欢的就是拆下固定座的格林机关炮,然后跳进敌人阵地把对方好好的洗礼一下。另外强到亡魂号也很爽。终于体会到光环3的乐趣了,原来做个超级英雄真是不错。哈哈
25 octobre

DLL调用成功

    DLL插件的添加,加载,调用,今天晚上测试成功,很好,这样编辑器就有了更大的扩展性!
    下午去见了下新的美术,希望新的力量加强我们的Team!

编辑器插件框架设计

    本来我并没有意识到会设计插件。原本的想法,只是想把界面功能和逻辑分开。但在设计过程中,发现,实现该功能用插件是最好的。使用DLL加载插件后,可以进一步提高编辑器的可重用性,可以支持以后的游戏逻辑。所以在这个原则下,我设计了DLL方式加载插件,通过对DLL导出类来实现。这种方式可以将逻辑,引擎,编辑器划分的更清楚。今天只把这个思路定下来后,实现了一个小类的DLL加载,底层搭的越来越细了。
24 octobre

感叹中国的大环境

    在国内,做为一技术人员,生存环境真的不太好。
    今天去amazon上逛了圈,见识了,多少好的书,好的资料,我们在国内看都没看到过。当别人已经开始把理论研究运用到实践中,我们可爱的无数憧憬向往技术的人,还只能热衷于QQ群,论坛上的讨论,或闭门造车,或纸上谈兵。当然了,我们有更多的技术人员可能碍于不怎么滴的英语水平,但总的来说,在国内,想看点好书真不容易,啥时候这方面才能接轨。
    由此想到的是国内的游戏业,如今,游戏企业正在面临竞争白热化的程度,也许过不了几年就会出现大洗牌。但,如同其他行业一样,这个行业的大鳄们正抹杀着游戏业的技术性,创造性。一切向前看。无奈的正确……
22 octobre

编辑器框架大体完成

    把我要用的MFC类,控件都添加进去了,接下去就是写编辑器的逻辑了,当然这是要和引擎同步的。
    最近忙的一塌糊涂,公司的程序代码BUG已经要我用反汇编和内核模式才能调试了。所以自己的项目更新很慢了。今天有点事,请假在家。抽空把编辑器的一点遗留问题解决。总算像点样子了。其实心里很急,接下去我想做alpha混合功能,没有编辑器不好看效果,好在终于完成,可以吧效果加进去看看。计划,Xml文档编辑,和贴图编辑一起同步进行。
    虽然现在很慢,但都是为了以后打基础。忍了。
 
    最近和同行交流很多,对这个行业有了新的看法。恩,希望我的选择没错
6 octobre

编辑器进展

    十一长假,免不了串串门,呵呵,今天开始算是没活动了,安心写程序。
    其实3号的时候已经在写了,不过在用一个控件的时候碰到了一个MFC非常诡异的问题……花了两天时间研究,结果是问题虽然解决,获得了我要的功能,但为什么会造成这个问题的原因仍旧不很明了,推测只是MFC的内部封装干的好事,和CSDN上一个朋友讨论了很久,最后只能暂时这样解决。真要知道原因,估计我得把MFC的内部机制好好跟踪一遍,没有这个心情了,这个灵异现象已经拖慢了我的进度。
    总之,以后控件初始话,同志们尽量在OnInitDialog里完成,切记。
    编辑器里已经可以展开文件数据路径,这样就可以实现下一步点击文件进行数据编辑功能了。另外添加了另一个控件PropTree,将来用作属性显示和编辑用。
29 septembre

编辑器框架

    这周主要在搞编辑器框架,MFC开发,恩,用了一个老外的组件,我还是想把编辑器做的美观点,因为公司那个太丑了~~~。打算使用一个stack窗口,上面是文件数据列表,下面是数据属性,图形数据的话有预览。View里面显示文本或是图形。
20 septembre

从内存数据生成贴图

    前几天完成直接加载贴图文件,今天把内存中的图形文件生成surface来生成贴图完成。我们可以自定义自己的贴图格式了……
    当中麻烦的还是JPEG得解压问题,一开始生成的图片颜色都发生了色偏。尝试了几次不行,最后只好去老外的论坛发帖求助,谁让这玩意是他们搞的。应用方面的说明老外写的相当少,包括Q&A。听一国外的好友说,老外都比较天才,不屑写这些说明,呵呵……
    嘛,反正后来晚上回到家冷静思考了下,又做了几个实验,最后被我试出来了,D3DFORMAT的内存格式问题,现在已经解决,放出最新截图,还是当年蓝老师说的对,Bug必有因果,慢慢静心分析,总能解决
 
另,N个MM说我们的LOGo可爱,印象深刻了,哈哈
18 septembre

2D场景显示完成

    本周忙公司项目的盛大β版本,通宵了一天,剩余几天也几乎围绕这个事情,所以场景显示的制作明显慢了,昨天把整个显示场景的过程调试通过完成,今天把结构和测试代码整理了下……
    添加了viewport相关的类。顺便感谢lim帮我解决了一个bug
12 septembre

今天郁闷了……

    我实在对libjpeg这库没想法了。事实证明我以前说过的两件事还是有道理的:1.用别人的库还不如自己写;2.标准在手就是NB。这个老外用C写的库,功能真的很全啊,但这也写的太耦合了,换句话说,你就必须按他的方式调用,否则这程序就出错。但这却让我的程序结构不能按预先设计的去写了,想到以前用havok那会,哎,谁让我们没有拿到JPEG标准,只好按别人的规则游戏了
    程序的结构性被打破了,很不爽啊……

jpeg lib库搞定,睡觉了

    下午就因为libjpeg的C函数连接报错,下班匆忙也没来得及搞定,回家上网查了下资料,搞定!另外一个引用计数也发生了连接出错,最后是因为我把库文件的输出地址给弄错了,好在都搞完,睡觉咯,明天做显示了……
 
转一篇资料:
 
C和C++函数的相互引用 extern "c"深入理解

1.引言

  C++语言的创建初衷是“a better C”,但是这并不意味着C++中类似C语言的全局变量和函数所采用的编译和连接方式与C语言完全相同。作为一种欲与C兼容的语言,C++保留了一部分过程 式语言的特点(被世人称为“不彻底地面向对象”),因而它可以定义不属于任何类的全局变量和函数。但是,C++毕竟是一种面向对象的程序设计语言,为了支 持函数的重载,C++对全局函数的处理方式与C有明显的不同。

2.从标准头文件说起
某企业曾经给出如下的一道面试题:为什么标准头文件都有类似以下的结构?

#ifndef __INCvxWorksh
#define __INCvxWorksh
#ifdef __cplusplus
extern "C" {
#endif
/*...*/
#ifdef __cplusplus
}
#endif
#endif /* __INCvxWorksh */

显然,头文件中的编译宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用是防止该头文件被重复引用。那么


#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif

的作用又是什么呢?我们将在下文一一道来。

3.深层揭密extern "C"

  extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。让我们来详细解读这两重含义。

被extern "C"限定的函数或变量是extern类型的;

extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。记住,下列语句:

  extern int a;


仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配内存空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出现连接错误。

通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。例如,如果模块B欲引用该模块A中定义的全局变量和函数 时只需包含模块A的头文件即可。这样,模块B中调用模块A中的函数时,在编译阶段,模块B虽然找不到该函数,但是并不会报错;它会在连接阶段中从模块A编 译生成的目标代码中找到此函数。

与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。

被extern "C"修饰的变量和函数是按照C语言方式编译和连接的;

未加extern “C”声明时的编译方式

首先看看C++中对类似C的函数是怎样编译的。

作为一种面向对象的语言,C++支持函数重载,而过程式语言C则不支持。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为:

void foo( int x, int y );


该函数被C编译器编译后在符号库中的名字为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。

_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。例如,在C++中,函数void foo( int x, int y )与void foo( int x, float y )编译生成的符号是不相同的,后者为_foo_int_float。

同样地,C++中的变量 除支持局部变量外,还支持类成员变量和全局变量。用户所编写程序的类成员变量可能与全局变量同名,我们以"."来区分。而本质上,编译器在进行编译时,与 函数的处理相似,也为类中的变量取了一个独一无二的名字,这个名字与用户程序中同名的全局变量名字不同。

未加extern "C"声明时的连接方式

假设在C++中,模块A的头文件如下:

// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
int foo( int x, int y );
#endif


在模块B中引用该函数:

// 模块B实现文件 moduleB.cpp
#include "moduleA.h"
foo(2,3);


实际上,在连接阶段,连接器会从模块A生成的目标文件moduleA.obj中寻找_foo_int_int这样的符号!

加extern "C"声明后的编译和连接方式

加extern "C"声明后,模块A的头文件变为:

// 模块A头文件 moduleA.h
#ifndef MODULE_A_H
#define MODULE_A_H
extern "C" int foo( int x, int y );
#endif


在模块B的实现文件中仍然调用foo( 2,3 ),其结果是:

(1)模块A编译生成foo的目标代码时,没有对其名字进行特殊处理,采用了C语言的方式;

(2)连接器在为模块B的目标代码寻找foo(2,3)调用时,寻找的是未经修改的符号名_foo。

如果在模块A中函数声明了foo为extern "C"类型,而模块B中包含的是extern int foo( int x, int y ) ,则模块B找不到模块A中的函数;反之亦然。

所以,可以用一句话概括extern “C”这个声明的真实目的(任何语言中的任何语法特性的诞生都不是随意而为的,来源于真实世界的需求驱动。我们在思考问题时,不能只停留在这个语言是怎么 做的,还要问一问它为什么要这么做,动机是什么,这样我们可以更深入地理解许多问题):
实现C++与C及其它语言的混合编程。
明白了C++中extern "C"的设立动机,我们下面来具体分析extern "C"通常的使用技巧。

4.extern "C"的惯用法

  (1)在C++中引用C语言中的函数和变量,在包含C语言头文件(假设为cExample.h)时,需进行下列处理:

extern "C"
{
#include "cExample.h"
}


而在C语言的头文件中,对其外部函数只能指定为extern类型,C语言中不支持extern "C"声明,在.c文件中包含了extern "C"时会出现编译语法错误。

笔者编写的C++引用C函数例子工程中包含的三个文件的源代码如下:

/* c语言头文件:cExample.h */
#ifndef C_EXAMPLE_H
#define C_EXAMPLE_H
extern int add(int x,int y);
#endif
/* c语言实现文件:cExample.c */
#include "cExample.h"
int add( int x, int y )
{
return x + y;
}
// c++实现文件,调用add:cppFile.cpp
extern "C"
{
#include "cExample.h"
}
int main(int argc, char* argv[])
{
add(2,3);
return 0;
}


如果C++调用一个C语言编写的.DLL时,当包括.DLL的头文件或声明接口函数时,应加extern "C" { }。

(2)在C中引用C++语言中的函数和变量时,C++的头文件需添加extern "C",但是在C语言中不能直接引用声明了extern "C"的该头文件,应该仅将C文件中将C++中定义的extern "C"函数声明为extern类型。
笔者编写的C引用C++函数例子工程中包含的三个文件的源代码如下:

//C++头文件 cppExample.h
#ifndef CPP_EXAMPLE_H
#define CPP_EXAMPLE_H
extern "C" int add( int x, int y );
#endif
//C++实现文件 cppExample.cpp
#include "cppExample.h"
int add( int x, int y )
{
return x + y;
}
/* C实现文件 cFile.c
/* 这样会编译出错:#include "cExample.h" */
extern int add( int x, int y );
int main( int argc, char* argv[] )
{
add( 2, 3 );
return 0;
}


  如果深入理解了第3节中所阐述的extern "C"在编译和连接阶段发挥的作用,就能真正理解本节所阐述的从C++引用C函数和C引用C++函数的惯用法。对第4节给出的示例代码,需要特别留意各个细节。

 

 

C++中的extern C

 


   本文主要讨论C++中extern C的使用。
   作者:tyc611, 2006-11-06

 

   在使用extern "C"声明时,有两种不同的形式:一是extern "C"后跟函数(或者变量)声明;另外就是extern "C"{函数(或变量)声明}。第一种形式(inline form)表示同时声明为外部连接和C风格连接;而第二种形式仅声明为C风格连接(并不附带外部声明)。例如:

//第一种形式 
extern "C" int foo;       //外部变量声明并且C风格连接
extern "C" void bar();    //外部函数声明并且C风格连接,此时就不能为static

//第二种形式
extern "C" {
   int foo;               //C风格连接,并且定义变量(不是外部连接声明!)
   void bar();
}

   所以当将第二种形式改写成如下形式时,两种形式才具有等价性:

//第二种形式修改
extern "C" {
   extern int foo;         //这儿的extern声明其作用对象为外部连接
   extern void bar();
}

   对于有extern "C"声明的函数,其作用只是改变了函数的连接形式(采用C风格,即在目标文件中的符号名与函数名相同),并非改变函数的性质(也就是说被修饰的C++函 数还可照常使用C++语言特性,与一般的C++函数除了多了个修饰之外,从外表上看并没有其它区别)。从如下示例程序中可以更清楚地看到这点:

// A.h

#ifndef MY_A_H
#define MY_A_H

#include <iostream>

class A
{
public:
 void print()
 {
  std::cout<<"Message from class A"<<std::endl;
 }
};

#endif //MY_A_H

////////////////////////////////////////////////////

// func.cpp

#include "A.h"

extern "C"
void func(A& a)
{
 int* p=new int[23];  // test new operator
 *p=1;

 a.print();

 delete [] p;
}

////////////////////////////////////////////////
// main.cpp

#include "A.h"

extern "C" void func(A& a);

int main()
{
 A a;
 func(a);

 return 0;
}

   另外,标准中规定这种形式是非法的:
     extern "C" static void f(); // error
因为extern "C"表明它是外部连接的,与static矛盾(多存储类型声明错误)。但在VC6.0和MinGW2.05上这样声明却没有错误,不知道为什么会这样。不过,在定义时:
     extern "C" static void f(){...} // error
在VC6.0中没有编译错误,但会有连接错误(main中找不到func的定义);而MinGW2.05有编译错误(多个存储类型声明错误)。看来,MinGW工作得更好些。

   使用extern "C"的一个很重要的因素是关于从动态库里提取函数等问题的需要,见下面的参考文献[2]。

 


参考文献:
[1]ISO-IEC-14882-1998.pdf, 7.5
[2]关于从动态库里提取对象:http://www.isotton.com/howtos/C++-dlopen-mini-HOWTO/C++-dlopen-mini-HOWTO.html#seealso
11 septembre

BUG修正,底层库整合使用,单元测试接口

    上周因为在开发过程中发现原本我使用常量来保存程序中的输出信息,已经不能满足扩展的需要了,因此改成了动态分配和保存。并可以通过接口随时添加客户程序员所需的信息。但没有经过单元测试……现在用的时候果然吃药了,书写时候的小疏忽,造成了一些比较低级的BUG。花了大半天的时间修正。同时,把调试信息输出到了调试器中。
    贴图加载到渲染的接口都测试了一下,基本没有问题了。说明渲染的基本工作流框架完成,接下去就是增加功能了。开始研究ljpeg的库的应用和增加对PNG的支持。
    另外,前期分开编写的XML库,内存管理库和文件读取,日志等基本库全部整合起来使用了,终于看上去像一个还挺浩大的工程了。
    最近公司也很忙,每天早上都要先解决A类的bug,希望能在下周,显示场景,这样,美术那就可以忙起来,我也可以转战服务器搭建和逻辑编写了先。
4 septembre

关于游戏的进展

进展还行,不是很快,但也不慢
 
这几天主要完成了将从场景数据文件读入二进制文件后,生成DX中的Texture部分。还是先搭建了数据加载和渲染的框架。目前功能比较单一,对于贴图混合,和多层贴图还没有实现,只是在代码结构中预留了接口……
 
搭建引擎的架构还是颇费心血,我的目标是对外提供更加简单,容易理解的图形引擎接口。内部封装DX,OPEN GL,等图形API。有计划支持SGL,不过这是后话了。目前的架构,我把DX和OPENGL的调用封装在了引擎的渲染层,大概深度在3层左右
20 août

更新

    创建了相册,因为MSN把我以前的相册删了。添加了很多照片,不是我的办公室。是国外知名游戏制作人的办公室,放出来激励下自己,只想说,那样的生活是我想要的,我追求的。希望哪天我的办公桌也能成为这样。
    今天还在和胖子说,游戏人的办公室,办公桌就应该像一个神奇的小乐园,充满了各种好玩的东西,对自己是一种放松,也是一种灵感的激发。
 
    另外,上传了两个文件,是关于ljpeg库的,一个对jpeg格式文件的读取,解压,压缩的开源库。可能因为作者更新了对jpeg2000的支持,导致最新的找个开源包,我无法在windows下编译通过。研究了下,终于把相关的配置,函数声明不上,放出我编译成功的库,方便需要的人下载吧。编译环境WINXP,VS2003
 
22 avril

社会现象

    每天都做地铁,已经习惯了地铁里有人收报纸。每天,他们站在熙熙攘攘的人流中,显得那么不合群,那么孤独,有时甚至让人觉得无助。在快节奏的人群中,没有人愿意多停留一下脚步,也没有人愿意多看他们一眼。大家生活在一个城市,但是却是两个世界的人。只有在觉得手中的报纸成为一种累赘时,我们才会想到是不是应该找一个收报纸的?如果没有找到,想必大家也会在垃圾筒前处理掉。他们存在的意义是不是就只是“回收站”的作用呢。
    偶尔,两个收报纸的同行还会吵架,原因无非是谁占了谁的地盘。然后从他们身边过往的人们,依旧不会多关心他们一点点。每次,把随意看过了而无用报纸交给他们,无论他们的年龄,外貌(有些人的衣着很惊讶是拾荒者,有一部分是志愿者,但更多的人应该近似于拾荒者吧),他们无不恭敬而谦卑的说谢谢。很感谢我们,他们感谢我们什么呢?我们给予的是连施舍都谈不上的东西啊
    这就是生存吗,在生存的压力下,我们自私,冷漠。我们从古到今,一直在这条路上进化着,我们是生来是孤独的个体,我们关心的,大概永远只是有限范围的人。
20 janvier

设计程序的繁琐

    又是很久没写东西了。原因也没撒,可能人大了就么撒想说的。
    闲话不说了,最近在看《修改代码的艺术》,正巧手上在做一个项目,在使用单元测试。我的习惯,是写完一个小模块后,自己写单元测试程序,然后做覆盖测试。但在看了《修改代码的艺术》后,结合最近的项目情况,觉得它所说的,将单元测试的模块细分到最小单元——函数,还是有参考价值的。我之所以没有采取写一个函数,测试一下,不是我觉得那样不对,可能是我个人的一个思维习惯,那样的方式,会打乱我对整个模块的一个设计概念思路。所以我习惯将整个模块勾勒出来后写测试程序,当然,这个模块不会很大,比如一个类而已,对一个函数写一个测试程序,我觉得过于极端……。这也是我一开始阅读此书时的一个保留态度。
    但,现在有了点新的想法,我发现因为个人项目的原因,我的模块开发存在断断续续的问题,出现了今天继续coding时,会发现前面几天的设计存在缺陷,于是重构代码。如果我能针对函数开发单元测试的话,也许这些缺陷会被考虑的更周全。因为在测试阶段,已经接受实践检验了。因为游戏开发的特殊性,往往我们没有时间做如此极端的单元测试,那样会让一个模块开发节奏很慢。但从我的项目经验上来说,总时间不变的。也许不做如此极端的单元测试,其时间,成本更长,所以我现在慎重的考虑是否要对一个函数做单元测试
26 novembre

MFC补遗

很久没有写东西了,发一点最近的程序记录

最近突然要用到MFC,很久不碰了,而且没有在2005中用VC8.0开发过,所以一开始上手遇到点问题,记录下

首先是对于在资源管理器中添加资源后,相应的要在代码里加载程序,使用DDX的函数来完成。原本在VC6里可以直接生成代码的,我一直没有在VC8里找到,不习惯啊,现在是通过添加类,然后选择ActiveX控件来添加,事先工程要支持ActiveX控件

4 mai

游戏中的项目划分

程序模块划分为UI,引擎,网络底层,游戏逻辑

其中,游戏逻辑中又划分为偏网络逻辑,和偏游戏逻辑。聊天,组队,邮件,好友,公会系统,交易和物品获得的底层逻辑应该交由网络服务器程序员完成

客户端程序员提供逻辑层的游戏底层功能,如内存分配方式,程序架构等

原则一:如果不是网游就不会拥有的功能,就应该交给网络程序员

原则二:如果不牵扯其他客户端逻辑,仅仅和显示相关的,但却有关联到服务器逻辑的,应该由网络程序员完成

 
de 
de 
de 
de 
de 
业界新闻观点,恶搞消息,好玩的不止是游戏