Setting, and reporting, angles of travel

Part of building audio games as a blind person means you’re not just building the world, but also the lens through which that world is viewed. Now that I have a working radar system that alerts me to contact with obstacles, I’m noticing that rotation feels very choppy. So now I’m questioning my logic for setting/getting rotation angles.

Essentially, I need to report a direction to the player in some form specific to the game type (degrees for flight games, cardinal direction for roleplaying, etc.) It’s this reporting requirement that seems to be tripping me up. If I just wanted to rotate, I imagine I could just apply a delta rotation to some axis and everything would be fine. I also understand that objects can invert if too much rotation is applied on a given axis. If it simplifies things, I’m happy to lock rotation on Z such that, for instance, a flight game is limited to pitches of ±90 and no roll.

If I understood the suggestion correctly, someone on the Amethyst forum suggested that the best way to achieve this was to make the angles your source of truth, modify them to reflect the player’s desired course, then sync them to the transform. So I have:

#[derive(Default, Deserialize, Serialize)]
struct Course(f32, f32, f32);

impl Component for Course {
    type Storage = DenseVecStorage<Self>;

struct CourseSystem;

impl<'s> System<'s> for CourseSystem {
    type SystemData = (WriteStorage<'s, Course>, WriteStorage<'s, Transform>);

    fn run(&mut self, (mut courses, mut transforms): Self::SystemData) {
        // Only handle Y rotation for now, walk before I crawl and such...
        for (course, transform) in (&mut courses, &mut transforms).join() {
            while course.1 < 0. {
                course.1 += consts::PI * 2.;
            while course.1 >= consts::PI * 2. {
                course.1 -= consts::PI * 2.;
            transform.set_rotation_euler(course.0, course.1, course.2);

Then to rotate left/right, I do:

            if input_handler.action_is_down("rotate_left").unwrap()
                && !should_snap_left
                && !should_snap_right
                course.1 += delta * config.player_rotation_rate;
            if input_handler.action_is_down("rotate_right").unwrap()
                && !should_snap_left
                && !should_snap_right
                course.1 -= delta * config.player_rotation_rate;

rotation_rate is radians/second, which I’ve set to PI. The delta is also correct. The code works well in so far as it correctly updates an angle with values that look sensible. It doesn’t have the desired effect when I rotate the transform, though. Here’s a sample of me rotating to, then past, 90 degrees:

[INFO][onslaught] Current euler: (0.0, 1.5198197, 0.0)
[INFO][onslaught] Current euler: (0.0, 1.570451, 0.0)
[INFO][onslaught] Current euler: (3.1415927, 1.5186837, 3.1415927)
[INFO][onslaught] Current euler: (3.1415927, 1.4661156, 3.1415927)

At no point is my code setting any euler angles, other than that around the Y axis, to anything other than 0. So I’m wondering if my audio jitters are due to me trying to set an euler of (0., PI, 0.) and almost immediately having it set to:

[INFO][onslaught] Current euler: (3.1415927, 0.050882015, 3.1415927)

which is what my logs show when I rotate to what my HUD claims is 180. Even though those may be equivalent, the fact that I’m setting (0, PI, 0) and getting that seems like it’d cause some choppiness. By choppy, I mean that the rotation doesn’t sound circular. It sounds slow, then moves very quickly across short arcs, then slows down again. If I’m at (0, 0, 0) and have a sound at (0, 0, -150), several taps of the arrow with the sound at the extreme right or left barely move it. As soon as it centers in front or behind, though, taps seem to move it drastically.

So clearly I’m way off-base with something, and now that my world sensors are advanced enough, I can actually perceive that. I just don’t know where to even begin setting correct rotations and being able to report angles to my player.

Thanks for all the help. This is tough but I’m having a blast with it.

OK, made some progress. Was a combination of inverting things I shouldn’t have, and not inverting things I should. This topic isn’t relevant anymore and I’ll return to a previous one.