接上一篇,这里我们使用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 Arrayinstances;106 ArrayMap constructors;107 float spawnTimer;108 109 btCollisionConfiguration collisionConfig;110 btDispatcher dispatcher;111 MyContactListener contactListener;112 btBroadphaseInterface broadphase;113 btCollisionWorld collisionWorld;114 115 @Override116 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.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 ();171 GameObject object = constructors.get("ground").construct();172 object.body.setUserValue(0);//貌似不设置就是0173 instances.add(object);174 collisionWorld.addCollisionObject(object.body, GROUND_FLAG, ALL_FLAG);//同时设置它自身的flag和可以和他碰撞的flag175 }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 @Override190 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 @Override218 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 @Override239 public void pause () {240 }241 242 @Override243 public void resume () {244 }245 246 @Override247 public void resize (int width, int height) {248 }249 }