InteractionManager.java
/*
* Copyright © 2012 Nokia Corporation. All rights reserved.
* Nokia and Nokia Connecting People are registered trademarks of Nokia Corporation.
* Oracle and Java are trademarks or registered trademarks of Oracle and/or its
* affiliates. Other product and company names mentioned herein may be trademarks
* or trade names of their respective owners.
* See LICENSE.TXT for license information.
*/
package com.nokia.example.amaze.ui;
import com.nokia.example.amaze.gestures.SafeGestureEvent;
import com.nokia.example.amaze.gestures.SafeGestureInteractiveZone;
import com.nokia.example.amaze.gestures.SafeGestureListener;
import com.nokia.example.amaze.gestures.SafeGestureRegistrationManager;
import com.nokia.example.amaze.model.GameModel;
import com.nokia.example.amaze.model.MarbleModel;
import com.nokia.example.amaze.sensors.AccelerationProvider;
/**
* The class for managing all user interactions (acceleration sensor readings
* and touch UI events).
*/
public class InteractionManager
implements AccelerationProvider.Listener,
DoubleTapDetector.Listener,
SafeGestureListener,
Menu.Listener
{
// Constants
public static final float ACCELERATION_THRESHOLD = 1.5f;
public final static float ACCELERATION_COEFFICIENT_X = 1.5f;
public final static float ACCELERATION_COEFFICIENT_Y = 0.3f;
private final static int MIN_CALIBRATION_VALUE = -6;
public final static int UNDEFINED = -20;
private final static int ZOOM_INTERVAL = 10;
// Members
private final MazeCanvas _mazeCanvas;
private final GameModel _gameModel;
private final MarbleModel _marbleModel;
private DoubleTapDetector _doubleTapDetector = null;
private double _calibration = UNDEFINED;
private double _ax;
private double _ay;
/**
* Constructor.
*/
public InteractionManager(MazeCanvas mazeCanvas,
GameModel gameModel)
{
if (mazeCanvas == null || gameModel == null) {
throw new IllegalArgumentException("Null arguments!");
}
_mazeCanvas = mazeCanvas;
_gameModel = gameModel;
_marbleModel = _gameModel.marble();
_doubleTapDetector = new DoubleTapDetector(this);
// Register to listen to the pinch event
// Note: If the device doesn't have multitouch support, this will cause
// unhandled exception.
SafeGestureRegistrationManager.setListener(_mazeCanvas, this);
SafeGestureInteractiveZone gestureZone = new SafeGestureInteractiveZone();
gestureZone.setGesture(SafeGestureInteractiveZone.GESTURE_PINCH);
gestureZone.setRectangle(0, 0, _mazeCanvas.getWidth(), _mazeCanvas.getHeight());
SafeGestureRegistrationManager.register(_mazeCanvas, gestureZone);
}
/**
* From AccelerationProvider.Listener.
*/
public void onDataReceived(double ax, double ay, double az) {
if (_mazeCanvas.gameState() != MazeCanvas.ONGOING) {
return;
}
if (_calibration == UNDEFINED) {
// Do calibrate now based on the current reading
if (_mazeCanvas.isPortrait()) {
setCalibration(-ay);
}
else {
setCalibration(-ax);
}
}
if (_mazeCanvas.isPortrait()) {
_ax = ax;
_ay = ay + _calibration;
}
else {
_ax = ax + _calibration;
_ay = ay;
}
}
/**
* From DoubleTapDetector.
*/
public void onDoubleTapDetected() {
if (!_mazeCanvas.povMode()) {
_mazeCanvas.resetZoom();
}
}
/**
* From SafeGestureListener.
*
* Handles pinch gestures and changes the distance of the camera based on
* the gesture.
*/
public void gestureAction(Object container,
SafeGestureInteractiveZone gestureInteractiveZone,
SafeGestureEvent gestureEvent)
{
if (!_mazeCanvas.povMode()
&& gestureEvent.getType() == SafeGestureInteractiveZone.GESTURE_PINCH)
{
if (gestureEvent.getPinchDistanceChange() < 0) {
// If the gesture was inwards, scale smaller
_mazeCanvas.doZoom(ZOOM_INTERVAL);
}
else if (gestureEvent.getPinchDistanceChange() > 0) {
// If the gesture was outwards, scale larger
_mazeCanvas.doZoom(-ZOOM_INTERVAL);
}
}
}
/**
* From Menu.Listener.
*/
public void onMenuItemSelected(int index) {
if (_mazeCanvas.gameState() == MazeCanvas.PAUSED) {
if (index == 0) {
// Resume
_mazeCanvas.resume();
}
else if (index == 1) {
// Toggle background
_mazeCanvas.setBackground(!_mazeCanvas.hasBackground());
MenuItem item = _mazeCanvas.menu().itemAt(1);
if (item != null) {
item.setText((_mazeCanvas.hasBackground() ? "Set background off"
: "Set background on"));
}
}
else if (index == 2) {
// Toggle debug mode
_mazeCanvas._debugMode = !_mazeCanvas._debugMode;
MenuItem item = _mazeCanvas.menu().itemAt(2);
if (item != null) {
item.setText((_mazeCanvas._debugMode ? "Switch debug mode off"
: "Switch debug mode on"));
}
}
else if (index == 3) {
// Restart the game
_mazeCanvas.startNewGame();
}
}
}
/**
* Starts listening for accelerometer readings.
*/
public void onUIInitialized() {
AccelerationProvider.getProvider(this);
}
/**
* Sets the accelerometer calibration value for the Y axis.
* @param calibrationY The value to set.
*/
public void setCalibration(final double calibration) {
_calibration = calibration;
if (_calibration < MIN_CALIBRATION_VALUE
&& _calibration != UNDEFINED)
{
_calibration = MIN_CALIBRATION_VALUE;
}
}
/**
* @return The current accelerometer calibration value.
*/
public final double calibration() {
return _calibration;
}
/**
* Resets the input state.
*/
public void reset() {
_marbleModel.setVelocity(new float[] { 0f, 0f, 0f });
}
/**
* Handles a key pressed event.
* @param key
*/
public void onKeyPressed(int key) {
System.out.println("InteractionManager::onKeyPressed(): " + key);
}
/**
* Handler for GameCanvas::pointerPressed() events.
*/
public void onPointerPressed(int x, int y) {
if (TipBox.visible()) {
TipBox.hide();
return;
}
if (_mazeCanvas.infoDialogVisible()) {
// TODO: These hard coded values are not good at all and need to
// be fixed sooner or later.
if (x > 6 && x < 234 && y > 300 && y < 340) {
_mazeCanvas.openProjectsLink();
}
else {
_mazeCanvas.setInfoDialogVisible(false);
}
return;
}
final int width = _mazeCanvas.getWidth();
final int height = _mazeCanvas.getHeight();
if (_mazeCanvas.gameState() == MazeCanvas.NOT_STARTED
|| _mazeCanvas.gameState() == MazeCanvas.PAUSED
|| _mazeCanvas.gameState() == MazeCanvas.GAME_OVER)
{
if (x > width - 42 && y > height - 42) {
// Exit button pressed
_mazeCanvas.setButtonPressed(IconButton.EXIT);
}
else if (x < 42 && y > height - 42) {
// Info button pressed
_mazeCanvas.setButtonPressed(IconButton.INFO);
}
else {
switch (_mazeCanvas.gameState()) {
case MazeCanvas.NOT_STARTED: {
_mazeCanvas.startNewGame();
break;
}
case MazeCanvas.PAUSED: {
_mazeCanvas.menu().onPressed(x, y);
break;
}
case MazeCanvas.GAME_OVER: {
_mazeCanvas.cameraAnimator().startAnimation(
CameraAnimator.LEVEL_RESET_ANIMATION_STEP);
break;
}
}
}
return;
}
if (_doubleTapDetector.onTapped(x, y)) {
// Double tap was detected
return;
}
if (x > width - 42 && y > height - 42) {
// Pause button pressed
_mazeCanvas.setButtonPressed(IconButton.PAUSE);
}
else if (x < 42 && y > height - 42) {
// View mode button pressed
// Do nothing yet
}
}
/**
* Handler for GameCanvas::pointerReleased() events.
*/
public void onPointerReleased(int x, int y) {
final int width = _mazeCanvas.getWidth();
final int height = _mazeCanvas.getHeight();
if (_mazeCanvas.gameState() == MazeCanvas.NOT_STARTED
|| _mazeCanvas.gameState() == MazeCanvas.PAUSED
|| _mazeCanvas.gameState() == MazeCanvas.GAME_OVER)
{
if (x > width - 42 && y > height - 42) {
// Do quit
_mazeCanvas.quit();
}
else if (x < 42 && y > height - 42) {
// Show info dialog
_mazeCanvas.setInfoDialogVisible(true);
}
else {
_mazeCanvas.menu().onReleased(x, y);
}
_mazeCanvas.setButtonPressed(-1);
return;
}
if (_mazeCanvas.gameState() == MazeCanvas.ONGOING) {
if (x > width - 42 && y > height - 42) {
// Do pause
System.out.println("MazeCanvas::pointerReleased(): Do pause");
_mazeCanvas.pause();
}
else if (x < 42 && y > height - 42) {
// Toggle view mode
_mazeCanvas.toggleViewMode();
}
}
_mazeCanvas.setButtonPressed(-1);
}
/**
* Handler for GameCanvas::pointerDragged() events.
*/
public void onPointerDragged(int x, int y) {
if (_mazeCanvas.gameState() == MazeCanvas.PAUSED) {
_mazeCanvas.menu().onPressed(x, y);
}
}
/**
* Handler for GameCanvas::pointerRepeated() events.
*/
public void onPointerRepeated(int x, int y) {
onPointerPressed(x, y);
}
// Getters for the calibrated accelerometer values. Used for debugging
// purposes e.g. displaying the values on the screen.
public final double ax() { return _ax; }
public final double ay() { return _ay; }
}