zoukankan      html  css  js  c++  java
  • libgdx 3D CameraInputController WASD控制器

    libgdx源码中有一个默认实现CameraInputController,基本实现了各种控制。

    我想要的和他的有点区别,可能更类似于WOW或者CS的操作方式吧。。。

    在他的基础上改改,见源码:

      1 package com.mygdx.game;
      2 
      3 import com.badlogic.gdx.Gdx;
      4 import com.badlogic.gdx.Input.Keys;
      5 import com.badlogic.gdx.Input.Buttons;
      6 import com.badlogic.gdx.graphics.Camera;
      7 import com.badlogic.gdx.input.GestureDetector;
      8 import com.badlogic.gdx.math.MathUtils;
      9 import com.badlogic.gdx.math.Vector2;
     10 import com.badlogic.gdx.math.Vector3;
     11 
     12 /**
     13  * Created by HanHongmin on 14-7-25.
     14  */
     15 public class CharacterCameraInputController extends GestureDetector {
     16     /** 按下鼠标左键可以旋转视角 */
     17     public int rotateButton = Buttons.LEFT;
     18     /** 当鼠标在屏幕上移动整个画面的宽和高时,视角转动角度 */
     19     public float rotateAngle = 360f;
     20     /** 鼠标右键拖动画面可使视角横竖方向平移,不会前后移动。我们这里会禁用掉这个功能,亦或使用A,D键实现横向平移 */
     21     public int translateButton = Buttons.RIGHT;
     22     /** The units to translate the camera when moved the full width or height of the screen. */
     23     public float translateUnits = 10f; // FIXME auto calculate this based on the target
     24     /** 鼠标滚轮控制视角的前后移动。我们这里会禁用掉这个功能,亦或增加移动距离的限制 */
     25     public int forwardButton = Buttons.MIDDLE;
     26     /** 开关,0全部开启 The key which must be pressed to activate rotate, translate and forward or 0 to always activate. */
     27     public int activateKey = 0;
     28     /** 开关键是否被按下 Indicates if the activateKey is currently being pressed. */
     29     protected boolean activatePressed;
     30     /** false 滚动时需要开关键按下,true不需要。Whether scrolling requires the activeKey to be pressed (false) or always allow scrolling (true). */
     31     public boolean alwaysScroll = true;
     32     /** The weight for each scrolled amount. */
     33     public float scrollFactor = -0.1f;
     34     /** World units per screen size */
     35     public float pinchZoomFactor = 10f;
     36     /** Whether to update the camera after it has been changed. */
     37     public boolean autoUpdate = true;
     38     /** 旋转镜头的基点,通常设置为cam的position. The target to rotate around. */
     39     public Vector3 target = new Vector3();
     40     /** Whether to update the target on translation */
     41     public boolean translateTarget = true;
     42     /** Whether to update the target on forward */
     43     public boolean forwardTarget = true;
     44     /** Whether to update the target on scroll */
     45     public boolean scrollTarget = false;
     46     public int forwardKey = Keys.W;//前进
     47     protected boolean forwardPressed;
     48     public int backwardKey = Keys.S;//后退
     49     protected boolean backwardPressed;
     50     public int goLeftKey = Keys.A;//添加左右平移
     51     protected boolean goLeftPressed;
     52     public int goRightKey = Keys.D;//添加左右平移
     53     protected boolean goRightPressed;
     54     public int rotateRightKey = Keys.Q;//画面向右旋转即视角向左看,更改为按键Q
     55     protected boolean rotateRightPressed;
     56     public int rotateLeftKey = Keys.E;//画面向左旋转即视角向右看,更改为按键E
     57     protected boolean rotateLeftPressed;
     58     /** The camera. */
     59     public Camera camera;
     60     /** The current (first) button being pressed. */
     61     protected int button = -1;
     62 
     63     private float startX, startY;
     64     private final Vector3 tmpV1 = new Vector3();
     65     private final Vector3 tmpV2 = new Vector3();
     66 
     67     protected static class CameraGestureListener extends GestureAdapter {
     68         public CharacterCameraInputController controller;
     69         private float previousZoom;
     70 
     71         @Override
     72         public boolean touchDown (float x, float y, int pointer, int button) {
     73             previousZoom = 0;
     74             return false;
     75         }
     76 
     77         @Override
     78         public boolean tap (float x, float y, int count, int button) {
     79             return false;
     80         }
     81 
     82         @Override
     83         public boolean longPress (float x, float y) {
     84             return false;
     85         }
     86 
     87         @Override
     88         public boolean fling (float velocityX, float velocityY, int button) {
     89             return false;
     90         }
     91 
     92         @Override
     93         public boolean pan (float x, float y, float deltaX, float deltaY) {
     94             return false;
     95         }
     96 
     97         @Override
     98         public boolean zoom (float initialDistance, float distance) {
     99             float newZoom = distance - initialDistance;
    100             float amount = newZoom - previousZoom;
    101             previousZoom = newZoom;
    102             float w = Gdx.graphics.getWidth(), h = Gdx.graphics.getHeight();
    103             return controller.pinchZoom(amount / ((w > h) ? h : w));
    104         }
    105 
    106         @Override
    107         public boolean pinch (Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
    108             return false;
    109         }
    110     };
    111 
    112     protected final CameraGestureListener gestureListener;
    113 
    114     protected CharacterCameraInputController(final CameraGestureListener gestureListener, final Camera camera) {
    115         super(gestureListener);
    116         this.gestureListener = gestureListener;
    117         this.gestureListener.controller = this;
    118         this.camera = camera;
    119     }
    120 
    121     public CharacterCameraInputController(final Camera camera) {
    122         this(new CameraGestureListener(), camera);
    123     }
    124 
    125     public void update () {
    126         if (rotateRightPressed || rotateLeftPressed || goLeftPressed|| goRightPressed || forwardPressed || backwardPressed) {
    127             final float delta = Gdx.graphics.getDeltaTime();
    128             if (rotateRightPressed) {
    129                 //camera.rotate(camera.up, -delta * rotateAngle);
    130                 camera.rotate(Vector3.Y, delta * rotateAngle);
    131             }
    132             if (rotateLeftPressed) {
    133                 //camera.rotate(camera.up, delta * rotateAngle);
    134                 camera.rotate(Vector3.Y, -delta * rotateAngle);
    135             }
    136             if (forwardPressed) {
    137                 Vector3 t = tmpV1.set(camera.direction).scl(delta * translateUnits);
    138                 t.y = 0;//将y设置为0,在y轴方向即高度上不移动
    139                 camera.translate(t);
    140                 if (forwardTarget) target.add(tmpV1);
    141             }
    142             if (backwardPressed) {
    143                 Vector3 t = tmpV1.set(camera.direction).scl(-delta * translateUnits);
    144                 t.y = 0;//将y设置为0,在y轴方向即高度上不移动
    145                 camera.translate(t);
    146                 if (forwardTarget) target.add(tmpV1);
    147             }
    148 
    149             if (goLeftPressed) {
    150                 //direction旋转90度
    151                 Vector3 v = camera.direction.cpy();
    152                 v.rotate(Vector3.Y,-90);
    153                 Vector3 t = tmpV1.set(v).scl(-delta * translateUnits);
    154                 t.y = 0;//将y设置为0,在y轴方向即高度上不移动
    155                 camera.translate(t);
    156                 if (forwardTarget) target.add(tmpV1);
    157             }
    158 
    159             if (goRightPressed) {
    160                 Vector3 v = camera.direction.cpy();
    161                 v.rotate(Vector3.Y,90);
    162                 Vector3 t = tmpV1.set(v).scl(-delta * translateUnits);
    163                 t.y = 0;//将y设置为0,在y轴方向即高度上不移动
    164                 camera.translate(t);
    165                 if (forwardTarget) target.add(tmpV1);
    166             }
    167             if (autoUpdate) camera.update();
    168         }
    169     }
    170 
    171     private int touched;
    172     private boolean multiTouch;
    173 
    174     @Override
    175     public boolean touchDown (int screenX, int screenY, int pointer, int button) {
    176         touched |= (1 << pointer);
    177         multiTouch = !MathUtils.isPowerOfTwo(touched);
    178         if (multiTouch)
    179             this.button = -1;
    180         else if (this.button < 0 && (activateKey == 0 || activatePressed)) {
    181             startX = screenX;
    182             startY = screenY;
    183             this.button = button;
    184         }
    185         return super.touchDown(screenX, screenY, pointer, button) || activatePressed;
    186     }
    187 
    188     @Override
    189     public boolean touchUp (int screenX, int screenY, int pointer, int button) {
    190         touched &= -1 ^ (1 << pointer);
    191         multiTouch = !MathUtils.isPowerOfTwo(touched);
    192         if (button == this.button) this.button = -1;
    193         return super.touchUp(screenX, screenY, pointer, button) || activatePressed;
    194     }
    195 
    196     protected boolean process (float deltaX, float deltaY, int button) {
    197         if (button == rotateButton) {
    198             tmpV1.set(camera.direction).crs(camera.up).y = 0f;
    199             camera.rotateAround(target, tmpV1.nor(), deltaY * rotateAngle);
    200             camera.rotateAround(target, Vector3.Y, deltaX * -rotateAngle);
    201         } else if (button == translateButton) {
    202             camera.translate(tmpV1.set(camera.direction).crs(camera.up).nor().scl(-deltaX * translateUnits));
    203             camera.translate(tmpV2.set(camera.up).scl(-deltaY * translateUnits));
    204             if (translateTarget) target.add(tmpV1).add(tmpV2);
    205         } else if (button == forwardButton) {
    206             camera.translate(tmpV1.set(camera.direction).scl(deltaY * translateUnits));
    207             if (forwardTarget) target.add(tmpV1);
    208         }
    209         if (autoUpdate) camera.update();
    210         return true;
    211     }
    212 
    213     @Override
    214     public boolean touchDragged (int screenX, int screenY, int pointer) {
    215         boolean result = super.touchDragged(screenX, screenY, pointer);
    216         if (result || this.button < 0) return result;
    217         final float deltaX = (screenX - startX) / Gdx.graphics.getWidth();
    218         final float deltaY = (startY - screenY) / Gdx.graphics.getHeight();
    219         startX = screenX;
    220         startY = screenY;
    221         return process(deltaX, deltaY, button);
    222     }
    223 
    224     @Override
    225     public boolean scrolled (int amount) {
    226         return zoom(amount * scrollFactor * translateUnits);
    227     }
    228 
    229     public boolean zoom (float amount) {
    230         if (!alwaysScroll && activateKey != 0 && !activatePressed) return false;
    231         camera.translate(tmpV1.set(camera.direction).scl(amount));
    232         if (scrollTarget) target.add(tmpV1);
    233         if (autoUpdate) camera.update();
    234         return true;
    235     }
    236 
    237     protected boolean pinchZoom (float amount) {
    238         return zoom(pinchZoomFactor * amount);
    239     }
    240 
    241     @Override
    242     public boolean keyDown (int keycode) {
    243         if (keycode == activateKey) activatePressed = true;
    244         if (keycode == forwardKey)
    245             forwardPressed = true;
    246         else if (keycode == backwardKey)
    247             backwardPressed = true;
    248         else if (keycode == goLeftKey)
    249             goLeftPressed = true;//添加了左右平移
    250         else if (keycode == goRightKey)
    251             goRightPressed = true;//添加了左右平移
    252         else if (keycode == rotateRightKey)
    253             rotateRightPressed = true;
    254         else if (keycode == rotateLeftKey)
    255             rotateLeftPressed = true;
    256         return false;
    257     }
    258 
    259     @Override
    260     public boolean keyUp (int keycode) {
    261         if (keycode == activateKey) {
    262             activatePressed = false;
    263             button = -1;
    264         }
    265         if (keycode == forwardKey)
    266             forwardPressed = false;
    267         else if (keycode == backwardKey)
    268             backwardPressed = false;
    269         else if (keycode == goLeftKey)
    270             goLeftPressed = false;//添加左右平移
    271         else if (keycode == goRightKey)
    272             goRightPressed = false;//添加左右平移
    273         else if (keycode == rotateRightKey)
    274             rotateRightPressed = false;
    275         else if (keycode == rotateLeftKey)
    276             rotateLeftPressed = false;
    277         return false;
    278     }
    279 }

    代码中将左右旋转改到了Q和E按键,增加了左右平移的A和D按键,修改了一些算法使其更适合作为角色视角。

    代码中有个target很重要啊,做第三人称视角用的吧~~。

    另:前进后退左右平移的速度是有变化的,比如看着脚面,速度就很慢。看使用场景吧,有兴趣的童鞋可以改改。

    最后贴个如何使用的代码。。。

     1         cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
     2         cam.position.set(0f, 7f, 0f);
     3         cam.lookAt(1,7,1);//y可视为人物高度,在camera的controller中将y固定,除非有跳跃动作
     4         cam.near = 1f;
     5         cam.far = 30f;//视角最远
     6         cam.update();
     7 
     8         camController = new CharacterCameraInputController(cam);
     9         camController.target = cam.position;//旋转视角时以镜头位置为基点
    10         Gdx.input.setInputProcessor(camController);    
  • 相关阅读:
    C# List<T>用法(转)
    任务列表 (Visual Studio)
    TSQL行转列、列转行
    HRESULT:0x80070057 (E_INVALIDARG)的异常的解决方案(转)
    JS正则表达式详解(转)
    Windows远程登录命令
    JavaScript中的try...catch和异常处理(转)
    javascript如何触发button 的click事件
    在ASP.NET中利JavaScript实现控件的聚焦(转)
    输入一个字符串,将其逆序后输出。(使用C++,不建议用伪码)
  • 原文地址:https://www.cnblogs.com/hanhongmin/p/3868414.html
Copyright © 2011-2022 走看看