Change Position with local not global coordinates in python

In my project I’ve decided that for some animations such as climbing onto objects it would be better to animate the character to do the entire climb and turn off the physics and leave the physics model behind. Once the action is done reposition the physics model and restore the dynamics. Rather than animate in place and mess with actuators to control the motion which looks sloppy and is difficult to guess.

So far I’ve had good success, yet I have one problem. What I’m doing is getting the location of the actor (x,y,z) and adding a set distance to those coordinates. (x,y-3,z+15) then setting the actor on those new coordinates. This works well only when facing one direction. Since the local forward (-y) changes in relation to the global coordinates I need to find a way to add to the local location instead of the global. Is there a way that anyone knows or should I do something different?

here is my script:

import GameLogic as g

c = g.getCurrentController()
o = c.getOwner()

alwys = c.getSensor(“alwys”)
climb = c.getActuator(“climbing”) #the climbing animation
forward = c.getActuator(“climbForward”) #not used
dyn = c.getActuator(“startDyn”) #restore dynamics
state = c.getActuator(“normalState”) #return to normal state
ac = c.getActuator(“ac”) #the “after climb” animation

firstFrame = climb.getStart()
lastFrame = climb.getEnd()
curFrame = climb.getFrame()

Up = 15 #how far to move up
Forward = -3 #how far to move forward

g.base = o.getPosition()

add = g.base
add[1] = g.base[1] + Forward # add to Y
add[2] = g.base[2] + Up # add to Z

#begin
if alwys.isPositive():
g.addActiveActuator(climb, 1)

if curFrame >= lastFrame-1:
g.addActiveActuator(climb, 0)
o.setPosition(add)
g.addActiveActuator(ac, 1)
g.addActiveActuator( dyn, 1)
g.addActiveActuator(state, 1)

one simple but not really efficient way to do it might be to: if say, he’s climbing onto a large rock, check the rock’s position, and set him to that position but with a higher z value.
x,y,z = rock.position
player.position = [x,y,z+2]

the more complex mathematical way would be to look at the orientation matrix, see where the y axis of the player is pointing, and move according to that. (If you’re not familiar with oprientation matrices, then I apologize for this not making sense.)

def localmoveyaxis(player,distance):
	yaxisofplayer = player.orientation[1]
	dx,dy,dz = yaxisofplayer
	dx *= distance
	dy *= distance
	dz *= distance
	#
	x,y,z = player.position
	player.position = [x+dx,y+dy,z+dz]

localmoveyaxis(player,-3)

That’s untested, but I think it’s right for what you want…
Also, there’s probably a simple way to do this with something like object.applyMovement() but I like my way

I think that’s what I’m looking for! Both methods are useful but the code is what I really need, though I can use the other for less precise things.

hi alaseridan,

From your code, I noticed that you are still using Blender 2.48.

Blender 2.49 added KX_GameObject variables that let you choose whether to use global or local position/orientation/scale.

localOrientation – worldOrientation
localPosition – worldPosition
localScale – worldScale

Link to KX_GameObject functions

Clark

I am using the new blender I just havn’t looked at the new python yet. But this is much simpler!