"蕃茄超人"在VC下的编译与调试经验

 

by -zh1110   2007.9.10

 

 

    蕃茄炸弹超人(I've no Tomatoes)是一个典型的智力游戏,Linux开源项目多数是由GCC编译的,它也由GCC开发,其用到的开发库有:SDL,SDL_Image、OpenGL,FMOD

 

我现在讲述将其移植到VC6下的编译过程:

 

安装SDL引擎:

首先首先必须下载SDL函数库,现在SDL的最高版本是1.2. 到官方网站http://www.libsdl.org ,然后你会在网页的左下脚发现一个叫下载(Download)的栏目,点击

 

将我们刚才解压后lib下的SDL.lib,SDLmain.lib拷贝到一个新的目录:D:\GAMEDEV\lib. 或VC6所在的lib子目录下:C:Program FilesMicrosoft Visual StudioVC98Lib
然后建立一个新文件夹,D:\GAMEDEV\include\SDL,解压的目录include中的文件拷贝到SDL目录中,或VC6的include目录

如果用DEV C++还要将SDL文件中子目录bin里的全部文件拷贝到DEV C++bin目录中,地址应该在c:dev-cppbin

 

安装SDL扩展函数库SDL image(读取PNG文件)

到下面的地址下载:

http://www.libsdl.org/projects/SDL_image/

 

然后按上面类似进行操作.

 

声音库:

到FMOD的网站下载开发包

http://www.fmod.org/index.php/download

 

 

将解压后的fmod.h,fmoddyn.h等头文件放到include目录

如果是VC++则fmodvc.lib放到lib目录,

如果是DEV C++则libfmod.a放到DEV C++的lib目录下

 

 

到炸弹超人主页下载执行文件和源代码

http://tomatoes.sourceforge.net/

http://sourceforge.net/project/showfiles.php?group_id=110031

 

 

选择一个下载速度较快的服务器。

 

将蕃茄炸弹超人运行文件和源代码解压到D:\GAMEDEV\tomatoes

 

注意保持开发包的版本与运行库版本一致

将运行库SDL.dll,SDL_image.dll,libpng12-0.dll,fmod.dll文件拷贝到 程序目录和WINDOWS目录。

 

 

右键Adds File To Folder 将tomatoes所有源代码(*.C ,*.H)加入工程:

 

 

打开VC6,打开”file”->Projects选项,建立一个空白的Win32 CONSOLE 项目,目录就是D:\GAMEDEV\tomatoes

 

下面我们对工程设置:

VC6主面板中选择“Project->Setting选项。在C/C++表,在“Category"中设置成"Code Generation",在"Use run-time library"下设置成multithreaded dll。

 

选择“Link表,在Object/Library modules添加静态库 fmodvc.lib SDL.lib SDLmain.lib SDL_image.lib opengl32.lib glu32.lib glaux.lib

 

 

Tools-Options 添加头文件,静态库文件 的查找目录,否则VC6提示无法找到文件:

 

 

 

由于VC对 ANSI C++ Standard 支持很低,所以对源文件做许多的修改才可以正确编译.

现在编译,出现多处错误:

错误提示1:

config.cpp(98) error C2065: 'CONFIG_DIR' : undeclared identifier

 

找到原句:
return (CONFIG_DIR "config.cfg");//返回配置文件的目录

 

CONFIG_DIR 就是宏定义的字符串,因为C++有一种很少用的字符串定义写法,在串常量很长时可以这样初始化:
char buff[] = "line1""line2";
等价于:
char buff[] = "line1line2";

 

打开makefile,查找到定义,将它们手动加到config.h的宏定义中.

 

 

 

错误提示2:

vect.h(103) : fatal error C1001: INTERNAL COMPILER ERROR
(compiler file 'msc1.cpp', line 1786)
Please choose the Technical Support command on the Visual C++
Help menu, or open the Technical Support help file for more information
 

找到原句:

friend VECT operator + (const VECT &v) {
return v;
}
friend VECT operator - (const VECT &v) {
return VECT(-v.x, -v.y, -v.z);
}
friend VECT operator + (const VECT &v1, const VECT &v2) {
return VECT(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}
friend VECT operator - (const VECT &v1, const VECT &v2) {
return VECT(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}
friend VECT operator * (const VECT &v, float s) {
return VECT(v.x * s, v.y * s, v.z * s);
}
friend VECT operator * (float s, const VECT &v) {
return VECT(v.x * s, v.y * s, v.z * s);
}
friend VECT operator / (const VECT &v, float s) {
return VECT(v.x / s, v.y / s, v.z / s);
}

因为VC6对于+,-,*的运算符重载,如果是定义在类内部的话,只能 带一个函数参数.

 

修改这些函数,移至VECT类外部,并内联:

class VECT {

......

};

inline VECT operator + (const VECT &v) {
return v;
}
inline VECT operator - (const VECT &v) {
return VECT(-v.x, -v.y, -v.z);
}
inline VECT operator + (const VECT &v1, const VECT &v2) {
return VECT(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
}
inline VECT operator - (const VECT &v1, const VECT &v2) {
return VECT(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
}
inline VECT operator * (const VECT &v, float s) {
return VECT(v.x * s, v.y * s, v.z * s);
}
inline VECT operator * (float s, const VECT &v) {
return VECT(v.x * s, v.y * s, v.z * s);
}
inline VECT operator / (const VECT &v, float s) {
return VECT(v.x / s, v.y / s, v.z / s);
}
 

 

错误提示3:

effects.cpp(169) : error C2374: 'f' : redefinition; multiple initialization
 see declaration of 'f'

找到原句:

for(int f=1; f < points-1; f++) {

......

}

......

for(int f=0; f<points; f++) {
......
}

因为对于for循环,ANSI C++规定f变量的作用域仅在for内部 ,VC6编译为for外层为f变量的作用域,所以出现重两个f重定义的错误.VC.NET可通过开关控制.

 

修改为:

int f;

for( f=1; f < points-1; f++) {

......

}

......

for( f=0; f<points; f++) {
......
}

 

错误提示4:

menu.h(66) : error C2955: 'list' : use of class template requires template argument list
c:\program files\microsoft visual studio\vc98\include\list(415) : see declaration of 'list'

 

找到原句:
void draw_menu(int menu_id, int menu_item, int place, float fade, HISCORE_LIST *list) {

if(place != -1 && list != NULL)
list->draw(place, 1.0f);

 

 因为参数HISCORE_LIST *list与STL::list名字相同导致冲突.

 

修改为:

void draw_menu(int menu_id, int menu_item, int place, float fade, HISCORE_LIST *list1) {

 

if(place != -1 && list1 != NULL)
list1->draw(place, 1.0f);

 

错误提示5:

soundmusic.cpp(35) : fatal error C1083: Cannot open include file: 'dirent.h': No such file or directory

 

dirent.h是Linux下目录查找 函数,VC6不包含,将其及search_music()屏蔽即可.

 

错误提示6:

texture.cpp(111) : error C2143: syntax error : missing ';' before '['
texture.cpp(111) : error C2143: syntax error : missing ';' before '['


找到原句:

Uint8 *line = new (Uint8)[img->w*img->format->BytesPerPixel];

 

因为 new内存申请,VC6不支持带有括号,它认为这是两句:

Uint8 *line = new (Uint8);

[img->w*img->format->BytesPerPixel];

 

修改

Uint8 *line = new Uint8[img->w*img->format->BytesPerPixel];

修改后问题解除

 

错误提示7:

mymath.cpp(52) : error C2065: 'M_PI' : undeclared identifier

 

这是作者将M_PI屏蔽了,mymath.h恢复既可:

 //PI....
#ifndef M_PI
#define M_PI 3.1415926536f
#endif
 

 

 

如果要稳定的编译推崇使用DEV C++,这款IDE所使用的编译程序就是 GCC的Win32版本 Mingw32下载一个Dev-CPP的安装程序http://www.bloodshed.net/dev/devcpp.html

最新版本应该是Dev-Cpp 4.9.9地址是

http://umn.dl.sourceforge.net/sourceforge/dev-cpp/devcpp4990setup.exe 

 

Dev-C的开发环境:

 

连接静态库设置(参考makefile)

 

编译成功后截图:

 

 

最后可以随意修改调试程序了.

1.修改宝物的数量:

在 levels.cpp 128行:

// Set the bonus system
for(int f=0; f<NUM_ICONS; f++)
icon_menu.count[f] = 300; //修改此行
next_bonus[BONUS_RED] = RED_POWER_TRAP;

 

2.释放资源包中的图片:

//texture.cpp Ln96:

FILE *fin = pakfile.open_file(file);
pakfile.extract_file(file); //加入此行

......

 

总结:经过一定修改使GUN项目能够在VC6下编译,有利我以后的调试.