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 @Override107 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 @Override175 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 @Override189 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 @Override214 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 @Override225 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 @Override242 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 @Override260 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);