ghost mode

This commit is contained in:
Dave Schuyler 2003-12-11 00:16:56 +00:00
parent a7d9badea0
commit 5a713cbba9
4 changed files with 108 additions and 71 deletions

View File

@ -6,6 +6,7 @@ from ShowBaseGlobal import *
import Avatar import Avatar
import DirectNotifyGlobal import DirectNotifyGlobal
import GhostWalker
import GravityWalker import GravityWalker
import NonPhysicsWalker import NonPhysicsWalker
import PhysicsWalker import PhysicsWalker
@ -21,7 +22,10 @@ class ControlManager:
def __init__(self, avatar): def __init__(self, avatar):
self.avatar = avatar self.avatar = avatar
assert(self.debugPrint("ControlManager()")) assert(self.debugPrint("ControlManager()"))
self.swimControls=NonPhysicsWalker.NonPhysicsWalker() self.swimControls=GravityWalker.GravityWalker(
gravity = -32.1740 * 2.0)
#self.swimControls=NonPhysicsWalker.NonPhysicsWalker()
self.ghostControls=GhostWalker.GhostWalker()
if self.wantAvatarPhysics: if self.wantAvatarPhysics:
self.walkControls=GravityWalker.GravityWalker( self.walkControls=GravityWalker.GravityWalker(
gravity = -32.1740 * 2.0) # * 2.0 is a hack; gravity = -32.1740 * 2.0) # * 2.0 is a hack;
@ -57,6 +61,7 @@ class ControlManager:
inputState.watch("jump", "alt-control", "alt-control-up") inputState.watch("jump", "alt-control", "alt-control-up")
inputState.watch("jump", "shift-control", "shift-control-up") inputState.watch("jump", "shift-control", "shift-control-up")
# FYI, ghost mode uses jump for slide.
inputState.watch("slide", "slide-is-disabled", "slide-is-disabled") inputState.watch("slide", "slide-is-disabled", "slide-is-disabled")
#inputState.watch("slideLeft", "shift-arrow_left", "shift-arrow_left-up") #inputState.watch("slideLeft", "shift-arrow_left", "shift-arrow_left-up")
@ -71,6 +76,24 @@ class ControlManager:
#inputState.watch("slideRight", "shift-arrow_right", "shift-arrow_right-up") #inputState.watch("slideRight", "shift-arrow_right", "shift-arrow_right-up")
inputState.watch("slideRight", "slide-is-disabled", "slide-is-disabled") inputState.watch("slideRight", "slide-is-disabled", "slide-is-disabled")
def add(self, controls, name="basic"):
controls = self.controls.get(name)
if controls is not None:
print "Replacing controls:", name
controls.delete()
self.controls[name] = controls
def use(self, name="basic"):
controls = self.controls.get(name)
if controls is not None:
if controls is not self.currentControls:
self.currentControls.disableAvatarControls()
self.currentControls.setCollisionsActive(0)
self.currentControls = controls
self.currentControls.setCollisionsActive(1)
else:
print "Unkown controls:", name
def useSwimControls(self): def useSwimControls(self):
assert(self.debugPrint("useSwimControls()")) assert(self.debugPrint("useSwimControls()"))
if self.currentControls is not self.swimControls: if self.currentControls is not self.swimControls:
@ -81,6 +104,16 @@ class ControlManager:
if self.isEnabled: if self.isEnabled:
self.currentControls.enableAvatarControls() self.currentControls.enableAvatarControls()
def useGhostControls(self):
assert(self.debugPrint("useGhostControls()"))
if self.currentControls is not self.ghostControls:
self.currentControls.disableAvatarControls()
self.currentControls.setCollisionsActive(0)
self.ghostControls.setCollisionsActive(1)
self.currentControls = self.ghostControls
if self.isEnabled:
self.currentControls.enableAvatarControls()
def useWalkControls(self): def useWalkControls(self):
assert(self.debugPrint("useWalkControls()")) assert(self.debugPrint("useWalkControls()"))
if self.currentControls is not self.walkControls: if self.currentControls is not self.walkControls:
@ -106,6 +139,11 @@ class ControlManager:
toonJumpForce, toonJumpForce,
toonReverseSpeed, toonReverseSpeed,
toonRotateSpeed) toonRotateSpeed)
self.ghostControls.setWalkSpeed(
toonForwardSpeed,
toonJumpForce,
toonReverseSpeed,
toonRotateSpeed)
self.walkControls.setWalkSpeed( self.walkControls.setWalkSpeed(
toonForwardSpeed, toonForwardSpeed,
toonJumpForce, toonJumpForce,
@ -116,7 +154,7 @@ class ControlManager:
return self.currentControls.getSpeeds() return self.currentControls.getSpeeds()
def initializeCollisions(self, cTrav, def initializeCollisions(self, cTrav,
wallBitmask, floorBitmask, avatarRadius, floorOffset): wallBitmask, floorBitmask, ghostBitMask, avatarRadius, floorOffset):
assert(self.debugPrint("initializeCollisions()")) assert(self.debugPrint("initializeCollisions()"))
self.walkControls.initializeCollisions(cTrav, self.avatar, self.walkControls.initializeCollisions(cTrav, self.avatar,
@ -130,6 +168,12 @@ class ControlManager:
self.swimControls.setAirborneHeightFunc(self.avatar.getAirborneHeight) self.swimControls.setAirborneHeightFunc(self.avatar.getAirborneHeight)
self.swimControls.disableAvatarControls() self.swimControls.disableAvatarControls()
self.swimControls.setCollisionsActive(0) self.swimControls.setCollisionsActive(0)
self.ghostControls.initializeCollisions(cTrav, self.avatar,
ghostBitMask, floorBitmask, avatarRadius, floorOffset)
self.ghostControls.setAirborneHeightFunc(self.avatar.getAirborneHeight)
self.ghostControls.disableAvatarControls()
self.ghostControls.setCollisionsActive(0)
self.walkControls.setCollisionsActive(1) self.walkControls.setCollisionsActive(1)
self.walkControls.enableAvatarControls() self.walkControls.enableAvatarControls()
@ -138,6 +182,7 @@ class ControlManager:
assert(self.debugPrint("deleteCollisions()")) assert(self.debugPrint("deleteCollisions()"))
self.walkControls.deleteCollisions() self.walkControls.deleteCollisions()
self.swimControls.deleteCollisions() self.swimControls.deleteCollisions()
self.ghostControls.deleteCollisions()
def collisionsOn(self): def collisionsOn(self):
assert(self.debugPrint("collisionsOn()")) assert(self.debugPrint("collisionsOn()"))

View File

@ -23,53 +23,5 @@ class GhostWalker(NonPhysicsWalker.NonPhysicsWalker):
notify = DirectNotifyGlobal.directNotify.newCategory("GhostWalker") notify = DirectNotifyGlobal.directNotify.newCategory("GhostWalker")
def handleAvatarControls(self, task): # Ghosts slide instead of jump:
""" slideName = "jump"
Check on the arrow keys and update the avatar.
"""
# get the button states:
forward = inputState.isSet("forward")
reverse = inputState.isSet("reverse")
turnLeft = inputState.isSet("turnLeft")
turnRight = inputState.isSet("turnRight")
# Ghosts slide instead of jump:
slide = inputState.isSet("jump")
# Determine what the speeds are based on the buttons:
self.speed=(forward and self.avatarControlForwardSpeed or
reverse and -self.avatarControlReverseSpeed)
# Should fSlide be renamed slideButton?
self.slideSpeed=slide and (
(turnLeft and -self.avatarControlForwardSpeed) or
(turnRight and self.avatarControlForwardSpeed))
self.rotationSpeed=not slide and (
(turnLeft and self.avatarControlRotateSpeed) or
(turnRight and -self.avatarControlRotateSpeed))
# How far did we move based on the amount of time elapsed?
dt=min(ClockObject.getGlobalClock().getDt(), 0.1)
# Check to see if we're moving at all:
if self.speed or self.slideSpeed or self.rotationSpeed:
if self.stopThisFrame:
distance = 0.0
slideDistance = 0.0
rotation = 0.0
self.stopThisFrame = 0
else:
distance = dt * self.speed
slideDistance = dt * self.slideSpeed
rotation = dt * self.rotationSpeed
# Take a step in the direction of our previous heading.
self.vel=Vec3(Vec3.forward() * distance +
Vec3.right() * slideDistance)
if self.vel != Vec3.zero():
# rotMat is the rotation matrix corresponding to
# our previous heading.
rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
step=rotMat.xform(self.vel)
self.avatarNodePath.setFluidPos(Point3(self.avatarNodePath.getPos()+step))
self.avatarNodePath.setH(self.avatarNodePath.getH()+rotation)
messenger.send("avatarMoving")
else:
self.vel.set(0.0, 0.0, 0.0)
return Task.cont

View File

@ -39,6 +39,11 @@ class GravityWalker(DirectObject.DirectObject):
self.mayJump = 1 self.mayJump = 1
self.jumpDelayTask = None self.jumpDelayTask = None
self.controlsTask = None
self.fixCliffTask = None
self.indicatorTask = None
self.falling = 0 self.falling = 0
self.needToDeltaPos = 0 self.needToDeltaPos = 0
self.physVelocityIndicator=None self.physVelocityIndicator=None
@ -149,7 +154,7 @@ class GravityWalker(DirectObject.DirectObject):
""" """
# This is a sphere on the ground to detect barrier collisions # This is a sphere on the ground to detect barrier collisions
self.avatarRadius = avatarRadius self.avatarRadius = avatarRadius
self.cSphere = CollisionSphere(0.0, 0.0, avatarRadius, avatarRadius) self.cSphere = CollisionSphere(0.0, 0.0, avatarRadius+0.5, avatarRadius)
cSphereNode = CollisionNode('GW.cWallSphereNode') cSphereNode = CollisionNode('GW.cWallSphereNode')
cSphereNode.addSolid(self.cSphere) cSphereNode.addSolid(self.cSphere)
cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode) cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
@ -159,8 +164,8 @@ class GravityWalker(DirectObject.DirectObject):
# set up collision mechanism # set up collision mechanism
handler = CollisionHandlerPusher() handler = CollisionHandlerPusher()
handler.setInPattern("enter%in") handler.setInPattern("pusher_enter%in")
handler.setOutPattern("exit%in") handler.setOutPattern("pusher_exit%in")
handler.addCollider(cSphereNodePath, self.avatarNodePath) handler.addCollider(cSphereNodePath, self.avatarNodePath)
self.pusher = handler self.pusher = handler
@ -172,7 +177,7 @@ class GravityWalker(DirectObject.DirectObject):
""" """
# This is a sphere on the ground to detect barrier collisions # This is a sphere on the ground to detect barrier collisions
self.avatarRadius = avatarRadius self.avatarRadius = avatarRadius
self.cSphere = CollisionSphere(0.0, 0.0, avatarRadius-0.1, avatarRadius) self.cSphere = CollisionSphere(0.0, 0.0, avatarRadius-0.1, avatarRadius*1.04)
cSphereNode = CollisionNode('GW.cFloorSphereNode') cSphereNode = CollisionNode('GW.cFloorSphereNode')
cSphereNode.addSolid(self.cSphere) cSphereNode.addSolid(self.cSphere)
cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode) cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
@ -204,7 +209,7 @@ class GravityWalker(DirectObject.DirectObject):
self.setupRay(floorBitmask, self.floorOffset) self.setupRay(floorBitmask, self.floorOffset)
self.setupWallSphere(wallBitmask, avatarRadius) self.setupWallSphere(wallBitmask, avatarRadius)
self.setupFloorSphere(floorBitmask, avatarRadius) self.setupFloorSphere(wallBitmask|floorBitmask, avatarRadius)
self.setCollisionsActive(1) self.setCollisionsActive(1)
@ -236,6 +241,9 @@ class GravityWalker(DirectObject.DirectObject):
assert(self.debugPrint("collisionsActive(active=%s)"%(active,))) assert(self.debugPrint("collisionsActive(active=%s)"%(active,)))
if self.collisionsActive != active: if self.collisionsActive != active:
self.collisionsActive = active self.collisionsActive = active
# Each time we change the collision geometry, make one
# more pass to ensure we aren't standing in a wall.
self.oneTimeCollide()
if active: if active:
self.cTrav.addCollider(self.cWallSphereNodePath, self.pusher) self.cTrav.addCollider(self.cWallSphereNodePath, self.pusher)
self.cTrav.addCollider(self.cFloorSphereNodePath, self.event) self.cTrav.addCollider(self.cFloorSphereNodePath, self.event)
@ -244,15 +252,25 @@ class GravityWalker(DirectObject.DirectObject):
self.cTrav.removeCollider(self.cWallSphereNodePath) self.cTrav.removeCollider(self.cWallSphereNodePath)
self.cTrav.removeCollider(self.cFloorSphereNodePath) self.cTrav.removeCollider(self.cFloorSphereNodePath)
self.cTrav.removeCollider(self.cRayNodePath) self.cTrav.removeCollider(self.cRayNodePath)
# Now that we have disabled collisions, make one more pass
# right now to ensure we aren't standing in a wall.
self.oneTimeCollide()
def getCollisionsActive(self): def getCollisionsActive(self):
assert(self.debugPrint("getCollisionsActive() returning=%s"%( assert(self.debugPrint("getCollisionsActive() returning=%s"%(
self.collisionsActive,))) self.collisionsActive,)))
return self.collisionsActive return self.collisionsActive
def FixCliff(self, task):
"""
People are still making polygons that are marked
as floor, but are nearly vertical. This ray is
a hack to help deal with the cliff.
"""
if self.lifter.isInOuterSpace():
temp = self.cRayNodePath.getZ()
self.cRayNodePath.setZ(14.0)
self.oneTimeCollide()
self.cRayNodePath.setZ(temp)
return Task.cont
def oneTimeCollide(self): def oneTimeCollide(self):
""" """
Makes one quick collision pass for the avatar, for instance as Makes one quick collision pass for the avatar, for instance as
@ -294,7 +312,7 @@ class GravityWalker(DirectObject.DirectObject):
reverse = inputState.isSet("reverse") reverse = inputState.isSet("reverse")
turnLeft = inputState.isSet("turnLeft") turnLeft = inputState.isSet("turnLeft")
turnRight = inputState.isSet("turnRight") turnRight = inputState.isSet("turnRight")
slide = inputState.isSet("slide") slide = 0 #hack -- was: inputState.isSet("slide")
jump = inputState.isSet("jump") jump = inputState.isSet("jump")
pie = inputState.isSet("pie") pie = inputState.isSet("pie")
# Determine what the speeds are based on the buttons: # Determine what the speeds are based on the buttons:
@ -328,6 +346,8 @@ class GravityWalker(DirectObject.DirectObject):
onScreenDebug.add("velocity", self.lifter.getVelocity()) #*# onScreenDebug.add("velocity", self.lifter.getVelocity()) #*#
onScreenDebug.add("isAirborne", self.isAirborne) #*# onScreenDebug.add("isAirborne", self.isAirborne) #*#
onScreenDebug.add("jump", jump) #*# onScreenDebug.add("jump", jump) #*#
onScreenDebug.add("inOuterSpace", self.lifter.isInOuterSpace()) #*#
if self.lifter.isOnGround(): if self.lifter.isOnGround():
if self.isAirborne: if self.isAirborne:
self.isAirborne = 0 self.isAirborne = 0
@ -408,13 +428,26 @@ class GravityWalker(DirectObject.DirectObject):
if __debug__: if __debug__:
self.accept("control-f3", self.spawnTest) #*# self.accept("control-f3", self.spawnTest) #*#
taskName = "AvatarControls%s"%(id(self),)
# remove any old # remove any old
taskMgr.remove(taskName) if self.controlsTask:
self.controlsTask.remove()
# spawn the new task # spawn the new task
taskMgr.add(self.handleAvatarControls, taskName, 25) taskName = "AvatarControls%s"%(id(self),)
self.controlsTask = taskMgr.add(self.handleAvatarControls, taskName, 25)
# remove any old
if self.fixCliffTask:
self.fixCliffTask.remove()
# spawn the new task
taskName = "AvatarControls-FixCliff%s"%(id(self),)
self.fixCliffTask = taskMgr.add(self.FixCliff, taskName, 31)
if self.physVelocityIndicator: if self.physVelocityIndicator:
taskMgr.add(self.avatarPhysicsIndicator, "AvatarControlsIndicator%s"%(id(self),), 35) if self.indicatorTask:
self.indicatorTask.remove()
self.indicatorTask = taskMgr.add(
self.avatarPhysicsIndicator,
"AvatarControlsIndicator%s"%(id(self),), 35)
def disableAvatarControls(self): def disableAvatarControls(self):
""" """
@ -422,11 +455,15 @@ class GravityWalker(DirectObject.DirectObject):
""" """
assert(self.debugPrint("disableAvatarControls()")) assert(self.debugPrint("disableAvatarControls()"))
print id(self), "GW.disableAvatarControls()" print id(self), "GW.disableAvatarControls()"
taskName = "AvatarControls%s"%(id(self),) if self.controlsTask:
taskMgr.remove(taskName) self.controlsTask.remove()
self.controlsTask = None
taskName = "AvatarControlsIndicator%s"%(id(self),) if self.fixCliffTask:
taskMgr.remove(taskName) self.fixCliffTask.remove()
self.fixCliffTask = None
if self.indicatorTask:
self.indicatorTask.remove()
self.indicatorTask = None
if __debug__: if __debug__:
self.ignore("control-f3") #*# self.ignore("control-f3") #*#

View File

@ -23,6 +23,9 @@ class NonPhysicsWalker(DirectObject.DirectObject):
notify = DirectNotifyGlobal.directNotify.newCategory("NonPhysicsWalker") notify = DirectNotifyGlobal.directNotify.newCategory("NonPhysicsWalker")
# Ghost mode overrides this:
slideName = "slide-is-disabled"
# special methods # special methods
def __init__(self): def __init__(self):
DirectObject.DirectObject.__init__(self) DirectObject.DirectObject.__init__(self)
@ -151,7 +154,7 @@ class NonPhysicsWalker(DirectObject.DirectObject):
reverse = inputState.isSet("reverse") reverse = inputState.isSet("reverse")
turnLeft = inputState.isSet("turnLeft") turnLeft = inputState.isSet("turnLeft")
turnRight = inputState.isSet("turnRight") turnRight = inputState.isSet("turnRight")
slide = inputState.isSet("slide") slide = inputState.isSet(self.slideName)
#jump = inputState.isSet("jump") #jump = inputState.isSet("jump")
# Determine what the speeds are based on the buttons: # Determine what the speeds are based on the buttons:
self.speed=(forward and self.avatarControlForwardSpeed or self.speed=(forward and self.avatarControlForwardSpeed or