3
\$\begingroup\$

I'm building a 2D game where the sole interaction of the player is rotating what they can see (this is currently the camera, though it could be the world) by plus or minus 60 degrees.

My current approach has their input rotating the camera. The issue I'm having is that I'm finding it impossible to keep track of how many degrees they've rotated it, since the camera is rotating and losing its initial position.

(I'm using libgdx, however, I think this problem is framework independent.)

Edit:

To help with the understanding, let me provide an example. Picture yourself in a school playground. You want to turn 90 degrees. To help you keep track, you mark the ground with the chalk in your hand. Turning 90 degrees is now easy since you have a reference point.

Now imagine you're in space and trying to do the same thing. Instead of chalking the ground, you chalk yourself. It's now nigh impossible to know how much you turn by when you do.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Can't you just store the initial position in a variable? Or is there something I'm missing here? \$\endgroup\$
    – Charanor
    Commented May 14, 2017 at 17:06
  • \$\begingroup\$ There's nothing I can store that makes sense to me. This could simply be my unfamiliarity with the framework.I've posted an answer that is not dissimilar to your suggestion. \$\endgroup\$
    – Didia
    Commented May 15, 2017 at 0:10
  • \$\begingroup\$ I don't understand why you have a three dimensional camera in a 2d world? \$\endgroup\$ Commented Mar 26, 2018 at 8:59
  • \$\begingroup\$ What if you create a variable float rot = 0;, then every time you rotate the world, also change that variable rot += 60; (or -60 if it rotates negatively)? That's what @Charanor meant (I assume). If that's not it, can you elaborate? Because it sounds like you are having a very simple problem but can't phrase it properly, like drowning in a spoon full of water. \$\endgroup\$ Commented Nov 23, 2018 at 14:28

3 Answers 3

0
\$\begingroup\$

Why don't you simply have a variable that stores your amount rotated?

private float totRot;   

/** Rotate camera by the specified degrees.
 *
 * @param degrees */
public void rotate(final float degrees) {
    Vector3 axis = Vector3.Z; /* Or whatever axis */
    camera.rotate(axis, degrees);
    totRot += degrees; // Track amount rotated
}

/** Rotates the camera to the specified degrees.
 *
 * @param degrees */
public void rotateTo(final float degrees) {
    rotate(degrees - totRot);
}

To interpolate the rotation over time you can use a helper class (untested, constructor and getters / setters omitted):

public class CameraRotator {
    private Camera camera;
    private Vector3 axis;
    private Interpolation interpolation;

    private float startRot;
    private float rotAmount;
    private float totRot;

    private float rotTime;
    private float timeCounter;

    private boolean rotationFinished;

    public void update(final float delta) {
        if (rotationFinished)
            return;

        /* Increment time spent */
        timeCounter += delta;
        /* Calculate progress */
        float alpha = timeCounter / rotTime;
        alpha = MathUtils.clamp(alpha, 0, 1);

        /* Interpolate rotation using alpha (progress) */
        rotateTo(interpolation.apply(startRot, rotAmount, alpha));

        /* If (alpha == 1) we're finished. */
        if (alpha == 1) {
            timeCounter = 0;
            rotationFinished = true;
        }
    }

    /** Rotate camera by the specified degrees in the specified
     * time.
     *
     * @param degrees
     * @param time */
    public void startRotation(final float degrees, final float time) {
        startRot = totRot;
        rotAmount = degrees;
        rotTime = time;
        rotationFinished = false;
    }

    /** Rotate camera by the specified degrees.
     *
     * @param degrees */
    private void rotate(final float degrees) {
        camera.rotate(axis, degrees);
        totRot += degrees; // Track amount rotated
    }

    /** Rotates the camera to the specified degrees.
     *
     * @param degrees */
    private void rotateTo(final float degrees) {
        rotate(degrees - totRot);
    }
}

Of course if you don't need the interpolation over time and plan on instantly rotating the camera the first method should work just fine.

\$\endgroup\$
2
  • \$\begingroup\$ Your solution doesn't seem to take into consideration that the object you're rotating is the same object that is the reference point for the rotation. In other words, when I see that the camera has visibly rotated by 60 degrees, it registers very little rotation at all. \$\endgroup\$
    – Didia
    Commented May 17, 2017 at 23:23
  • \$\begingroup\$ @Didia Sorry but I don't understand exactly what you mean? \$\endgroup\$
    – Charanor
    Commented May 18, 2017 at 5:43
0
\$\begingroup\$

I've found an answer, but I don't consider it to be a good one because it's tied to Libgdx and not a generic approach.

Libgdx's Camera has a vector called up equalling (0,1,0). During testing, on rotating the camera 90 degrees to the left, I discovered this vector became (1,0,0).

In other words, the relationship between the rotated angle and this vector is (sinθ, cosθ, 0).

Again, I don't consider this to be a great solution from a mathematical perspective. I was just lucky. If anyone knows how to answer from the perspective of view & projection matrices, please do share.

\$\endgroup\$
0
\$\begingroup\$

Store a unit vector for your initial facing, I. At any point in the rotation you can use the unit vector of your current facing, C. Calculate the angle between the two vectors using I \dot C = |I| * |C| * cos(\theta).

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .