Hi All, thanks in advance for any help anyone can offer.
I’m modifying the rts scroller camera from this post:
[Real-Time Strategy Camera)
I’ve got it setup almost entirely except for one problem. I am scrolling over a 3d mesh (flat plane for now) that is 128X128 and centered on the origin. Scrolling works fine, zooming works fine, but my clamping system needs to be improved. I obviously don’t want to over scroll the mesh, so I calculate the center of my scene and clamp my X and Y camera position to be within the map size, shifted by the distance of my zoom and angle of camera view. This works fine. I am clamping successfully, but only based on the coordinate at the center of my screen. What I really need to do is clamp based when my viewable area will display outside of my ground plane. This number can be thought of my as current clamp coords minus 1/2 of a screen in any direction.
Basically I need to know how to calculate how many units in 3d space == 1/2 a 2d screen, or I need a new approach for clamping to my groundplane.
Here is my code:
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import VBase3, Point2, Point3
from math import tan, radians
class gamecam(DirectObject):
def __init__(self):
self._gameCam = base.cam
base.camLens.setFov(40.0)
base.camLens.setFocalLength(35.0)
self._gameCam.setPos(0,0,30)
self.tolerance = 35 # How many pixels from the edge of the window
self.cameraMoveDist = 14 # How many units to move the camera
self.cameraZBounds = [25, 60]
self.cameraXBounds = [-64,64]
self.cameraYBounds = [-64,64]
#base.disableMouse()
self._gameCam.lookAt(0,15,0) # Make the camera look at the floater (creates angle)
taskMgr.add(self.handleMouseInput,"mouse_scroll")
self.accept( 'wheel_up', self.zoom, [1] ) # Listen for mouse scrolling
self.accept( 'wheel_down', self.zoom, [-1] ) # for zooming
def handleMouseInput(self, task):
# Get the position of the cursor if it is in the window
if( base.mouseWatcherNode.hasMouse() ):
movementDirection = VBase3(0, 0, 0) # Which direction to move the camera
md = base.win.getPointer(0)
x = md.getX()
y = md.getY()
# If the cursor is on the edges, move the camera
if( x + self.tolerance > 640 ):
movementDirection.setX(1)
elif( x < self.tolerance ):
movementDirection.setX(-1)
if( y + self.tolerance > 480 ):
movementDirection.setY(-1)
elif( y < self.tolerance ):
movementDirection.setY(1)
if movementDirection.x != 0 or movementDirection.y !=0:
self.moveCamera( movementDirection )
return task.cont
def moveCamera(self, dir):
deltaPos = dir * self.cameraMoveDist * globalClock.getDt()
cpos = self._gameCam.getPos() + deltaPos
zoomModifiedBound = tan(radians(26.5651)) * self._gameCam.getPos().getZ() #This num is specific to this: self._gameCam.lookAt(0,15,0).
cpos.x = min (max(cpos.x, self.cameraXBounds[0]),self.cameraXBounds[1])
cpos.y = min (max(cpos.y, self.cameraYBounds[0] - zoomModifiedBound),self.cameraYBounds[1] - zoomModifiedBound)
self._gameCam.setPos( cpos )
# Determines the vector from the camera to the floater and moves the
# camera closer to or farther from the floater along the vector
def zoom(self, dir):
camToFloater = VBase3(0, 0.15,0) - VBase3(0,0,0.30)
camToFloater *= dir
newPos = self._gameCam.getPos() + camToFloater
z = newPos.getZ()
if( z < self.cameraZBounds[1] and z > self.cameraZBounds[0]):
self._gameCam.setPos(newPos)
def setXBounds(self, arr2):
self.cameraXBounds = arr2
def setYBounds(self, arr2):
self.cameraYBounds = arr2