Two Questions: slow parent on one axis, move character while in mid air

I am working on my third person character setup, and have got everything working great except for two things. The first one is that I have a setup so that when the camera hits a wall it moves closer to character so that the camera isn’t behind the wall, which works great except that it just instantly jumps to the closer position. What I would like to do is an effect like slow parent, but only on the camera’s local Z axis. So the camera would move normal, with no slow parenting, on the local X and Y axes, but move with the slow parenting on the local Z axis.
My other question is for when my character jumps on runs off a cliff. What I want is that it retains its current world velocity, but you can still move around like you were on ground. So if the character has a linear velocity of 5 on the world Y axis, when it jumps it will still have that velocity, but also be able to move around in the air. I can’t figure out just how to explain it, I hope you understand what I mean.
All help is very much appreciated, thank you in advance.

First question: Yo Frankie got the camera movement down well, you could look at their script.

Second question: I assume that your using a Move.py script, those are built to only let you move if your on the ground. Just use the movement actuator, I know Dloc will let you move side to side anytime.

I’m not sure what you’re referring to as Move.py, I made my own movement script from scratch. I am using setLinearVelocity so I don’t have the problem with going through walls that dLoc has. DLoc does give the desired results, but I don’t want to have to worry about it going through walls, and I want to keep the movement constant by using linearVelocity in the entire script. As for the Yo Frankie camera, I am downloading it now and will report if it works. And thank you for the replies, you’re doing about half the work for my game;).

Oh yeah, glad to help :slight_smile:

I just thought that you might be using a generic move.py script you could download offline.
I did a few demos and I think I know what you want. Just add the current linear velocity to the new linear velocity, like so:

m = own.linearVelocity

#adding new linear velocity
own.setLinearVelocity([the velocity you want + m[0], the velocity you want + m[1], the velocity you want + m[2]], True)

I’ve tried that, actually my script has that still in it at the moment. This solution works great until you try to turn, because the velocity is local, so it turns with it. I looked at the Yo Frankie camera setup, but the problem is that it still slow parents when it turns, I want the camera to only get the slow parent affect when it’s moving on it’s Z axis.

I’ll have to look at the Yo Frankie file again. Are you trying to avoid the:

posit = collision_sensor.getHitPosition()
own.setPosition = posit

That’s what I think about when I think of this script.

To the problem of velocity if you want to ignore any effect when turning you could do:

if not ray.positive:
m = own.linearVelocity

own.worldLinearVelocity = (5.0 + m[0], 0.0 + m[1], 0.0 + m[2]) 

With this script only the WASD keys will work in midair.

I just realized why

own.setLinearVelocity([the velocity you want + m[0], the velocity you want + m[1], the velocity you want + m[2]], True)

didn’t work. It set the linear velocity in a new direction, it wasn’t adding to the existing linear velocity it was just giving a larger number for the new linear velocity.

I think I can solve this by using a little trig, I need to find the sum of the vectors.
I’ll get back to you.

I don’t think I’m explaining what I mean clear enough. Here is a file showing what I have so far, you should be able to see the problems when you jump, turn in midair, then tap a movement key.

You posted while I was posting. I should of thought of using vectors, I look it up too, we’ll see what we can find. I swear I don’t need math classes with all the stuff I learn on the internet.

I think I see what you mean with the movement. I took a look at your code, I bet I could understand it if I really took the time, but you could probably edit it better.

I achieved a movement that looks like my player is on ice by using .localLinearVelocity


m = own.localLinearVelocity

if key.positive:
    own.localLinearVelocity = (5.0 + m[0], 0.0 + m[1], 0.0 + m[2])

I don’t understand what you want with the camera movement.

I tried integrating that into my script, but it behaves the same as with using .getLinearVelocity and .setLinearVelocity. Here is an updated script which you can just replace the old one with. I think fixing this has something to do with .getAxisVect(), but I don’t understand vectors well enough at the moment. The camera thing I can live without, it’s just when you turn so that you should be looking behind a wall, the camera snaps to the wall. I would prefer if it slowly moved to the new position. Thank you for all the help.

import GameLogic as gl

cont = gl.getCurrentController()
own = cont.owner

# Define Sensors
for i in cont.sensors:
    exec(i.name + " = i")
# Define Actuators
for i in cont.actuators:
    exec(i.name + " = i")

