Directional movement system.

Hello,

I am going to make a “true action movement” system. The concept is simple, movement in the direction of the pressed key(s) where W is always north, camera follows player and can be rotated freely around the character while standing stil. When a key is pressed camera locks onto player and the camera get used to rotate the character.

My first question is regarding the directional movement (how would you do it?).
I am thinking of using 10 empties (1 center->mid height, 9 for the directions) and simply trackto the right one when you press a key.

My second question, zooming… there are a few options on this subject.

  1. set the camera.lens to zoom in/out
  2. move the camera to positions
  3. animate it.

I want to do this the right way, but i also think about… if i use it to move to position and them lets say zoom out, the camera will be for example 50 meters away from the player, if you get indoors the camera jumps/move like 48 meters. At this point i would say set the lens so the camera is always at a fixed distance.

This will be my first attempt at a 3d movement system only done fps before.
i know how i need to build it, i only want some advice about those 2 setups.

I’m not 100% sure of what you mean, but from what I can gather, I think I use this exact system myself.

For the character, I use a single empty with an action that changes its relative position to the player depending on the key pressed (for example, A-key sets the empty’s action frame to the frame in which it’s to the left of the player). I’d show you my script, but I’m not at home right now. =P

In total for the movement system, I have four objects (five if I’m using vehicles, but that’s a different story): The player, the directional empty (dir), the camera empty, and the camera. The parenting heirarchy I use is as such:

  • camera is parented to the camera empty
  • camera empty is vertex parented to the player, on a vertex set to the player object’s origin point
  • the dir empty is parented to the camera empty

Use the mouse-rotation logic on the camera empty. Use the directional logic on the dir empty. Now, when you look around with the mouse, the player will always move forward/backward/left/right based on the direction that the camera is facing.

you could just use 1 object, and some offset vectors to create your focus points

also, you can always just point to your linV with the Z chopped off

so basically, no matter which way you push the actor they walk that way and animate, freeing you to push them with physics

LocalPoint in space

LP = object.worldPosition+(object.worldOrientation*Vector([X,Y,Z,]))

or even
#local point using camera world orientation

LPC = object.worldPosition + (Camera.worldOrientation*Vector([X,Y,Z]))

so no need for empties at all, push the actor the way you wish for them to go, and they point that way and then animate themselves?

is not as Gran Thief Auto ? in that case “A” mean at left of the camera, W mean forward the camera , ienormally you see the player from back .(and the player walk only forward , not back not at side) keeping pressed “A” for a bit of time, the player should walking around the camera making a circle.in this case the inputs have to be converted from the camera to the global space.if is that i not see advantages to use a bunch of empties

is not as Gran Thief Auto ? in that case “A” mean at left of the camera, W mean forward the camera

i think its something like that only in gta the camera is rotating with the player i thought, this sytem is like the game TERA.

Ok had some time this morning and i made this:

I have used 10 empties for this and the brick to trackto them. I tried with alignAxisToVect but it kept messing up my character (turning up side down etc) i coulnd get it working properly, but i need to say it works great with the empties.

If you want an idea you might have a look at camera relative alignment/movement.

Be aware manipulating camera (zoom) and moving player (walk) are different things. I would treat them differently.

Be aware manipulating camera (zoom) and moving player (walk) are different things. I would treat them differently.

meaning in separate topics, or just different ways to program them?

At the moment i use a fps mouse look converted (well added 7 characters) to get it to work as 3d camera. And while i got the basic setup now, i gonna work on the mouse look to add more functions etc, so the zooming is approached differently?

As for the movement setup, i am willing to share them in the resource section if there is a need for it. (the raw edition as seen in the video)

If you want an idea you might have a look at camera relative alignment/movement.

i did take a look, and gonna look a bit closer to it tonight. I noticed the camera/mouse movement bugs it. but key controls works.

Yes, I mean separate topic.

You move the character (user input) where the camera (orientation and position) is an input parameter (beside others). It does not matter how you control the camera. Imagine you want to control other characters/things (e.g. a car) with camera relative movement. You can use another character/car/whatever and apply the same control (including the camera) to it.

Moving and zooming the camera need the character? No, it does not need it. The character might be an input parameter as well, when it is used as focus object of the camera. Imagine you want a complete different object to look at. It would not work when you tightly bind your camera operations on a character.

The character motion is complicated by itself. I would not clutter it with more things than necessary.

Just some thoughts.

I use vectors in a list that corresponds to key commands:


keyboard_input = get_keys()

commands = ["left","down","right","up"]
directions = [[-1,0,0],[0,-1,0],[1,0,0],[0,1,0]]
                   
