• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

SOLVED Moving Object Twitching While Turning Towards Mouse - Using Physics Engine

I have a space ship coded to turn and face the mouse position. Physics is on. Works great. However, when the object is moving specifically diagonally and the mouse is positioned perpendicular to the ship's movement, its phy_rotation twitches slightly. I did a lot of playing around with different ways to code it, moving certain lines of code in and out of the Step and End_Step events, and I can reduce it a bit but not completely. I also tried adjusting the angular_dampening, but that had no effect.

Now, the camera is following the spaceship, and that coding is in the spaceship object. I started suspecting that the mouse, because it's not really part of the game, is, in a sense, instantly where it always needs to be relative to the screen, whereas the ship object has to be processed by the game. Because of this delay in processing, the exact angle from the spaceship to the mouse wouldn't always be consistent, causing the ship to rapidly turn slightly either way and creating a twitch effect. So I had the ship object draw the angles, and found that, indeed, while moving at a constant, diagonal speed and with the mouse still, the angle was changing slightly.

My solution was to create a buffer relative to the ship's speed. Basically, if the ship's phy_rotation wasn't perfectly aligned with the mouse but still within the buffer, it wouldn't turn. This solved the twitching issue, but then made for really choppy turning when the angle_difference wasn't drastic.

I'm not the most advanced coder out there, but I'm not quite a baby at GMS2 anymore. I can't imagine there's a way to fix it, but it so or if I'm doing something wrong, by all means. Otherwise, I'm more so looking for a workaround or a different way to code this. I don't think my scripts are necessary, but here they are if anyone wants to take a gander:

Turning the object (doesn't make a difference if in the Step or End_Step):

GML:
///@param current_angle
///@param goal_angle
///@param turn_speed
function turn_towards(_a,_g,_s) {
    var _ad = angle_difference(_a,_g)
    return min(abs(_ad),_s) * sign(-_ad)
}


if (phy_rotation != 360 - goal_dir) {
    phy_rotation -= turn_towards(360 - phy_rotation, goal_dir, turn_spd)
}
Updating the camera position (in the End_Step of the spaceship). For simplicity, I tried setting the camera view to gx and gy to bypass all the in-between coding, and it didn't make a difference, so issue doesn't lie here:

GML:
var gx = phy_position_x - middlex //middlex is just the offset for the camera
var gy = phy_position_y - middley //middley is just the offset for the camera

if (c_lock = false) {
    var pan_dist = point_distance(cx,cy,gx,gy)
    if (pan_dist > pan_spd) {
        var shift_spd = min(10,pan_dist)//pan_dist * pan_spd
        var shift_dir = point_direction(cx,cy,gx,gy)
      
        cx += lengthdir_x(shift_spd,shift_dir) + phy_speed_x
        cy += lengthdir_y(shift_spd,shift_dir) + phy_speed_y
    }
    else {
        c_lock = true
        cx = gx
        cy = gy
    }
}
else {
    cx = gx
    cy = gy
}

camera_set_view_pos(view_camera[0],cx,cy)
Finally, this is my adjusted coding to turn the ship towards the mouse, but with the buffer. Basically, it adjusts the size of the buffer (in degrees) based off the speed of the ship and the distance the mouse is from the ship. You will need to know the trigonometry function of tangents to decipher this (it works fine, I think):
GML:
var dif = angle_difference(360 - phy_rotation,goal_dir)
var percent = (90 - angle_difference((360 - phy_rotation) + (90 * sign(dif)), goal_dir)) / 90
var point_offset = percent * darctan(phy_speed / point_distance(x,y,mouse_x,mouse_y))

if (abs(dif) > point_offset) {
    phy_rotation -= turn_towards(360 - phy_rotation,goal_dir,turn_spd)
}
So, to recap, it twitches when {ship moving diagonally + mouse perpendicular to ship's movement}. Moving the mouse closer to the ship makes the twitch worse, farther away isn't as bad (the angle difference gets bigger when the mouse is closer, cuz, trigonometry). Moving scripts between the Step and End_Step events doesn't eliminate the issue.
 

chamaeleon

Member
I am not a heavy user of the built-in physics, but I'm curious about one thing. Is physics supposed to play any part in the rotation updates at all or should every change in the angle only be controlled by your code? In the latter case, setting phy_fixed_rotation to true could be beneficial (maybe you already have, in which case I'm not adding very much). If it's the former, is there any chance you can apply torque instead to make it turn and apply the opposite torque to make it stop turning, or reduce turning speed, when needed? Because you indicate it should point towards the mouse, it seems you're looking for manual rotation, but maybe I'm missing something.

I'm sure you're aware of most people arguing one should not do much manual modification of the physics variables but simply let the physics system do its thing, and if you do want to modify physics variables for some reason, maybe the game shouldn't use physics in the first place but could use normal x, y, and image_angle modification instead. If you have a space ship moving by applying physics, how much different is that from just using speed variables, really? Are you going to let things bounce around when they collide, not unlike billiard balls?
 
I am not a heavy user of the built-in physics, but I'm curious about one thing. Is physics supposed to play any part in the rotation updates at all or should every change in the angle only be controlled by your code? In the latter case, setting phy_fixed_rotation to true could be beneficial (maybe you already have, in which case I'm not adding very much). If it's the former, is there any chance you can apply torque instead to make it turn and apply the opposite torque to make it stop turning, or reduce turning speed, when needed? Because you indicate it should point towards the mouse, it seems you're looking for manual rotation, but maybe I'm missing something.