#define localSpeed
localSpeed = own.localLinearVelocity

#jumping
if space.positive and nz.positive:
    own.setLinearVelocity([own.getLinearVelocity(True)[0],own.getLinearVelocity(True)[1],7.0],True)
    own['localSpeed1'] = 0
    own['localSpeed2'] = 0

#if you wak off a ledge    
if (own['nzOn'] == 1 and not nz.positive):
    own['localSpeed1'] = own.getLinearVelocity(True)[0]
    own['localSpeed2'] = own.getLinearVelocity(True)[1]
    own['nzOn'] = 0

#if you are on the ground    
if nz.positive:
    own['nzOn'] = 1
    own['speed'] = 10.0
    if not space.positive:
        own['localSpeed1'] = 0
        own['localSpeed2'] = 0
    #set speed if going diagonaly
    if (w.positive and (a.positive or d.positive)) or (s.positive and (a.positive or d.positive)):
        own['speed'] = 7.071068
    #press shift to run
    if shift.positive:
        own['speed'] = 20.0
        #diagonal and shift
        if (w.positive and (a.positive or d.positive)) or (s.positive and (a.positive or d.positive)):
            own['speed'] = 14.142136
#in the air
else:
    own['speed'] = 5
    #diagonal
    if (w.positive and (a.positive or d.positive)) or (s.positive and (a.positive or d.positive)):
            own['speed'] = 3.535534
               
speed = own['speed']
localSpeed1 = own['localSpeed1']
localSpeed2 = own['localSpeed2']

#the actual movement
if not w.positive:
    own.localLinearVelocity=[localSpeed[0],localSpeed2,localSpeed[2]]
    
if not a.positive:
    own.localLinearVelocity=[localSpeed1,localSpeed[1],localSpeed[2]]
    
if not s.positive:
    own.localLinearVelocity=[localSpeed[0],localSpeed2,localSpeed[2]]
    
if not d.positive:
    own.localLinearVelocity=[localSpeed1,localSpeed[1],localSpeed[2]]  

if w.positive:
    own.localLinearVelocity=[localSpeed[0],speed + localSpeed[1],localSpeed[2]]
    
if a.positive:
    own.localLinearVelocity=[-speed + localSpeed[0],localSpeed[1],localSpeed[2]]
    
if s.positive:
    own.localLinearVelocity=[localSpeed[0],-speed + localSpeed[1],localSpeed[2]]
    
if d.positive:
    own.localLinearVelocity=[speed + localSpeed[0],localSpeed[1],localSpeed[2]]

I’ll take a look at your script. My setup was really simple just a cube, a turn logic brick, and that code.

Okay, played around with your file for a while and this is what I got.

movement_problems.blend (541 KB)

I changed a few .getLinearVelocity to .localLinearVelocity. I also changed it so if your in the air localSpeed1 and localSpeed2 are equal to localSpeed[0] and localSpeed[1], respectively. This gives you the ice skating effect I achieved before.

The one problem though is that when your in the air you accelerate to incredible speeds. You must have fixed that before because you can walk around normally but of course you don’t have your character sliding around.

I’m going to bed I’ll look at it more tomorrow.

I think I found a solution. If we get the angle of the local axis to the world axis, we can use that angle and the local velocity we want to calculate the appropriate world velocity. If you look at the last solver on this page, this is what I need to code. I have to go to work, so I will get it coded when I get home(in 3-4 hours).

Okay. I wrote this, this morning.



import GameLogic as gl

cont = gl.getCurrentController()
own = cont.owner

# Define Sensors
for i in cont.sensors:
    exec(i.name + " = i")
# Define Actuators
for i in cont.actuators:
    exec(i.name + " = i")

#define localSpeed
localSpeed = own.localLinearVelocity

#jumping
if space.positive and nz.positive:
    own.setLinearVelocity([own.getLinearVelocity(True)[0],own.getLinearVelocity(True)[1],7.0],True)
    own['localSpeed1'] = 0
    own['localSpeed2'] = 0

#if you wak off a ledge    
if (own['nzOn'] == 1 and not nz.positive):
    own['localSpeed1'] = own.localLinearVelocity[0]
    own['localSpeed2'] = own.localLinearVelocity[1]
    own['nzOn'] = 0

