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);    
  • 相关阅读:
    Android自定义之仿360Root大师水纹效果
    Android之TextView的Span样式源码剖析
    Android之TextView的样式类Span的使用详解
    随着ScrollView的滑动,渐渐的执行动画View
    仿微信主界面导航栏图标字体颜色的变化
    android自定义之 5.0 风格progressBar
    Android性能优化之内存篇
    Android性能优化之运算篇
    How to install Zabbix5.0 LTS version with Yum on the CentOS 7.8 system?
    How to install Zabbix4.0 LTS version with Yum on the Oracle Linux 7.3 system?
  • 原文地址:https://www.cnblogs.com/hanhongmin/p/3868414.html
Copyright © 2011-2022 走看看