HGE/Box2D/C++ guru

关于HGE/Box2D/C++编程的一些注意事项文档

1.用VS编译后的hge程序不能在其他机器上运行:
  首先先确定hge.dll和bass.dll还有其他相关文件是否在hge程序的目录
  下或者其找得到的地方.
  然后请确认项目属性中公共语言运行库是否为关闭
  具体做法项目属性(project properties)->配置属性(configuration p
  roperties)->公共语言运行库(common language runtime support)
  将该项关闭。
  其次请确认Release的运行时库为MT模式
  具体做法在之前提到配置属性中->C/C++->代码生成(code genera
  tion)->运行时哭(runtime library)中修改。
 
2.使用hgeSprite类中的GetBoundingBox()时,注意其接受一个hgeRect
  指针参数,将得到的sprite的boundingbox存储在该指针所指的对象中
  因此,改指针指向的对象必须要先初始化后才能使用。
  例如:
  m_boundingbox = new hgeRect();
  m_sprite = GetBoundingBox(m_posX, m_posY, m_boundingBox);
 
3.hgeSprite中的SetHotSpot的功用是设定该sprite的热点(锚点)。其接
  受的参数a,b代表改热点据sprite坐上角的相对横,纵距离。设置热点
  是初始化一个sprite过程中的一部分。之后再对该sprite进行处理时其
  坐标就是其热点坐标。
  例如:
  hgeSprite* spr = new hgeSprite(0, 0, 0, 20, 20)//20x20
  spr.SetHotSpot(10, 10);//Hot spot (10, 10) in center
 
4.当要将FrameFunc和RenderFunc封装到类里面时,注意用System_Se
  tState是无法将类成员函数直接设为hge的FrameFunc和RenderFunc
  的。  因为类成员函数属于一个具体的对象,不能直接从类调用他。
  例如:
  class GameState
  {
  public:
      bool FrameFunc();
      bool RenderFunc();
  }
  hge->System_SetState(HGE_FRAMEFUNC,
                          GameState::FrameFunc);//ERROR
    hge->System_SetState(HGE_RENDERFUNC,
                          GameState::RenderFunc);//ERROR
  代替的方法是将该类建立为Singleton,为其提供Static的FrameFunc
  和RenderFunc来调用成员函数进行真正的工作。
  例如
  class GameState
  {
  public:
      static instance;
      static bool FrameFunc() {
           return instance.doUpdate();
      }
      static bool RenderFunc() {
           return instance.doRender();
      }
  private:
      bool doUpdate();
      bool doRender();
  }
 
5.使用hge中Input系列函数时,区分GetKeyState和KeyDown的区别并
  选择你需要的使用。KeyDown 用于侦测按键被按下的事件,适合于
  监测单次按下键做出反应的情况。GetKeyState则是侦测某个键是否
  被按下的状态。用于按下并保持按下按键进行操作情况比较合适。
 
6.我们一般用hge指针来操作hge。但是hge指针不需要是全局变量。由
  于hge是Singleton,每次采用hgeCreate返回的指针都是指向同一个h
  ge类。所以任何时候你需要用到hge中的功能就能用hgeCreate 来得
  到一个指向hge的指针。
  要记得使用release来释放hge。
 
7.尽量使用hgeResourceManager类。因为他它真的很好用。
  如果没有使用他,那么注意在初始化texture/font时一定要确保hge
  已经初始化过(System_Initiate已成功)。否则会产生运行时错误。

8.如果你将hgeSprite,hgeFont这些类封装在你自定义的类中,记得不
  要把delete放在析构函数中。如果这样将导致游戏退出时出错。
  将需要执行的delete操作提取出来放入一个函数中(如命名为Clear)
  在合适的地方手动调用。
  例如:
  if (hge->System_Initiate())
  {
    RenderUnit::instance();//singleton
    hge->System_Start();
    RenderUnit::instance().clearup();//clearup includes deletes
  }

9.HGE的Color格式为0xAARGGBB
  其中A - alpha R -red G - green B - blue
  但事实上传统C++颜色值表示为
  0xBBGGRR
  记得不要弄错。
 
10.HGE和Box2D混用时很容易采用一比一的单位, 即1个像素代表1个
   Box2D中的一个单位。但这样是严重错误的。Box2D中1代表的单位
   为1米。所以HGE中渲染一个30像素的正方形在Box2D中意味着一栋
   楼房。Box2D在其文档中明确指出,Box2D只能模拟0,1至10米的物
   体,对于超出范围以外的物体的物理模拟将会很不正常,一般表现
   为速度慢,惯性大且难以加速到很大的速度。
   所以一定不能在HGE和Box2D直接采用一比一单位比。


11.Box2D中如果为了给物体一个线性速度,比较好的方法是使用SetLi
   nearVelocity()而不是ApplyImpulse()来设置冲量。
 
 
12.HGE和Box2D中获得的radius是相同的。所以下面语句能正确的将Bo
   x2D模拟的情况反应到屏幕上。
   objspr->RenderEx(dynbody->GetPosition().x,
   dynbody->GetPosition().y, dynbody->GetAngle())
   但是务必注意10条中的内容,一比一的单位制必然导致灾难性结果
  
