mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
lifter hacks (lollypop collision)
This commit is contained in:
parent
55e83fdc5c
commit
44baf4eb14
@ -29,6 +29,9 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
notify = DirectNotifyGlobal.directNotify.newCategory("PhysicsWalker")
|
||||
wantAvatarPhysicsIndicator = base.config.GetBool('want-avatar-physics-indicator', 0)
|
||||
|
||||
useLifter = 0
|
||||
useHeightRay = 0
|
||||
|
||||
# special methods
|
||||
def __init__(self, gravity = -32.1740, standableGround=0.707,
|
||||
hardLandingForce=16.0):
|
||||
@ -114,25 +117,83 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
#assert(self.debugPrint("getSpeeds()"))
|
||||
return (self.__speed, self.__rotationSpeed)
|
||||
|
||||
def initializeCollisions(self, collisionTraverser, avatarNodePath,
|
||||
wallBitmask, floorBitmask,
|
||||
avatarRadius = 1.4, floorOffset = 1.0):
|
||||
"""
|
||||
Set up the avatar collisions
|
||||
"""
|
||||
assert(self.debugPrint("initializeCollisions()"))
|
||||
|
||||
assert not avatarNodePath.isEmpty()
|
||||
|
||||
self.cTrav = collisionTraverser
|
||||
def setupRay(self, floorBitmask, floorOffset):
|
||||
# This is a ray cast from your head down to detect floor polygons
|
||||
# A toon is about 4.0 feet high, so start it there
|
||||
self.cRay = CollisionRay(0.0, 0.0, 4.0, 0.0, 0.0, -1.0)
|
||||
cRayNode = CollisionNode('cRayNode')
|
||||
cRayNode.addSolid(self.cRay)
|
||||
self.cRayNodePath = self.avatarNodePath.attachNewNode(cRayNode)
|
||||
self.cRayBitMask = floorBitmask
|
||||
cRayNode.setFromCollideMask(self.cRayBitMask)
|
||||
cRayNode.setIntoCollideMask(BitMask32.allOff())
|
||||
|
||||
# Set up the collision sphere
|
||||
if self.useLifter:
|
||||
# set up floor collision mechanism
|
||||
self.lifter = CollisionHandlerFloor()
|
||||
self.lifter.setInPattern("enter%in")
|
||||
self.lifter.setOutPattern("exit%in")
|
||||
self.lifter.setOffset(floorOffset)
|
||||
|
||||
# Limit our rate-of-fall with the lifter.
|
||||
# If this is too low, we actually "fall" off steep stairs
|
||||
# and float above them as we go down. I increased this
|
||||
# from 8.0 to 16.0 to prevent this
|
||||
self.lifter.setMaxVelocity(16.0)
|
||||
|
||||
#self.bobNodePath = self.avatarNodePath.attachNewNode("bob")
|
||||
self.lifter.addCollider(self.cRayNodePath, self.cRayNodePath)
|
||||
else: # useCollisionHandlerQueue
|
||||
self.cRayQueue = CollisionHandlerQueue()
|
||||
self.cTrav.addCollider(self.cRayNodePath, self.cRayQueue)
|
||||
self.cRayNodePath.show()
|
||||
|
||||
def determineHeight(self):
|
||||
"""
|
||||
returns the height of the avatar above the ground.
|
||||
If there is no floor below the avatar, 0.0 is returned.
|
||||
aka get airborne height.
|
||||
"""
|
||||
if self.useLifter:
|
||||
height = self.avatarNodePath.getPos(self.cRayNodePath)
|
||||
# If the shadow where not pointed strait down, we would need to
|
||||
# get magnitude of the vector. Since it is strait down, we'll
|
||||
# just get the z:
|
||||
#spammy --> assert self.debugPrint("getAirborneHeight() returning %s"%(height.getZ(),))
|
||||
assert onScreenDebug.add("height", height.getZ())
|
||||
return height.getZ() - self.floorOffset
|
||||
else: # useCollisionHandlerQueue
|
||||
"""
|
||||
returns the height of the avatar above the ground.
|
||||
If there is no floor below the avatar, 0.0 is returned.
|
||||
aka get airborne height.
|
||||
"""
|
||||
height = 0.0
|
||||
#*#self.cRayTrav.traverse(render)
|
||||
if self.cRayQueue.getNumEntries() != 0:
|
||||
# ...we have a floor.
|
||||
# Choose the highest of the possibly several floors we're over:
|
||||
self.cRayQueue.sortEntries()
|
||||
floorPoint = self.cRayQueue.getEntry(0).getFromIntersectionPoint()
|
||||
height = -floorPoint.getZ()
|
||||
self.cRayQueue.clearEntries()
|
||||
onScreenDebug.add("height", height)
|
||||
return height
|
||||
|
||||
def setupSphere(self, bitmask, avatarRadius):
|
||||
"""
|
||||
Set up the collision sphere
|
||||
"""
|
||||
# This is a sphere on the ground to detect barrier collisions
|
||||
self.cSphere = CollisionSphere(0.0, 0.0, avatarRadius, avatarRadius)
|
||||
self.avatarRadius = avatarRadius
|
||||
centerHeight = avatarRadius
|
||||
if self.useHeightRay:
|
||||
centerHeight *= 2.0
|
||||
self.cSphere = CollisionSphere(0.0, 0.0, centerHeight, avatarRadius)
|
||||
cSphereNode = CollisionNode('cSphereNode')
|
||||
cSphereNode.addSolid(self.cSphere)
|
||||
self.cSphereNodePath = avatarNodePath.attachNewNode(cSphereNode)
|
||||
self.cSphereBitMask = wallBitmask|floorBitmask
|
||||
self.cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
|
||||
self.cSphereBitMask = bitmask
|
||||
|
||||
cSphereNode.setFromCollideMask(self.cSphereBitMask)
|
||||
cSphereNode.setIntoCollideMask(BitMask32.allOff())
|
||||
@ -142,6 +203,10 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
self.pusher.setInPattern("enter%in")
|
||||
self.pusher.setOutPattern("exit%in")
|
||||
|
||||
self.pusher.addCollider(self.cSphereNodePath, self.avatarNodePath)
|
||||
|
||||
def setupPhysics(self, avatarNodePath):
|
||||
assert(self.debugPrint("setupPhysics()"))
|
||||
# Connect to Physics Manager:
|
||||
self.actorNode=ActorNode("physicsActor")
|
||||
self.actorNode.getPhysicsObject().setOriented(1)
|
||||
@ -189,12 +254,27 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
self.phys.addLinearForce(self.acForce)
|
||||
#self.phys.removeLinearForce(self.acForce)
|
||||
#fnp.remove()
|
||||
return avatarNodePath
|
||||
|
||||
# activate the collider with the traverser and pusher
|
||||
self.collisionsOn()
|
||||
self.pusher.addCollider(self.cSphereNodePath, avatarNodePath)
|
||||
def initializeCollisions(self, collisionTraverser, avatarNodePath,
|
||||
wallBitmask, floorBitmask,
|
||||
avatarRadius = 1.4, floorOffset = 1.0):
|
||||
"""
|
||||
Set up the avatar collisions
|
||||
"""
|
||||
assert(self.debugPrint("initializeCollisions()"))
|
||||
|
||||
self.avatarNodePath = avatarNodePath
|
||||
assert not avatarNodePath.isEmpty()
|
||||
|
||||
self.cTrav = collisionTraverser
|
||||
self.floorOffset = floorOffset = 7.0
|
||||
|
||||
self.avatarNodePath = self.setupPhysics(avatarNodePath)
|
||||
if self.useHeightRay:
|
||||
self.setupRay(floorBitmask, avatarRadius)
|
||||
self.setupSphere(wallBitmask|floorBitmask, avatarRadius)
|
||||
|
||||
self.collisionsOn()
|
||||
|
||||
def setAirborneHeightFunc(self, getAirborneHeight):
|
||||
self.getAirborneHeight = getAirborneHeight
|
||||
@ -258,6 +338,11 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
assert(self.debugPrint("deleteCollisions()"))
|
||||
del self.cTrav
|
||||
|
||||
if self.useHeightRay:
|
||||
del self.cRayQueue
|
||||
self.cRayNodePath.removeNode()
|
||||
del self.cRayNodePath
|
||||
|
||||
del self.cSphere
|
||||
self.cSphereNodePath.removeNode()
|
||||
del self.cSphereNodePath
|
||||
@ -267,6 +352,8 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
def collisionsOff(self):
|
||||
assert(self.debugPrint("collisionsOff()"))
|
||||
self.cTrav.removeCollider(self.cSphereNodePath)
|
||||
if self.useHeightRay:
|
||||
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()
|
||||
@ -274,6 +361,11 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
def collisionsOn(self):
|
||||
assert(self.debugPrint("collisionsOn()"))
|
||||
self.cTrav.addCollider(self.cSphereNodePath, self.pusher)
|
||||
if self.useHeightRay:
|
||||
if self.useLifter:
|
||||
self.cTrav.addCollider(self.cRayNodePath, self.lifter)
|
||||
else:
|
||||
self.cTrav.addCollider(self.cRayNodePath, self.cRayQueue)
|
||||
|
||||
def oneTimeCollide(self):
|
||||
"""
|
||||
@ -293,7 +385,6 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
if self.wantAvatarPhysicsIndicator:
|
||||
onScreenDebug.append("localToon pos = %s\n"%(toonbase.localToon.getPos().pPrintValues(),))
|
||||
onScreenDebug.append("localToon h = % 10.4f\n"%(toonbase.localToon.getH(),))
|
||||
#onScreenDebug.append("localToon name = %s\n"%(toonbase.localToon.getName(),))
|
||||
onScreenDebug.append("localToon anim = %s\n"%(toonbase.localToon.animFSM.getCurrentState().getName(),))
|
||||
#assert(self.debugPrint("handleAvatarControls(task=%s)"%(task,)))
|
||||
physObject=self.actorNode.getPhysicsObject()
|
||||
@ -350,14 +441,6 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
onScreenDebug.add("posDelta1",
|
||||
self.avatarNodePath.getPosDelta(render).pPrintValues())
|
||||
|
||||
# is same as posDelta1:
|
||||
#onScreenDebug.add("posDelta2",
|
||||
# self.avatarNodePath.getPosDelta(self.priorParentNp).pPrintValues())
|
||||
|
||||
# is always zero:
|
||||
#onScreenDebug.add("posDelta2.5",
|
||||
# self.avatarNodePath.getPosDelta(self.avatarNodePath).pPrintValues())
|
||||
|
||||
if 0:
|
||||
onScreenDebug.add("posDelta3",
|
||||
render.getRelativeVector(
|
||||
@ -406,8 +489,8 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
if 1:
|
||||
onScreenDebug.add("contact",
|
||||
contact.pPrintValues())
|
||||
onScreenDebug.add("airborneHeight", "% 10.4f"%(
|
||||
self.getAirborneHeight(),))
|
||||
#onScreenDebug.add("airborneHeight", "% 10.4f"%(
|
||||
# self.getAirborneHeight(),))
|
||||
|
||||
if 0:
|
||||
onScreenDebug.add("__oldContact",
|
||||
@ -421,7 +504,9 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
self.highMark,))
|
||||
#if airborneHeight < 0.1: #contact!=Vec3.zero():
|
||||
if 1:
|
||||
if airborneHeight > 0.7: # Check stair angles before chaning this.
|
||||
if (airborneHeight > self.avatarRadius*0.5
|
||||
or physObject.getVelocity().getZ() > 0.0
|
||||
): # Check stair angles before chaning this.
|
||||
# ...the avatar is airborne (maybe a lot or a tiny amount).
|
||||
self.isAirborne = 1
|
||||
else:
|
||||
@ -448,6 +533,8 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
jumpVec*=self.avatarControlJumpForce
|
||||
physObject.addImpulse(Vec3(jumpVec))
|
||||
self.isAirborne = 1 # Avoid double impulse before fully airborne.
|
||||
else:
|
||||
self.isAirborne = 0
|
||||
onScreenDebug.add("isAirborne", "%d"%(self.isAirborne,))
|
||||
else:
|
||||
if contact!=Vec3.zero():
|
||||
@ -481,21 +568,25 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
self.__oldAirborneHeight=airborneHeight
|
||||
|
||||
moveToGround = Vec3.zero()
|
||||
if self.isAirborne:
|
||||
if not self.useHeightRay or self.isAirborne:
|
||||
# ...the airborne check is a hack to stop sliding.
|
||||
self.phys.doPhysics(dt)
|
||||
onScreenDebug.add("phys", "on")
|
||||
else:
|
||||
physObject.setVelocity(Vec3.zero())
|
||||
if airborneHeight>0.001 and contact==Vec3.zero():
|
||||
moveToGround = Vec3(0.0, 0.0, -airborneHeight)
|
||||
#if airborneHeight>0.001 and contact==Vec3.zero():
|
||||
# moveToGround = Vec3(0.0, 0.0, -airborneHeight)
|
||||
#moveToGround = Vec3(0.0, 0.0, -airborneHeight)
|
||||
moveToGround = Vec3(0.0, 0.0, -self.determineHeight())
|
||||
onScreenDebug.add("phys", "off")
|
||||
# Check to see if we're moving at all:
|
||||
if self.__speed or self.__slideSpeed or self.__rotationSpeed:
|
||||
if 1 or self.__speed or self.__slideSpeed or self.__rotationSpeed:
|
||||
distance = dt * self.__speed
|
||||
slideDistance = dt * self.__slideSpeed
|
||||
rotation = dt * self.__rotationSpeed
|
||||
|
||||
#debugTempH=self.avatarNodePath.getH()
|
||||
assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
|
||||
assert self.avatarNodePath.getHpr().getStandardizedHpr().almostEqual(physObject.getOrientation().getHpr().getStandardizedHpr(), 0.0001)
|
||||
assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001)
|
||||
|
||||
# update pos:
|
||||
@ -520,7 +611,7 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
# sync the change:
|
||||
self.actorNode.updateTransform()
|
||||
|
||||
assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
|
||||
assert self.avatarNodePath.getHpr().getStandardizedHpr().almostEqual(physObject.getOrientation().getHpr().getStandardizedHpr(), 0.0001)
|
||||
assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001)
|
||||
#assert self.avatarNodePath.getH()==debugTempH-rotation
|
||||
messenger.send("avatarMoving")
|
||||
@ -529,105 +620,6 @@ class PhysicsWalker(DirectObject.DirectObject):
|
||||
# Clear the contact vector so we can tell if we contact something next frame:
|
||||
self.actorNode.setContactVector(Vec3.zero())
|
||||
return Task.cont
|
||||
|
||||
#def handleAvatarControls_wip(self, task):
|
||||
# """
|
||||
# Check on the arrow keys and update the avatar.
|
||||
# """
|
||||
# #assert(self.debugPrint("handleAvatarControls(task=%s)"%(task,)))
|
||||
# physObject=self.actorNode.getPhysicsObject()
|
||||
# #rotAvatarToPhys=Mat3.rotateMatNormaxis(-self.avatarNodePath.getH(), Vec3.up())
|
||||
# #rotPhysToAvatar=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
|
||||
# contact=self.actorNode.getContactVector()
|
||||
#
|
||||
# # hack fix for falling through the floor:
|
||||
# if contact==Vec3.zero() and self.avatarNodePath.getZ()<-50.0:
|
||||
# # reset:
|
||||
# self.avatarNodePath.setPos(Vec3(0.0, 0.0, 20.0))
|
||||
#
|
||||
# # Determine what the speeds are based on the buttons:
|
||||
# buttons = inputState.state
|
||||
# self.__speed=(buttons["forward"] and self.avatarControlForwardSpeed or
|
||||
# self.__reverseButton and -self.avatarControlReverseSpeed)
|
||||
# self.__slideSpeed=self.__slideButton and (
|
||||
# (self.__leftButton and -self.avatarControlForwardSpeed) or
|
||||
# (self.__rightButton and self.avatarControlForwardSpeed))
|
||||
# self.__rotationSpeed=not self.__slideButton and (
|
||||
# (inputState.isSet("turnLeft") and self.avatarControlRotateSpeed) or
|
||||
# (self.__rightButton and -self.avatarControlRotateSpeed))
|
||||
# # How far did we move based on the amount of time elapsed?
|
||||
# dt=min(ClockObject.getGlobalClock().getDt(), 0.1)
|
||||
#
|
||||
# doPhysics=1
|
||||
# if not contact.almostEqual(Vec3.zero()):
|
||||
# contactLength = contact.length()
|
||||
# contact.normalize()
|
||||
# angle=contact.dot(Vec3.up())
|
||||
# if angle>self.__standableGround:
|
||||
# # ...avatar is on standable ground.
|
||||
# #print "standableGround"
|
||||
# if self.__oldContact==Vec3.zero():
|
||||
# if contactLength>self.__hardLandingForce:
|
||||
# # ...avatar was airborne.
|
||||
# messenger.send("jumpHardLand")
|
||||
# else:
|
||||
# messenger.send("jumpLand")
|
||||
# if self.__jumpButton:
|
||||
# self.__jumpButton=0
|
||||
# messenger.send("jumpStart")
|
||||
# jump=Vec3(contact+Vec3.up())
|
||||
# #jump=Vec3(rotAvatarToPhys.xform(jump))
|
||||
# jump.normalize()
|
||||
# jump*=self.avatarControlJumpForce
|
||||
# physObject.addImpulse(Vec3(jump))
|
||||
# else:
|
||||
# physObject.setVelocity(Vec3(0.0))
|
||||
# self.__vel.set(0.0, 0.0, 0.0)
|
||||
# doPhysics=0
|
||||
# if contact!=self.__oldContact:
|
||||
# # We must copy the vector to preserve it:
|
||||
# self.__oldContact=Vec3(contact)
|
||||
# #print "doPhysics", doPhysics
|
||||
# #print "contact", contact
|
||||
# if doPhysics:
|
||||
# self.phys.doPhysics(dt)
|
||||
# # Check to see if we're moving at all:
|
||||
# if self.__speed or self.__slideSpeed or self.__rotationSpeed:
|
||||
# distance = dt * self.__speed
|
||||
# slideDistance = dt * self.__slideSpeed
|
||||
# rotation = dt * self.__rotationSpeed
|
||||
#
|
||||
# #debugTempH=self.avatarNodePath.getH()
|
||||
# assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
|
||||
# assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001)
|
||||
#
|
||||
# # update pos:
|
||||
# # Take a step in the direction of our previous heading.
|
||||
# self.__vel=Vec3(Vec3.forward() * distance +
|
||||
# Vec3.right() * slideDistance)
|
||||
# # rotMat is the rotation matrix corresponding to
|
||||
# # our previous heading.
|
||||
# rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
|
||||
# step=rotMat.xform(self.__vel)
|
||||
# physObject.setPosition(Point3(
|
||||
# physObject.getPosition()+step))
|
||||
# # update hpr:
|
||||
# o=physObject.getOrientation()
|
||||
# r=LOrientationf()
|
||||
# r.setHpr(Vec3(rotation, 0.0, 0.0))
|
||||
# physObject.setOrientation(o*r)
|
||||
# # sync the change:
|
||||
# self.actorNode.updateTransform()
|
||||
#
|
||||
# assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
|
||||
# assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001)
|
||||
# #assert self.avatarNodePath.getH()==debugTempH-rotation
|
||||
# messenger.send("avatarMoving")
|
||||
# else:
|
||||
# self.__vel.set(0.0, 0.0, 0.0)
|
||||
# # Clear the contact vector so we can tell if we contact something next frame:
|
||||
# self.actorNode.setContactVector(Vec3.zero())
|
||||
# return Task.cont
|
||||
|
||||
def doDeltaPos(self):
|
||||
assert(self.debugPrint("doDeltaPos()"))
|
||||
|
Loading…
x
Reference in New Issue
Block a user