【问题标题】:JMonkey - Shooting in Direction of CrosshairsJMonkey - 朝十字准线方向射击
【发布时间】:2013-05-22 23:45:50
【问题描述】:

如何朝十字准线指向的方向射击?

使用 JMonkey 引擎,我正在创建一个游戏,我需要一艘船来射击其他船。

所以,我创建了可以根据用户输入在屏幕上移动(上、下、左、右)的十字准线,这样用户就可以瞄准某个地方。

现在我需要从我的船上朝十字准线所在的方向发射一门大炮。

如何在十字准线指向的地方射击?

【问题讨论】:

    标签: java 3d jmonkeyengine aim


    【解决方案1】:

    您可以通过以下方式获取相机方向:

    directionXYZ=cam.getDirection(); //Vector3f form
    

    并且可以从以下位置获取位置:

    positionXYZ=cam.getLocation(); //Vector3f
    

    您可以进行光线投射:

     Ray ray = new Ray(directionXYZ, positionXYZ);
    

    然后可以收集碰撞数据:

    shootables.collideWith(ray, results)
    

    其中可射击是一个“节点”。

    最后,检查你想要的:

     for (int i = 0; i < results.size(); i++) {
          // For each hit, we know distance, impact point, name of geometry.
          float dist = results.getCollision(i).getDistance();
          Vector3f pt = results.getCollision(i).getContactPoint();
          String hit = results.getCollision(i).getGeometry().getName();
          System.out.println("* Collision #" + i);
          System.out.println("  You shot " + hit + " at " + pt + ", " + dist + " wu away.");
        }
    

    取自jmonkey wiki

    【讨论】:

      【解决方案2】:

      我对这个问题的解读是,目标不是拍摄相机所面对的位置,而是光标(不在屏幕中心)指向的位置。

      这可以使用cam.getWorldCoordinates(screenPosition, zDepth); 命令来实现,这将返回空间中的 3D 点,该点将在屏幕上的 screenPosition 点结束。因此,如果我们在 zDepth 为 0 处创建一个点,在 zDepth 为 1 处创建一个点,我们可以创建一条从光标位置向外传播的光线,因此选择光标“上方”的任何内容。 screenPosition 距离窗口左下角的像素数

      使用此技术的示例程序如下,它基于hello picking 的第二部分。

      在我的示例中,光标是使用键盘(H、J、K、U)移动的,但也可以使用鼠标单击(但我使用鼠标环顾四周)

      import com.jme3.app.SimpleApplication;
      import com.jme3.collision.CollisionResults;
      import com.jme3.font.BitmapText;
      import com.jme3.input.KeyInput;
      import com.jme3.material.Material;
      import com.jme3.math.ColorRGBA;
      import com.jme3.math.Ray;
      import com.jme3.math.Vector2f;
      import com.jme3.math.Vector3f;
      import com.jme3.renderer.RenderManager;
      import com.jme3.scene.Geometry;
      import com.jme3.scene.Node;
      import com.jme3.scene.shape.Box;
      
      public class Main extends SimpleApplication {
      
          public static KeyBindings keyBindings;
          public Vector2f cursorPosition=new Vector2f(100,100);
          public Node shootables=new Node();
      
          public Node crossHairNode=new Node();
      
          public static void main(String[] args) {
              Main app = new Main();
              app.start();
          }
      
          @Override
          public void simpleInitApp() {
              //bind keys to move cursor
              keyBindings=new KeyBindings(inputManager); //for managing keystrokes
              keyBindings.registerKeyBinding(KeyInput.KEY_SPACE, "fire");
              keyBindings.registerKeyBinding(KeyInput.KEY_U, "up"); 
              keyBindings.registerKeyBinding(KeyInput.KEY_J, "down");
              keyBindings.registerKeyBinding(KeyInput.KEY_H, "left");
              keyBindings.registerKeyBinding(KeyInput.KEY_K, "right");
      
              initGui();
      
              Box b = new Box(Vector3f.ZERO, 2, 2, 2);
              Geometry geom = new Geometry("BigBox", b);
      
              Box b2 = new Box(Vector3f.ZERO, 1, 1, 1);
              Geometry geom2 = new Geometry("SmallBox", b2);
              geom2.setLocalTranslation(3, 0, 3);
      
      
              Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
              mat.setColor("Color", ColorRGBA.Blue);
              geom.setMaterial(mat);
              geom2.setMaterial(mat);
              rootNode.attachChild(shootables);
      
              shootables.attachChild(geom);
              shootables.attachChild(geom2);
          }
      
          @Override
          public void simpleUpdate(float tpf) {
      
              updateCrossHairs();
      
              if (keyBindings.getBinding("fire").hasBecomeTrueSinceLastAccess()){
                  CollisionResults results = new CollisionResults();
      
                  Vector3f cursor3dLocation = cam.getWorldCoordinates(
                      new Vector2f(cursorPosition.x, cursorPosition.y), 0f).clone();
                  Vector3f dir = cam.getWorldCoordinates(
                      new Vector2f(cursorPosition.x, cursorPosition.y), 1f).subtractLocal(cursor3dLocation).normalizeLocal();
                  Ray ray = new Ray(cursor3dLocation, dir);
                  shootables.collideWith(ray, results);
      
                  if (results.size()>0){
                      resultsText.setText("Hit: " + results.getClosestCollision().getGeometry().getName());
                      resultsText.setLocalTranslation(settings.getWidth()-resultsText.getLineWidth(),resultsText.getLineHeight(), 0);
                  }else{
                      resultsText.setText("Missed");
                      resultsText.setLocalTranslation(settings.getWidth()-resultsText.getLineWidth(),resultsText.getLineHeight(), 0);                
                  }
      
              }
      
      
      
          }
      
          private void updateCrossHairs(){
              if (keyBindings.getBinding("up").getValue()==true){
                  cursorPosition.y+=1;
              }
              if (keyBindings.getBinding("down").getValue()==true){
                  cursorPosition.y+=-1;
              }
      
              if (keyBindings.getBinding("left").getValue()==true){
                  cursorPosition.x+=-1;
              }
              if (keyBindings.getBinding("right").getValue()==true){
                  cursorPosition.x+=+1;
              }
      
              crossHairNode.setLocalTranslation(cursorPosition.x - crossHair.getLineWidth()/2,cursorPosition.y + crossHair.getLineHeight()/2, 0);
      
          }
      
          BitmapText crossHair;
          BitmapText instructions;
          BitmapText resultsText;
      
          private void initGui() {
              setDisplayStatView(false);
              guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
              crossHair = new BitmapText(guiFont, false);
              crossHair.setSize(guiFont.getCharSet().getRenderedSize() * 2);
              crossHair.setText("+"); // crosshairs
      
              crossHairNode.setLocalTranslation(cursorPosition.x - crossHair.getLineWidth()/2,cursorPosition.y + crossHair.getLineHeight()/2, 0);
      
      
              guiNode.attachChild(crossHairNode);
              crossHairNode.attachChild(crossHair);
      
              instructions= new BitmapText(guiFont, false);
              instructions.setSize(guiFont.getCharSet().getRenderedSize());
              instructions.setText("Move cross hairs with U,H,J,K keys, fire with space \n (WSAD moves camera position and look with mouse)"); 
              instructions.setLocalTranslation(0, settings.getHeight(), 0);
      
              guiNode.attachChild(instructions);
      
              resultsText= new BitmapText(guiFont, false);
              resultsText.setSize(guiFont.getCharSet().getRenderedSize());
              resultsText.setText("Press Space to fire"); 
              resultsText.setLocalTranslation(settings.getWidth()-resultsText.getLineWidth(),resultsText.getLineHeight(), 0);
      
              guiNode.attachChild(resultsText);
      
      
      
         }
      
          @Override
          public void simpleRender(RenderManager rm) {
              //TODO: add render code
          }
      }
      

      键绑定,仅用于控制光标移动:

      import com.jme3.input.InputManager;
      import com.jme3.input.KeyInput;
      import com.jme3.input.controls.ActionListener;
      import com.jme3.input.controls.KeyTrigger;
      import com.jme3.input.controls.MouseButtonTrigger;
      import java.util.ArrayList;
      import java.util.Locale;
      
      public class KeyBindings  implements ActionListener{
      
          private InputManager inputManager;
          private ArrayList<String> bindingString=new ArrayList<String>(100);
          private ArrayList<KeyBinding> binding=new ArrayList<KeyBinding>(100);
      
          public KeyBindings(InputManager inputManager){
              this.inputManager=inputManager;
          }
      
          public void registerKeyBinding(int key,String bindingName){
              bindingName=preprocess(bindingName);
              inputManager.addMapping( bindingName, new KeyTrigger(key));
              inputManager.addListener(this,  bindingName);
      
              binding.add(new KeyBinding());
              bindingString.add(bindingName);
          }
      
         public void registerMouseBinding(int button,String bindingName){
              bindingName=preprocess(bindingName);
              inputManager.addMapping( bindingName, new MouseButtonTrigger(button));
              inputManager.addListener(this,  bindingName);
      
              binding.add(new KeyBinding());
              bindingString.add(bindingName);
          }
      
      
          public KeyBinding getBinding(String bindingName){
              //get which binding we're after
              bindingName=preprocess(bindingName);
      
              int index=bindingString.indexOf(bindingName);
      
              if (index!=-1){
                  return binding.get(index);
              }else{
                  return null;
              }
          }
      
          public void onAction(String  bindingName, boolean isPressed, float tpf) {
              bindingName=preprocess(bindingName);
      
              //get which binding we're after
              int index=bindingString.indexOf(bindingName);
      
              if (index!=-1){
                  binding.get(index).setValue(isPressed);
              }
          }
      
      
          private String preprocess(String string){
              return string.toUpperCase();
          }
      
      }
      


      public class KeyBinding {
      
          private boolean value;
          private boolean changedSinceLastAccess; //to avoid multiclicks etc
          private boolean valueTrueSinceLastAccess;
      
      
          public void setValue(boolean value){
               this.value=value;
               changedSinceLastAccess=true;
      
               if (value==true){
                   valueTrueSinceLastAccess=true;
               }
          }
      
          public boolean hasChangedSinceLastAccess(){
              return changedSinceLastAccess;
          }
      
          public boolean hasBecomeTrueSinceLastAccess(){
              //this collects any trues since the last access, is good for things like mouse clicks,
              //which are instantaneous and you want then recorded on the next tick
              if (valueTrueSinceLastAccess==true){
                  valueTrueSinceLastAccess=false;
                  return true;
              }else{
                  return false;
              }
          }
      
      
          public boolean getValue(){
              changedSinceLastAccess=false;
              valueTrueSinceLastAccess=false;
              return value;
          }
      
          public boolean getValue_withoutNotifying(){
              return value;
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2017-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-04
        • 1970-01-01
        相关资源
        最近更新 更多