No luck
I’ve pasted the entire example below, thanks
#!/usr/bin/env python
Author: Ryan Myers
Models: Jeff Styers, Reagan Heller
Last Updated: 6/13/2005
This tutorial provides an example of creating a character
and having it walk around on uneven terrain, as well
as implementing a fully rotatable camera.
import direct.directbase.DirectStart
from panda3d.core import CollisionTraverser,CollisionNode
from panda3d.core import CollisionHandlerQueue,CollisionRay
from panda3d.core import Filename,AmbientLight,DirectionalLight
from panda3d.core import PandaNode,NodePath,Camera,TextNode
from panda3d.core import Point3,Vec3,Vec4,BitMask32
from direct.interval.IntervalGlobal import *
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
from direct.fsm.FSM import FSM
import random, sys, os, math
#import my class
from AddActor import AddActor
SPEED = 0.5
#Using PyTables to read HDF5 file
import tables
Function to put instructions on the screen.
def addInstructions(pos, msg):
return OnscreenText(text=msg, style=1, fg=(1,1,1,1),
pos=(-1.3, pos), align=TextNode.ALeft, scale = .05)
Function to put title on the screen.
def addTitle(text):
return OnscreenText(text=text, style=1, fg=(1,1,1,1),
pos=(1.3,-0.95), align=TextNode.ARight, scale = .07)
class World(DirectObject):
actors = []
positions = []
start_pos = 0
intervals = []
# Game state variables
isMoving = False
def __init__(self):
self.getpositions()
base.win.setClearColor(Vec4(0,0,0,1))
# Post the instructions
self.title = addTitle("Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)")
self.inst1 = addInstructions(0.95, "[ESC]: Quit")
self.inst2 = addInstructions(0.90, "Playback of actor positions")
# Set up the environment
#
# This environment model contains collision meshes. If you look
# in the egg file, you will see the following:
#
# <Collide> { Polyset keep descend }
#
# This tag causes the following mesh to be converted to a collision
# mesh -- a mesh which is optimized for collision, not rendering.
# It also keeps the original mesh, so there are now two copies ---
# one optimized for rendering, one for collisions.
self.environ = loader.loadModel("models/world")
self.environ.reparentTo(render)
self.environ.setPos(0,0,0)
# Create the main character, Ralph, from my AddActor class
self.ralph = AddActor(position=self.getposition(0),
name="Ralph")
#must attach actor to renderer
self.ralph.reparentTo(render)
# Create a floater object. We use the "floater" as a temporary
# variable in a variety of calculations.
self.floater = NodePath(PandaNode("floater"))
self.floater.reparentTo(render)
# Accept the escape key to exit application
self.accept("escape", sys.exit)
taskMgr.add(self.incrementpos,"movePosTask")
base.disableMouse()
base.camera.setPos( self.ralph.getX(), self.ralph.getY() + 5, 5 )
# We will detect the height of the terrain by creating a collision
# ray and casting it downward toward the terrain. One ray will
# start above ralph's head, and the other will start above the camera.
# A ray may hit the terrain, or it may hit a rock or a tree. If it
# hits the terrain, we can detect the height. If it hits anything
# else, we rule that the move is illegal.
self.cTrav = CollisionTraverser()
self.ralphGroundRay = CollisionRay()
self.ralphGroundRay.setOrigin(0,0,1000)
self.ralphGroundRay.setDirection(0,0,-1)
self.ralphGroundCol = CollisionNode('ralphRay')
self.ralphGroundCol.addSolid(self.ralphGroundRay)
self.ralphGroundCol.setFromCollideMask(BitMask32.bit(0))
self.ralphGroundCol.setIntoCollideMask(BitMask32.allOff())
self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol)
self.ralphGroundHandler = CollisionHandlerQueue()
self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler)
self.camGroundRay = CollisionRay()
self.camGroundRay.setOrigin(0,0,1000)
self.camGroundRay.setDirection(0,0,-1)
self.camGroundCol = CollisionNode('camRay')
self.camGroundCol.addSolid(self.camGroundRay)
self.camGroundCol.setFromCollideMask(BitMask32.bit(0))
self.camGroundCol.setIntoCollideMask(BitMask32.allOff())
self.camGroundColNp = base.camera.attachNewNode(self.camGroundCol)
self.camGroundHandler = CollisionHandlerQueue()
self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler)
# Uncomment this line to see the collision rays
self.ralphGroundColNp.show()
self.camGroundColNp.show()
# Uncomment this line to show a visual representation of the
# collisions occuring
self.cTrav.showCollisions(render)
# Create some lighting
ambientLight = AmbientLight("ambientLight")
ambientLight.setColor(Vec4(.3, .3, .3, 1))
directionalLight = DirectionalLight("directionalLight")
directionalLight.setDirection(Vec3(-5, -5, -5))
directionalLight.setColor(Vec4(1, 1, 1, 1))
directionalLight.setSpecularColor(Vec4(1, 1, 1, 1))
render.setLight(render.attachNewNode(ambientLight))
render.setLight(render.attachNewNode(directionalLight))
def getpositions(self):
"""Read HDF5 file for actor positions"""
h5file = tables.openFile('actor_position.h5')
self.positions = h5file.root.actors.position.read()
del h5file
def getposition(self, index):
"""Get position at index value"""
p = Vec3( self.positions[index][0],self.positions[index][1],self.positions[index][2] )
return p
def cross(self, a, b):
"""Compute cross product for 2 vectors"""
c = [a[1]*b[2] - a[2]*b[1],
a[2]*b[0] - a[0]*b[2],
a[0]*b[1] - a[1]*b[0]]
return c
def dot_product(self, a, b):
"""Compute ot product for 2 vectors"""
return sum([a[i]*b[i] for i in range(len(a))])
def incrementpos(self, task):
"""Return next row"""
if self.isMoving is False:
print 'Moving......'
self.ralph.loop("run")
self.ralph.lookAt(self.positions[task.frame])
self.isMoving = True
else:
pass
base.camera.lookAt(self.ralph)
# If the camera is too far from ralph, move it closer.
# If the camera is too close to ralph, move it farther.
camvec = self.ralph.getPos() - base.camera.getPos()
camvec.setZ(0)
camdist = camvec.length()
camvec.normalize()
if (camdist > 15.0):
base.camera.setPos(base.camera.getPos() + camvec*(camdist-15))
camdist = 15.0
if (camdist < 10.0):
base.camera.setPos(base.camera.getPos() - camvec*(10-camdist))
camdist = 10.0
# Now check for collisions.
self.cTrav.traverse(render)
# Adjust ralph's Z coordinate. If ralph's ray hit terrain,
# update his Z. If it hit anything else, or didn't hit anything, put
# him back where he was last frame.
entries = []
for i in range(self.ralphGroundHandler.getNumEntries()):
entry = self.ralphGroundHandler.getEntry(i)
entries.append(entry)
entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
x.getSurfacePoint(render).getZ()))
if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"):
self.ralph.setZ(entries[0].getSurfacePoint(render).getZ())
else:
self.ralph.setPos(self.getposition(0))
# Keep the camera at one foot above the terrain,
# or two feet above ralph, whichever is greater.
entries = []
for i in range(self.camGroundHandler.getNumEntries()):
entry = self.camGroundHandler.getEntry(i)
entries.append(entry)
entries.sort(lambda x,y: cmp(y.getSurfacePoint(render).getZ(),
x.getSurfacePoint(render).getZ()))
if (len(entries)>0) and (entries[0].getIntoNode().getName() == "terrain"):
base.camera.setZ(entries[0].getSurfacePoint(render).getZ()+1.0)
if (base.camera.getZ() < self.ralph.getZ() + 2.0):
base.camera.setZ(self.ralph.getZ() + 2.0)
# The camera should look in ralph's direction,
# but it should also try to stay horizontal, so look at
# a floater which hovers above ralph's head.
self.floater.setPos(self.ralph.getPos())
self.floater.setY(self.ralph.getY() + 2.0)
self.floater.setZ(self.ralph.getZ() + 2.0)
base.camera.lookAt(self.floater)
#Right now we are using the frame number to cycle through the
#positions, when we get to the end we need to either reset the frame number
#or find a new index algorithm
try:
self.ralph.setPos(self.positions[task.frame][0],
self.positions[task.frame][1],self.positions[task.frame][2])
except IndexError, e:
print "End of positions"
return task.cont
if name==“main”:
w = World()
run()