Completely reworked how the spinner spins
Added a “weight” to the spinner to make the RPM more like osu! May need to tweak constants to make the spinner feel more natural.
This commit is contained in:
parent
6c7aac53f4
commit
548e389724
|
@ -39,7 +39,10 @@ import org.newdawn.slick.Image;
|
||||||
public class Spinner implements HitObject {
|
public class Spinner implements HitObject {
|
||||||
|
|
||||||
/** The rate at which the spinner slows down in rotations/second^2. */
|
/** The rate at which the spinner slows down in rotations/second^2. */
|
||||||
private static final float angularDrag = 20f;
|
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. */
|
/** Container dimensions. */
|
||||||
private static int width, height;
|
private static int width, height;
|
||||||
|
@ -51,7 +54,7 @@ public class Spinner implements HitObject {
|
||||||
private GameData data;
|
private GameData data;
|
||||||
|
|
||||||
/** The last rotation angle. */
|
/** The last rotation angle. */
|
||||||
private float lastAngle = -1f;
|
private float lastAngle = 0f;
|
||||||
|
|
||||||
/** The current number of rotations. */
|
/** The current number of rotations. */
|
||||||
private float rotations = 0f;
|
private float rotations = 0f;
|
||||||
|
@ -62,6 +65,13 @@ public class Spinner implements HitObject {
|
||||||
/** The current angular velocity of the spinner in rotations/second. */
|
/** The current angular velocity of the spinner in rotations/second. */
|
||||||
private float angularVelocity;
|
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.
|
* Initializes the Spinner data type with images and dimensions.
|
||||||
* @param container the game container
|
* @param container the game container
|
||||||
|
@ -128,8 +138,14 @@ public class Spinner implements HitObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
// rotations per minute
|
// rotations per minute
|
||||||
g.setColor(new Color(0,0,0));
|
g.setColor(new Color(255,255,255));
|
||||||
g.drawString(String.format("RPM: %d", Math.round(angularVelocity * 60)), 100, 100);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -183,28 +199,62 @@ public class Spinner implements HitObject {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// not spinning: spinner slows down
|
// game button is released
|
||||||
if (!Utils.isGameKeyPressed()) {
|
if (isSpinning && !Utils.isGameKeyPressed()) {
|
||||||
lastAngle = -1f;
|
isSpinning = false;
|
||||||
angularVelocity = Math.max(0, angularVelocity - angularDrag * delta / 1000);
|
}
|
||||||
rotate(angularVelocity * (float)Math.PI * 2 * delta / 1000);
|
|
||||||
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// scale angle from [-pi, +pi] to [0, +pi]
|
float angleDiff = angle - lastAngle;
|
||||||
float angle = (float) Math.atan2(mouseY - (height / 2), mouseX - (width / 2));
|
|
||||||
if (angle < 0f)
|
// make angleDiff the smallest angle change possible
|
||||||
angle += Math.PI;
|
// (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);
|
||||||
|
|
||||||
|
//debug stuff
|
||||||
|
cv = cursorVelocity;
|
||||||
|
mv = momentumVelocity;
|
||||||
|
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
|
||||||
if (lastAngle >= 0f) { // skip initial clicks
|
|
||||||
float angleDiff = Math.abs(lastAngle - angle);
|
|
||||||
if (angleDiff < Math.PI / 2) { // skip huge angle changes...
|
|
||||||
angularVelocity = (float)Math.max(angularVelocity - angularDrag * delta / 1000,
|
|
||||||
angleDiff / (Math.PI * 2) / ((float)delta / 1000));
|
|
||||||
data.changeHealth(delta * GameData.HP_DRAIN_MULTIPLIER);
|
data.changeHealth(delta * GameData.HP_DRAIN_MULTIPLIER);
|
||||||
rotate(angularVelocity * (float)Math.PI * 2 * delta / 1000);
|
rotate(angularVelocity * (float)Math.PI*2 * delta / 1000);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lastAngle = angle;
|
lastAngle = angle;
|
||||||
return false;
|
return false;
|
||||||
|
@ -215,6 +265,7 @@ public class Spinner implements HitObject {
|
||||||
* @param angle the angle to rotate (in radians)
|
* @param angle the angle to rotate (in radians)
|
||||||
*/
|
*/
|
||||||
private void rotate(float angle) {
|
private void rotate(float angle) {
|
||||||
|
angle = Math.abs(angle);
|
||||||
float newRotations = rotations + (angle / (float) (2 * Math.PI));
|
float newRotations = rotations + (angle / (float) (2 * Math.PI));
|
||||||
|
|
||||||
// added one whole rotation...
|
// added one whole rotation...
|
||||||
|
|
Loading…
Reference in New Issue
Block a user