Filed in: Resources.ProgrammingPanda3dTutorialInteraktiveManipulation · Modified on : Fri, 31 Jul 09
====== Interaktive manipulation ======
<code type="Python"> import direct.directbase.DirectStart from pandac.PandaModules import * from direct.showbase.DirectObject import DirectObject
import string
POLLKEYS = list(string.ascii_lowercase+string.digits) POLLKEYS.extend(
[ '_del', 'alt', 'asciiKey', 'backspace', 'capsLock', 'control', 'down', 'end', 'enter', 'escape', 'f1', 'f10', 'f11', 'f12', 'f13', 'f14', 'f15', 'f16', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'help', 'home', 'insert', 'lalt', 'lcontrol', 'left', 'lshift', 'meta', 'numLock', 'pageDown', 'pageUp', 'pause', 'printScreen', 'ralt', 'rcontrol', 'right', 'rshift', 'scrollLock', 'shift', 'shiftLock', 'space', 'tab', 'this', 'this_metatype', 'up', 'arrow_up', 'arrow_down', 'arrow_left', 'arrow_right' ] )
class KeyPollerClass( DirectObject ):
def __init__( self ):
self.data = dict()
for key in POLLKEYS:
self.accept( key, self.event, [key, True] )
self.accept( key+"-up", self.event, [key, False] )
self.data[ key ] = False
def event( self, key, active ):
self.data[key] = active
def __getitem__( self, key ):
return self.data[key]
keyPoller = KeyPollerClass()
base.disableMouse() camera.setPos( Vec3(0,-30,20) ) camera.lookAt( 0,0,3 )
panda = loader.loadModel('panda') panda.reparentTo(render) panda.setScale(.5)
MOVEFUNCTIONS = { 'arrow_up' : Vec3(0,-10,0),
'arrow_down' : Vec3(0, 10,0) }
ROTATEFUNCTIONS = { 'arrow_left' : Vec3( 90,0,0),
'arrow_right': Vec3(-90,0,0) }
def moveTask( task ):
# vergangene zeit seit dem letzten frame
dt = globalClock.getDt()
# fuer jede gedrueckte taste aus den MOVEFUNCTIONS
for key, action in MOVEFUNCTIONS.items():
if keyPoller[ key ]:
# bewege den panda relativ zu sich selbst um den Vektor*Zeit
panda.setPos( panda, action*dt )
for key, action in ROTATEFUNCTIONS.items():
if keyPoller[ key ]:
# rotiere den panda relativ zu sich selbst um den Vektor*Zeit
panda.setHpr( panda, action*dt )
# wiederhole diesen task
return task.cont
taskMgr.add( moveTask, 'moveTask' )
run() </code>
In diesem Beispiel werden die Eventbasierten inputs gespeichert und permanent zugänglich gemacht.
<code type="Python">
class keyPollerClass( DirectObject ):
</code>
Definiert eine Klasse namens keyPollerClass, sie wird von DirectObject abgeleitet. Dies ermöglicht es Events abzufangen. Vorteilhaft gegenüber base.accept ist dass wir die events auch wieder ausschalten können (self.ignoreAll).
<code type="Python">
MOVEFUNCTIONS = { 'arrow_up' : Vec3(0,-10,0),
'arrow_down' : Vec3(0, 10,0) }
ROTATEFUNCTIONS = { 'arrow_left' : Vec3( 90,0,0),
'arrow_right': Vec3(-90,0,0) }
</code> Definiert ein dictionary mit den tasten und deren auswirkungen. Ein dictionary hat immer einen Key und einen Value, der Key muss hashable sein (String, Zahl oder Tuple; keine Dictionary's oder Listen). Die Werte eines Dictionary's können ähnlich wie bei einer Liste abgefragt werden: <code type="Python"> MOVEFUNCTIONS['arrow_up'] </code>
<code type="Python">
taskMgr.add( moveTask, 'moveTask' )
</code>
der Taskmanager verwaltet funktionen die zBsp bei jedem Frame ausführt werden, als Parameter wird die auszuführende Funktion sowie ein Name dafür angegeben.
<code type="Python">
def moveTask( task ):
</code>
Dies ist nun ein solcher Task, er wird bei jedem Frame ausgeführt und benötigt mindestens task als Parameter.
<code type="Python">
</code> globalClock ist der Zeitgeber von Panda3d, es können diverse Zeitinformationen abgefragt werden. Hier zBsp. die vergangene Zeit seit dem letzten Frame.
<code type="Python">
if keyPoller[ key ]:
# bewege den panda relativ zu sich selbst um den Vektor*Zeit
panda.setPos( panda, action*dt )
if keyPoller[ key ]:
# rotiere den panda relativ zu sich selbst um den Vektor*Zeit
panda.setHpr( panda, action*dt )
# wiederhole diesen task
</code> In diesem teil werden die beiden Dictionary's welche vorhin erstellt wurden durchlaufen und geprüft ob die gewünschten Tasten gedrückt sind.
<code type="Python">
return task.cont
</code>
Am ende eines Task's muss festgelegt werden ob diese weiterhin laufen soll (über task.cont), es gibt andere Rückgabewerte wie task.done (task wird beendet) oder task.again (wiederholt den task mit der festgelegten verzögerung), wird kein Parameter zurückgegeben bricht der task ab (task.done).
weiterführende erkärung der Interaktiven Manipulation?
Wie eben kurz angetönt können Tasks auch verzögert aufgerufen werden:
<code type="Python">
taskMgr.doMethodLater( delayTime, function, 'task name' )
</code>
===== Weitere Informationen zu Task's unter =====
http://www.panda3d.org/wiki/index.php/Tasks