#if you are on the ground    
if nz.positive:
    own['nzOn'] = 1
    own['speed'] = 10.0
    if not space.positive:
        own['localSpeed1'] = 0
        own['localSpeed2'] = 0
    #set speed if going diagonaly
    if (w.positive and (a.positive or d.positive)) or (s.positive and (a.positive or d.positive)):
        own['speed'] = 7.071068
    #press shift to run
    if shift.positive:
        own['speed'] = 20.0
        #diagonal and shift
        if (w.positive and (a.positive or d.positive)) or (s.positive and (a.positive or d.positive)):
            own['speed'] = 14.142136
#in the air
else:
    own['speed'] = 5
    own["localSpeed1"] = localSpeed[0]
    own["localSpeed2"] = localSpeed[1]
    #diagonal
    if (w.positive and (a.positive or d.positive)) or (s.positive and (a.positive or d.positive)):
            own['speed'] = 3.535534

print(own.linearVelocity[1], "speed")

speed = own['speed']
localSpeed1 = own['localSpeed1']
localSpeed2 = own['localSpeed2']

#the actual movement
if not w.positive:
    own.localLinearVelocity=([localSpeed[0],localSpeed2,localSpeed[2]])
    
if not a.positive:
    own.localLinearVelocity=([localSpeed1,localSpeed[1],localSpeed[2]])
    
if not s.positive:
    own.localLinearVelocity=([localSpeed[0],localSpeed2,localSpeed[2]])
    
if not d.positive:
    own.localLinearVelocity=([localSpeed1,localSpeed[1],localSpeed[2]])  

if w.positive:
    #if speed exceeds cap
    #+2 there to ensure smooth movement
    if own.linearVelocity[1] + speed > speed + 2:
        speed = 0
        own.localLinearVelocity=([localSpeed[0],speed + localSpeed[1],localSpeed[2]])
    #otherwise do it normally
    else:
        own.localLinearVelocity=([localSpeed[0],speed + localSpeed[1],localSpeed[2]])
    
if a.positive:
    if own.linearVelocity[0] - speed < -speed - 2:
        speed = 0
        own.localLinearVelocity=([-speed + localSpeed[0],localSpeed[1],localSpeed[2]])
    else:
        own.localLinearVelocity=([-speed + localSpeed[0],localSpeed[1],localSpeed[2]])

if s.positive:
    if own.linearVelocity[1] - speed < -speed - 2:
        speed = 0
        own.localLinearVelocity=([localSpeed[0],-speed + localSpeed[1],localSpeed[2]])
    else:
        own.localLinearVelocity=([localSpeed[0],-speed + localSpeed[1],localSpeed[2]])

if d.positive:
    if own.linearVelocity[0] + speed > speed + 2:
        speed = 0
        own.localLinearVelocity=([speed + localSpeed[0],localSpeed[1],localSpeed[2]])
    else:
         own.localLinearVelocity=([speed + localSpeed[0],localSpeed[1],localSpeed[2]])
   

I think it’s about what you were going to do. I revised the code so it caps the speed while your in the air.

I tried it, but that still doesn’t work. To see what I mean, run forward and jump, then tap “s” in midair. You will see how it completely cancels the forward movement, I want it to keep going forward when you let go of “s”. I will try my idea and see if it actually works.

Got it working, Yay!!! Here is the working code.

import GameLogic as gl
import math as m

cont = gl.getCurrentController()
own = cont.owner

# Define Sensors
for i in cont.sensors:
    exec(i.name + " = i")
# Define Actuators
for i in cont.actuators:
    exec(i.name + " = i")

#define localSpeed
worldSpeed = own.worldLinearVelocity

#vector to y axis
axis = own.getAxisVect([0.0,1.0,0.0])

#angle in degrees to y axis
angle = m.degrees(axis.angle([0.0,1.0,0.0]))

#jumping
if space.positive and nz.positive:
    own.setLinearVelocity([own.getLinearVelocity(True)[0],own.getLinearVelocity(True)[1],7.0],True)
    own['worldSpeed1'] = 0
    own['worldSpeed2'] = 0

#if you wak off a ledge    
if (own['nzOn'] == 1 and not nz.positive):
    own['worldSpeed1'] = own.worldLinearVelocity[0]
    own['worldSpeed2'] = own.worldLinearVelocity[1]
    own['nzOn'] = 0

