﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-NSnow</title><link>http://www.cppblog.com/NSnow/</link><description /><language>zh-cn</language><lastBuildDate>Tue, 09 Jun 2026 21:30:58 GMT</lastBuildDate><pubDate>Tue, 09 Jun 2026 21:30:58 GMT</pubDate><ttl>60</ttl><item><title>HGE/Box2D/C++ guru</title><link>http://www.cppblog.com/NSnow/archive/2009/10/21/99125.html</link><dc:creator>逸浩</dc:creator><author>逸浩</author><pubDate>Wed, 21 Oct 2009 09:47:00 GMT</pubDate><guid>http://www.cppblog.com/NSnow/archive/2009/10/21/99125.html</guid><wfw:comment>http://www.cppblog.com/NSnow/comments/99125.html</wfw:comment><comments>http://www.cppblog.com/NSnow/archive/2009/10/21/99125.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/NSnow/comments/commentRss/99125.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/NSnow/services/trackbacks/99125.html</trackback:ping><description><![CDATA[<span style="font-size: 10pt; font-family: Comic Sans MS;">关于HGE/Box2D/C++编程的一些注意事项文档<br><br>1.用VS编译后的hge程序不能在其他机器上运行:<br>&nbsp; 首先先确定hge.dll和bass.dll还有其他相关文件是否在hge程序的目录<br>&nbsp; 下或者其找得到的地方.<br>&nbsp; 然后请确认项目属性中公共语言运行库是否为关闭<br>&nbsp; 具体做法项目属性(project properties)-&gt;配置属性(configuration p<br>&nbsp; roperties)-&gt;公共语言运行库(common language runtime support)<br>&nbsp; 将该项关闭。<br>&nbsp; 其次请确认Release的运行时库为MT模式<br>&nbsp; 具体做法在之前提到配置属性中-&gt;C/C++-&gt;代码生成(code genera<br>&nbsp; tion)-&gt;运行时哭(runtime library)中修改。<br>&nbsp; <br>2.使用hgeSprite类中的GetBoundingBox（）时，注意其接受一个hgeRect<br>&nbsp; 指针参数，将得到的sprite的boundingbox存储在该指针所指的对象中<br>&nbsp; 因此，改指针指向的对象必须要先初始化后才能使用。<br>&nbsp; 例如:<br>&nbsp; m_boundingbox = new hgeRect();<br>&nbsp; m_sprite = GetBoundingBox(m_posX, m_posY, m_boundingBox);<br>&nbsp; <br>3.hgeSprite中的SetHotSpot的功用是设定该sprite的热点(锚点)。其接<br>&nbsp; 受的参数a,b代表改热点据sprite坐上角的相对横，纵距离。设置热点<br>&nbsp; 是初始化一个sprite过程中的一部分。之后再对该sprite进行处理时其<br>&nbsp; 坐标就是其热点坐标。<br>&nbsp; 例如:<br>&nbsp; hgeSprite* spr = new hgeSprite(0, 0, 0, 20, 20)//20x20<br>&nbsp; spr.SetHotSpot(10, 10);//Hot spot (10, 10) in center<br>&nbsp; <br>4.当要将FrameFunc和RenderFunc封装到类里面时，注意用System_Se<br>&nbsp; tState是无法将类成员函数直接设为hge的FrameFunc和RenderFunc <br>&nbsp; 的。&nbsp; 因为类成员函数属于一个具体的对象，不能直接从类调用他。<br>&nbsp; 例如:<br>&nbsp; class GameState<br>&nbsp; {<br>&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool FrameFunc();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool RenderFunc();<br>&nbsp; }<br>&nbsp; hge-&gt;System_SetState(HGE_FRAMEFUNC, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GameState::FrameFunc);//ERROR<br>&nbsp;&nbsp;&nbsp; hge-&gt;System_SetState(HGE_RENDERFUNC, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GameState::RenderFunc);//ERROR<br>&nbsp; 代替的方法是将该类建立为Singleton，为其提供Static的FrameFunc<br>&nbsp; 和RenderFunc来调用成员函数进行真正的工作。<br>&nbsp; 例如<br>&nbsp; class GameState<br>&nbsp; {<br>&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static instance;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static bool FrameFunc() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return instance.doUpdate();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static bool RenderFunc() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return instance.doRender();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp; private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool doUpdate();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool doRender();<br>&nbsp; }<br>&nbsp; <br>5.使用hge中Input系列函数时，区分GetKeyState和KeyDown的区别并<br>&nbsp; 选择你需要的使用。KeyDown 用于侦测按键被按下的事件，适合于<br>&nbsp; 监测单次按下键做出反应的情况。GetKeyState则是侦测某个键是否<br>&nbsp; 被按下的状态。用于按下并保持按下按键进行操作情况比较合适。<br>&nbsp; <br>6.我们一般用hge指针来操作hge。但是hge指针不需要是全局变量。由<br>&nbsp; 于hge是Singleton，每次采用hgeCreate返回的指针都是指向同一个h<br>&nbsp; ge类。所以任何时候你需要用到hge中的功能就能用hgeCreate 来得<br>&nbsp; 到一个指向hge的指针。<br>&nbsp; 要记得使用release来释放hge。<br>&nbsp; <br>7.尽量使用hgeResourceManager类。因为他它真的很好用。<br>&nbsp; 如果没有使用他，那么注意在初始化texture/font时一定要确保hge <br>&nbsp; 已经初始化过(System_Initiate已成功)。否则会产生运行时错误。<br><br>8.如果你将hgeSprite,hgeFont这些类封装在你自定义的类中，记得不<br>&nbsp; 要把delete放在析构函数中。如果这样将导致游戏退出时出错。<br>&nbsp; 将需要执行的delete操作提取出来放入一个函数中(如命名为Clear)<br>&nbsp; 在合适的地方手动调用。<br>&nbsp; 例如:<br>&nbsp; if (hge-&gt;System_Initiate())<br>&nbsp; {<br>&nbsp;&nbsp;&nbsp; RenderUnit::instance();//singleton<br>&nbsp;&nbsp;&nbsp; hge-&gt;System_Start();<br>&nbsp;&nbsp;&nbsp; RenderUnit::instance().clearup();//clearup includes deletes<br>&nbsp; }<br><br>9.HGE的Color格式为0xAARGGBB<br>&nbsp; 其中A - alpha R -red G - green B - blue<br>&nbsp; 但事实上传统C++颜色值表示为<br>&nbsp; 0xBBGGRR<br>&nbsp; 记得不要弄错。<br>&nbsp; <br>10.HGE和Box2D混用时很容易采用一比一的单位， 即1个像素代表1个 <br>&nbsp;&nbsp; Box2D中的一个单位。但这样是严重错误的。Box2D中1代表的单位<br>&nbsp;&nbsp; 为1米。所以HGE中渲染一个30像素的正方形在Box2D中意味着一栋<br>&nbsp;&nbsp; 楼房。Box2D在其文档中明确指出，Box2D只能模拟0,1至10米的物<br>&nbsp;&nbsp; 体，对于超出范围以外的物体的物理模拟将会很不正常，一般表现<br>&nbsp;&nbsp; 为速度慢，惯性大且难以加速到很大的速度。<br>&nbsp;&nbsp; 所以一定不能在HGE和Box2D直接采用一比一单位比。<br><br><br>11.Box2D中如果为了给物体一个线性速度，比较好的方法是使用SetLi<br>&nbsp;&nbsp; nearVelocity()而不是ApplyImpulse()来设置冲量。<br>&nbsp; <br>&nbsp; <br>12.HGE和Box2D中获得的radius是相同的。所以下面语句能正确的将Bo<br>&nbsp;&nbsp; x2D模拟的情况反应到屏幕上。<br>&nbsp;&nbsp; objspr-&gt;RenderEx(dynbody-&gt;GetPosition().x, <br>&nbsp;&nbsp; dynbody-&gt;GetPosition().y, dynbody-&gt;GetAngle())<br>&nbsp;&nbsp; 但是务必注意10条中的内容，一比一的单位制必然导致灾难性结果<br>&nbsp;&nbsp; <br>13.HGE中sprite的淡入淡出效果可以通过SetColor不断更改sprite的颜色<br>&nbsp;&nbsp; 值来做到。<br>&nbsp;&nbsp; 对于一个带有自定义的texture的sprite，将其颜色设置为0xFFFFFFF<br>&nbsp;&nbsp; 在一般的BlendMode设定下为最标准的值。如果更改为0x88FFFFFF<br>&nbsp;&nbsp; 则正好是半透明状态。以此类推0x00FFFFFF时则为完全透明。<br>&nbsp;&nbsp; 下面给出一个简单的渐变色的类的例子。<br>&nbsp;&nbsp; 一个简单的办法是设置一个int的factor，将其乘以0x1000000对颜色<br>&nbsp;&nbsp; 进行加减来控制其alpha值。<br>&nbsp;&nbsp; 但要注意的是HGE中颜色值的类型是<br>&nbsp;&nbsp; typedef unsigned long DWORD<br>&nbsp;&nbsp; 是非符号数。<br>&nbsp;&nbsp; 如果用下面这种方式进行操作必然导致错误。<br>&nbsp;&nbsp; colorword -= factor*0x1000000;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (colorword &lt; 0x00FFFFFF) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colorword = 0x00FFFFFF;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;//fade finished<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return true;//fading<br>&nbsp;&nbsp; 由于colorword是非符号树，if判断支内语句永远无法执行<br>&nbsp;&nbsp; 可以改为下面的方法<br>&nbsp;&nbsp;&nbsp; DWORD delta = factor*0x1000000;<br>&nbsp;&nbsp;&nbsp; if (colorword &lt; delta) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colorword = 0x00FFFFFF;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return false;<br>&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; colorword -= delta;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return true;<br>&nbsp;&nbsp;&nbsp; }<br>14.Box2D中一个Body的默认弹性系数是0，即不反弹。这个设定使得<br>&nbsp;&nbsp; 在初期进行渲染测试时容易产生误解。<br>&nbsp;&nbsp; 如果要设置一个Body使其能够反弹，首先检查其是否创建了Shape<br>&nbsp;&nbsp; 然后看是否执行了SetMasses类语句，之后设置Restitution设置弹性<br>&nbsp;&nbsp; 如果还是不能反弹则需检查该Body是否冻结(用IsFrozen()检查)<br>&nbsp;&nbsp; <br>15.第10条中提到了不能在HGE和Box2D直接直接用一比一的单位制。<br>&nbsp;&nbsp; 比较好的方法是预先建立你想要大小的Sprite，将Box2D模拟的结<br>&nbsp;&nbsp; 果乘以系数加上偏移来渲染到屏幕上。<br>&nbsp;&nbsp; 例如<br>&nbsp;&nbsp; //建立一个Box2D中的物件，尺寸为5m x 5m正方形<br>&nbsp;&nbsp; b2BodyDef dynBodyDef;<br>&nbsp;&nbsp; b2PolygonDef dynPolyDef;<br>&nbsp;&nbsp;&nbsp; &nbsp;dynPolyDef.SetAsBox(2.5f, 2.5f);<br>&nbsp;&nbsp; dynbody = world-&gt;CreateBody(&amp;dynBodyDef);<br>&nbsp;&nbsp;&nbsp; &nbsp;dynbody-&gt;CreateShape(&amp;dynPolyDef);<br>&nbsp;&nbsp;&nbsp; &nbsp;dynbody-&gt;SetMassFromShapes();<br>&nbsp;&nbsp;&nbsp; &nbsp;//根据上面Box3D中物件的尺寸创建Sprite,这里是1:10<br>&nbsp;&nbsp;&nbsp; &nbsp;dynspr = new hgeSprite(dyntex, 0, 0, 50.0f, 50.0f);<br>&nbsp;&nbsp;&nbsp; &nbsp;dynspr-&gt;SetHotSpot(25.0f, 25.0f);<br>&nbsp;&nbsp;&nbsp; &nbsp;//渲染，计算坐标要计入全局的偏移量和缩放量<br>&nbsp;&nbsp;&nbsp; &nbsp;dynspr-&gt;RenderEx(dynbody-&gt;GetPosition().x * GLOBSCALE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + GLOBSHIFT, <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; dynbody-&gt;GetPosition().y * GLOBSCALE <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + GLOBSHIFT,<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dynbody-&gt;GetAngle());<br>&nbsp;&nbsp;&nbsp; &nbsp;容易看出来对Body/Shape建立相应的Sprite时要用到Shape的尺寸<br>&nbsp;&nbsp;&nbsp; &nbsp;所以最好在Body的ShapeDef可见的地方就建立Sprite。<br><br>16.对于包装FrameFunc的类对象，慎用Singleton模式。<br>&nbsp;&nbsp; Singleton只要实例化后很难销毁重建。对于需要完成游戏重置的<br>&nbsp;&nbsp; 情况会早成很大的麻烦。<br>&nbsp;&nbsp; 含有RenderFunc的对象偶尔可以考虑用Singleton模式。<br>&nbsp;&nbsp; 总的来说，程序进程中需要重置的对象最好都不要用Singleton。<br>&nbsp;&nbsp; EDIT:<br>&nbsp;&nbsp; 后来发现对于这些对象还是尽量使用Singleton比较好<br>&nbsp;&nbsp; 这样有一个比较可靠的可以全局取得的实例在<br>&nbsp;&nbsp; 可以避免很多类似两个头文件需要互相包含的问题<br>&nbsp;&nbsp; 对于重置问题<br>&nbsp;&nbsp; 建议设置两个函数分别负责初始化和数据清除，在重置时可以先调用清<br>&nbsp;&nbsp; 除函数，再进行初始化即可。注意要照顾到所有数据成员。<br>&nbsp;&nbsp; <br>17.Box2D中实现"子弹时间"效果，只要动态修改world的timestep大小<br>&nbsp;&nbsp; 即可。而且效果相当完美。<br>&nbsp;&nbsp; <br>18.HGE中的卷轴问题，可以用Gfx_SetTransform解决。但是这个函数<br>&nbsp;&nbsp; 貌似有点问题。<br>&nbsp;&nbsp; void Gfx_SetTransform(<br>&nbsp;&nbsp;&nbsp; float x = 0,<br>&nbsp;&nbsp;&nbsp; float y = 0,<br>&nbsp;&nbsp;&nbsp; float dx = 0,<br>&nbsp;&nbsp;&nbsp; float dy = 0,<br>&nbsp;&nbsp;&nbsp; float rot = 0,<br>&nbsp;&nbsp;&nbsp; float hscale = 0,<br>&nbsp;&nbsp;&nbsp; float vscale = 0<br>&nbsp;&nbsp;&nbsp; );<br>&nbsp;&nbsp;&nbsp; 虽然每个都有默认参数但是如果根据源码中，如果忽略设置vscale<br>&nbsp;&nbsp;&nbsp; 那么之前的参数都会被忽略。这应该是个bug。<br>&nbsp;&nbsp;&nbsp; 所以如果要使用SetTransform必须将提供所有参数。<br>&nbsp;&nbsp;&nbsp; hge-&gt;Gfx_SetTransform(0，0, 10.0f, 10.0f, 0, 1.0f, 1.0f);<br>&nbsp;&nbsp;&nbsp; //前两个参数目前作用不明...<br><br>19.Box2D中隐藏的函数<br>&nbsp;&nbsp; 有一些简单的计算函数在Box2D API文档中貌似是找不到的<br>&nbsp;&nbsp; 比如b2vec2这个向量类的点乘和差乘操作，在b2Vec2类中没有相关描述<br>&nbsp;&nbsp; 实际上在b2math.h中有定义一系列的相关函数，比如b2dot就是对两个向<br>&nbsp;&nbsp; 量进行点乘。当你发现一些很常用的操作没有相关函数时不妨自己打开相<br>&nbsp;&nbsp; 应的源代码翻看一下。 <br> </span><img src ="http://www.cppblog.com/NSnow/aggbug/99125.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/NSnow/" target="_blank">逸浩</a> 2009-10-21 17:47 <a href="http://www.cppblog.com/NSnow/archive/2009/10/21/99125.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>