3

To gain experience in android I'm making a decisionmaking app. I'm trying to add a spinning wheel (wheel of fortune like). I have an animation that works fine (just need some little tweaking but fine for now). The problem I'm having is to detect where the wheel has stopped. If I look at the rotation and match it to precalculated values it makes sense, but visually it seems off.

For example:

Begin state is always like this. I tap it and it starts to rotate.

begin state

It stops rotating at red (visually), but in the model it says 51, hence my model detects it stopped rotating at yellow:

stop state

model state

Cur pos and Prev pos is not currently implemented. Rnd pos is the relative number of degrees it needs to rotate (relative to 0). Rnd rot is number of extra rotations it has to make before stopping. True pos is the absolute number of degrees it has to rotate. Total time: the time the animation takes. Corner: number of degrees one piece has.

SpinWheel method in activity:

private void spinWheel() {
    Roulette r = Roulette.getInstance();
    r.init(rouletteItemsDEBUG);
    r.spinRoulette();
    final int truePos = r.getTruePosition();
    final long totalTime = r.getTotalTime();

    final ObjectAnimator anim = ObjectAnimator.ofFloat(imgSpinningWheel, "rotation", 0, truePos);
    anim.setDuration(totalTime);
    anim.setInterpolator(new DecelerateInterpolator());
    anim.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) {
            imgSpinningWheel.setEnabled(false);
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            imgSpinningWheel.setEnabled(true);
            txtResult.setText(Roulette.getInstance().getSelectedItem().getValue());
            Log.d(TAG, Roulette.getInstance().toString());
            Log.d(TAG, imgSpinningWheel.getRotation() + "");
            Log.d(TAG, imgSpinningWheel.getRotationX() + "");
            Log.d(TAG, imgSpinningWheel.getRotationY() + "");
        }

        @Override
        public void onAnimationCancel(Animator animation) {
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
        }
    });
    anim.start();
}

Roulette.java:

public class Roulette { private static Roulette instance;

private static final long TIME_IN_WHEEL = 1000; //time in one rotation (speed of rotation)
private static final int MIN_ROT = 5;
private static final int MAX_ROT = 6;
private static final Random rnd = new Random();

private RouletteItem currentItem;
private RouletteItem[] rouletteItems;
private NavigableMap<Integer, RouletteItem> navigableMap;

private int randomRotation;     
private int randomPosition;    
private int truePosition;     
private int corner;           
private long totalTime;       


private Roulette() {
}

public void init(RouletteItem[] rouletteItems) {
    this.rouletteItems = rouletteItems;
    navigableMap = new TreeMap<>();
    for (int i = 0; i < getNumberOfItems(); i++) {
        navigableMap.put(i * 51, rouletteItems[i]);
    }
}

public void spinRoulette() {
    if (rouletteItems == null || rouletteItems.length < 2) {
        throw new RouletteException("You need at least 2 rouletteItems added to the wheel!");
    }

    calculateCorner();
    calculateRandomPosition();
    calculateRandomRotation();
    calculateTruePosition();
    calculateTotalTime();
}

/**
 * Pinpoint random position in the wheel
 */
private void calculateRandomPosition() {
    randomPosition = corner * rnd.nextInt(getNumberOfItems());
}


/**
 * Calculates the points one RouletteItem has
 */
private void  calculateCorner() {
    corner = 360 / getNumberOfItems();
}


/**
 * Calculates the time needed to spin to the chosen random position
 */
private void calculateTotalTime() {
    totalTime = (TIME_IN_WHEEL * randomRotation + (TIME_IN_WHEEL / 360) * randomPosition);
}


/**
 * Calculates random rotation
 */
private void calculateRandomRotation() {
    randomRotation = MIN_ROT + rnd.nextInt(MAX_ROT - MIN_ROT);
}


/**
 * Calculates the true position
 */
private void calculateTruePosition() {
    truePosition = (randomRotation * 360 + randomPosition);
}

//getters and to string omitted
}

The map is used to map rouletteItems to a range of degrees.

My guess is that the animation takes too long or something like that. But I don't really see how to fix it. Anyone who does?

Thanks in advance!

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
JC97
  • 1,530
  • 2
  • 23
  • 44

1 Answers1

2

Um, doesn't Java implement rotation in radians rather than degrees?

That could lead to a offset between the visual rotation graphic and the number from the maths. Perhaps check by replacing all the assumed degree calculations (ie x/360) with radian calcs (ie. x/(2*pi))?

Mark_Anderson
  • 1,229
  • 1
  • 12
  • 34