Box2d中,物体可以接受力(Force)、冲量(Impulse)和扭矩(Torque)。这些物理元素都能改变物体的运动形式,并且默认都会唤醒物体,当然只是针对动态物体。
力是一个持久的效果,通过Box2d内置的积分器实现运动变化。
冲量是一个瞬时效果,能立马改变其效果。
主要函数:
body.applyLinearImpulse( Vector2 impulse, Vector2 position, boolean wakeup
)
第一个参数表示冲量,包含x和y方向的大小。
第二个参数表示施加冲量的位置。
第三个参数表示是否唤醒物体。
物体碰撞时,可以检测到碰撞的过程,开始和结束,并能够通过其Contact类获取碰撞的2个物体形状,进而获取物体。
物体可以设置UserData,然后可以在render函数中获取对应的UserData,并设置对应的角度和位置就能够显示图片等元素。
关节(Joint)是物体之间连接的方式,添加关节后物体的自由度会减少,运动轨迹会受到一定约束。
Box2d中有距离、旋转、滑轮、鼠标等一系列关节,这些都很方便的帮我们模拟现实。
具体示例:
1 package com.fxb.newtest;
2
3 import com.badlogic.gdx.ApplicationAdapter;
4 import com.badlogic.gdx.Gdx;
5 import com.badlogic.gdx.Input;
6 import com.badlogic.gdx.InputAdapter;
7 import com.badlogic.gdx.graphics.GL10;
8 import com.badlogic.gdx.graphics.OrthographicCamera;
9 import com.badlogic.gdx.graphics.Texture;
10 import com.badlogic.gdx.graphics.g2d.Sprite;
11 import com.badlogic.gdx.graphics.g2d.SpriteBatch;
12 import com.badlogic.gdx.graphics.g2d.TextureRegion;
13 import com.badlogic.gdx.math.MathUtils;
14 import com.badlogic.gdx.math.Vector2;
15 import com.badlogic.gdx.physics.box2d.Body;
16 import com.badlogic.gdx.physics.box2d.BodyDef;
17 import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
18 import com.badlogic.gdx.physics.box2d.CircleShape;
19 import com.badlogic.gdx.physics.box2d.Contact;
20 import com.badlogic.gdx.physics.box2d.ContactImpulse;
21 import com.badlogic.gdx.physics.box2d.ContactListener;
22 import com.badlogic.gdx.physics.box2d.FixtureDef;
23 import com.badlogic.gdx.physics.box2d.Joint;
24 import com.badlogic.gdx.physics.box2d.JointDef;
25 import com.badlogic.gdx.physics.box2d.JointDef.JointType;
26 import com.badlogic.gdx.physics.box2d.Manifold;
27 import com.badlogic.gdx.physics.box2d.PolygonShape;
28 import com.badlogic.gdx.physics.box2d.World;
29 import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
30 import com.badlogic.gdx.physics.box2d.joints.DistanceJointDef;
31 import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;
32 import com.badlogic.gdx.utils.Array;
33
34 public class Lib021_Box2d1 extends ApplicationAdapter{
35
36 World world;
37 OrthographicCamera camera;
38 //DebugRenderer debugRenderer;
39 Box2DDebugRenderer debugRenderer;
40 Body bodyBox, bodyCircle;
41 TextureRegion region;
42 Sprite sprite;
43 SpriteBatch batch;
44 final Array<Body> arrBody = new Array<Body>();
45
46 @Override
47 public void create() {
48 // TODO Auto-generated method stub
49 super.create();
50
51 camera = new OrthographicCamera();
52 camera.setToOrtho( false, Gdx.graphics.getWidth()/10, Gdx.graphics.getHeight()/10 );
53 debugRenderer = new Box2DDebugRenderer();
54 world = new World( new Vector2(0, -10), true );
55
56 batch = new SpriteBatch();
57 region = new TextureRegion( new Texture( Gdx.files.internal( "data/badlogicsmall.jpg" ) ) );
58 sprite = new Sprite( region );
59 sprite.setSize( 4, 4 );
60
61
62 BodyDef bodyGroundDef = new BodyDef();
63 bodyGroundDef.type = BodyType.StaticBody;
64 bodyGroundDef.position.set( 0, 2 );
65 Body bodyGround = world.createBody( bodyGroundDef );
66
67 PolygonShape shapeGround = new PolygonShape();
68 shapeGround.setAsBox( camera.viewportWidth, 1 );
69 bodyGround.createFixture( shapeGround, 1 );
70 shapeGround.dispose();
71
72
73 BodyDef bodyBoxDef = new BodyDef();
74 bodyBoxDef.type = BodyType.DynamicBody;
75 bodyBoxDef.position.set( 5, 60 );
76 bodyBox = world.createBody( bodyBoxDef );
77 PolygonShape shapeBox = new PolygonShape();
78 shapeBox.setAsBox( 2, 2 );
79 FixtureDef fixtureDefBox = new FixtureDef();
80 fixtureDefBox.friction = 0.1f;
81 fixtureDefBox.shape = shapeBox;
82 fixtureDefBox.restitution = 0.3f;
83 //bodyBox.createFixture( shapeBox, 1 );
84 bodyBox.createFixture( fixtureDefBox );
85 shapeBox.dispose();
86 //bodyBox.setUserData( sprite );
87
88 BodyDef bodyCircleDef = new BodyDef();
89 bodyCircleDef.type = BodyType.DynamicBody;
90 bodyCircleDef.position.set( 20, 30 );
91 bodyCircle = world.createBody( bodyCircleDef );
92 CircleShape shapeCircle = new CircleShape();
93 shapeCircle.setRadius(2);
94 FixtureDef fixtureDefCir = new FixtureDef();
95 fixtureDefCir.friction = 0.1f;
96 fixtureDefCir.shape = shapeCircle;
97 fixtureDefCir.restitution = 0.3f;
98 bodyCircle.createFixture( fixtureDefCir );
99 shapeCircle.dispose();
100
101 InputAdapter processor = new InputAdapter(){
102 @Override
103 public boolean keyDown(int keycode) {
104 if( keycode == Input.Keys.A ){
105 //bodyBox.applyForce( 2f, 0, bodyBox.getPosition().x, bodyBox.getPosition().y, true );
106 //bodyBox.applyForceToCenter( 2f, 2f, true );
107 bodyBox.applyLinearImpulse( 12f, 0, bodyBox.getPosition().x, bodyBox.getPosition().y, true );
108 System.out.println( "a" );
109 }
110 return super.keyDown(keycode);
111 }
112 };
113 Gdx.input.setInputProcessor( processor );
114
115
116 world.setContactListener( new ContactListener(){
117 @Override
118 public void beginContact(Contact contact) {
119 // TODO Auto-generated method stub
120 System.out.println( "begin" );
121 Body body1 = contact.getFixtureA().getBody();
122 Body body2 = contact.getFixtureB().getBody();
123 System.out.println( body1.getPosition().x + "," + body1.getPosition().y );
124 System.out.println( body2.getPosition().x + "," + body2.getPosition().y );
125
126 if( body1.getType() == BodyType.DynamicBody ){
127 body1.setUserData( sprite );
128 }
129 if( body2.getType() == BodyType.DynamicBody ){
130 body2.setUserData( sprite );
131 }
132 }
133
134 @Override
135 public void endContact(Contact contact) {
136 // TODO Auto-generated method stub
137 System.out.println( "end" );
138
139 Body body1 = contact.getFixtureA().getBody();
140 Body body2 = contact.getFixtureB().getBody();
141 if( body1.getType() == BodyType.DynamicBody ){
142 body1.setUserData( null );
143 }
144 if( body2.getType() == BodyType.DynamicBody ){
145 body2.setUserData( null );
146 }
147 }
148
149 @Override
150 public void preSolve(Contact contact, Manifold oldManifold) {
151 // TODO Auto-generated method stub
152 }
153 @Override
154 public void postSolve(Contact contact, ContactImpulse impulse) {
155 // TODO Auto-generated method stub
156 }
157
158 });
159
160
161 DistanceJointDef jointDefDis = new DistanceJointDef();
162 jointDefDis.bodyA = bodyBox;
163 jointDefDis.bodyB = bodyCircle;
164 jointDefDis.type = JointType.DistanceJoint;
165 jointDefDis.length = 10;
166 Joint jointDis = world.createJoint( jointDefDis );
167
168
169 /* RevoluteJointDef jointDefRevo = new RevoluteJointDef();
170 //jointDefRevo.bodyA = bodyBox;
171 //jointDefRevo.bodyB = bodyCircle;
172 jointDefRevo.initialize( bodyBox, bodyCircle, bodyCircle.getWorldCenter() );
173 jointDefRevo.type = JointType.RevoluteJoint;
174 Joint jointRevo = world.createJoint( jointDefRevo );*/
175 }
176
177 @Override
178 public void render() {
179 // TODO Auto-generated method stub
180 super.render();
181 Gdx.gl.glClear( GL10.GL_COLOR_BUFFER_BIT );
182
183
184 if( Gdx.input.isKeyPressed( Input.Keys.D ) ){
185 bodyBox.applyForce( 12f, 0, bodyBox.getPosition().x, bodyBox.getPosition().y, true );
186 }
187
188 world.step( Gdx.graphics.getDeltaTime(), 6, 2 );
189 camera.update();
190
191 batch.setProjectionMatrix( camera.combined );
192 batch.begin();
193
194 world.getBodies( arrBody );
195 for( int i=0; i<arrBody.size; ++i ){
196 Body body = arrBody.get(i);
197 Sprite sprite0 = (Sprite)body.getUserData();
198 if( sprite0 != null ){
199 sprite0.setPosition( body.getPosition().x-2, body.getPosition().y-2 );
200 sprite0.setRotation( MathUtils.radiansToDegrees*body.getAngle() );
201 sprite0.draw( batch );
202 }
203 }
204 batch.end();
205
206 debugRenderer.render( world, camera.combined );
207
208 }
209
210 @Override
211 public void dispose() {
212 // TODO Auto-generated method stub
213 super.dispose();
214 }
215
216 }
运行效果:
落地后与地面发生碰撞,物体中间的图片都正常显示。
按下‘A’键后,方块物体向右移动,与圆环发生碰撞,内部UserData都设为null,没有图片显示。
添加了距离关节,两者连在了一起。
同时Box2d与stage也能够很好的结合起来一起显示,很方便。
时间: 2024-10-24 23:56:27