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.