13.HGE中sprite的淡入淡出效果可以通过SetColor不断更改sprite的颜色
   值来做到。
   对于一个带有自定义的texture的sprite,将其颜色设置为0xFFFFFFF
   在一般的BlendMode设定下为最标准的值。如果更改为0x88FFFFFF
   则正好是半透明状态。以此类推0x00FFFFFF时则为完全透明。
   下面给出一个简单的渐变色的类的例子。
   一个简单的办法是设置一个int的factor,将其乘以0x1000000对颜色
   进行加减来控制其alpha值。
   但要注意的是HGE中颜色值的类型是
   typedef unsigned long DWORD
   是非符号数。
   如果用下面这种方式进行操作必然导致错误。
   colorword -= factor*0x1000000;
        if (colorword < 0x00FFFFFF) {
            colorword = 0x00FFFFFF;
            return false;//fade finished
        }
        return true;//fading
   由于colorword是非符号树,if判断支内语句永远无法执行
   可以改为下面的方法
    DWORD delta = factor*0x1000000;
    if (colorword < delta) {
        colorword = 0x00FFFFFF;
        return false;
    } else {
        colorword -= delta;
        return true;
    }
14.Box2D中一个Body的默认弹性系数是0,即不反弹。这个设定使得
   在初期进行渲染测试时容易产生误解。
   如果要设置一个Body使其能够反弹,首先检查其是否创建了Shape
   然后看是否执行了SetMasses类语句,之后设置Restitution设置弹性
   如果还是不能反弹则需检查该Body是否冻结(用IsFrozen()检查)
  
15.第10条中提到了不能在HGE和Box2D直接直接用一比一的单位制。
   比较好的方法是预先建立你想要大小的Sprite,将Box2D模拟的结
   果乘以系数加上偏移来渲染到屏幕上。
   例如
   //建立一个Box2D中的物件,尺寸为5m x 5m正方形
   b2BodyDef dynBodyDef;
   b2PolygonDef dynPolyDef;
     dynPolyDef.SetAsBox(2.5f, 2.5f);
   dynbody = world->CreateBody(&dynBodyDef);
     dynbody->CreateShape(&dynPolyDef);
     dynbody->SetMassFromShapes();
     //根据上面Box3D中物件的尺寸创建Sprite,这里是1:10
     dynspr = new hgeSprite(dyntex, 0, 0, 50.0f, 50.0f);
     dynspr->SetHotSpot(25.0f, 25.0f);
     //渲染,计算坐标要计入全局的偏移量和缩放量
     dynspr->RenderEx(dynbody->GetPosition().x * GLOBSCALE
                      + GLOBSHIFT,
            dynbody->GetPosition().y * GLOBSCALE
                    + GLOBSHIFT,
                 dynbody->GetAngle());
     容易看出来对Body/Shape建立相应的Sprite时要用到Shape的尺寸
     所以最好在Body的ShapeDef可见的地方就建立Sprite。

16.对于包装FrameFunc的类对象,慎用Singleton模式。
   Singleton只要实例化后很难销毁重建。对于需要完成游戏重置的
   情况会早成很大的麻烦。
   含有RenderFunc的对象偶尔可以考虑用Singleton模式。
   总的来说,程序进程中需要重置的对象最好都不要用Singleton。
   EDIT:
   后来发现对于这些对象还是尽量使用Singleton比较好
   这样有一个比较可靠的可以全局取得的实例在
   可以避免很多类似两个头文件需要互相包含的问题
   对于重置问题
   建议设置两个函数分别负责初始化和数据清除,在重置时可以先调用清
   除函数,再进行初始化即可。注意要照顾到所有数据成员。
  
17.Box2D中实现"子弹时间"效果,只要动态修改world的timestep大小
   即可。而且效果相当完美。
  
18.HGE中的卷轴问题,可以用Gfx_SetTransform解决。但是这个函数
   貌似有点问题。
   void Gfx_SetTransform(
    float x = 0,
    float y = 0,
    float dx = 0,
    float dy = 0,
    float rot = 0,
    float hscale = 0,
    float vscale = 0
    );
    虽然每个都有默认参数但是如果根据源码中,如果忽略设置vscale
    那么之前的参数都会被忽略。这应该是个bug。
    所以如果要使用SetTransform必须将提供所有参数。
    hge->Gfx_SetTransform(0,0, 10.0f, 10.0f, 0, 1.0f, 1.0f);
    //前两个参数目前作用不明...

19.Box2D中隐藏的函数
   有一些简单的计算函数在Box2D API文档中貌似是找不到的
   比如b2vec2这个向量类的点乘和差乘操作,在b2Vec2类中没有相关描述
   实际上在b2math.h中有定义一系列的相关函数,比如b2dot就是对两个向
   量进行点乘。当你发现一些很常用的操作没有相关函数时不妨自己打开相
   应的源代码翻看一下。

你可能感兴趣的:(HGE/Box2D/C++ guru)