Perhaps something like this :
from pandac.PandaModules import *
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.interval.IntervalGlobal import *
from direct.actor.Actor import Actor
from direct.task import Task
import sys, types
base.cTrav = CollisionTraverser()
base.cTrav.setRespectPrevTransform(True)
BIT_OFF = BitMask32.allOff()
BIT_BODY = BitMask32.bit(1)
BIT_LEVEL = BitMask32.bit(2)
BIT_STUFF = BitMask32.bit(3)
SPEED=5
FWD=Vec3(0,1,0)
BWD=Vec3(0,-1,0)
LF=Vec3(-1,0,0)
RG=Vec3(1,0,0)
KEY_REG={}
def registerKey(key):
if type(key)==types.TupleType:
for k in key:
registerKey(k)
else:
if len(key)==1:
kb=KeyboardButton.asciiKey(key)
else:
if key=='del': key='_del'
kb=getattr(KeyboardButton,key)()
KEY_REG[key]=kb
def keyDown(key):
return base.mouseWatcherNode.isButtonDown(KEY_REG[key])
def loop(task):
dt=globalClock.getDt()
if dt>.02:
return Task.cont
vec=Vec3(0)
if keyDown('w'): vec+=FWD
if keyDown('s'): vec+=BWD
if keyDown('a'): vec+=LF
if keyDown('d'): vec+=RG
md = base.win.getPointer(0)
x = md.getX()
y = md.getY()
if base.win.movePointer(0, winXhalf, winYhalf):
avatar.setH(avatar, (x - winXhalf)*-0.1)
TPScam.setP( clampScalar(-80,80, TPScam.getP() - (y - winYhalf)*0.1) )
avatar.setFluidPos(avatar,vec*SPEED*dt)
camera.setFluidPos(camPos)
return Task.cont
def setTo1stCam(entry):
Sequence(
LerpFunc( camPos.setY, duration=.5,
fromData=camera.getY(),toData=.25, blendType='easeInOut'),
Func(avatar.hide),
LerpFunc( camPos.setX, duration=.5,
fromData=camera.getX(),toData=0, blendType='easeOut'),
).start()
print '1st cam'
def setTo3rdCam(entry):
Sequence(
LerpFunc( camPos.setX, duration=.15,
fromData=camera.getX(),toData=camPos3rd[0]),
Func(avatar.show),
LerpFunc( camPos.setY, duration=.5,
fromData=camera.getY(),toData=camPos3rd[1], blendType='easeInOut'),
).start()
print '3rd cam'
roomScale=35
wallHeight=.35
CM=CardMaker('')
CM.setFrame(-.5,.5,0,wallHeight)
room=render.attachNewNode('')
# walls
room.attachNewNode(CM.generate())
room.attachNewNode(CM.generate()).setH(180)
room.attachNewNode(CM.generate()).setH(90)
room.attachNewNode(CM.generate()).setH(-90)
floorTex=loader.loadTexture('maps/grid.rgb')
floorTex.setMinfilter(Texture.FTLinearMipmapLinear)
floorTex.setMagfilter(Texture.FTLinearMipmapLinear)
wallTex=loader.loadTexture('maps/lilsmiley.rgba')
wallTex.setMinfilter(Texture.FTLinearMipmapLinear)
for wall in room.getChildrenAsList():
wall.setY(wall,.5)
wall.setTexture(wallTex)
wall.setTexScale(TextureStage.getDefault(),roomScale,wallHeight*roomScale)
# floor
CM.setFrame(-.5,.5,-.5,.5)
floor=room.attachNewNode(CM.generate())
floor.setTexture(floorTex)
floor.setP(-90)
room.setScale(roomScale)
room.setTransparency(TransparencyAttrib.MAlpha)
room.setTwoSided(1)
room.flattenLight()
room.setCollideMask(BIT_LEVEL)
avatar=render.attachNewNode('avatar')
avatar.setPos(-12,-12,0)
avatar.setH(-30)
panda=Actor('panda',{'walk':'panda-walk'})
panda.reparentTo(avatar)
# print panda.getTightBounds()
panda.setScale(.15)
panda.setH(180)
panda.flattenLight()
panda.loop('walk')
# setup collisions for avatar and camera
bodyRadius=.7
reachRadius=10
avatarSphere=avatar.attachCollisionSphere( 'avatarBody', 0,.2,bodyRadius,bodyRadius,
BIT_LEVEL|BIT_STUFF, BIT_BODY)
avatarReach=avatar.attachCollisionSphere( 'reach', 0,0,0,reachRadius,
BIT_STUFF, BIT_OFF)
TPScam=avatar.attachNewNode('')
TPScam.setZ(1.5)
TPScamSphere=camera.attachCollisionSphere( 'camSphere', 0,0,0,.2,
BIT_LEVEL|BIT_BODY, BIT_OFF)
camPos3rd=Point3(0.43, -3, 0)
# wrap it so we get a brand new Point3,
# to avoid accidentally modifying the original camPos3rd
camPos=Point3(camPos3rd)
camera.reparentTo(TPScam)
camera.setPos(camPos)
pandaPUSHER = CollisionHandlerPusher()
pandaPUSHER.addCollider(avatarSphere,avatar)
base.cTrav.addCollider(avatarSphere,pandaPUSHER)
camPUSHER = CollisionHandlerPusher()
camPUSHER.addCollider(TPScamSphere,camera)
camPUSHER.setHorizontal(0)
base.cTrav.addCollider(TPScamSphere,camPUSHER)
reachEvent = CollisionHandlerEvent()
reachEvent.addInPattern('%fn-in')
reachEvent.addOutPattern('%fn-out')
base.cTrav.addCollider(avatarReach,reachEvent)
# load objects
panda4=loader.loadModel('panda-model')
panda4.reparentTo(render)
panda4.setPos(8,8,0)
panda4.setScale(.003)
bc=panda4.getBounds().getCenter()
b3=panda4.getTightBounds()
dims=b3[1]-b3[0]
panda4.getParent().attachCollisionSphere( 'objSphere', bc[0],bc[1],bc[2],
.5*max(dims[0],dims[1],dims[2]),
BIT_OFF,BIT_STUFF).wrtReparentTo(panda4)
winXhalf=.5*base.win.getXSize()
winYhalf=.5*base.win.getYSize()
registerKey( ('w','s','a','d') )
DO=DirectObject()
DO.accept('escape',sys.exit)
DO.accept('reach-in',setTo1stCam)
DO.accept('reach-out',setTo3rdCam)
taskMgr.add(loop,'loop')
base.camLens.setNearFar(.1,100000)
base.camLens.setFov(80)
base.disableMouse()
#~ render.showCS()
# user may moves the pointer during loading, so put it to the rest position
base.win.movePointer(0, winXhalf, winYhalf)
run()
The camera is also pushed by the wall.