Limiting the terrain that an actor can walk on

To simplify the calculation, I prefer using P3D’s nodepath relative transform mechanism.
Here it is, without using Terrain.egg :

import direct.directbase.DirectStart 
from direct.showbase.DirectObject import DirectObject 
from pandac.PandaModules import *
import os


class Game(DirectObject): 
  def __init__(self): 
    base.disableMouse() 
    
    terrainSize = 512.
    cm = CardMaker('')
    cm.setFrame(-terrainSize,0, -terrainSize,0)
    self.card = render.attachNewNode(cm.generate())
    self.card.setTexture(loader.loadTexture('Terrain.png'))
    base.camera.setPos(self.card.getBounds().getCenter())
    self.card.setY(1000)
    
    self.dude = loader.loadModel("panda.egg")
    self.dude.reparentTo(base.camera)
    self.dude.setColor(1,0,0,1)
    self.dude.setY(100)
    
    self.image = PNMImage()
    self.image.read("Terrain.png")
    self.imgSize = self.image.getXSize()
    
    self.keyMap = {  "w" : False,
            "s" : False,
            "a" : False,
            "d" : False }
    
    self.accept("escape", os._exit,[0])
    for key in self.keyMap.keys():
        self.accept(key, self.keyMap.__setitem__, [key, True])
        self.accept(key+"-up", self.keyMap.__setitem__, [key, False])
    
    taskMgr.add(self.moveTask, "Move Task")
    
    self.conversionNP = render.attachNewNode('')
    minb, maxb = self.card.getTightBounds()
    self.conversionNP.setPos(minb.x,0,maxb.z)
    self.conversionNP.setScale(terrainSize/self.imgSize,1,-terrainSize/self.imgSize)
    
  def moveTask(self, task):
    dt = globalClock.getDt()
    if (dt > .05):
      return task.cont

    newCamPos = base.camera.getPos()

    if self.keyMap["w"]:
      newCamPos += Point3(0,0, dt * 100)
    elif self.keyMap["s"]:
      newCamPos += Point3(0,0, dt * -100)

    if self.keyMap["a"]:
      newCamPos += Point3(dt * -100, 0,0)
    elif self.keyMap["d"]:
      newCamPos += Point3(dt * 100, 0,0)

    imageX,imageY = self.conversionNP.getRelativePoint(render,newCamPos).xz
    if 0<imageX<self.imgSize and 0<imageY<self.imgSize:
        bright = self.image.getBright(int(imageX), int(imageY))
        if(bright < .5):
          base.camera.setPos(newCamPos)

    return task.cont

g = Game()
run()

Change the terrain size and origin as you like, the result remains correct.