|
前些日子曾经说过,想做一个小游戏
后来以Kdevelop为开发工具,用C++和SDL做了点尝试:
目前只初步做了一个类,这个类在一定程度上能满足设计要求,然而现在这个类面临着一个不小的缺陷,这个类定义了可以运动的物体,它有自己的位置坐标、质量、速度、加速度、受到的合力等,先看看这个成员函数:
[code:1]
/** update the position,speed and acceleration of this object */
int Obj::update(float t){//参数t表示了此次更新距离上次更新的时间,单位是秒
//update the position//更新位置
px+=sx*t;
py+=sy*t;
pz+=sz*t;
//update the speed//更新速度
sx+=acx*t;
sy+=acy*t;
sz+=acz*t;
//update the acceleration//更新加速度
acx=fx/m;
acy=fy/m;
acz=fz/m;
return 0;
}
[/code:1]
看起来通过这个类能够很好地模拟物体的运动,在我第一次单独测试它时,也的确兴奋地发现在运动模拟方面它显得那么完美;但是等我加入一个引力源后再进行测试时却发现了问题。先看看整个程序的结构,在两个“//test”注释行之间的是测试代码:
[code:1]
int main(int argc, char *argv[])
{
if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0 ){
cerr << "Can not init SDL: " << SDL_GetError() << endl;
exit(1);
}
atexit(SDL_Quit);
int width=640;
int height=480;
int bpp=16;
screen = SDL_SetVideoMode(width, height, bpp, SDL_HWSURFACE|SDL_DOUBLEBUF/*|SDL_FULLSCREEN*/);
if ( NULL == screen ) {
cerr << "Can not set a VideoMode of " << width << " X " << height << " at " << bpp << " : " << SDL_GetError() << endl;
exit(1);
}
//test
/* if (0 == screen->flags & SDL_HWSURFACE){
printf("Can't get hardware surface\n");
exit(1);
}
*/
tt=new Obj;
tt->setpx(50.0);
tt->setpy(50.0);
image=SDL_LoadBMP("/home/sjinny/test.bmp");
image2=SDL_LoadBMP("/home/sjinny/test3.bmp");
dest2.w = image2->w;
dest2.h = image2->h;
dest.x = (int)tt->getpx();
dest.y = (int)tt->getpy();
dest.w = image->w;
dest.h = image->h;
//test
SDL_Event event;
SDLKey key;
while ( 1 == gaming ){//在游戏运行的过程中,每次游戏循环都做一遍以下工作:
event_process(event, key);//处理游戏中各种外设的事件(比如键盘之类的);
run();//更新游戏中各个对象;
display();//显示游戏中需要显示的东东。
}
return EXIT_SUCCESS;
}
[/code:1]
注意最后一个while循环,前面都是初始化的工作,游戏的真正过程是在这个游戏循环中完成的。大家看看run()函数:
[code:1]
int run(void)
{
//test
static float fx,fy;
float f,fx0,fy0;
float x,y,r,r2;
x=320.0-tt->getpx();
cout << "x=" << x << endl;
y=240.0-tt->getpy();
cout << "y=" << y << endl;
r2=x*x+y*y;
//cout << "r2=" << r2 << endl;
r=(float)sqrt((double)r2);
cout << "r=" << r << endl;
if ( 0.0!=r2 ){
f=50000.0/r2;
fx0=fx;
//cout << "fx0=" << fx0 << " "; //<< endl;
fx=f*x/r;
cout << "fx=" << fx << " "; //<< endl;
fy0=fy;
//cout << "fy0=" << fy0 << endl;
fy=f*y/r;
cout << "fy=" << fy << endl;
tt->setfx(tt->getfx()+fx-fx0);
tt->setfy(tt->getfy()+fy-fy0);
}
cout << "tt.px=" << tt->getpx() << endl;
cout << "tt.py=" << tt->getpy() << endl;
cout << "tt.sx=" << tt->getsx() << endl;
cout << "tt.sy=" << tt->getsy() << endl;
cout << "tt.acx=" << tt->getacx() << endl;
cout << "tt.acy=" << tt->getacy() << endl;
cout << "tt.fx=" << tt->getfx() << endl;
cout << "tt.fy=" << tt->getfy() << endl;
cout << "+++++++++++++++++++++++++++++" << endl;
tt->update(0.10);// <--注意!
dest2.x=dest.x;
dest2.y=dest.y;
dest.x = (int)tt->getpx();
//cout << "dest.x=" << dest.x << " "; //<< endl;
dest.y = (int)tt->getpy();
//cout << "dest.y=" << dest.y << endl;
//test
return 0;
}
[/code:1]
看到那个tt->update(0.10);了吗?这里为了简化,我假设(或者说认为)每两次update之间隔了0.1s,当然实际用的时候还是应该计算经过的真正时间间隔。
在加入引力源后再测试,发现当测试物体经过引力源的位置后(我没做碰撞检测)一闪就不见了。查看输出信息后发现,当经过引力源后物体的位置坐标突然变得很大,这种变化是数量级的增大。看看下面这些测试时输出的信息:
x=6.57886//物体距离引力源的横向距离
y=4.62959//物体距离引力源的纵向距离
r=8.04453//物体距离引力源的距离
fx=631.856 fy=444.642//这是x方向和y方向上物体当时所受的力
tt.px=313.421//物体的位置|横坐标
tt.py=235.37//物体的位置|纵坐标
tt.sx=63.9691//物体的速度|x方向的分量
tt.sy=45.0154//物体的速度|y方向的分量
tt.acx=189.565//物体的加速度|x方向的分量
tt.acy=133.398//物体的加速度|y方向的分量
tt.fx=631.856//物体所受的合外力|x方向的分量
tt.fy=444.642//物体所受的合外力|y方向的分量
+++++++++++++++++++++++++++++
x=0.181946
y=0.128052
r=0.222489// <--注意!
fx=826008 fy=581337
tt.px=319.818
tt.py=239.872
tt.sx=82.9256
tt.sy=58.3552
tt.acx=631.856//正常
tt.acy=444.642//正常
tt.fx=826008//物体受力异常
tt.fy=581337//物体受力异常
+++++++++++++++++++++++++++++
x=-8.11063
y=-5.70747
r=9.91754// <--注意!上次update还<1,这次一下子变成了>9
fx=-415.732 fy=-292.552
tt.px=328.111
tt.py=245.707
tt.sx=146.111//正常
tt.sy=102.819//正常
tt.acx=826008//物体加速度异常
tt.acy=581337//物体加速度异常
tt.fx=-415.732
tt.fy=-292.552
+++++++++++++++++++++++++++++
x=-22.7217
y=-15.9894
r=27.7838
fx=-52.9709 fy=-37.2759
tt.px=342.722//正常
tt.py=255.989//正常
tt.sx=82746.9//物体速度异常
tt.sy=58236.5//物体速度异常
tt.acx=-415.732
tt.acy=-292.552
tt.fx=-52.9709
tt.fy=-37.2759
+++++++++++++++++++++++++++++
x=-8297.41
y=-5839.64
r=10146.3
fx=-0.000397176 fy=-0.000279529
tt.px=8617.41//物体位置坐标异常
tt.py=6079.64//物体位置坐标异常
tt.sx=82705.3
tt.sy=58207.2
tt.acx=-52.9709
tt.acy=-37.2759
tt.fx=-0.000397176
tt.fy=-0.000279529
+++++++++++++++++++++++++++++
x=-16567.9
y=-11660.4
r=20259.8
fx=-9.96165e-05 fy=-7.01091e-05
tt.px=16887.9
tt.py=11900.4
tt.sx=82700
tt.sy=58203.5
tt.acx=-0.000397176
tt.acy=-0.000279529
tt.fx=-9.96165e-05
tt.fy=-7.01091e-05
+++++++++++++++++++++++++++++
我分析了一下,问题是这样的:引力源在窗体的中心位置,因为是万有引力,所以这里我计算时用一个常数除以物体和引力源距离的平方,然后再计算出x方向和y方向上的引力的分量。看到两个“<--注意”了吗?比较一下发现,两次update,第一次时因为离引力源很近,所以会产生很大的引力,照理说在引力源另一边对应的位置会产生大小相同、方向相反的引力,这样在经过引力源后速度应该不会变得太大,因为只是重力势能和动能间的转化嘛~但是注意,前一个update时离引力源很近,而此时速度已经不小了,于是在下一次update的时候,位置不会和上次update时的位置关于引力源对称,而是离引力源更远(上次的距离还不到1,这次的距离却接近10了),这样第二次update时受到的引力比上次要小不少,这样引力就不足以使物体以后的速度减到足够小的程度,也就是不能产生足够大的加速度,而在使用过大的速度update之后位置又离引力源更远了,于是更加不能产生足够大的加速度,然后物体就会这样以很高的速度运动下去,这样就导致了物体经过引力源时一闪就不见了。这样会带来很大的问题:物体不能离引力源太近,速度不能太大,引力源产生引力的能力不能太强。这么多的“太”严重影响了程序的功能。很显然,这是机制问题,而不是一个简单的编码错误。我一时半会也还想不出什么更好的办法~
另外,目前还面临着以下问题:
1。地图应该用什么数据结构来保存和管理?
2。碰撞检测怎么办?按照上述的运动模拟方案,如果速度过快,就会漏掉某些碰撞。
3。关于服务器端我还不明确要做哪些工作。
4。游戏需要一些图片~ ;-)
我用的是Kdevelop,项目文件打包后有1.1MB,论坛里似乎不能上传这么大的文件~ :-(
另外,我给这个游戏起的名称叫“SpaceHunter” |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?注册
×
|