#if you are on the ground    
if nz.positive:
    own['nzOn'] = 1
    own['speed'] = 10.0
    if not space.positive:
        own['worldSpeed1'] = 0
        own['worldSpeed2'] = 0

    #press shift to run
    if shift.positive:
        own['speed'] = 20.0

#in the air
else:
    own['speed'] = 5
               
speed = own['speed']
worldSpeed1 = own['worldSpeed1']
worldSpeed2 = own['worldSpeed2']

speedA = speed * (m.sin(m.radians(angle)))
speedB = speed * (m.cos(m.radians(angle)))

if w.positive:
    if axis[0] > 0 and axis[1] > 0:
        own.worldLinearVelocity = [worldSpeed1 + speedA,worldSpeed2 + speedB,worldSpeed[2]]

    elif axis[0] > 0 and axis[1] < 0:
        own.worldLinearVelocity = [worldSpeed1 + speedA,worldSpeed2 + speedB,worldSpeed[2]]

    elif axis[0] < 0 and axis[1] < 0:
        own.worldLinearVelocity = [worldSpeed1 - speedA,worldSpeed2 + speedB,worldSpeed[2]]
    
    elif axis[0] < 0 and axis[1] > 0:
        own.worldLinearVelocity = [worldSpeed1 - speedA,worldSpeed2 + speedB,worldSpeed[2]]

elif s.positive:
    if axis[0] > 0 and axis[1] > 0:
        own.worldLinearVelocity = [worldSpeed1 - speedA,worldSpeed2 - speedB,worldSpeed[2]]

    elif axis[0] > 0 and axis[1] < 0:
        own.worldLinearVelocity = [worldSpeed1 - speedA,worldSpeed2 - speedB,worldSpeed[2]]

    elif axis[0] < 0 and axis[1] < 0:
        own.worldLinearVelocity = [worldSpeed1 + speedA,worldSpeed2 - speedB,worldSpeed[2]]
    
    elif axis[0] < 0 and axis[1] > 0:
        own.worldLinearVelocity = [worldSpeed1 + speedA,worldSpeed2 - speedB,worldSpeed[2]]  

elif a.positive:
    if axis[0] > 0 and axis[1] > 0:
        own.worldLinearVelocity = [worldSpeed1 - speedB,worldSpeed2 + speedA,worldSpeed[2]]

    elif axis[0] > 0 and axis[1] < 0:
        own.worldLinearVelocity = [worldSpeed1 - speedB,worldSpeed2 + speedA,worldSpeed[2]]

    elif axis[0] < 0 and axis[1] < 0:
        own.worldLinearVelocity = [worldSpeed1 - speedB,worldSpeed2 - speedA,worldSpeed[2]]
    
    elif axis[0] < 0 and axis[1] > 0:
        own.worldLinearVelocity = [worldSpeed1 - speedB,worldSpeed2 - speedA,worldSpeed[2]] 

elif d.positive:
    if axis[0] > 0 and axis[1] > 0:
        own.worldLinearVelocity = [worldSpeed1 + speedB,worldSpeed2 - speedA,worldSpeed[2]]

    elif axis[0] > 0 and axis[1] < 0:
        own.worldLinearVelocity = [worldSpeed1 + speedB,worldSpeed2 - speedA,worldSpeed[2]]

    elif axis[0] < 0 and axis[1] < 0:
        own.worldLinearVelocity = [worldSpeed1 + speedB,worldSpeed2 + speedA,worldSpeed[2]]
    
    elif axis[0] < 0 and axis[1] > 0:
        own.worldLinearVelocity = [worldSpeed1 + speedB,worldSpeed2 + speedA,worldSpeed[2]]

if not w.positive and not a.positive and not s.positive and not d.positive:
    own.worldLinearVelocity=[worldSpeed1,worldSpeed2,worldSpeed[2]]

Basically it changes the directions to world velocity. Thank you so much for all the help. I’m not worried about the camera thing, I can live without it.

Oh your right. I guess it only slides if your turning and moving forward. I didn’t do much work, if you look at the posts none of my ideas worked.
Didn’t even have to use vectors :slight_smile:

Actually I did have to use vectors to convert from local to world velocities. Even if you didn’t get it working, it still helps to talk things out with people.