Hi
I have spent several weeks working on Panda3D hoping to build a small game at last. And inevitablly I got some problems. Here are some them.
the code is listed below those problem, it looks a little bit long but the part where i got the problem is highlighted.
when I attaching a odebody to an actor, it seemed impossible to control the actor’s hpr by method setHpr(). I only can use the odebody method setRotation() to do the rotation but still can get the angle by actor method getH().Is it a rule or something?
When I dragging the window, charactor with an odebody shaked like a tumbler, make everything a little naughty. Is there a way to tackle this?
and about ode collision detection, thanks pro-rsoft for uploading a new ode sample in the forum. now I can use self.accept(“ode-collision”, self.onCollision) to accept collision. but is there a more particular way I mean in which I can specify more details like “from object” and “into boject” etc.
and in the code below, I got a very weird problem. In this program, I wanted to control a charactor to do some performence like running, jumping, and some animation. others looked fine, but the “running part"did not. In the “running part” I intended to control the charactor to run in several velocities and whin max and min range by using “arrow_up” and " arrow_down”. I used some global virables to act like constants, and give it to the keyMap dictionary. unexpectedly those “constants” changed when I give it to variables. I know it’s stupid, but I can’t find where I reset those “constants”.
by the way, is there a genuine constant expression in python?
still, one last question: Is there a place I can got more “free-downloadable” eggs other than the art gallery. I tried and failed to learn 3DS max, since my time is limited. I only want a animal charactor(a sheep) with several animation. but I can’t find any existed models with enough animations(2~3 beside “walking”)in the art gallery. now I use “the boxing robert” which is in the tutorial instead.
At last, thanks for all hard working for the new release of V1.6.0 and especially the downloadable manual since I am a newbie and it’s not easy to get access to Internet 24*7 in my country~
#sheep Ver. 0.9
#an overall test about all the sheep can do
#from jumping, performence, landing to sending point
#use ODE physics engine
#use a exited model to fake sheep, since the sheep haven't been modeled yet
#run stably :)
#jump and run look fine :)
#can do some performence:)
#can spin :)
#Problems:
#can't control the velocity of running correctly
#MAX_vel changed when I set self.keyMap["runVel"]
#press space to jump
#arrow-up to accelerate
#arrow-down to decelrate
#April 9th 2009
from direct.directbase import DirectStart
from pandac.PandaModules import AmbientLight,DirectionalLight
from pandac.PandaModules import LightAttrib
from pandac.PandaModules import OdeWorld, OdeSimpleSpace, OdeJointGroup
from pandac.PandaModules import OdeBody, OdeMass, OdeBoxGeom, OdePlaneGeom
from pandac.PandaModules import BitMask32, CardMaker, Vec3, Vec4, Quat,Mat3
from direct.actor import Actor
from direct.showbase.DirectObject import DirectObject
from direct.interval.MetaInterval import Sequence
#create game states global viriables
gameStates = {"jumping": False,
"running": False,
"inTheAir": False}
#Constants that will control the behavior of the game.
SHEEP_INIT_VEL = Vec3(0,0,0)#-0.5)
SHEEP_MAX_VEL = Vec3(40.0,40.0,0.0)#-0.5)
SHEEP_MIN_VEL = Vec3(-40.0,-40.0,0.0)#-0.5)
SHEEP_ACCEL = Vec3(20,20,0)
SHEEP_DECEL = Vec3(-20,-20,0)
SHEEP_FORCE_DURATION = 0.5
class Environment:
def __init__(self):
# Load the first environment model
Environment._environ = loader.loadModel( "models/environment" )
Environment._environ.reparentTo( render )
Environment._environ.setScale( 0.25, 0.25, 0.25 )
Environment._environ.setPos( -8, 42, 0 )
# Setup our physics world
Environment.world = OdeWorld()
Environment.world.setGravity(0, 0, -9.81)
# Create a space and add a contactgroup to it to add the contact joints
Environment.space = OdeSimpleSpace()
Environment.space.setAutoCollideWorld(Environment.world)
Environment.contactgroup = OdeJointGroup()
Environment.space.setAutoCollideJointGroup(Environment.contactgroup)
# The surface table is needed for autoCollide
Environment.world.initSurfaceTable(1)
Environment.world.setSurfaceEntry(0, 0,
mu = 0.001,
bounce = 0.0,
bounce_vel = 9.1,
soft_erp = 0.9,
soft_cfm = 0.00001,
slip = 0.0,
dampen = 0.9)
# Add a plane to collide with
Environment._groundGeom = OdePlaneGeom(Environment.space, Vec4(0, 0, 1, 0))
Environment._groundGeom.setCollideBits(BitMask32(0x00000001))
Environment._groundGeom.setCategoryBits(BitMask32(0x00000002))
#set collision event ???
Environment.space.setCollisionEvent("ode-collision")
# Set the camera position
base.disableMouse()
base.camera.setPos(80, -20, 40)
base.camera.lookAt(0, 0, 10)
#setup Lights
self.setupLights()
##end __init__
#This function sets up the lighting
def setupLights(self):
lAttrib = LightAttrib.makeAllOff()
ambientLight = AmbientLight( "ambientLight" )
ambientLight.setColor( Vec4(.8, .8, .75, 1) )
lAttrib = lAttrib.addLight( ambientLight )
directionalLight = DirectionalLight( "directionalLight" )
directionalLight.setDirection( Vec3( 0, 0, -2.5 ) )
directionalLight.setColor( Vec4( 0.9, 0.8, 0.9, 1 ) )
lAttrib = lAttrib.addLight( directionalLight )
render.attachNewNode( directionalLight.upcastToPandaNode() )
render.attachNewNode( ambientLight.upcastToPandaNode() )
render.node().setAttrib( lAttrib )
##end Environment
class sheep(DirectObject):
def __init__(self):
self._sheep = Actor.Actor('samples/Boxing-Robots/models/robot',
{'leftPunch' : 'samples/Boxing-Robots/models/robot_left_punch',
'rightPunch' : 'samples/Boxing-Robots/models/robot_right_punch',
'headUp' : 'samples/Boxing-Robots/models/robot_head_up',
'headDown' : 'samples/Boxing-Robots/models/robot_head_down'})
#wrap animation into Sequence
self.performence1 = Sequence(self._sheep.actorInterval('leftPunch'))
self.performence2 = Sequence(self._sheep.actorInterval('rightPunch'))
self.performence3 = Sequence(self._sheep.actorInterval('headUp'),self._sheep.actorInterval('headDown'))
#Actors need to be positioned and parented like normal objects
self._sheep.setPosHprScale(0,0,2,45,0,0,1,1,1)
self._sheep.reparentTo(render)
#setup sheep body
self._sheepBody = OdeBody(Environment.world)
self._sheepMass = OdeMass()
self._sheepMass.setBox(100, 1, 1, 1)
self._sheepBody.setMass(self._sheepMass)
self._sheepBody.setPosition(self._sheep.getPos(render))
self._sheepBody.setQuaternion(self._sheep.getQuat(render))
# Create collision geometry
self._sheepGeom = OdeBoxGeom(Environment.space, 2,2,2)
self._sheepGeom.setCollideBits(BitMask32(0x00000002))
self._sheepGeom.setCategoryBits(BitMask32(0x00000001))
self._sheepGeom.setBody(self._sheepBody)
#create a control keys' dictionary
self.keyMap = {"jump": False,
"runVel": SHEEP_INIT_VEL,
"per1": False,
"per2": False,
"spinLeft": False,
"spinRight": False}
# Accept the control keys for movement
self.accept("space", self.setJumpKey, [True])
self.accept("space-up", self.setJumpKey, [False])
self.accept("arrow_up", self.setRunKey, [SHEEP_ACCEL])
##self.accept("arrow_up-up", self.setKey, ["runVel", vec3(0,0,0)])
self.accept("arrow_down", self.setRunKey, [SHEEP_DECEL])
##self.accept("arrow_down-up", self.setKey, ["runVel", vec3(0,0,0)])
self.accept("q", self.setPerformanceKey, ["per1", True])
self.accept("q-up", self.setPerformanceKey, ["per1", False])
self.accept("w", self.setPerformanceKey, ["per2", True])
self.accept("w-up", self.setPerformanceKey, ["per2", False])
self.accept("a", self.setPerformanceKey, ["spinLeft", True])
self.accept("a-up", self.setPerformanceKey, ["spinLeft", False])
self.accept("s", self.setPerformanceKey, ["spinRight", True])
self.accept("s-up", self.setPerformanceKey, ["spinRight", False])
self.accept("ode-collision", self.onCollision)
#add perform task
performTask = taskMgr.add(self.perform, "perform")
performTask.last = 0 #last task.time
performTask.jumpDtAccum = 0 #delta time accumulator for jumping
performTask.perDtAccum = 0 #delta time accumulator for performence
#run sheepDetection once per second
##taskMgr.doMethodLater(1,self.sheepDetection,"sheepDetection")
##end __init__
#these are a set of setKey method to set keyMap dictionary and change the gameStates dictionary
def setPerformanceKey(self, key, value):
self.keyMap[key] = value
def setJumpKey(self,value):
self.keyMap["jump"] = value
gameStates["jumping"] = True
gameStates["running"] = False
gameStates["inTheAir"] = True
##--------------------------------------------------------------------------##
#here I got problems
def setRunKey(self, value):
gameStates["running"] = True
if self.keyMap["runVel"] > SHEEP_MAX_VEL:
print self.keyMap["runVel"],">", SHEEP_MAX_VEL
self.keyMap["runVel"] = SHEEP_MAX_VEL
print "setmax", self.keyMap["runVel"]
print "MAX_VEL is:",SHEEP_MAX_VEL
elif self.keyMap["runVel"] < SHEEP_MIN_VEL:
print self.keyMap["runVel"],"<", SHEEP_MIN_VEL
self.keyMap["runVel"] = SHEEP_MIN_VEL
print "min", self.keyMap["runVel"]
print "MIN_VEL is:",SHEEP_MIN_VEL
else:
self.keyMap["runVel"] += value
print "setkey",self.keyMap["runVel"]
print "MAX_VEL is:",SHEEP_MAX_VEL
print "MIN_VEL is:",SHEEP_MIN_VEL
##end setKey
##--------------------------------------------------------------------------##
#create a perform task
def perform(self,task):
dt = task.time - task.last
task.last = task.time
#when sheep is jumping give it a static force in duration of SHEEP_FORCE_DURATION
if gameStates["jumping"]:
task.jumpDtAccum += dt
if task.jumpDtAccum < SHEEP_FORCE_DURATION:
self._sheepBody.setForce(Vec3(0,0,4000))
else:
print "force duration is:",task.jumpDtAccum
task.jumpDtAccum = 0
gameStates["jumping"] = False
##end if
#when sheep is running update it's running velocity
if gameStates["running"]:
self._sheepBody.setLinearVel(self.keyMap["runVel"])
##end if
if self.keyMap["spinLeft"]:
task.perDtAccum += dt
rotation =self._sheepBody.getRotation()
rotation.setRotateMat(task.perDtAccum*300)
#print "after:",rotation
self._sheepBody.setRotation(rotation)
if self.keyMap["spinRight"]:
task.perDtAccum -= dt
rotation =self._sheepBody.getRotation()
rotation.setRotateMat(task.perDtAccum*300)
#print "after:",rotation
self._sheepBody.setRotation(rotation)
if gameStates["inTheAir"]:
if self.keyMap["per1"] and not self.performence1.isPlaying() and not self.performence2.isPlaying():
self.performence1.start()
if self.keyMap["per2"] and not self.performence1.isPlaying() and not self.performence2.isPlaying():
self.performence2.start()
##end if
return task.cont
##end jump
#when collision is detected chang gameState["jumping"] to False
#it seems it's been called everyframe since sheep lands ground
def onCollision(self, entry):
gameStates["inTheAir"] = False
##print "jumping = ",gameStates["jumping"]
##end onCollision
def sheepDetection(self, task):
print "vel is:",self._sheepBody.getLinearVel()
print "heading is:",self._sheep.getH()
for name in gameStates:
print name, ":", gameStates[name]
return task.again
##end sheep
class World:
def __init__(self):
Environment()
self.sheep00 = sheep()
self.gameTask = taskMgr.doMethodLater(0.5, self.simulationTask, "simulationTask", extraArgs = [self.sheep00], appendTask=True)
##end init
def simulationTask(self, sheepObj, task):
Environment.space.autoCollide() # Setup the contact joints
Environment.world.quickStep(globalClock.getDt())
sheepObj._sheep.setPosQuat(render, sheepObj._sheepBody.getPosition(), Quat(sheepObj._sheepBody.getQuaternion()))
Environment.contactgroup.empty() # Clear the contact joints
return task.cont
##end simulationTask
#main loop
World()
run()
thanks again