/**
* 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;
}
}