I'm sure you're aware of most people arguing one should not do much manual modification of the physics variables but simply let the physics system do its thing, and if you do want to modify physics variables for some reason, maybe the game shouldn't use physics in the first place but could use normal x, y, and image_angle modification instead. If you have a space ship moving by applying physics, how much different is that from just using speed variables, really? Are you going to let things bounce around when they collide, not unlike billiard balls?
Thanks for the input. The physics would be preferable, yes, because I do want things to bounce around, knock each other into a spin, and stuff like that. Gives it a real spacey feel.

The thing is (and I just double checked) it's not isolated to just the physics system. Using normal, non-physics variables still has the same issue of the ship twitching. I have noticed that when the ship is moving, its phy_rotation (or image_angle) tends to lead ahead of the mouse position. That is, when the ship is moving to the top-right, and the mouse is in the bottom-right, the ship points slightly above the mouse position, almost as if it were anticipating the mouse ahead of where it actually was. Now this is a separate issue that I was able to easily fix by adjusting for the ship's x and y speeds, but the twitching remained (unsurprisingly) unaffected.

As mentioned, I tried negating the phy_angular_velocity without any success, so I don't think there's any physics interactions/collisions affecting it. But I went ahead anyways and threw in the phy_fixed_rotation = true to no avail.

I still lean towards it having to do with a lag possibly in the ship's position, the camera position, or the mouse position, causing the angle to constantly change. Although I'm uncertain how to isolate it since I've tried shifted them all around between the Step and End-Step events.

In reality, it's probably a really simple oversight or just something I'm ignorant towards. Maybe a fresh pair of eyes can point it out for me.
 
So I discovered a workaround that completely eliminates the issue of the ship's phy_rotation twitching. To do so, I had to base the point_direction() on the gui positioning of the mouse relative to the center of the gui screen. That is, rather than point_direction(ship.phy_position_x,ship.phy_position_y,mouse_x,mouse_y), I used the following lines of code:

GML:
var xx = device_mouse_x_to_gui(0)
var yy = device_mouse_y_to_gui(0)
var face_dir = point_direction(gui_midx,gui_midy,xx,yy)
if (360 - phy_rotation != face_dir) phy_rotation -= turn_towards(360 - phy_rotation,face_dir,turn_spd)
This way, the miniscule, not-visible shifting of the ship did not affect the point_direction() angle.
 
Top