/** * Copyright (c) 2012-2013 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.model; import com.nokia.example.amaze.ui.MazeCanvas; /** * Model of the marble. */ public class MarbleModel { // Constants public static final float DEFAULT_SIZE = 4.0f; // Marble width and height public static final float DEFAULT_SIZE_HALVED = DEFAULT_SIZE / 2; private static final float DEFAULT_Y = 10.0f; public static final float HYPOTENUSE = (float)Math.sqrt(DEFAULT_SIZE_HALVED * DEFAULT_SIZE_HALVED + DEFAULT_SIZE_HALVED * DEFAULT_SIZE_HALVED); private static final float DEFAULT_DRAG = 0.1f; // Acts as a mass public static final float DEFAULT_BOUNCE_DRAG = DEFAULT_DRAG * 0.8f; private static final float MAX_VELOCITY_PER_AXIS = 3.5f; private static final float FRICTION = 0.2f; // Members private float[] _position = null; private float[] _velocity = null; private float[] _newVelocity = null; private float _drag = DEFAULT_DRAG; /** * Constructor. */ public MarbleModel() { _position = new float[3]; _position[1] = DEFAULT_Y; _velocity = new float[3]; _newVelocity = new float[3]; } /** * @param drag The drag to set ]0.0, 1.0]. This value defines how much the * marble resists the acceleration. */ public void setDrag(final float drag) { if (drag > 0 && drag <= 1.0) { // Subtract the given mass from 100 so that we don't have to do it // later in the calculations _drag = drag; } } /** * @return The drag. */ public final float drag() { return _drag; } /** * @param velocity The velocity to set. */ public final void setVelocity(final float[] velocity) { _velocity = velocity; } /** * @return The velocity. */ public final float[] velocity() { return _velocity; } /** * Sets the marble position. * @param position The new position. */ public final void setPosition(final float[] position) { _position = position; _position[1] = DEFAULT_Y; } /** * Sets the marble position. * @param x X coordinate * @param y Y coordinate * @param z Z coordinate */ public final void setPosition(final float x, final float y, final float z) { _position[0] = x; //_position[1] = y; _position[2] = z; } /** * Moves the marble based on the current velocity and the given ticks. * @param ticks The milliseconds since last time the method was called. */ public final void move(final int ticks) { final float ticksCoefficient = (float)ticks / MazeCanvas.TICKS_COEFFICIENT; _position[0] += _velocity[0] * ticksCoefficient; _position[2] += _velocity[2] * ticksCoefficient; } /** * Moves the marble. * @param x X coordinate * @param y Y coordinate * @param z Z coordinate */ public final void move(final float x, final float y, final float z) { _position[0] += x; //_position[1] += y; _position[2] += z; } /** * @return The marble position. */ public final float[] position() { return _position; } /** * Calculates the marble velocity based on the current velocity and the * given values of acceleration. * @param accelerationX * @param accelerationY * @param ticks The milliseconds since last time the method was called. * @return The modified velocity. */ public final float[] calculateVelocity(final double accelerationX, final double accelerationY, final int ticks) { final float coefficient = _drag * (float)ticks / MazeCanvas.TICKS_COEFFICIENT; _newVelocity[1] = _velocity[1]; _newVelocity[0] = _velocity[0] - (float)accelerationX * coefficient; _newVelocity[2] = _velocity[2] + (float)accelerationY * coefficient; // Note: Y => Z for (int i = 0; i < 3; ++i) { if (i == 1) { continue; } final float absVelocity = Math.abs(_newVelocity[i]); // Apply friction if (absVelocity < FRICTION) { _newVelocity[i] = 0; } else { _newVelocity[i] -= FRICTION * (_newVelocity[i] / absVelocity); } // Limit the velocity based on maximum if (absVelocity > MAX_VELOCITY_PER_AXIS) { _newVelocity[i] = MAX_VELOCITY_PER_AXIS * (_newVelocity[i] / absVelocity); } } return _newVelocity; } }