[Camera and player help...] player axis accoding to the camera

https://youtu.be/BAHFiEqaSHM

Blend : http://www.mediafire.com/file/m226id599pvi672/camera_player.blend

Hello,

I have two problems with python scripts. There are two python scripts that I picked from resources from this forum.
In the video I have the mouselook script and a player directional movement script. When I move the camera around the player orientation changes every where and I don’t know whats the problem. I want to be able to move my character with directional axis (up go forward back go backward and so forth) , but I want the axis to kinda face in the direction of the of any active camera like the camera actuator. Any way for the camera to don’t have to be parented to player, because the camera actuator can’t be parented to the player to work.

In the video if you take away player orientation problem and add the camera actuator player axis according to the camera : that what I’m trying to do.

I hope I made any sense.

You’re basically looking at two problems that are the same:

How do you get a player to move in the direction of the camera and keep his feet on the ground?

The way I’d recommend is to parent the object that should face a direction (like the player’s armature) to the player’s collision box. Rotate the armature by the direction it’s moving, and rotate it independently from the collision box, which should basically face the exact same direction as the camera.

Python’s the way. … I guess I should post an example…

Okay, here’s the example.

CamOrient.blend (403 KB)

Use the arrow keys to move about. As you do so, you’ll find that no matter which camera you switch to (or even in the normal, ‘out of camera’ view), the Up-arrow key will always move the object away from the camera. In addition, the mesh will face the direction you’re moving in.

wow SolarLune this is boss!
Thanks alot for helping me!
this could also help me with my python learning process.

@SolarLune

There is really no need to convert to euler angles, or use trig functions.

The key task in this case is the transformation of the player-space velocity vector to a camera relative velocity vector, which can be done with very simple operations:


movespd = 5.0

vec_vel = Vector((0, 0, 0))

if keyboard[events.LEFTARROWKEY]:
    vec_vel.x = -movespd
elif keyboard[events.RIGHTARROWKEY]:
    vec_vel.x = movespd

if keyboard[events.UPARROWKEY]:
    vec_vel.y = movespd
elif keyboard[events.DOWNARROWKEY]:
    vec_vel.y = -movespd
    
# Camera looks into the -Z direction, so swap to match
vec_vel = vec_vel.xzy; vec_vel.z *= -1 

if vec_vel.magnitude:
    vec_vel = cam.worldOrientation * vec_vel # The transform
    vec_vel.z = 0; # you don't need the z, so drop it
    vec_vel.magnitude = movespd # speed is 5.0, even when moving diagonally ;)
    
    obj.alignAxisToVect(vec_vel, 0) # if you want to rotate with it
    obj.setLinearVelocity(vec_vel) # move

Also, note the use of worldOrientation instad of orientation -> the latter method is deprecated: Link

Thanks for that info, Goran. I read about multiplying the camera’s orientation by the velocity a long time ago, but never could figure out how to get it to work. Thanks!

I just now got around to trying this by multiplying the orientation, but the character doesn’t head in the direction of the active camera. Any ideas?



            if kleft:
                obj['movevec'].x -= obj['movespd']
            elif kright:
                obj['movevec'].x += obj['movespd']
            else:
                obj['movevec'].x *= obj['friction']
                
            if kforward:
                obj['movevec'].y -= obj['movespd']
            elif kback:
                obj['movevec'].y += obj['movespd']
            else:
                obj['movevec'].y *= obj['friction']
                
            obj['movevec'].x = BGHelper.Clamp(obj['movevec'].x, -obj['maxmovespd'])
            obj['movevec'].y = BGHelper.Clamp(obj['movevec'].y, -obj['maxmovespd'])
            
            # APPLYING MOVEMENT
            
            if obj['movevec'].magnitude:
            
                movevec = obj['movevec'].copy().xzy
                movevec.z *= -1
                
                movevec = cam.worldOrientation * movevec
                movevec.z = 0
                
                movevec.magnitude = max(abs(obj['movevec'].x), abs(obj['movevec'].y))
                
                obj.setLinearVelocity(movevec, 0)


EDIT: I guess I don’t have to use clamping for the individual X and Y values above - I could just check the magnitude of the vector. :stuck_out_tongue:

EDIT 2: I tried your code, Goran, but that didn’t work either. From a certain angle it works (If I’m looking down +Y), but from any other angle, it’s broken…

