MarbleModel.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.model;
/**
* 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.35f; // Acts as a mass
public static final float DEFAULT_BOUNCE_DRAG = DEFAULT_DRAG * 0.4f;
private static final int DEFAULT_MAX_VELOCITY_PER_AXIS = 5;
private static final float FRICTION = 0.1f;
// Members
private float[] _position = null;
private float[] _velocity = null;
private float[] _newVelocity = null;
private float _drag = DEFAULT_DRAG;
private int _maxVelocityPerAxis = DEFAULT_MAX_VELOCITY_PER_AXIS;
/**
* 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 void setVelocity(final float[] velocity) {
_velocity = velocity;
}
/**
* @return The velocity.
*/
public final float[] velocity() {
return _velocity;
}
/**
* @param maxVelocity The maximum velocity per axis to set.
*/
public void setMaxVelocityPerAxis(final int maxVelocity) {
if (maxVelocity >= 0) {
_maxVelocityPerAxis = maxVelocity;
}
}
/**
* Sets the marble position.
* @param position The new position.
*/
public 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 void setPosition(final float x, final float y, final float z) {
_position[0] = x;
//_position[1] = y;
_position[2] = z;
}
/**
* Moves the marble.
* @param x X coordinate
* @param y Y coordinate
* @param z Z coordinate
*/
public 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
* @return The modified velocity.
*/
public final float[] calculateVelocity(final double accelerationX,
final double accelerationY)
{
_newVelocity[1] = _velocity[1];
_newVelocity[0] = _velocity[0] - (float)accelerationX * _drag;
_newVelocity[2] = _velocity[2] + (float)accelerationY * _drag; // Note: Y => Z
float absVelocity;
for (int i = 0; i < 3; ++i) {
if (i == 1) {
continue;
}
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 > _maxVelocityPerAxis) {
_newVelocity[i] = _maxVelocityPerAxis
* (_newVelocity[i] / absVelocity);
}
}
return _newVelocity;
}
}