This won’t work verbatim because it relies on some other code, but hopefully it’s clear how everything works. I’ll try to answer questions if you have any. This works best fullscreen - I had some problems getting it to work the way I wanted in a window.
import settings
from direct.showbase.DirectObject import DirectObject
from panda3d.core import VBase3
class RTS_Camera( DirectObject ):
def __init__(self):
self.floater = render.attachNewNode('cam_floater') # Camera looks at this node to create an angle
self.tolerance = 10 # How many pixels from the edge of the window
self.cameraMoveDist = 14 # How many units to move the camera
self.cameraZoomDist = 4 # How many units to zoom the camera
self.cameraZBounds = [4, 60] # Lower and upper bounds of camera height
base.disableMouse() # Turn off default mouse control
base.camera.setPos(0, -10, 15) # Default camera position
base.camera.lookAt(self.floater) # Make the camera look at the floater (creates angle)
self.accept( 'wheel_up', self.zoom, [1] ) # Listen for mouse scrolling
self.accept( 'wheel_down', self.zoom, [-1] ) # for zooming
# This gets run every frame by the game engine.
# Here we find the position of the cursor - if it is
# near the edges of the screen (within a tolerance),
# we will update the position of the camera
def handleMouseInput(self):
movementDirection = VBase3(0, 0, 0) # Which direction to move the camera
# Get the position of the cursor if it is in the window
if( base.mouseWatcherNode.hasMouse() ):
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 > settings.WIDTH ):
movementDirection.setX(1)
elif( x < self.tolerance ):
movementDirection.setX(-1)
if( y + self.tolerance > settings.HEIGHT ):
movementDirection.setY(-1)
elif( y < self.tolerance ):
movementDirection.setY(1)
self.moveCamera( movementDirection )
def moveCamera(self, dir):
deltaPos = dir * self.cameraMoveDist * globalClock.getDt()
self.floater.setPos( self.floater.getPos() + deltaPos )
base.camera.setPos( base.camera.getPos() + deltaPos )
# 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 = self.floater.getPos() - base.camera.getPos()
camToFloater.normalize()
camToFloater *= dir * self.cameraZoomDist
newPos = base.camera.getPos() + camToFloater
z = newPos.getZ()
if( z < self.cameraZBounds[1] and z > self.cameraZBounds[0]):
base.camera.setPos(newPos)