2013-05-02 3 views
4

JMonkeyEngine을 사용하여 Java 게임을 만들고 있으며 사이트에서 자습서를 따라 벽에 볼 (총알)을 쐈습니다. 나는 모든 것이 작동하는 방법을 얻지 만, 총알의 속도를 증가 시키면 벽을 똑바로 통과합니다.jmonkeyengine 움직임이 너무 빨라서 충돌 감지가 발생했습니다.

이제 총알이 프레임 당 너무 빨리 이동하여 등록 할 수있는 이유가 있습니다. 나는 또한 이것을 해결하는 방법을 알고 있고 나는 그들의 웹 사이트 (JMonkeyEngine)에 다음과 같은 방법을 발견했다.

setCcdMotionThreshold(0f) 

그러나 구현 방법이나 다른 사람이이 샘플을 사용할 수있는 곳을 알 수 있습니까? 용지 문제 대 총알

답변

6

소개
연속 충돌 감지 (CCD)를 다룬다. 빠르게 움직이는 물체가 한 타임 스텝에서 얇은 물체의 한면이고 다음 단계에서 다른면이 충돌이 전혀 발생하지 않았다고 믿는 물리 엔진으로 연결되는 곳입니다. 반면에 연속 충돌 감지는 시간 단계를 전혀 사용하지 않습니다. 타임 스텝의 전체 기간 동안 스윕 볼륨을 생성하고 스윕 볼륨이 무엇인가와 충돌하는지 찾습니다. 이는 비용이 많이 들고 부정확합니다 (전체 충돌 셰이프보다는 단순한 원형 충돌 셰이프가 사용되기 때문에).

사용이 연속 충돌 감지는 개체 당 기본 설정되어
, 당신은 CCD와 같은 시간에 같은 장면에서하지 않는 개체를 사용하여 객체를 가질 수 있습니다, CCD는 물리학에 설정되어 객체는

RigidBodyControl physicsObject = new RigidBodyControl(mass); 
physicsObject.setCcdMotionThreshold(expectedWidthOfThinObject); 
physicsObject.setCcdSweptSphereRadius(radiusOfSphereThatWillFullyContainObject); 
  • 당신은 높은 expectedWidthOfThinObject을 설정하려면 아래와 같이 멀리 과를 얻을 수 있습니다; ccd가 비싸고 부정확하다는 것을 기억하십시오. 완전히 객체에게

