• libgdx 3D Bullet 碰撞检测二


    接上一篇,这里我们使用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 }
  • 相关阅读:
    用Fragment实现如新浪微博一样的底部菜单的切换
    Android基础之使用Fragment控制切换多个页面
    Android_Fragment_Fragment详解
    android下拉菜单spinner的使用方法
    eclipse / ADT(Android Develop Tool) 一些方便的初始设置
    Android Studio如何设置代码自动提示
    <交流贴>android语音识别之科大讯飞语音API的使用
    原 [Android]LIstView的HeaderView
    001 Java 深拷贝、浅拷贝及Cloneable接口
    GenericServlet与HttpServlet
  • 原文地址:https://www.cnblogs.com/hanhongmin/p/3931616.html
Copyright © 2020-2023  润新知