QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 591|回复: 6

SpaceHunter

[复制链接]
发表于 2004-1-11 14:55:49 | 显示全部楼层 |阅读模式
前些日子曾经说过,想做一个小游戏
后来以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”

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
 楼主| 发表于 2004-1-13 21:38:10 | 显示全部楼层
呼~终于知道往哪上传文件了~
SpaceHunter的项目文件打包:

ftp://www.linuxfans.org/incoming/spacehunter-0.1.tar.gz

解包后用Kdevelop打开其中的spacehunter.kdevprj文件。
源代码中在两行“//test”之间的部分是用于测试的~
看到什么令你不爽的代码就来这里拍砖,别客气~
回复

使用道具 举报

 楼主| 发表于 2004-1-13 21:42:39 | 显示全部楼层
晕,忘了两个图片,把这两个图片放到一个目录里,然后把源代码里两个图片的路径修改成你的那个路径,但是文件名就不要改了~

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
回复

使用道具 举报

发表于 2004-1-15 10:48:01 | 显示全部楼层
看过了
不过   突然向左边飞出去的奇怪结果
回复

使用道具 举报

 楼主| 发表于 2004-1-15 11:36:12 | 显示全部楼层
applepie, “突然向左边飞出去的奇怪结果”具体是指什么?
回复

使用道具 举报

发表于 2004-1-15 20:03:33 | 显示全部楼层
就是  我一直按着向左的按键  开始方块是以比较慢得速度向左 后来突然向左飞出了边框 消失了
回复

使用道具 举报

 楼主| 发表于 2004-1-15 20:11:49 | 显示全部楼层
键盘上向左的箭头那个键,按下它的时候就使方块受到了一个水平向左的力,这样它就作匀加速直线运动,然后就会向作运动,有什么不对的吗?当然,下载的程序里面还加了个引力源,不过一开始那么远那点引力还不用考虑的~
你说的“突然”是指……?
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-11-9 00:54 , Processed in 0.042706 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表