Your code seems fine, but, like my code, it depends on certain conditions that are probably not satisfied in your new environment.

So, it could be the wrong thing in your new context (whatever that may be).

EDIT: I guess I don’t have to use clamping for the individual X and Y values above - I could just check the magnitude of the vector. :stuck_out_tongue:
Right. Also, swizzle properties should return a new vector, so you don’t have to make a copy.

You can just do this: obj[“movevec”].xzy

EDIT 2: I tried your code, Goran, but that didn’t work either. From a certain angle it works (If I’m looking down +Y), but from any other angle, it’s broken…
My code assumes the global XY plane to be the “movement surface”. So, if I had to guess, I would say that you’re probably trying to move on some arbitrary plane, and that’s why the whole example breaks down.

Could you modify a copy of CamOrient.blend (using my code), to reflect your new situation, where the whole thing breaks down?

That would really help me pin it down.

Thanks. Here it is - I just pasted in your code and tested it.

camorient.blend (408 KB)

… So, is this the situation where it’s not supposed to work?

Everything seems fine to me.

Huh? From when you initially load the scene and press P, the keys don’t move relative to the camera’s facing. Rotating the view around still doesn’t solve the problems. Do you mean it works if you go to the game camera? I reference the active camera in the scene, so it should work with Blender’s User camera.

I’m running the .blend as is, so it’s using the editing cam.

It works perfectly fine …

Are you using an svn build?

r42671 - Not sure if it’s an SVN build (not sure if official builds display their revisions). It’s Blender 2.61. This is weird - it doesn’t work the same for me. What version are you using?

I’m using 2.61, Linux official.

When you say “it doesn’t work”, do you mean completely, as in input does nothing, or it moves, but not in the right direction?

Do you have an additional windows computer around? Try installing 2.61 on that, and testing this .blend. If it still doesn’t work, then I guess there’s something iffy with the latest windows version.

If it does, it’s an issue with your primary system.

PS:

What is the output of “blender -v” - is the build type “Release”?

I meant it moved, but not in the correct direction (like W and A both moved left, and D and S both moved right, though this changed if the view changed). It’s cool, though - I got another method to work.

Could you do me a favor, and try changing this line:

vec_vel = cam.worldOrientation * vec_vel

To this:

vec_vel = vec_vel * cam.worldOrientation

It seems like someone forgot to sync the matrix multiply order when they went mucking around in the new linear algebra library.

… If true, it’s almost an unforgivable oversight.

It’s cool, though - I got another method to work.
Other methods are probably less efficient, and mathematically primitive (especially if you’re using trig functions … ughh).

But when you can’t rely on a consistent linear algebra subsystem … I guess you have no choice.

That switch fixed it, thanks. So, how recent is your (working) build?

The build date is listed as “2012-01-05”.

I’m on Arch Linux, which is a bleeding edge rolling release distribution, and I got the latest version of blender from the package manager. Now, the rolling release methodology should be: “Whenever a new release of software X is available, that official release will be made available in the repositories, and you can update immediately.”.

As it turns out, the official Linux build, on blender.org, is actually older - “2011-12-13”, so it seems that Arch people compile their own, but do they use the official revision snapshot of the source (which is “42615”, for linux), or do they actually pull from trunk? I can’t tell, because my revision field is set to “runknown”.

If they pull from trunk, then they’re not joking around when they say “bleeding edge” … On one hand, that’s awesome, but on the other, it’s quite insane, so I’m pretty sure they pull the release revision, and then compile that into a package that fits very elegantly into Arch.

Why is the revision field set to “runknown”? I don’t know, but I’m guessing that they use git to access the blender svn repo, because I use git too, and I noticed that “runknown” would be set as the revision number displayed in blender, but other than that, everything was perfectly fine.

The official Linux build on blender.org works the same as my (seemingly more recent) Arch build, so it’s not a problem with my specific build.

Now, the question is: What is the right matrix multiply order? I mean, I remember that it was switched back and forth for some time, for reasons that I’m not really sure about, but what was the ultimate decision?

To be perfectly honest, I prefer the way it works on your end:

vec_vel  = vec_vel * cam.worldOrientation

It’s perfectly sensible, and it makes this shorthand possible:

vec_vel *= cam.worldOrientation

Well, anyway, I’m going to make a bug report, and link to this thread.