文章中的概念来自《Box2D》中文手册

上一节中我们介绍了关节和鼠标关节的使用方法,本章中我们继续介绍距离关节和旋转关节

距离关节(DistanceJoint)

距离关节是两个物体上各有一点,两点之间的距离必须固定不变。当指定一个距离关节时,两个物体必须已在应有的位置上。之后指定世界坐标中的两个锚点。第一个锚点连接到物体1,第二个锚点连接到物体2。这两点隐含距离约束的长度。

// Define the distance joint
DistanceJointDef distanceJointDef = new DistanceJointDef();
// 距离关节连接的2个Body
distanceJointDef.bodyA=smallBall;
distanceJointDef.bodyB=bigBall;
// 是否允许两个Body碰撞
distanceJointDef.collideConnected=false;
// 两个Body之间的距离
distanceJointDef.length = 2.0f;

关节可以具有弹性,通过定义2个常数:频率(frequency)和阻尼率(damping ratio)。频率影响震动的快慢,典型情况下频率要小于时间步的一半。比如每秒执行60次时间步,距离关节的频率就要小于30。
阻尼率无单位,取值在「0,1」之间。当阻尼率设置为1时,没有振动。

        // 下面2个参数使关节具有弹性distanceJointDef.dampingRatio = 0.4f;distanceJointDef.frequencyHz = 4.0f;

下面是测代码

/*** 距离关节*/
public class DistanceJointTest extends ApplicationAdapter {World world;Box2DDebugRenderer box2DDebugRenderer;Body hitBody, groundBody;OrthographicCamera camera;Vector3 point = new Vector3();float scene_width = 12.8f;float scene_height = 7.2f;QueryCallback callback = new QueryCallback() {@Overridepublic boolean reportFixture(Fixture fixture) {if (fixture.testPoint(point.x, point.y)) {hitBody = fixture.getBody();return  false;} elsereturn true;}};@Overridepublic void create() {world = new World(new Vector2(0.0f, -9.8f), true);box2DDebugRenderer = new Box2DDebugRenderer();camera = new OrthographicCamera(scene_width, scene_height);camera.position.set(scene_width / 2, scene_height / 2, 0);camera.update();groundBody = createGroundWall();Gdx.input.setInputProcessor(new HandA());createDistanceJoint();}@Overridepublic void render() {world.step( 1/ 60f, 6, 2);Gdx.gl.glClearColor(0.39f, 0.58f, 0.92f, 1.0f);Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);box2DDebugRenderer.render(world, camera.combined);}@Overridepublic void dispose() {world.dispose();box2DDebugRenderer.dispose();}public void createDistanceJoint() {Body smallBall = createSphere(BodyDef.BodyType.DynamicBody, 0f, 3.75f, .8f, .8f, .4f, .25f);Body bigBall = createSphere(BodyDef.BodyType.DynamicBody, 3.0f, 4.5f, .8f, 1f, .4f, .5f);// Define the distance jointDistanceJointDef distanceJointDef = new DistanceJointDef();distanceJointDef.bodyA=smallBall;distanceJointDef.bodyB=bigBall;distanceJointDef.collideConnected=false;distanceJointDef.length = 5.0f;// 下面2个参数使关节具有弹性distanceJointDef.dampingRatio = 0.4f;distanceJointDef.frequencyHz = 4.0f;distanceJointDef.localAnchorA.set(0,0);distanceJointDef.localAnchorB.set(0,0);world.createJoint(distanceJointDef);}private Body createSphere(BodyDef.BodyType type, float x, float y, float d, float r, float f, float radius) {BodyDef bodyDef = new BodyDef();bodyDef.type = type;bodyDef.position.set(scene_width * 0.5f+x,y);bodyDef.angle=0;Body ball = world.createBody(bodyDef);FixtureDef fixtureDef=new FixtureDef();fixtureDef.density=d;fixtureDef.restitution=r;fixtureDef.friction=f;fixtureDef.shape=new CircleShape();fixtureDef.shape.setRadius(radius);ball.createFixture(fixtureDef);fixtureDef.shape.dispose();return ball;}public Body createGroundWall() {BodyDef bodyDef = new BodyDef();bodyDef.position.set(scene_width * 0.5f, 0.2f);Body body1 = world.createBody(bodyDef);PolygonShape polygonShape = new PolygonShape();polygonShape.setAsBox(scene_width * 0.5f, 0.2f);body1.createFixture(polygonShape, 0.0f);bodyDef.position.set(0.4f, scene_height * 0.5f);Body body2 = world.createBody(bodyDef);polygonShape.setAsBox(0.2f, scene_height * 0.5f);body2.createFixture(polygonShape, 0);bodyDef.position.set(12.4f, scene_height * 0.5f);Body body3 = world.createBody(bodyDef);polygonShape.setAsBox(0.2f, scene_height * 0.5f);body3.createFixture(polygonShape, 0);bodyDef.position.set(scene_width * 0.5f, 7.0f);Body body4 = world.createBody(bodyDef);polygonShape.setAsBox(scene_width * 0.5f, 0.2f);body4.createFixture(polygonShape, 0);polygonShape.dispose();return body1;}class HandA extends InputAdapter {MouseJoint mouseJoint;Vector2 target = new Vector2();@Overridepublic boolean touchDragged(int screenX, int screenY, int pointer) {if (mouseJoint != null) {camera.unproject(point.set(screenX, screenY, 0));mouseJoint.setTarget(target.set(point.x, point.y));}return false;}@Overridepublic boolean touchDown(int screenX, int screenY, int pointer, int button) {camera.unproject(point.set(screenX, screenY, 0));hitBody = null;world.QueryAABB(callback, point.x - 0.0001f, point.y - 0.0001f, point.x + 0.0001f, point.y + 0.0001f);if (hitBody == null || hitBody.equals(groundBody)) return false;MouseJointDef mouseJointDef = new MouseJointDef();mouseJointDef.bodyA = groundBody;mouseJointDef.bodyB = hitBody;mouseJointDef.collideConnected = true;mouseJointDef.target.set(point.x, point.y);mouseJointDef.maxForce = 1000.0f * hitBody.getMass();mouseJoint = (MouseJoint) world.createJoint(mouseJointDef);hitBody.setAwake(true);return false;}@Overridepublic boolean touchUp(int screenX, int screenY, int pointer, int button) {// 鼠标关节,不再使用时要销毁if (mouseJoint != null) {world.destroyJoint(mouseJoint);mouseJoint = null;}return false;}}
}

