请注意, 本demo需要配置box2d才能编译运行
本demo由网友 Samuel Ni 提供, 以下是源代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
/* * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. * * 以上是 Box 2D库原作者 Erin Catto 的著作权声明,请勿删除 */ /* 源程序修改说明 * 本源程序的原始版本来自 BOX2D 安装包中的 demo 程序 Helloworld.cpp。原始 demo 程 * 序定义并计算了一个无形状、初速度为零的自由落体,在特定高度释放后的位置变化,用 * printf(...) 做简单的文本输出。 * * 本源程序重新定义了一个具有初始线速度和角速度、正方形的刚体。刚体和地面接触时有 * 摩擦力,动能有损耗。刚体的形状、空间位置改变采用 EGE 图形库做动画输出。 * * BOX2D 版本 2.12 和 2.3.0 以及 EGE 库的最新版本被用于本程序的编译和链接,IDE/VC++ * 环境采用微软的VS 2015 或 VS 2008。使用的操作系统为 Windows XP 和 Windows 7。 * * 有关 BOX2D 安装包下载、安装和测试,请参见Erin Catto 的著作权声明。 * * 程序里有一个“微妙”的Bug, 如果你能找出来,请和大家分享。程序也没有优化,原代码 * 格式也不尽规范,仅供参考。 * * 又及,源代码中用了一些数据类型强制转换(casting),主要是在 VS 2015 环境下编译 * 64 位 EXE 时,系统把这类属于“警告”性质的问题当中错误处理。编译、生成 32 位 EXE * 执行程序时,不作强制转换也无所谓。 * * Sept.,2016, Samuel Ni, email: samuel_ni@yahoo.com */ #include <Box2D/Box2D.h> #include <cstdio> #include <graphics.h> #include <math.h> /* 定义一些常量,如视窗的宽、高等。 SCALE_FACTOR 用于EGE 的函数中,把BOX2D 用的物理长度单位(如 0.1 米) 转换为视窗的像素点数。 */ #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 480 #define SCALE_FACTOR 100.0f int main(/* int argc, char** argv */) { // 定义一个大小为9.8 米/秒^2, 方向朝下的重力加速度矢量。 // b2Vec2 是Box2D中的矢量数据类型,可以用于声明各种物理矢量。 b2Vec2 gravity(0.0f, -9.8f); // 声明、构造一个有重力的2维虚拟“物理世界” b2World world(gravity); // 对于 Box2D ver 2.12, 用函数 b2World world(gravity, TRUE); // 定义一个地面物件以及X-Y位置 b2BodyDef groundBodyDef; groundBodyDef.position.Set(0.0f, -10.5f); // 用上述定义的“地面物件”,在“物理世界”里构造一个“地面”。 b2Body* groundBody = world.CreateBody(&groundBodyDef); // 定义一个多边形 b2PolygonShape groundBox; // 设定上述多边形为一个(长)方形 groundBox.SetAsBox(100.0f, 10.0f); // 用上述(长)方形生成一个“地面”物件”。 groundBody->CreateFixture(&groundBox, 0.0f); // 定义一个动态(刚体)物件并设定其基本属性 b2BodyDef bodyDef; bodyDef.type = b2_dynamicBody; // b2_dynamicBody 属性指示该刚体的位置等是动态的, // 并将和其他物体相互作用,如发生碰撞等 bodyDef.position.Set(0.0f, 4.0f); // 初始位置(物理单位) bodyDef.linearVelocity.Set(2.0f, 3.5f); // 初始速度(物理单位) bodyDef.angularVelocity = -1.0f; // 初始角速度(物理单位: 弧度/秒),负号表示顺时针 b2Body* body = world.CreateBody(&bodyDef); // 生成一个用 body 做指针的刚体 // 用多边形数据类型(b2PolygonShape)定义一个方形并确定其大小 b2PolygonShape dynamicBox; dynamicBox.SetAsBox(1.0f, 1.0f); //定义动态(刚体)的附加属性并设定其形状为上述定义的方形 b2FixtureDef fixtureDef; fixtureDef.shape = &dynamicBox; // 设定刚体密度这一附加属性。刚体的质量 = 密度 X 物件的面积,面积由BOX 2D 引擎自动计算 fixtureDef.density = 1.0f; // 设定刚体摩擦系数这一附加属性。请改变这个属性值,观察效果。 fixtureDef.friction = 0.3f; // 设定刚体碰撞后恢复能力这一附加属性。请改变这个属性值,观察效果。 fixtureDef.restitution = 0.5f; // 1.0f 表示刚体碰撞后没有动能损失 // Add the shape to the body. body->CreateFixture(&fixtureDef); // 设定有关物理模拟的时间步数和迭代运算次数,这些参数影响模拟的精度或逼真程度 float timeStep = 1.0f / 60.0f; // 每秒对“物理世界”中的每个物件的状态做 60 次更新 int velocityIterations = 6; // 每次更新对动态物件的速度做 6 次迭代运算 int positionIterations = 2; // 每次更新对动态物件的位置做 2次迭代运算 // 声明一个位置矢量并用刚体“body”的当前位置为其赋值 b2Vec2 position = body->GetPosition(); // 声明刚体的一个初始角度 float angle = 0.2f; // 声明一个POINT 结构数组,用于存储正方形刚体的四个顶点坐标。 // 多用一个POINT 是考虑到稍后调用 GEG::drawpoly 函数时的需要 // 这个 结构数组,可方便地用于 EasyX 图形库的 poly(...) 函数,对于 // GEG::drawpoly(...)函数,调用时有点“笨拙”。 POINT pts[] = { { 0, 0 },{ 0, 0 },{ 0, 0 },{ 0, 0 },{ 0, 0 } }; // 声明两个临时变量,用于存储三角函数计算时的中间值,以避免重复计算。 double trig_cos; double trig_sin; // EGE 相关函数从这里开始被调用 setinitmode(0); // 不要显示 EGE logo initgraph(WINDOW_WIDTH, WINDOW_HEIGHT); // 设定图形视窗的宽、高 // 在视窗的标题栏做一些说明,显示 Samuel Ni 的联系信息 setcaption("BOX 2D Algorithm Explorer. ver 1.5, 2016, Samuel Ni. samuel_ni@yahoo.com"); // 用红色显示长方形“地面”和一个长方形“障碍物” setfillcolor(RED); bar(0, WINDOW_HEIGHT - 50, WINDOW_WIDTH, WINDOW_HEIGHT - 45); bar((int)(WINDOW_WIDTH * 0.65), WINDOW_HEIGHT - 68, (int)(WINDOW_WIDTH * 0.65) + 70, WINDOW_HEIGHT - 45); // 开始物理世界“动画模拟”,一共 160 帧,每帧约 timeStep (1.0/60.0)秒 for (int i = 0; i < 160; ++i) { //稍作延迟,防止动画“闪烁”... 可以采用 EGE 的 img buffer, 效果也许更好 Sleep(20); // 用黑色擦掉四方形刚体 setcolor(BLACK); drawpoly(5, (int *)&pts); // Box 2D 物理引擎对动态物件的速度、位置等做更新运算 world.Step(timeStep, velocityIterations, positionIterations); // 获得四方形刚体更新的位置和角度 position = body->GetPosition(); angle = angle + body->GetAngularVelocity() * timeStep; // 计算四方形刚体每个顶点的更新坐标 for (int j = 0;j<4;j++) { trig_cos = cos(angle + 0.5 * PI * j); trig_sin = sin(angle + 0.5 * PI * j); pts[j].x = (LONG)(SCALE_FACTOR* (position.x + 0.3f * trig_cos)); pts[j].y = (LONG)(WINDOW_HEIGHT - SCALE_FACTOR*(position.y + 0.3f * trig_sin)); } pts[4].x = pts[0].x; // 这个第 5 个 点的坐标计算是 EGE::drawpoly 的要求,easyX::poly 比较简单。 pts[4].y = pts[0].y; //用绿色画出当前位置的四方形刚体 setcolor(GREEN); drawpoly(5, (int *)&pts); //用白色画出当前位置的四方形刚体的中心点(质心) putpixel((int)(SCALE_FACTOR *position.x), WINDOW_HEIGHT - (int)(SCALE_FACTOR*position.y), WHITE); } //“打印”欢迎文字 setcolor(YELLOW); setfont(26, 0, "宋体"); outtextxy(WINDOW_WIDTH / 2 - 180, WINDOW_HEIGHT / 2 - 50, "欢迎来到 BOX2D 虚拟刚体力学世界"); getch(); // 停一下程序,按任意键继续 closegraph(); // 关闭图形界面 return 0; } |
近期评论