接上一篇,这里我们使用collisionWorld
直接上代码,细节看注释:
1 package org.forus.game.test; 2 3 import com.badlogic.gdx.ApplicationListener; 4 import com.badlogic.gdx.Gdx; 5 import com.badlogic.gdx.graphics.Color; 6 import com.badlogic.gdx.graphics.GL20; 7 import com.badlogic.gdx.graphics.PerspectiveCamera; 8 import com.badlogic.gdx.graphics.VertexAttributes.Usage; 9 import com.badlogic.gdx.graphics.g3d.Environment; 10 import com.badlogic.gdx.graphics.g3d.Material; 11 import com.badlogic.gdx.graphics.g3d.Model; 12 import com.badlogic.gdx.graphics.g3d.ModelBatch; 13 import com.badlogic.gdx.graphics.g3d.ModelInstance; 14 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute; 15 import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight; 16 import com.badlogic.gdx.graphics.g3d.utils.CameraInputController; 17 import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder; 18 import com.badlogic.gdx.math.MathUtils; 19 import com.badlogic.gdx.math.Vector3; 20 import com.badlogic.gdx.physics.bullet.Bullet; 21 import com.badlogic.gdx.physics.bullet.collision.ContactListener; 22 import com.badlogic.gdx.physics.bullet.collision.btBoxShape; 23 import com.badlogic.gdx.physics.bullet.collision.btBroadphaseInterface; 24 import com.badlogic.gdx.physics.bullet.collision.btCapsuleShape; 25 import com.badlogic.gdx.physics.bullet.collision.btCollisionConfiguration; 26 import com.badlogic.gdx.physics.bullet.collision.btCollisionDispatcher; 27 import com.badlogic.gdx.physics.bullet.collision.btCollisionObject; 28 import com.badlogic.gdx.physics.bullet.collision.btCollisionShape; 29 import com.badlogic.gdx.physics.bullet.collision.btCollisionWorld; 30 import com.badlogic.gdx.physics.bullet.collision.btConeShape; 31 import com.badlogic.gdx.physics.bullet.collision.btCylinderShape; 32 import com.badlogic.gdx.physics.bullet.collision.btDbvtBroadphase; 33 import com.badlogic.gdx.physics.bullet.collision.btDefaultCollisionConfiguration; 34 import com.badlogic.gdx.physics.bullet.collision.btDispatcher; 35 import com.badlogic.gdx.physics.bullet.collision.btSphereShape; 36 import com.badlogic.gdx.utils.Array; 37 import com.badlogic.gdx.utils.ArrayMap; 38 import com.badlogic.gdx.utils.Disposable; 39 40 /** 41 * Created by HanHongmin on 14-8-23. 42 */ 43 public class CollisionWorldTest implements ApplicationListener { 44 final static short GROUND_FLAG = 1<<8; 45 final static short OBJECT_FLAG = 1<<9;//为什么设置成这样我没细看,可能为了和别的不冲突 http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=5449#p19521 46 final static short ALL_FLAG = -1; 47 class MyContactListener extends ContactListener { 48 @Override 49 public boolean onContactAdded (int userValue0, int partId0, int index0, int userValue1, int partId1, int index1) { 50 //此处过滤掉任何两个物体碰撞 51 //有一个是0,即ground的情况,才把另一个停下来 52 53 //if (userValue1 == 0) 54 instances.get(userValue0).moving = false; 55 //else if (userValue0 == 0) 56 instances.get(userValue1).moving = false; 57 58 //如果添加时collisionWorld.addCollisionObject(object.body, GROUND_FLAG, ALL_FLAG)这种带了标记参数,这里不用判断哪个是ground了 59 return true; 60 } 61 } 62 63 static class GameObject extends ModelInstance implements Disposable { 64 public final btCollisionObject body; 65 public boolean moving; 66 67 public GameObject (Model model, String node, btCollisionShape shape) { 68 super(model, node); 69 body = new btCollisionObject(); 70 body.setCollisionShape(shape); 71 } 72 73 @Override 74 public void dispose () { 75 body.dispose(); 76 } 77 78 static class Constructor implements Disposable { 79 public final Model model; 80 public final String node; 81 public final btCollisionShape shape; 82 83 public Constructor (Model model, String node, btCollisionShape shape) { 84 this.model = model; 85 this.node = node; 86 this.shape = shape; 87 } 88 89 public GameObject construct () { 90 return new GameObject(model, node, shape); 91 } 92 93 @Override 94 public void dispose () { 95 shape.dispose(); 96 } 97 } 98 } 99 100 PerspectiveCamera cam; 101 CameraInputController camController; 102 ModelBatch modelBatch; 103 Environment environment; 104 Model model; 105 Array<GameObject> instances; 106 ArrayMap<String, GameObject.Constructor> constructors; 107 float spawnTimer; 108 109 btCollisionConfiguration collisionConfig; 110 btDispatcher dispatcher; 111 MyContactListener contactListener; 112 btBroadphaseInterface broadphase; 113 btCollisionWorld collisionWorld; 114 115 @Override 116 public void create () { 117 Bullet.init(); 118 119 modelBatch = new ModelBatch(); 120 environment = new Environment(); 121 environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f)); 122 environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f)); 123 124 cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); 125 cam.position.set(3f, 7f, 10f); 126 cam.lookAt(0, 4f, 0); 127 cam.near = 1f; 128 cam.far = 300f; 129 cam.update(); 130 131 camController = new CameraInputController(cam); 132 Gdx.input.setInputProcessor(camController); 133 134 ModelBuilder mb = new ModelBuilder(); 135 mb.begin(); 136 mb.node().id = "ground"; 137 mb.part("ground", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.RED))) 138 .box(5f, 1f, 5f); 139 mb.node().id = "sphere"; 140 mb.part("sphere", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.GREEN))) 141 .sphere(1f, 1f, 1f, 10, 10); 142 mb.node().id = "box"; 143 mb.part("box", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.BLUE))) 144 .box(1f, 1f, 1f); 145 mb.node().id = "cone"; 146 mb.part("cone", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.YELLOW))) 147 .cone(1f, 2f, 1f, 10); 148 mb.node().id = "capsule"; 149 mb.part("capsule", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.CYAN))) 150 .capsule(0.5f, 2f, 10); 151 mb.node().id = "cylinder"; 152 mb.part("cylinder", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, 153 new Material(ColorAttribute.createDiffuse(Color.MAGENTA))).cylinder(1f, 2f, 1f, 10); 154 model = mb.end(); 155 156 constructors = new ArrayMap<String, GameObject.Constructor>(String.class, GameObject.Constructor.class); 157 constructors.put("ground", new GameObject.Constructor(model, "ground", new btBoxShape(new Vector3(2.5f, 0.5f, 2.5f)))); 158 constructors.put("sphere", new GameObject.Constructor(model, "sphere", new btSphereShape(0.5f))); 159 constructors.put("box", new GameObject.Constructor(model, "box", new btBoxShape(new Vector3(0.5f, 0.5f, 0.5f)))); 160 constructors.put("cone", new GameObject.Constructor(model, "cone", new btConeShape(0.5f, 2f))); 161 constructors.put("capsule", new GameObject.Constructor(model, "capsule", new btCapsuleShape(.5f, 1f))); 162 constructors.put("cylinder", new GameObject.Constructor(model, "cylinder", new btCylinderShape(new Vector3(.5f, 1f, .5f)))); 163 164 collisionConfig = new btDefaultCollisionConfiguration(); 165 dispatcher = new btCollisionDispatcher(collisionConfig); 166 broadphase = new btDbvtBroadphase(); 167 collisionWorld = new btCollisionWorld(dispatcher, broadphase, collisionConfig); 168 contactListener = new MyContactListener(); 169 170 instances = new Array<GameObject>(); 171 GameObject object = constructors.get("ground").construct(); 172 object.body.setUserValue(0);//貌似不设置就是0 173 instances.add(object); 174 collisionWorld.addCollisionObject(object.body, GROUND_FLAG, ALL_FLAG);//同时设置它自身的flag和可以和他碰撞的flag 175 } 176 177 public void spawn () { 178 GameObject obj = constructors.values[1 + MathUtils.random(constructors.size - 2)].construct(); 179 obj.moving = true; 180 obj.transform.setFromEulerAngles(MathUtils.random(360f), MathUtils.random(360f), MathUtils.random(360f)); 181 obj.transform.trn(MathUtils.random(-2.5f, 2.5f), 9f, MathUtils.random(-2.5f, 2.5f)); 182 obj.body.setWorldTransform(obj.transform); 183 obj.body.setUserValue(instances.size);//注意 184 obj.body.setCollisionFlags(obj.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK); 185 instances.add(obj); 186 collisionWorld.addCollisionObject(obj.body, OBJECT_FLAG, GROUND_FLAG); 187 } 188 189 @Override 190 public void render () { 191 final float delta = Math.min(1f / 30f, Gdx.graphics.getDeltaTime()); 192 193 for (GameObject obj : instances) { 194 if (obj.moving) { 195 obj.transform.trn(0f, -delta, 0f); 196 obj.body.setWorldTransform(obj.transform); 197 } 198 } 199 200 collisionWorld.performDiscreteCollisionDetection();//语意 执行离散碰撞检测 201 202 if ((spawnTimer -= delta) < 0) { 203 spawn(); 204 spawnTimer = 1.5f; 205 } 206 207 camController.update(); 208 209 Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1.f); 210 Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); 211 212 modelBatch.begin(cam); 213 modelBatch.render(instances, environment); 214 modelBatch.end(); 215 } 216 217 @Override 218 public void dispose () { 219 for (GameObject obj : instances) 220 obj.dispose(); 221 instances.clear(); 222 223 for (GameObject.Constructor ctor : constructors.values()) 224 ctor.dispose(); 225 constructors.clear(); 226 227 collisionWorld.dispose(); 228 broadphase.dispose(); 229 dispatcher.dispose(); 230 collisionConfig.dispose(); 231 232 contactListener.dispose(); 233 234 modelBatch.dispose(); 235 model.dispose(); 236 } 237 238 @Override 239 public void pause () { 240 } 241 242 @Override 243 public void resume () { 244 } 245 246 @Override 247 public void resize (int width, int height) { 248 } 249 }