mouselook and planetary gravity

I have run into a game breaking problem with my movement mechanic. The issue is with the horizontal (left-right) mouselook. This is the current module;


def hmouse():
    sensitivity = 0.001
    hlimit = math.radians(0)
    own = bge.logic.getCurrentController().owner
    mouse = own.sensors['mouse']
    mid = Vector([200,200])
    mpos = Vector(mouse.position)

    if not "ml_angle" in own:
        own["ml_start_mat"] = own.localOrientation.copy() 
        own["ml_angle"] = Vector([0,0])
        mpos = mid.copy()
        bge.render.showMouse(0)

    if (("mouselook_active" in own and own["mouselook_active"]) or not "mouselook_active" in own):
        own["ml_angle"] += (mpos - mid)*sensitivity

    own["ml_angle"][1] = max(min(own["ml_angle"][1],hlimit),-hlimit)
    xmat = Matrix.Rotation(-own["ml_angle"][1],3,"X")
    zmat = Matrix.Rotation(-own["ml_angle"][0],3,"Z")
    own.localOrientation = own["ml_start_mat"]*zmat*xmat
    bge.render.setMousePosition(int(mid[0]),int(mid[1]))

It breaks when used in conjunction with this module;


def movement(): 
    cont = bge.logic.getCurrentController() 
    player = cont.owner 
    keyboard = bge.logic.keyboard 
    mouse = bge.logic.mouse 
    scene = bge.logic.getCurrentScene()

    if bge.logic.KX_INPUT_ACTIVE == keyboard.events[bge.events.WKEY]: player.applyMovement((0, 1, 0), True) 


This is supposed to cause the player to move along the local +Y axis, which it does. However, as soon as you rotate left or right, the movement locks on to the direction you were facing prior to rotation. I can’t seem to figure out why and there are no errors reported in the terminal. My best guess is that I have to update the mouse position every frame to account for the new direction. Can anyone take a look and let me know where this would go?

Get rid of “mouse = bge.logic.mouse” in the 2nd code snippet. You are redefining the variable set to own.sensors[“mouse”] in the first snippet.
Also, you don’t need to use KX_INPUT_ACTIVE to check for keyboard status. You can just do


from bge import logic, events

key = logic.keyboard.events
if key[events.WKEY]:
    player.applyMovement ...

Also be careful with the second argument of applyMovement, because the API is faulty on this. First it’s stated that False is local movement, then it’s saying the opposite:

applyMovement(movement, local=False)
[…]
° True: you get the “local” movement ie: relative to object orientation.

But this probably isn’t the problem.

Edit: ??? It’s not only with applyMovement I see. I must be the problem then. Sorry about that.
Edit2: However, I do find this very confusing -> Compare with replaceMesh() (Sorry, off-topic)

Thanks for the help, I have adjusted the scripts and removed the unnecessary lines but I still have the original problem. Anyone have any thoughts on how to update the hmouse module so it stays in sync with the characters local +y orientation?

As Raco stated, you must change the line


player.applyMovement((0, 1, 0), True)

to


player.applyMovement((0, 1, 0), False)

I think this should solve it?

EDIT: Are you using a separate object (the “player” object) for your movement than to your camera? If so, then that object isn’t being affected by the rotation of the camera. You need to apply rotation to that object too.

OK, these scripts are both applied to a dynamic object rather than the camera. I have a camera that follows the object, but it does not have any other movement. I am trying to make it so that the dynamic object rotates with mouse movement and moves in its local +y direction. I am sure I am reading it right, True = local and False = global.

True is local. So that’s not the problem. (Again, sorry about that). But it’s curious, because I just tested out your modules and to me it works fine. Have a look. Only thing, I think your code could be shorter, clearer, more efficient, but maybe for some reason you need two separate controllers?

Attachments

Motion_test.blend (80 KB)

Thanks for the help, I really do appreciate it. There is no specific need to have separate controllers, it is just development habit of mine.

My apologies, there is another factor that I neglected to mention. I am also using a vector gravity module to simulate planetoid gravity, i.e. Super Mario Galaxy style. I updated your test to demonstrate the script. If you move without rotating it works, as soon as you rotate it breaks.

Attachments

Motion_test.blend (119 KB)

Maybe there’s a solution for this with your code, but I would recommend to leave this approach. You would have greater control over things when using localLinearVelocity. Is there any special reason why you are using applyMovement?

Edit: Maybe you could still use applyMovement, but than you would have to rotate using another approach. You have to take into account the Vector to which the player is aligned. Another reason why you should structure your code differently. I’ll have a look at it tomorrow.

Thank you for the help. In making that test I realized there was something I have not tried, namely adding alignAxisToVect to keep the vectors in sync. My gravity script is normally supposed to do that anyway, so I had overlooked that as the cause. I added a few lines and now it works as I intended. Thanks for the help.


def hmouse():
    scene = logic.getCurrentScene()
    cont = logic.getCurrentController()
    own = bge.logic.getCurrentController().owner
    mouse = own.sensors['mouse']
    sensitivity = 0.001
    hlimit = math.radians(0)
    player = logic.getCurrentScene().objects["Cube"]
    gravity = logic.getCurrentScene().objects["Icosphere"]
    mid = Vector([200,200])
    mpos = Vector(mouse.position)
    up_vec = gravity.getVectTo(player)[1]


    if not "ml_angle" in own:
        own["ml_start_mat"] = own.localOrientation.copy() 
        own["ml_angle"] = Vector([0,0])
        mpos = mid.copy()
        bge.render.showMouse(0)

    if (("mouselook_active" in own and own["mouselook_active"]) or not "mouselook_active" in own):
        own["ml_angle"] += (mpos - mid)*sensitivity

    own["ml_angle"][1] = max(min(own["ml_angle"][1],hlimit),-hlimit)
    xmat = Matrix.Rotation(-own["ml_angle"][1],3,"X")
    zmat = Matrix.Rotation(-own["ml_angle"][0],3,"Z")
    own.localOrientation = own["ml_start_mat"]*zmat*xmat
    bge.render.setMousePosition(int(mid[0]),int(mid[1]))
    player.alignAxisToVect(up_vec, 2, 1)