旋转关节(RevoluteJoint)

旋转关节会强制两个物体公用一个锚点。旋转关节只有一个自由度:两个物体相对旋转。这称之为关节角。
要指定一个旋转关节,需要提供两个物体以及世界坐标的一个锚点,可以参考下面定义:

// Define the revolute joint
RevoluteJointDef revoluteJointDef = new RevoluteJointDef();
revoluteJointDef.bodyA=smallBall;
revoluteJointDef.bodyB=bigBall;
revoluteJointDef.collideConnected=false;
// 指定锚点
revoluteJointDef.localAnchorA.set(0,0);
revoluteJointDef.localAnchorB.set(-2.0f,0);

在Box2D中默认是逆时针旋转的,此时关节角为正,而且旋转角也是弧度制的。在创建两个物体时物理当前的角度是怎样的,旋转关节角都为0。

每次执行step后,可以更新马达的参数。这样可以实现有些有趣的功能。可以在每个时间步中更新关节速度,使得它像正炫波或者任意一个想要的函数那样前后摆动

/*** 旋转关节*/
public class RevoluteJointTest extends ApplicationAdapter {World world;Box2DDebugRenderer box2DDebugRenderer;Body hitBody, groundBody;OrthographicCamera camera;Vector3 point = new Vector3();float scene_width = 12.8f;float scene_height = 7.2f;QueryCallback callback = new QueryCallback() {@Overridepublic boolean reportFixture(Fixture fixture) {if (fixture.testPoint(point.x, point.y)) {hitBody = fixture.getBody();return  false;} elsereturn true;}};@Overridepublic void create() {world = new World(new Vector2(0.0f, -9.8f), true);box2DDebugRenderer = new Box2DDebugRenderer();camera = new OrthographicCamera(scene_width, scene_height);camera.position.set(scene_width / 2, scene_height / 2, 0);camera.update();groundBody = createGroundWall();Gdx.input.setInputProcessor(new HandA());createRevoluteJoin();}@Overridepublic void render() {world.step( 1/ 60f, 6, 2);Gdx.gl.glClearColor(0.39f, 0.58f, 0.92f, 1.0f);Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);box2DDebugRenderer.render(world, camera.combined);}@Overridepublic void dispose() {world.dispose();box2DDebugRenderer.dispose();}public void createRevoluteJoin() {// 第一个Body要设置为Static才能保证第二个Body围绕第一个旋转Body smallBall = createSphere(BodyDef.BodyType.StaticBody, 0f, 3.75f, 1f, 1f, 0f, .25f);Body bigBall = createSphere(BodyDef.BodyType.DynamicBody, 0f, 3.75f, 1f, 1f, 0f, .5f);// Define the revolute jointRevoluteJointDef revoluteJointDef = new RevoluteJointDef();revoluteJointDef.bodyA=smallBall;revoluteJointDef.bodyB=bigBall;revoluteJointDef.collideConnected=false;revoluteJointDef.localAnchorA.set(0,0);revoluteJointDef.localAnchorB.set(-2.0f,0);revoluteJointDef.enableMotor=true;revoluteJointDef.maxMotorTorque=360;revoluteJointDef.motorSpeed=100f* MathUtils.degreesToRadians;world.createJoint(revoluteJointDef);}private Body createSphere(BodyDef.BodyType type, float x, float y, float d, float r, float f, float radius) {BodyDef bodyDef = new BodyDef();bodyDef.type = type;bodyDef.position.set(scene_width * 0.5f+x,y);bodyDef.angle=0;Body ball = world.createBody(bodyDef);FixtureDef fixtureDef=new FixtureDef();fixtureDef.density=d;fixtureDef.restitution=r;fixtureDef.friction=f;fixtureDef.shape=new CircleShape();fixtureDef.shape.setRadius(radius);ball.createFixture(fixtureDef);fixtureDef.shape.dispose();return ball;}public Body createGroundWall() {BodyDef bodyDef = new BodyDef();bodyDef.position.set(scene_width * 0.5f, 0.2f);Body body1 = world.createBody(bodyDef);PolygonShape polygonShape = new PolygonShape();polygonShape.setAsBox(scene_width * 0.5f, 0.2f);body1.createFixture(polygonShape, 0.0f);bodyDef.position.set(0.4f, scene_height * 0.5f);Body body2 = world.createBody(bodyDef);polygonShape.setAsBox(0.2f, scene_height * 0.5f);body2.createFixture(polygonShape, 0);bodyDef.position.set(12.4f, scene_height * 0.5f);Body body3 = world.createBody(bodyDef);polygonShape.setAsBox(0.2f, scene_height * 0.5f);body3.createFixture(polygonShape, 0);bodyDef.position.set(scene_width * 0.5f, 7.0f);Body body4 = world.createBody(bodyDef);polygonShape.setAsBox(scene_width * 0.5f, 0.2f);body4.createFixture(polygonShape, 0);polygonShape.dispose();return body1;}class HandA extends InputAdapter {MouseJoint mouseJoint;Vector2 target = new Vector2();@Overridepublic boolean touchDragged(int screenX, int screenY, int pointer) {if (mouseJoint != null) {camera.unproject(point.set(screenX, screenY, 0));mouseJoint.setTarget(target.set(point.x, point.y));}return false;}@Overridepublic boolean touchDown(int screenX, int screenY, int pointer, int button) {camera.unproject(point.set(screenX, screenY, 0));hitBody = null;world.QueryAABB(callback, point.x - 0.0001f, point.y - 0.0001f, point.x + 0.0001f, point.y + 0.0001f);if (hitBody == null || hitBody.equals(groundBody)) return false;MouseJointDef mouseJointDef = new MouseJointDef();mouseJointDef.bodyA = groundBody;mouseJointDef.bodyB = hitBody;mouseJointDef.collideConnected = true;mouseJointDef.target.set(point.x, point.y);mouseJointDef.maxForce = 1000.0f * hitBody.getMass();mouseJoint = (MouseJoint) world.createJoint(mouseJointDef);hitBody.setAwake(true);return false;}@Overridepublic boolean touchUp(int screenX, int screenY, int pointer, int button) {// 鼠标关节,不再使用时要销毁if (mouseJoint != null) {world.destroyJoint(mouseJoint);mouseJoint = null;}return false;}}
}

