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);    
原文地址:https://www.cnblogs.com/hanhongmin/p/3868414.html