전체 예제를 포함하는 동안 제로로 설정하면
다음 소스 코드를 연속 충돌을 사용하여 차이점을 보여줍니다 당신은 가능한 한 작게 radiusOfSphereThatWillFullyContainObject을 설정할

  • 떨어져 CCD를 설정합니다 감지 및 표준 충돌 감지를 사용합니다. 그것은 두 세트의 공을 발사합니다. 하나는 빠르며 다른 하나는 천천히 회전하고 5 초 간격으로 ccd를 켜고 끕니다. 느린 볼은 항상 종이와 충돌합니다. 빠른 속도는 ccd가 켜져있을 때만 가능합니다. 공 두 세트의 연속적인 검출을

    import com.jme3.app.SimpleApplication; 
    import com.jme3.bullet.BulletAppState; 
    import com.jme3.bullet.control.RigidBodyControl; 
    import com.jme3.font.BitmapText; 
    import com.jme3.material.Material; 
    import com.jme3.math.ColorRGBA; 
    import com.jme3.math.Vector3f; 
    import com.jme3.scene.Geometry; 
    import com.jme3.scene.shape.Box; 
    import com.jme3.scene.shape.Sphere; 
    
    public class BulletTest extends SimpleApplication { 
    
        public static void main(String args[]) { 
        BulletTest app = new BulletTest(); 
        app.start(); 
        } 
    
        /** Prepare the Physics Application State (jBullet) */ 
        private BulletAppState bulletAppState; 
    
        /** Prepare Materials */ 
        Material wall_mat; 
        Material slow_mat; 
        Material fast_mat; 
        Material floor_mat; 
    
    
        private RigidBodyControl brick_phy; 
        private static final Box box; 
        private static final Sphere sphere; 
        private RigidBodyControl floor_phy; 
        private static final Box floor; 
    
        /** dimensions used for wall */ 
        private static final float brickLength = 2f; 
        private static final float brickWidth = 0.015f; 
        private static final float brickHeight = 1f; 
    
        static { 
        /** Initialize the cannon ball geometry */ 
        sphere = new Sphere(32, 32, 0.1f, true, false); 
        /** Initialize the brick geometry */ 
        box = new Box(brickWidth, brickHeight, brickLength); 
        /** Initialize the floor geometry */ 
        floor = new Box(10f, 0.1f, 5f); 
    
        } 
    
        @Override 
        public void simpleInitApp() { 
        /** Set up Physics Game */ 
        bulletAppState = new BulletAppState(); 
        stateManager.attach(bulletAppState); 
        //bulletAppState.getPhysicsSpace().enableDebug(assetManager); 
    
        /** Configure cam to look at scene */ 
        cam.setLocation(new Vector3f(0, 4f, 6f)); 
        cam.lookAt(new Vector3f(2, 2, 0), Vector3f.UNIT_Y); 
    
        /** Initialize the scene, materials, and physics space */ 
        initMaterials(); 
        initWall(); 
        initFloor(); 
        setUpHUDText(); 
        } 
    
        public static final float FIREPERIOD=0.5f; 
        double fireTimer=0; 
    
        public static final float SWEEPPERIOD=5f; 
        double sweepTimer=0; 
        boolean continuouslySweeping=true; 
    
    
        @Override 
        public void simpleUpdate(float tpf) { 
         fireTimer+=tpf; 
         sweepTimer+=tpf; 
    
         if (sweepTimer>SWEEPPERIOD){ 
          sweepTimer=0; 
          continuouslySweeping=!continuouslySweeping; 
         } 
    
         hudText.setText("ContinouslySweeping=" + continuouslySweeping + "(" + (int)(SWEEPPERIOD-sweepTimer) + ")"); 
    
         if (fireTimer>FIREPERIOD){ 
          fireTimer=0; 
          makeCannonBall(new Vector3f(-4,3,0),new Vector3f(6,4,0),slow_mat,continuouslySweeping); //slow arcing ball 
          makeCannonBall(new Vector3f(-4,3,-0.5f),new Vector3f(10,1,0),fast_mat,continuouslySweeping); //fast straight ball 
         } 
        } 
    
        public BitmapText hudText; 
    
        private void setUpHUDText(){ 
         hudText = new BitmapText(guiFont, false);   
         hudText.setSize(guiFont.getCharSet().getRenderedSize());  // font size 
         hudText.setColor(ColorRGBA.White);        // font color 
         hudText.setText("ContinouslySweeping=true");    // the text 
         hudText.setLocalTranslation(300, hudText.getLineHeight(), 0); // position 
         guiNode.attachChild(hudText); 
        } 
    
        /** Initialize the materials used in this scene. */ 
        public void initMaterials() { 
        wall_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); 
        wall_mat.setColor("Color", ColorRGBA.Blue); 
    
        fast_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); 
        fast_mat.setColor("Color", ColorRGBA.Red); 
    
        slow_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); 
        slow_mat.setColor("Color", ColorRGBA.Green); 
    
        floor_mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); 
        floor_mat.setColor("Color", ColorRGBA.Gray); 
        } 
    
        /** Make a solid floor and add it to the scene. */ 
        public void initFloor() { 
        Geometry floor_geo = new Geometry("Floor", floor); 
        floor_geo.setMaterial(floor_mat); 
        floor_geo.setLocalTranslation(0, -0.1f, 0); 
        this.rootNode.attachChild(floor_geo); 
        /* Make the floor physical with mass 0.0f! */ 
        floor_phy = new RigidBodyControl(0.0f); 
        floor_geo.addControl(floor_phy); 
        bulletAppState.getPhysicsSpace().add(floor_phy); 
        } 
    
        /** This loop builds a wall out of individual bricks. */ 
        public void initWall() { 
    
         Vector3f location=new Vector3f(2,2,0); 
         Geometry brick_geo = new Geometry("brick", box); 
         brick_geo.setMaterial(wall_mat); 
         rootNode.attachChild(brick_geo); 
         /** Position the brick geometry */ 
         brick_geo.setLocalTranslation(location); 
    
         //paper thin objects will fall down, mass 0 clamps it in position 
         brick_phy = new RigidBodyControl(0); 
    
         /** Add physical brick to physics space. */ 
         brick_geo.addControl(brick_phy); 
         bulletAppState.getPhysicsSpace().add(brick_phy); 
        } 
    
    
        public void makeCannonBall(Vector3f startPoint, Vector3f initialVelocity, Material material, boolean continuouslySwept) { 
         /** Create a cannon ball geometry and attach to scene graph. */ 
         Geometry ball_geo = new Geometry("cannon ball", sphere); 
         ball_geo.setMaterial(material); 
         rootNode.attachChild(ball_geo); 
         /** Position the cannon ball */ 
         ball_geo.setLocalTranslation(startPoint); 
         /** Make the ball physcial with a mass > 0.0f */ 
         RigidBodyControl ball_phy = new RigidBodyControl(1f); 
         /** Add physical ball to physics space. */ 
         ball_geo.addControl(ball_phy); 
         bulletAppState.getPhysicsSpace().add(ball_phy); 
         /** Accelerate the physcial ball to shoot it. */ 
         ball_phy.setLinearVelocity(initialVelocity); 
    
         if (continuouslySwept){ 
          ball_phy.setCcdMotionThreshold(0.015f); 
          ball_phy.setCcdSweptSphereRadius(0.01f); 
         } 
    
        } 
    
    
    } 
    

    는 (공은 좌측 상단에서 입력) 예상 바운스 :
    enter image description here

    연속 검출을 공 (적색)의 신속한 세트 꺼짐 통과 종이는 없었다 (아주 가끔 느린 하나 (녹색)도 않습니다)처럼 :
    enter image description here

    NB :이 코드가 느슨하게 추가 기능과 함께 hello physics 코드를 기반으로 advanced physics

  • +0

    이 예제는 매우 좋습니다!나는 340f로 멀티 임펄스를 만들었고 여전히 효과가있었습니다! 그 코드는 실제로 JME 테스트 저장소에있을 수 있습니다. 나 또한 우리가 원할만큼 디버그 모드로 테스트를 쉽게 진행할 수 있도록 20 시까 지 볼을 종료하는 데 제한을 추가했습니다. :) –