/** * Copyright 2008 - 2012 * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. * * @project loon * @author cping * @email:javachenpeng@yahoo.com * @version 0.3.3 */ package loon; import loon.action.map.Config; import loon.core.geom.Vector3f; import loon.core.processes.RealtimeProcess; import loon.core.processes.RealtimeProcessManager; import loon.utils.MathUtils; //0.3.3版修改后重力感应方式,与原有的Screen重力感应方式不同,该类非绑定于Screen(JavaSE版只能键盘模拟重力) public class LAccelerometer { public static enum SensorDirection { EMPTY, LEFT, RIGHT, UP, DOWN; } public interface Event { public void onDirection(SensorDirection direction, float x, float y, float z); public void onShakeChanged(float force); } // 四方向手机朝向 private SensorDirection _direction = SensorDirection.EMPTY; // 八方向手机朝向 private int _all_direction = Config.EMPTY; private Event event; private long lastUpdate; private float currentX, currentY, currentZ, currenForce; private float lastX, lastY, lastZ; private float orientation, magnitude; public LAccelerometer() { } private final void onOrientation(float x, float y, float z) { // 换算手机翻转角度 orientation = 0; magnitude = x * x + y * y; if (magnitude * 4 >= z * z) { float angle = MathUtils.atan2(-y, x) * MathUtils.RAD_TO_DEG; orientation = 90 - MathUtils.round(angle); while (orientation >= 360) { orientation -= 360; } while (orientation < 0) { orientation += 360; } } // 将手机翻转角度转为手机朝向 if (CheckAngle(0, orientation) || CheckAngle(360, orientation)) { _all_direction = Config.TUP; _direction = SensorDirection.UP; } else if (CheckAngle(45, orientation)) { _all_direction = Config.LEFT; _direction = SensorDirection.LEFT; } else if (CheckAngle(90, orientation)) { _all_direction = Config.TLEFT; _direction = SensorDirection.LEFT; } else if (CheckAngle(135, orientation)) { _all_direction = Config.DOWN; _direction = SensorDirection.LEFT; } else if (CheckAngle(180, orientation)) { _all_direction = Config.TDOWN; _direction = SensorDirection.DOWN; } else if (CheckAngle(225, orientation)) { _all_direction = Config.RIGHT; _direction = SensorDirection.RIGHT; } else if (CheckAngle(270, orientation)) { _all_direction = Config.TRIGHT; _direction = SensorDirection.RIGHT; } else if (CheckAngle(315, orientation)) { _all_direction = Config.UP; _direction = SensorDirection.RIGHT; } else { _all_direction = Config.EMPTY; _direction = SensorDirection.EMPTY; } } public static boolean CheckAngle(float angle, float actual) { return actual > angle - 22.5f && actual < angle + 22.5f; } private final void onSensor(float[] values) { synchronized (this) { long curTime = System.currentTimeMillis(); currentX = values[0]; currentY = values[1]; currentZ = values[2]; onOrientation(currentX, currentY, currentZ); if ((curTime - lastUpdate) > 30) { long diffTime = (curTime - lastUpdate); lastUpdate = curTime; currenForce = MathUtils.abs(currentX + currentY + currentZ - lastX - lastY - lastZ) / diffTime * 10000; if (currenForce > 500 && event != null) { event.onShakeChanged(currenForce); } } lastX = currentX; lastY = currentY; lastZ = currentZ; if (event != null) { event.onDirection(_direction, currentX, currentY, currentZ); } } } public class AccelerometerState { boolean _isConnected; final Vector3f _acceleration = new Vector3f(); public Vector3f getAcceleration() { return _acceleration; } public boolean isConnected() { return _isConnected; } } class SensorProcess extends RealtimeProcess { final float[] accelerometerValues; public SensorProcess(float[] values) { this.accelerometerValues = values; this.setDelay(_sleep); } public void run() { if (_state._isConnected) { accelerometerValues[2] = -1f; if (Key.isDown() && Key.getKeyCode() == Key.LEFT) { accelerometerValues[0]--; } if (Key.isDown() && Key.getKeyCode() == Key.RIGHT) { accelerometerValues[0]++; } if (Key.isDown() && Key.getKeyCode() == Key.UP) { accelerometerValues[1]++; } if (Key.isDown() && Key.getKeyCode() == Key.DOWN) { accelerometerValues[1]--; } onSensor(accelerometerValues); _state._acceleration.set(currentX, currentY, currentZ); } } } private final AccelerometerState _state = new AccelerometerState(); private int _sleep = 30; private final float[] accelerometerValues = new float[3]; private SensorProcess sensorProcess; public void start() { if (!_state._isConnected) { _state._isConnected = true; sensorProcess = new SensorProcess(accelerometerValues); RealtimeProcessManager.get().addProcess(sensorProcess); } } public void stop() { _state._isConnected = false; } public float getLastX() { return lastX; } public float getLastY() { return lastY; } public float getLastZ() { return lastZ; } public float getX() { return currentX; } public float getY() { return currentY; } public float getZ() { return currentZ; } public final AccelerometerState getState() { return _state; } public int getSleep() { return _sleep; } public void sleep(int sleep) { this._sleep = sleep; if (sensorProcess != null) { sensorProcess.setDelay(sleep); } } /** * 屏幕方向(返回Config类中配置值) * * @return */ public int getAllDirection() { return _all_direction; } public Event getEvent() { return event; } /** * 事件监听 * * @param event */ public void setEvent(Event event) { this.event = event; } /** * 屏幕旋转度数 * * @return */ public float getOrientation() { return orientation; } /** * 返回四方向手机朝向 * * @return */ public SensorDirection getDirection() { return _direction; } }