1. The first step to using a key map is to actually create the dictionary that serves the purpose. Right after the line that calls self.cycle.setPos() method in the __init__ method, insert the following block of code to create the dictionary:
    self.keyMap = {"w" : False,
    "s" : False,
    "a" : False,
    "d" : False}
    
  2. Now we need to register events for the four keys in our key map. Replace the current self.accept() call, with the following code:
    self.accept("w", self.setKey, ["w", True])
    self.accept("s", self.setKey, ["s", True])
    self.accept("a", self.setKey, ["a", True])
    self.accept("d", self.setKey, ["d", True])
    self.accept("w-up", self.setKey, ["w", False])
    self.accept("s-up", self.setKey, ["s", False])
    self.accept("a-up", self.setKey, ["a", False])
    self.accept("d-up", self.setKey, ["d", False])
    
  3. Next, we need to change our setKey() method to look like this:
    def setKey(self, key, value):
    self.keyMap[key] = value
    
  4. The key map is ready to go but we won't get any results at this point because we aren't using the key map for anything. To fix that, change the line where we add the cycleMove1() method to the task manager from a taskMgr.doMethodLater () call to a taskMgr.add() call and rename the method it uses.
    taskMgr.add(self.cycleControl, "Cycle Control"
    
  5. Scroll down to the cycleMove1() method and change its name to cycleControl. We'll also add an if statement to this method.
    if(self.keyMap["w"] == True):
    self.cycle.setY(self.cycle, 10 * dt)
    
  6. Our code should look like the following one when we're done:
    import direct.directbase.DirectStart
    from direct.showbase.DirectObject import DirectObject
    class World(DirectObject):
    def __init__(self):
    base.setBackgroundColor(0, 0, 0)
    self.track = loader.loadModel("../Models/Track.egg")
    self.track.reparentTo(render)
    self.track.setPos(0,0,-5)
    self.cycle = loader.loadModel("../Models/Cycle.bam")
    self.cycle.reparentTo(render)
    self.cycle.setPos(2,15,0)
    self.keyMap = {"w" : False,
    "s" : False,
    "a" : False,
    "d" : False}
    taskMgr.add(self.cycleControl, "Cycle Control")
    taskMgr.doMethodLater(10, self.debugTask, "Debug Task")
    self.accept("w", self.setKey, ["w", True])
    self.accept("s", self.setKey, ["s", True])
    self.accept("a", self.setKey, ["a", True])
    self.accept("d", self.setKey, ["d", True])
    self.accept("w-up", self.setKey, ["w", False])
    self.accept("s-up", self.setKey, ["s", False])
    self.accept("a-up", self.setKey, ["a", False])
    self.accept("d-up", self.setKey, ["d", False])
    def setKey(self, key, value):
    self.keyMap[key] = value
    def cycleControl(self, task):
    dt = globalClock.getDt()
    if( dt > .20):
    return task.cont
    if(self.keyMap["w"] == True):
    self.cycle.setY(self.cycle, 10 * dt)
    return task.cont
    def debugTask(self, task):
    print(taskMgr)
    taskMgr.removeTasksMatching("Cycle Move *")
    return task.again
    w = World()
    run()
    
  7. After doing all that, save the file as chp04_02.py and run it. While it's running press the W key and hold it for a second or two. Note that the Panda3D window needs to have focus to respond to keyboard input. If you click on another window or Alt+Tab for another window, the game won't respond to the keyboard anymore.
Time for action - creating and using a key map