Merge pull request #1 from PizzaLovers007/PizzaLovers007-patch-1

Full implementation of a "weighted" spinner. May need to tweak some constants to make it more like osu!
This commit is contained in:
PizzaLovers007 2015-02-13 17:15:43 -06:00
commit 6b85354eeb

View File

@ -37,6 +37,13 @@ import org.newdawn.slick.Image;
* Data type representing a spinner object.
*/
public class Spinner implements HitObject {
/** The rate at which the spinner slows down in rotations/second^2. */
private static final float ANGULAR_DRAG = 12f;
/** The maximum rate at which the spinner can speed up in rotations/second^2. */
private static final float MAX_ANGULAR_INCREASE = 26f;
/** Container dimensions. */
private static int width, height;
@ -47,13 +54,23 @@ public class Spinner implements HitObject {
private GameData data;
/** The last rotation angle. */
private float lastAngle = -1f;
private float lastAngle = 0f;
/** The current number of rotations. */
private float rotations = 0f;
/** The total number of rotations needed to clear the spinner. */
private float rotationsNeeded;
/** The current angular velocity of the spinner in rotations/second. */
private float angularVelocity;
private float cv;
private float mv;
private int limitUpdate = 0;
/** True if the mouse cursor is pressed. */
private boolean isSpinning;
/**
* Initializes the Spinner data type with images and dimensions.
@ -119,6 +136,16 @@ public class Spinner implements HitObject {
if (extraRotations > 0)
data.drawSymbolNumber(extraRotations * 1000, width / 2, height * 2 / 3, 1.0f);
}
// rotations per minute
g.setColor(new Color(255,255,255));
g.drawString(String.format("RPM: %d", Math.abs(Math.round(angularVelocity * 60))), 100, 100);
// debug stuff
g.drawString("key down: " + Utils.isGameKeyPressed(), 200, 100);
g.drawString("momentum velocity: " + mv, 100, 200);
g.drawString("cursor velocity: " + cv, 100, 300);
g.drawString("angular velocity: " + angularVelocity, 100, 400);
}
/**
@ -172,35 +199,74 @@ public class Spinner implements HitObject {
return false;
}
// not spinning: nothing to do
if (!Utils.isGameKeyPressed()) {
lastAngle = -1f;
// game button is released
if (isSpinning && !Utils.isGameKeyPressed()) {
isSpinning = false;
}
float angle = (float) Math.atan2(mouseY - (height / 2), mouseX - (width / 2));
// set initial angle to current mouse position to skip first click
if (!isSpinning && Utils.isGameKeyPressed()) {
lastAngle = angle;
isSpinning = true;
return false;
}
float angleDiff = angle - lastAngle;
// make angleDiff the smallest angle change possible
// (i.e. 1/4 rotation instead of 3/4 rotation)
if (angleDiff < -Math.PI) {
angleDiff = (float) (angleDiff + Math.PI*2);
} else if (angleDiff > Math.PI) {
angleDiff = (float) (angleDiff - Math.PI*2);
}
// spin caused by the cursor
float cursorVelocity = 0;
if (isSpinning)
cursorVelocity = (float)(angleDiff / (Math.PI*2) / delta * 1000);
// spin from the momentum of the spinner
float momentumVelocity = (angularVelocity > 0) ?
Math.max(0, angularVelocity - ANGULAR_DRAG * delta / 1000) :
Math.min(0, angularVelocity + ANGULAR_DRAG * delta / 1000);
// scale angle from [-pi, +pi] to [0, +pi]
float angle = (float) Math.atan2(mouseY - (height / 2), mouseX - (width / 2));
if (angle < 0f)
angle += Math.PI;
//debug stuff
cv = cursorVelocity;
mv = momentumVelocity;
if (lastAngle >= 0f) { // skip initial clicks
float angleDiff = Math.abs(lastAngle - angle);
if (angleDiff < Math.PI / 2) { // skip huge angle changes...
data.changeHealth(delta * GameData.HP_DRAIN_MULTIPLIER);
rotate(angleDiff);
//sets the new angular velocity of the spinner
if (momentumVelocity > 0 && cursorVelocity < 0 ||
momentumVelocity < 0 && cursorVelocity > 0) {
angularVelocity = momentumVelocity + cursorVelocity;
} else if (Math.abs(cursorVelocity) > Math.abs(momentumVelocity)) {
// limit the increase in angular velocity
if (momentumVelocity > 0) {
angularVelocity = Math.min(cursorVelocity,
angularVelocity + MAX_ANGULAR_INCREASE * delta / 1000);
} else {
angularVelocity = Math.max(cursorVelocity,
angularVelocity - MAX_ANGULAR_INCREASE * delta / 1000);
}
} else {
angularVelocity = momentumVelocity;
}
data.changeHealth(delta * GameData.HP_DRAIN_MULTIPLIER);
rotate(angularVelocity * (float)Math.PI*2 * delta / 1000);
lastAngle = angle;
return false;
}
/**
* Rotates the spinner by a number of degrees.
* @param degrees the angle to rotate (in radians)
* Rotates the spinner by a number of radians.
* @param angle the angle to rotate (in radians)
*/
private void rotate(float degrees) {
float newRotations = rotations + (degrees / (float) (2 * Math.PI));
private void rotate(float angle) {
angle = Math.abs(angle);
float newRotations = rotations + (angle / (float) (2 * Math.PI));
// added one whole rotation...
if (Math.floor(newRotations) > rotations) {
@ -215,4 +281,4 @@ public class Spinner implements HitObject {
rotations = newRotations;
}
}
}