for c in range(len(commands)):
    command = commands[c]
    if command in keyboard_input:   
        direction = directions[c]
        vector = Vector(direction)

You could also make it in to a dictionary instead.

My camera is parented to a “hook” object which lerps to the same position as the player.
By rotating the vector by the hook object’s rotation you can get a local vector.

vector.rotate(self.camera_hook.worldOrientation)

You can multiply the vector by your movement speed, or build that in to the code at the directions stage.

My player is just a box, and the armature is parented to the box. The box doesn’t rotate, only the armature rotates to give the appearance of rotation without getting messy. In most of my games I don’t use physics, it’s all tile based. So keeping things constrained to a fixed axis helps a lot.

well done :Dyes is different, but not too much the imputs work the same way(dependent from the camera rotation)the orbiter also (of course mouse vs right stick) in gta there is also another stuff that influence the camera orbitationdependent from the player movement , so giving to the player box the command "forward"for a bit the camera tend to go back to it.i guess depend also from the type of game , if the player has not to walk too muchcan be better your system with orbitation dependent from mouse onlygood work anyway :wink: also if the 10 empties seem a bit excessive

So i have been playing a bit with it, and added a zoom and obstacle option for the camera

Update video:

I am not so happy with the zooming it bugs a bit due to scrollwheel i guess.
camera position is fixed, zooming by adjusting the camera lens and a property set the keyframe, and a ray to check from player to cam hook.

also if the 10 empties seem a bit excessive

Thanks, yes indeed i think 9 empties(directions) are a bit overkill, but i thought about it and i can actually use those empties for skills/item drops as well, so its not that bad (double functions). but i am also thinking to convert it to smoking_mirror’s option.

To breakdown what i have done:
9 directional empties parented to an center empty.
the center empty is vertex parented to the player cube.
the camera is parented to the cam hook
the cam hook is parented to the center empty.

player cube tracks to a direction empty with the right name/direction.
the camera moves its own.parent.parent (the center empty) and this setup can easy be transferred to an other vehicle.

That is basically it.

There’s a bit more to the code I posted, you can actually get diagonals from combining key presses, the function should add the vectors and then set the length to 1. Dictionary would be best, I’m not sure I remember why I used lists there.

doh , just to say , this is my “input converter” (note im not implement almost never the player so can contain some bad design :D)


    # code of the camera
    # send imputs to player box    
    kev = bge.logic.keyboard.events
    w, s, a, d = [kev[ord(k)]==2 for k in "wsad"]
    space = kev[bge.events.SPACEKEY]
     
    vec_keys = Vector((d-a,w-s,0))
    vec_move = ((-own.worldOrientation.col[2]).copy().to_2d().to_3d().to_track_quat("Y","Z")).to_matrix() * vec_keys
    box["imput_direction"] = vec_move
    box["imput_speed"] = 5.0 if vec_keys.magnitude else 0.0
    box["input_jump"] = space == 1

There’s a bit more to the code I posted, you can actually get diagonals from combining key presses, the function should add the vectors and then set the length to 1. Dictionary would be best, I’m not sure I remember why I used lists there.

Yes i know, i got what you mean, i made a key-bind script so all my keys are already in a dict forwards = Wkey etc, so its easy to adjust and compare them. but i don’t know for sure yet, due to i actually like the way it works with the empties.

doh , just to say , this is my “input converter” (note im not implement almost never the player so can contain some bad design :D)

Don’t worry i get the point :slight_smile:

Thanks all for your examples and ideas, i will think about it and try a few options out.

Took a while but i have converted it into alignaxistovect using this way:


        #setting vectors to be used in the tracking / facing of the player
        vector_obj = own.scene.objects['player_direction_controller']
        
        vec_x   = vector_obj.worldOrientation.col[0]
        vec_y   = vector_obj.worldOrientation.col[1]


        vec_north       = vec_y
        vec_north_east  = vec_y + vec_x
        vec_east        = vec_x
        vec_south_east  = -vec_y + vec_x
        vec_south       = -vec_y
        vec_south_west  = -vec_y + -vec_x
        vec_west        = -vec_x
        vec_north_west  = vec_y - vec_x


def face_direction(obj, vector):
    
    track_axis = 1 # x,y,z = 0,1,2
    turn_speed = 1.0 # 0.0 - 1.0
    
    # face direction
    obj.alignAxisToVect(vector, track_axis, turn_speed)
    # head up
    obj.alignAxisToVect([0.0,0.0,1.0], 2, turn_speed)

i tried many ways, this way worked for me.