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);