7.Libgdx扩展学习之Box2D_距离关节 旋转关节相关推荐

  1. 6.Libgdx扩展学习之Box2D_鼠标关节

    下面一些内容定义来自<Box2D中文手册> 关于 关节用于把物体约束到世界,或约束到其它物体上.在游戏中,典型例子有木偶,跷跷板和滑轮.用不同的方式将关节结合起来使用,可以创造出有趣的运动 ...

  2. 1.Libgdx扩展学习之Box2D_入门介绍

    文章中涉及的很多概念,都是来自<Box2D中文手册>.有统一的解释方便理解. Box2D简单介绍 Box2D 是一个用于游戏的 2D 刚体仿真库, 是用可移植的C++写成的.程序员可以在他 ...

  3. 2.Libgdx扩展学习之Box2D_刚体和形状

    文章中涉及的很多概念,都是来自<Box2D中文手册>.有统一的解释方便理解. 物体(刚体/Body) 概念介绍 物体具有位置和速度.可以将力(forces).扭矩(torques).冲量( ...

  4. 3.Libgdx扩展学习之Box2D_夹具

    文章中涉及的很多概念,都是来自<Box2D中文手册>.有统一的解释方便理解 夹具 概念介绍 形状不知道物体的存在,并可独立于物理模拟而被使用.因此 Box2D 提供 Fixture 类,用 ...

  5. 5.Libgdx扩展学习之Box2D_刚体的运动和贴图

    主要根据这2篇文章来写的: 1. http://bbs.9ria.com/thread-135588-1-1.html 2. http://bbs.9ria.com/thread-137127-1-1 ...

  6. 4.Libgdx扩展学习之Box2D_创建多边形刚体和圆角矩形

    主要是根据这2篇博客来写的 1. http://bbs.9ria.com/thread-136661-1-1.html 2. http://bbs.9ria.com/thread-136794-1-1 ...

  7. oracle segment undo_71_UNDO扩展学习

    UNDO扩展学习 UNDO是Oracle在UNDO SEGMENT(回滚段)中记录的信息.下面使用UNDO这名字可能会包含两种意思,一是前面说的回滚段中的记录.二是UNDO整个机制. 在这部分内容里, ...

  8. PHP的OpenSSL加密扩展学习(三):证书操作

    PHP的OpenSSL加密扩展学习(三):证书操作 关于对称和非对称的加密操作,我们已经学习完两篇文章的内容了,接下来,我们就继续学习关于证书的生成. 生成 CSR 证书签名请求 CSR 是用于生成证 ...

  9. Elasticsearch扩展学习

    ES扩展学习 文章目录 ES扩展学习 基本概念 分片 重新索引实现分片数量的修改 副本 两者的作用 ES扩容分片及磁盘基本情况 分片情况 集群分片分配策略. 分片数量和数据的关系 磁盘情况 磁盘使用率 ...

最新文章

  1. codeforces D Prefixes and Suffixes(kmp)
  2. CTFshow 爆破 web26
  3. ni软件可以卸载吗_黑科技 | 2020全新AI人工智能修图汉化版软件!这下可以放心卸载PS啦!...
  4. mysql多表联查到新的表中_MySQL中的多表联查
  5. python小城市创业好项目_小城市创业好项目有哪些?
  6. 3分钟快速presentation
  7. IDEA JetBrains Mono字体介绍和安装
  8. Vue指令之v-if
  9. C#读取所有PC中所有进程
  10. 上下定高 中间自适应_B站微服务框架Kratos详细教程(3)中间件
  11. 学Java看这就完事了!javasocket编程例子
  12. c++调用powershell_告别 Windows 终端的难看难用,从改造 PowerShell 的外观开始
  13. 30套后台管理界面分享
  14. UE4母材质之法线贴图
  15. 特稿 | 纳德拉成长史 x 微软重生之路
  16. 360无线wifi路由器连接到服务器,把360无线路由器设置为二级路由器 | 192路由网...
  17. css怎么设置图片卷角效果,CSS3 带分隔线卷角贴纸效果
  18. X书x-mini-sig_x-mini-mua
  19. VMWare:vSphere6 企业版参考序列号
  20. html5我的心灵小屋,描写我的小屋优美句子

热门文章

  1. OPPO A7在哪里打开Usb调试模式的简单教程
  2. 教你正确使iphone 4s进入DFU模式及恢复模式
  3. Native memory allocation (mmap) failed to map 6215958528 bytes for committing reserved memory
  4. Win7怎么使用计划任务定时重新启动电脑
  5. 弘辽科技:80后创业故事:开网店1年内卖鞋3万双
  6. linux usb 动态pm 学习记录
  7. 关于TFT LCD屏ST7735S驱动移植STM32HAL库的部分问题总结
  8. 【汇正财经】汽车行业,销量恢复快速增长
  9. 漫步英伦14:雾里看花都柏林
  10. Markdown转Html应用与实践