Trouble rotating actor

I have created a basic movable player and a camera. Player moves with “W” “A” “S” and “D”. When I try to rotate the player model in order to face the direction that he’s walking, the player model moves away from the camera.

But if you comment out


at the line marked “#PROBLEM” in, the player moves fine. Any help would be appreciated.

import direct.directbase.DirectStart
from import Actor
from direct.task import Task

from pandac.PandaModules import *

# my modules
import keyEvents
class playableChar():
	def __init__(self, child):
		# Direction constants
		self.UP = 1
		self.DOWN = 2
		self.LEFT = 3
		self.RIGHT = 4
		# Actor or Model that this object will handle
		self.__child = child
		# Handle animation
			self.__animName = self.__child.getCurrentAnim()
			self.__animCtl = self.__child.getAnimControl(self.__animName)
		except AttributeError:
			self.__animCtl = None
		# internal dummy node
		self.__dummyNode = render.attachNewNode('dummyNode') 
		# public dummy node
		self.publicNode = self.__dummyNode.attachNewNode('publicNode')

		self.direction = self.DOWN
	def move(self, toMove):			
		moveTable = {
			"move-left" 	: {'pos':(-0.5, 0.0, 0.0),	'h':-90, 	'dir':self.LEFT},
			"move-right"	: {'pos':(0.5, 0.0, 0.0), 	'h':90, 	'dir':self.RIGHT},
			"move-up"		: {'pos':(0.0, -0.5, 0.0), 	'h':180, 	'dir':self.UP},
			"move-down"		: {'pos':(0.0, 0.5, 0.0), 	'h':0, 		'dir':self.DOWN}
		# Rotate model, if he is not facing the correct direction
		if self.direction != moveTable[toMove]['dir']:
			self.direction = moveTable[toMove]['dir']
			coord = moveTable[toMove]['h']
			self.publicNode.setH(coord)  # PROBLEM
		coords = moveTable[toMove]['pos']
		self.publicNode.setPos(self.publicNode, coords[0], coords[1], coords[2])
	def acceptCam(self, camera):
		""" 'Accept' a playerCam() object as a sort of 'child node' """
		self.__camera = camera
	def getCam(self):
		return self.__camera
	def disableCam(self):
		self.__camera = None
	def playAnimation(self):
		if self.__animCtl != None:
	def pauseAnimation(self):
		if self.__animCtl != None:
class playerCam():
	def __init__(self, player, = camera
		self.__player = player
		self.enabled = False
	def enable(self):
		if self.enabled == False:, -16, 0), -25, 12)
			self.enabled = True
	def disable(self):
		if self.enabled == True:, -16, 0), -25, 12)	
			self.enabled = False
	def doParent(self):		
		# "Attach" the camera to the player object
	def noParent(self):

# load the base panda
pandaObj = Actor.Actor("models/panda-model", {"animate" : "models/panda-walk4"})
pandaObj.setPos(0, 0, 0)

# key response handler
kh = keyEvents.keyHandler()

# moveable player
player = playableChar(pandaObj)
playerAnim = False
playerWalking = False

# camera
cam = playerCam(player)

def gameLoop(task):
	global playerAnim, playerWalking
	playerWalking = False
	for key, pressed in kh.keyStates.iteritems():
		if pressed == True:
			cmd = kh.controls[key]
			playerWalking = True
	if playerWalking == True:
		if playerAnim == False:
			playerAnim = True
		if playerAnim == True:
			playerAnim = False
	return Task.cont

taskMgr.add(gameLoop, "gameLoop")

from direct.showbase.DirectObject import DirectObject
import sys

class keyHandler(DirectObject):
	def __init__(self):
		self.accept("escape", sys.exit)
		self.controls = {
			"a"	: "move-left",
			"w"	: "move-up",
			"d"	: "move-right",
			"s"	: "move-down"
		# at start, no key is active
		self.keyStates = {}
		for key in self.controls:
			self.keyStates[key] = 0
		# go through keys and 'accept' them
		for key, action in self.controls.items():
			self.accept(key, self.chKeyState, [key, True])
			self.accept(key+"-up", self.chKeyState, [key, False])
	def chKeyState(self, key, pressed):
		print("%s is %s" % (key, (pressed==True and "pressed" or "released"))) 
		self.keyStates[key] = pressed


Your problem lies in the combination of these two lines:

moveTable = {
         "move-left"    : {'pos':(-0.5, 0.0, 0.0),   'h':-90,    'dir':self.LEFT},
         "move-right"   : {'pos':(0.5, 0.0, 0.0),    'h':90,    'dir':self.RIGHT},
         "move-up"      : {'pos':(0.0, -0.5, 0.0),    'h':180,    'dir':self.UP},
         "move-down"      : {'pos':(0.0, 0.5, 0.0),    'h':0,       'dir':self.DOWN}


self.publicNode.setPos(self.publicNode, coords[0], coords[1], coords[2])

The problem is that when you want to move say left, your ‘pos’ argument gives a negative x component (which would be correct from the global standpoint) but you change your position with a relative assignment. If you want your character to rotate first, then walk in his relative forward direction, change all of your pos’s to (0,5,0). When you disabled the rotation, he suddenly moved correctly because when you wanted him to walk left he would sidestep left.

Hope that helps!

PS: I like the use of the self.controls dictionary in your to act as an intermediary between the event and the passed function - I will be shamelessly stealing it to make an easy user preferences system (unless you have strong objections). That said, nested dictionaries in move and the combo of public/private nodes seems rather complicated for the task at hand?