def create_node(self): if self.model == "Grenade": m = Actor("grenade.egg") shell = m.find("**/shell") shell.setColor(1, 0.3, 0.3, 1) inner_top = m.find("**/inner_top") inner_bottom = m.find("**/inner_bottom") inner_top.setColor(0.4, 0.4, 0.4, 1) inner_bottom.setColor(0.4, 0.4, 0.4, 1) self.spin_bone = m.controlJoint(None, "modelRoot", "grenade_bone") m.set_scale(GRENADE_SCALE) elif self.model == "Missile": m = load_model("missile.egg") body = m.find("**/bodywings") body.set_color(0.3, 0.3, 1, 1) main_engines = m.find("**/mainengines") wing_engines = m.find("**/wingengines") main_engines.set_color(0.1, 0.1, 0.1, 1) wing_engines.set_color(0.1, 0.1, 0.1, 1) m.set_scale(MISSILE_SCALE) else: m = load_model("misc/rgbCube") m.set_scale(0.5) m.set_hpr(45, 45, 45) return m
def create_node(self): if self.model == "Grenade": m = Actor('grenade.egg') shell = m.find('**/shell') shell.setColor(1,.3,.3,1) inner_top = m.find('**/inner_top') inner_bottom = m.find('**/inner_bottom') inner_top.setColor(.4,.4,.4,1) inner_bottom.setColor(.4,.4,.4,1) self.spin_bone = m.controlJoint(None, 'modelRoot', 'grenade_bone') m.set_scale(GRENADE_SCALE) elif self.model == "Missile": m = load_model('missile.egg') body = m.find('**/bodywings') body.set_color(.3,.3,1,1) main_engines = m.find('**/mainengines') wing_engines = m.find('**/wingengines') main_engines.set_color(.1,.1,.1,1) wing_engines.set_color(.1,.1,.1,1) m.set_scale(MISSILE_SCALE) else: m = load_model('misc/rgbCube') m.set_scale(.5) m.set_hpr(45,45,45) return m
def create_node(self): if self.model == "Grenade": m = Actor('grenade.egg') shell = m.find('**/shell') shell.setColor(1, .3, .3, 1) inner_top = m.find('**/inner_top') inner_bottom = m.find('**/inner_bottom') inner_top.setColor(.4, .4, .4, 1) inner_bottom.setColor(.4, .4, .4, 1) self.spin_bone = m.controlJoint(None, 'modelRoot', 'grenade_bone') m.set_scale(GRENADE_SCALE) elif self.model == "Missile": m = load_model('missile.egg') body = m.find('**/bodywings') body.set_color(.3, .3, 1, 1) main_engines = m.find('**/mainengines') wing_engines = m.find('**/wingengines') main_engines.set_color(.1, .1, .1, 1) wing_engines.set_color(.1, .1, .1, 1) m.set_scale(MISSILE_SCALE) else: m = load_model('misc/rgbCube') m.set_scale(.5) m.set_hpr(45, 45, 45) return m
def __init__(self): ShowBase.__init__(self) self.accept("escape", sys.exit) base.disableMouse() base.camera.set_pos(0, -10, 0) base.camera.look_at(0, 0, 0) a = Actor('box.egg') a.reparentTo(render) self.j_1 = a.controlJoint(None, 'modelRoot', 'Key1') self.j_2 = a.controlJoint(None, 'modelRoot', 'Key2') base.taskMgr.add(self.animate, "Shape Key Animation")
def __init__(self): ShowBase.__init__(self) self.accept("escape", sys.exit) base.disableMouse() base.camera.set_pos(0, -10, 0) base.camera.look_at(0, 0, 0) a = Actor('box.egg') a.reparentTo(render) self.j_1 = a.controlJoint(None,'modelRoot' ,'Key1') self.j_2 = a.controlJoint(None,'modelRoot' ,'Key2') base.taskMgr.add(self.animate, "Shape Key Animation")
def loadPlaneModel(self, modelname): """Loads models and animations from the planes directory.""" animcontrols = {} model = loader.loadModel("planes/{0}/{0}".format(modelname)) actor = Actor(model, setFinal=True, mergeLODBundles=True, allowAsyncBind=False, okMissing=False) #actor = Actor(model, lodNode="mid") subparts = ( # subpart, joints, animations ("Doors", ["Windscreen*", "Door*"], ("Open", "Close")), #("Landing Gear", ["Landing?Gear*", "LG*"], ("LG Out", "LG In")), ("Landing Gear", ["Landing?Gear*", "LG*"], ("LG Out", )), ("Ailerons", ["Aileron*"], ("Roll Left", "Roll Right")), ("Rudders", ["Rudder*"], ("Head Left", "Head Right")), ("Elevators", ["Elevator*"], ("Pitch Up", "Pitch Down"))) for line in subparts: subpart, joints, anims = line actor.makeSubpart(subpart, joints) path = "planes/{0}/{0}-{{0}}".format(modelname) d = dict((anim, path.format(anim)) for anim in anims) #actor.loadAnims(d, subpart, "mid") actor.loadAnims(d, subpart) for anim in anims: #actor.bindAnim(anim, subpart, "mid") actor.bindAnim(anim, subpart) #animcontrols[anim] = actor.getAnimControls(anim, subpart, # "mid", False)[0] animcontrols[anim] = actor.getAnimControls( anim, subpart, None, False)[0] actor.makeSubpart("propellers", "Propeller*") actor.verifySubpartsComplete() actor.setSubpartsComplete(True) for p in actor.getJoints("propellers", "Propeller*", "lodRoot"): self.propellers.append( actor.controlJoint(None, "propellers", p.getName())) #actor.pprint() cams = model.findAllMatches("**/camera ?*") if not cams.isEmpty(): cameras = actor.attachNewNode("cameras") cams.reparentTo(cameras) return actor, animcontrols
class CoreografiaSS(ShowBase): def __init__(self): ShowBase.__init__(self) self.disableMouse() self.Ralph = Actor("models/ralph") self.Ralph.setScale(.5, .5, .5) self.Ralph.reparentTo(self.render) self.Ralph.setPos(0, 10, -1) self.Ralph.listJoints() #Mover Piesecillo Ralph self.PieRalphIzq = self.Ralph.controlJoint(None, 'modelRoot', 'LeftBall') self.BrazoRalphDrc = self.Ralph.controlJoint(None, 'modelRoot', 'RightShoulder') self.CodoRalphDrc = self.Ralph.controlJoint(None, 'modelRoot', 'RightElbow') self.PieIzqAbajo = self.PieRalphIzq.hprInterval(0.3, Point3(0, 0, 0)) self.PieIzqArriba = self.PieRalphIzq.hprInterval(0.3, Point3(0, -20, 0)) self.MoverPieIzq = Sequence(self.PieIzqArriba, self.PieIzqAbajo) self.MoverPieIzq.loop() #BajarBrazo RotarMano self.BrazoRalphDrc.setHpr(10, 0, 10) self.CodoRalphDrc.setHpr(60, 170, 0) self.accept("q", self.moverDerecha) self.accept("e", self.moverIzquierda) self.accept("escape", sys.exit) def moverDerecha(self): x = self.Ralph.getH() self.Ralph.setHpr(x+10, 0, 0) def moverIzquierda(self): x = self.Ralph.getH() self.Ralph.setHpr(x-10, 0, 0)
def loadPlaneModel(self, modelname): """Loads models and animations from the planes directory.""" animcontrols = {} model = loader.loadModel("planes/{0}/{0}".format(modelname)) actor = Actor(model, setFinal=True, mergeLODBundles=True, allowAsyncBind=False, okMissing=False) #actor = Actor(model, lodNode="mid") subparts = ( # subpart, joints, animations ("Doors", ["Windscreen*", "Door*"], ("Open", "Close")), #("Landing Gear", ["Landing?Gear*", "LG*"], ("LG Out", "LG In")), ("Landing Gear", ["Landing?Gear*", "LG*"], ("LG Out",)), ("Ailerons", ["Aileron*"], ("Roll Left", "Roll Right")), ("Rudders", ["Rudder*"], ("Head Left", "Head Right")), ("Elevators", ["Elevator*"], ("Pitch Up", "Pitch Down")) ) for line in subparts: subpart, joints, anims = line actor.makeSubpart(subpart, joints) path = "planes/{0}/{0}-{{0}}".format(modelname) d = dict((anim, path.format(anim)) for anim in anims) #actor.loadAnims(d, subpart, "mid") actor.loadAnims(d, subpart) for anim in anims: #actor.bindAnim(anim, subpart, "mid") actor.bindAnim(anim, subpart) #animcontrols[anim] = actor.getAnimControls(anim, subpart, # "mid", False)[0] animcontrols[anim] = actor.getAnimControls(anim, subpart, None, False)[0] actor.makeSubpart("propellers", "Propeller*") actor.verifySubpartsComplete() actor.setSubpartsComplete(True) for p in actor.getJoints("propellers", "Propeller*", "lodRoot"): self.propellers.append(actor.controlJoint(None, "propellers", p.getName())) #actor.pprint() cams = model.findAllMatches("**/camera ?*") if not cams.isEmpty(): cameras = actor.attachNewNode("cameras") cams.reparentTo(cameras) return actor, animcontrols
class Player: def __init__(self, x, y, z, id): self.health = 100 radius = .15 height = 1 shape = BulletCylinderShape(radius, height, ZUp) self.playerNode = BulletCharacterControllerNode(shape, 0.4, str(id)) self.playerNode.setMaxJumpHeight(2.0) self.playerNode.setJumpSpeed(4.0) self.playerNP = base.render.attachNewNode(self.playerNode) self.playerNP.setPos(x, y, z) self.playerModel = Actor('models/soldier.egg', {"idle": "models/soldier_ani_idle.egg", "walk": "models/soldier_ani_walk.egg", "pistol": "models/soldier_ani_pistol.egg", "death": "models/soldier_ani_death.egg",}) self.playerModel.makeSubpart("legs", ["mixamorig:LeftUpLeg", "mixamorig:RightUpLeg"]) self.playerModel.makeSubpart("hips", ["mixamorig:Hips"], ["mixamorig:LeftUpLeg", "mixamorig:RightUpLeg", "mixamorig:Spine"]) self.playerModel.makeSubpart("upperBody", ["mixamorig:Spine"]) self.playerModel.pose("idle", 0, partName="hips") self.playerModel.setH(90) self.playerModel.setScale(.06) self.playerModel.setZ(-.45) self.playerModel.flattenLight() # self.playerModel.setLightOff()self.playerSpine self.playerModel.reparentTo(self.playerNP) self.playerSpine = self.playerModel.controlJoint(None, 'modelRoot', 'mixamorig:Spine') self.hand = self.playerModel.exposeJoint(None, 'modelRoot', 'mixamorig:RightHand') self.spineExpose = self.playerModel.exposeJoint(None, 'modelRoot', 'mixamorig:Spine') self.playerSpine.setH(-7) # player weapon self.weapon = Ak47(self.hand) # player animation self.xSpeed = 0 self.ySpeed = 0 self.animation = Animation(self) self.model = NodePath("MySpineNode") def bendBody(self): self.model.setPos(self.spineExpose, 0, 0, 0) obj = RayCollider.getObjectHit() self.model.lookAt(obj) self.playerSpine.setP(self.model.getP())
class Effects(ShowBase): def __init__(self): #ShowBase.__init__(self) #################fulscreen############### root = Tkinter.Tk() w = root.winfo_screenwidth() h = root.winfo_screenheight() props = WindowProperties() props.setSize(w, h) base.win.requestProperties(props) #################end####################3 #camera.setPos(-500,-80,0) base.enableParticles() self.txt = "" self.p = ParticleEffect() st_x = 5.0 ####-515,-60,0 st_y = 8.0 st_z = 0.0 self.c2 = Actor( 'Models/dancer/dancer' ) #Actor("Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve",{"run":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-run", "jump":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-jump", "offbalance":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-offbalance", "tireroll":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-tireroll"}) self.c2.setPos(offset_x + st_x, offset_y + st_y + 7, offset_z + st_z) self.c2.reparentTo(render) self.c2.loadAnims({'win': 'Models/dancer/dancer'}) self.c2.loop('win') '''self.tex = Texture() self.tex.setMinfilter(Texture.FTLinear) base.win.addRenderTexture(self.tex, GraphicsOutput.RTMTriggeredCopyTexture) self.backcam = base.makeCamera2d(base.win, sort=-10) self.background = NodePath("background") self.backcam.reparentTo(self.background) self.background.setDepthTest(0) self.background.setDepthWrite(0) self.backcam.node().getDisplayRegion(0).setClearDepthActive(0) #taskMgr.add(self.takeSnapShot, "takeSnapShot") self.bcard = base.win.getTextureCard() self.bcard.reparentTo(self.background) self.bcard.setTransparency(1) self.fcard = base.win.getTextureCard() self.fcard.reparentTo(render2d) self.fcard.setTransparency(1) base.setBackgroundColor(0,0,0,1) self.bcard.hide() self.fcard.show() self.fcard.setColor(1.0,1.0,1.0,0.99) self.fcard.setScale(1.00) self.fcard.setPos(0,0,0) self.fcard.setR(0) self.clickrate = 30 self.nextclick = 0''' self.c4 = Actor('Models/dancer/dancer') #self.c2.loadModel('Models/dancer/dancer') self.c4.setPos(offset_x - st_x, offset_y + st_y + 7, offset_z + st_z) self.c4.reparentTo(render) self.c4.loadAnims({'win': 'Models/dancer/dancer'}) self.c4.loop('win') #self.c2.setR(-90) #self.c2.loop('tireroll') #base.setSleep(0.5) self.c3 = Actor( "Models/cat-humans/bvw-f2004--ralph-egg/bvw-f2004--ralph/ralph") self.c3.setScale(2) self.c3.setPos(offset_x + 0, offset_y + 20, offset_z + (-1)) self.c3.reparentTo(render) self.c3.listJoints() #self.c4.listJoints() self.actorRh = self.c3.controlJoint(None, 'modelRoot', 'RightShoulder') self.actorLh = self.c3.controlJoint(None, 'modelRoot', 'LeftShoulder') self.actorNeck = self.c3.controlJoint(None, 'modelRoot', 'Neck') self.actorNeck1 = self.c3.controlJoint(None, 'modelRoot', 'Neck') #self.actorNeck.hprInterval(3,Point3(0,90,0)).loop() self.actorLh.hprInterval(3, Point3(90, 0, 0)).loop() self.actorRh.hprInterval(3, Point3(0, 0, -180)).loop() #self.actorRh.hprInterval(3,Point3(0,90,0)).loop() self.actorRh.setHpr(180, 180, -60) # For Both hands upward self.actorLh.setHpr(90, -90, 120) self.loadchar('', '') self.duckPlane = loader.loadModel('Models/plane/plane') self.duckPlane.setPos(offset_x - 2, offset_y + 8, offset_z + 10) #set its position self.duckPlane.reparentTo(render) #reparent to render self.duckPlane.setTransparency(1) self.duckTexs = self.loadTextureMovie(24, 'duck/duck_fly_left', 'png', padding=2) self.duckTask = taskMgr.add(self.textureMovie, "duckTask") self.duckTask.fps = 36 self.duckTask.obj = self.duckPlane self.duckTask.textures = self.duckTexs self.duckPlane.node().setEffect(BillboardEffect.makePointEye()) self.expPlane = loader.loadModel( 'Models/plane/plane') #load the object self.expPlane.setScale(18, 10, 10) self.expPlane.setPos(offset_x + 0, offset_y + 22, offset_z + 4) #set the position self.expPlane.reparentTo(render) #reparent to render self.expPlane.setTransparency(1) #enable transparency self.expTexs = self.loadTextureMovie(50, 'explosion/def', 'png', padding=4) #create the animation task self.expTask = taskMgr.add(self.textureMovie, "movieTask") self.expTask.fps = 30 #set framerate self.expTask.obj = self.expPlane #set object self.expTask.textures = self.expTexs #set texture list #self.expPlane.node().setEffect(BillboardEffect.makePointEye()) self.c1 = loader.loadModel("Models/Dynamite/Dynamite") self.c1.setPos(offset_x - 6, offset_y + 10, offset_z + 2) self.c1.reparentTo(render) self.expPlane1 = loader.loadModel( 'Models/plane/plane') #load the object #self.expPlane1.setScale(1,10,10) self.expPlane1.setPos(offset_x - 8, offset_y + 10, offset_z + 3) #set the position self.expPlane1.reparentTo(render) #reparent to render self.expPlane1.setTransparency(1) self.expTexs1 = self.loadTextureMovie(50, 'explosion1/explosion', 'png', padding=4) #create the animation task self.expTask1 = taskMgr.add(self.textureExplosion, "explosionTask") self.expTask1.fps = 30 #set framerate self.expTask1.obj = self.expPlane1 #set object self.expTask1.textures = self.expTexs1 #set texture list self.expPlane1.node().setEffect(BillboardEffect.makePointEye()) self.orientPlane = loader.loadModel( 'Models/plane/plane') #Load the object #self.orientPlane.setScale(1) self.orientTex = loader.loadTexture("Models/plane/textures/carpet.jpg") self.orientPlane.setTexture(self.orientTex, 1) #Set the texture self.orientPlane.reparentTo(render) #Parent to render #Set the position, orientation, and scale self.orientPlane.setPosHprScale(offset_x + 0, offset_y + 18, offset_z, 0, -90, 0, 20, 20, 20) def textureMovie(self, task): currentFrame = int(task.time * task.fps) task.obj.setTexture(task.textures[currentFrame % len(task.textures)], 1) return Task.cont def textureExplosion(self, task): currentFrame = int(task.time * task.fps) #print "curr " #print currentFrame%51 if ((currentFrame % len(task.textures)) > 10): self.c1.hide() elif ((currentFrame % len(task.textures)) <= 0): self.c1.show() task.obj.setTexture(task.textures[currentFrame % len(task.textures)], 1) return Task.cont def takeSnapShot(self, task): if (task.time > self.nextclick): self.nextclick += 1.0 / self.clickrate if (self.nextclick < task.time): self.nextclick = task.time base.win.triggerCopy() return Task.cont def loadTextureMovie(self, frames, name, suffix, padding=1): return [ loader.loadTexture( (name + "%0" + str(padding) + "d." + suffix) % i) for i in range(frames) ] def loadchar(self, main_char, txt): self.txt = txt if (txt == ''): self.t = loader.loadModel("Models/DJTable/DJTable") self.t.setPos(offset_x + 0, offset_y + 20, offset_z) self.t.setH(180) self.t.reparentTo(render) self.setupLights() self.loadParticleConfig('fountain2.ptf') else: self.t = main_char #loader.loadModel("Models/cat-vehicles-road/bvw-f2004--girlscar-egg/bvw-f2004--girlscar/girlcar")#loader.loadModel("Models/cat-vehicles-road/bvw-f2004--carnsx-egg/bvw-f2004--carnsx/carnsx") #self.t.setPos(0,20,0) #self.t.reparentTo(render) self.setupLights() self.loadParticleConfig('steam.ptf') def loadParticleConfig(self, file): #Start of the code from steam.ptf self.p.cleanup() self.p = ParticleEffect() if (self.txt == ''): self.txt = '' self.p.loadConfig(Filename(file)) self.p.setPos(0.000, 0, 2.500) elif (self.txt == 'blue'): self.txt = '' self.p.loadConfig(Filename('steam_front.ptf')) self.p.setPos(0.000, -1.8, -0.800) elif (self.txt == 'red'): self.txt = '' self.p.loadConfig(Filename(file)) self.p.setPos(0.000, 1.800, 0.250) self.p.start(self.t) def setupLights(self): ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.4, .4, .35, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0, 8, -2.5)) directionalLight.setColor(Vec4(0.9, 0.8, 0.9, 1)) self.t.setLight(self.t.attachNewNode(directionalLight)) self.t.setLight(self.t.attachNewNode(ambientLight)) #w = Effects() #run()
class ActorParcial(ShowBase): def __init__(self): ShowBase.__init__(self) self.disableMouse() # Instrucciones en pantalla self.Salir = addInstructions(.06, "[ESC]: Para Salir") self.Camara = addInstructions(.12, "[Q,E,A,D,W,S]: Para Controlar Camara") self.CabezaL = addInstructions(.18, "[G]: Para Mover Cabeza") self.CaderaL = addInstructions(.18, "[G]: Para Mover Cadera") # Cargar el Actor con sus animaciones self.Ralph = Actor("models/ralph") self.Ralph.setScale(.5, .5, .5) self.Ralph.setPos( 0, 10, -1) #(x -IZQ +DER ,y PROFUNDIDAD ,z +ARRIBA -ABAJO ) self.Ralph.reparentTo(self.render) # Declaración de partes del cuerpo self.Cabeza = self.Ralph.controlJoint(None, 'modelRoot', 'Neck') self.CaderaDerecha = self.Ralph.controlJoint(None, 'modelRoot', 'RightHip') self.CaderaIzquierda = self.Ralph.controlJoint(None, 'modelRoot', 'LeftHip') # Movimiento de Cabeza self.CabezaAbajo = self.Cabeza.hprInterval(0.5, Point3(0, 0, 0)) self.CabezaArriba = self.Cabeza.hprInterval(0.5, Point3(20, 0, 0)) # Movimientos de cadera derecha self.CaderaDerechaDerecha = self.CaderaDerecha.hprInterval( 0.5, Point3(4.9762, 0, 120)) self.CaderaDerechaNormal = self.CaderaDerecha.hprInterval( 0.5, Point3(4.9762, 0, 90)) # Movimientos de cadera izquierda self.CaderaIzquierdaIzquierda = self.CaderaIzquierda.hprInterval( 0.5, Point3(5.02118, -0.862563, 62.9857)) self.CaderaIzquierdaNormal = self.CaderaIzquierda.hprInterval( 0.5, Point3(5.02118, -0.862563, 92.9857)) # Secuencias de movimientos self.MoverCabeza = Sequence(self.CabezaArriba, self.CabezaAbajo) self.MoverCaderaDerechaIzquierda = Sequence( self.CaderaDerechaDerecha, self.CaderaDerechaNormal, self.CaderaIzquierdaIzquierda, self.CaderaIzquierdaNormal) # Eventos de los botones self.accept("escape", sys.exit) self.accept("q", self.camLeft) self.accept("e", self.camRight) self.accept("a", self.camIn) self.accept("d", self.camOut) self.accept("w", self.camUp) self.accept("s", self.camDown) self.accept("g", self.eventCabeza) self.accept("h", self.eventCadera) def eventCabeza(self): self.MoverCabeza.loop() def eventCadera(self): self.MoverCaderaDerechaIzquierda.loop() def camLeft(self): x = self.camera.getX() self.camera.setX(x - 2) def camRight(self): x = self.camera.getX() self.camera.setX(x + 2) def camUp(self): y = self.camera.getY() self.camera.setY(y + 2) def camDown(self): y = self.camera.getY() self.camera.setY(y - 2) def camIn(self): z = self.camera.getZ() self.camera.setZ(z + 2) def camOut(self): z = self.camera.getZ() self.camera.setZ(z - 2)
class Effects(ShowBase): def __init__(self): #ShowBase.__init__(self) #################fulscreen############### root = Tkinter.Tk() w = root.winfo_screenwidth() h = root.winfo_screenheight() props = WindowProperties() props.setSize(w, h) base.win.requestProperties(props) #################end####################3 #camera.setPos(-500,-80,0) base.enableParticles() self.txt = "" self.p = ParticleEffect() st_x = 5.0 ####-515,-60,0 st_y = 8.0 st_z = 0.0 self.c2 = Actor('Models/dancer/dancer')#Actor("Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve",{"run":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-run", "jump":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-jump", "offbalance":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-offbalance", "tireroll":"Models/cat-humans/bvw-f2004--eve-egg/bvw-f2004--eve/eve-tireroll"}) self.c2.setPos(offset_x+st_x,offset_y+st_y+7,offset_z+st_z) self.c2.reparentTo(render) self.c2.loadAnims({'win':'Models/dancer/dancer'}) self.c2.loop('win') '''self.tex = Texture() self.tex.setMinfilter(Texture.FTLinear) base.win.addRenderTexture(self.tex, GraphicsOutput.RTMTriggeredCopyTexture) self.backcam = base.makeCamera2d(base.win, sort=-10) self.background = NodePath("background") self.backcam.reparentTo(self.background) self.background.setDepthTest(0) self.background.setDepthWrite(0) self.backcam.node().getDisplayRegion(0).setClearDepthActive(0) #taskMgr.add(self.takeSnapShot, "takeSnapShot") self.bcard = base.win.getTextureCard() self.bcard.reparentTo(self.background) self.bcard.setTransparency(1) self.fcard = base.win.getTextureCard() self.fcard.reparentTo(render2d) self.fcard.setTransparency(1) base.setBackgroundColor(0,0,0,1) self.bcard.hide() self.fcard.show() self.fcard.setColor(1.0,1.0,1.0,0.99) self.fcard.setScale(1.00) self.fcard.setPos(0,0,0) self.fcard.setR(0) self.clickrate = 30 self.nextclick = 0''' self.c4 = Actor('Models/dancer/dancer') #self.c2.loadModel('Models/dancer/dancer') self.c4.setPos(offset_x-st_x,offset_y+st_y+7,offset_z+st_z) self.c4.reparentTo(render) self.c4.loadAnims({'win':'Models/dancer/dancer'}) self.c4.loop('win') #self.c2.setR(-90) #self.c2.loop('tireroll') #base.setSleep(0.5) self.c3 = Actor("Models/cat-humans/bvw-f2004--ralph-egg/bvw-f2004--ralph/ralph") self.c3.setScale(2) self.c3.setPos(offset_x+0,offset_y+20,offset_z+(-1)) self.c3.reparentTo(render) self.c3.listJoints() #self.c4.listJoints() self.actorRh = self.c3.controlJoint(None, 'modelRoot', 'RightShoulder') self.actorLh = self.c3.controlJoint(None, 'modelRoot', 'LeftShoulder') self.actorNeck = self.c3.controlJoint(None, 'modelRoot', 'Neck') self.actorNeck1 = self.c3.controlJoint(None, 'modelRoot', 'Neck') #self.actorNeck.hprInterval(3,Point3(0,90,0)).loop() self.actorLh.hprInterval(3,Point3(90,0,0)).loop() self.actorRh.hprInterval(3,Point3(0,0,-180)).loop() #self.actorRh.hprInterval(3,Point3(0,90,0)).loop() self.actorRh.setHpr(180,180,-60) # For Both hands upward self.actorLh.setHpr(90,-90,120) self.loadchar('','') self.duckPlane = loader.loadModel('Models/plane/plane') self.duckPlane.setPos(offset_x-2, offset_y+8, offset_z+10) #set its position self.duckPlane.reparentTo(render) #reparent to render self.duckPlane.setTransparency(1) self.duckTexs = self.loadTextureMovie(24, 'duck/duck_fly_left', 'png', padding = 2) self.duckTask = taskMgr.add(self.textureMovie, "duckTask") self.duckTask.fps = 36 self.duckTask.obj = self.duckPlane self.duckTask.textures = self.duckTexs self.duckPlane.node().setEffect(BillboardEffect.makePointEye()) self.expPlane = loader.loadModel('Models/plane/plane') #load the object self.expPlane.setScale(18,10,10) self.expPlane.setPos(offset_x+0, offset_y+22, offset_z+4) #set the position self.expPlane.reparentTo(render) #reparent to render self.expPlane.setTransparency(1) #enable transparency self.expTexs = self.loadTextureMovie(50, 'explosion/def','png', padding = 4) #create the animation task self.expTask = taskMgr.add(self.textureMovie, "movieTask") self.expTask.fps = 30 #set framerate self.expTask.obj = self.expPlane #set object self.expTask.textures = self.expTexs #set texture list #self.expPlane.node().setEffect(BillboardEffect.makePointEye()) self.c1 = loader.loadModel("Models/Dynamite/Dynamite") self.c1.setPos(offset_x-6,offset_y+10,offset_z+2) self.c1.reparentTo(render) self.expPlane1 = loader.loadModel('Models/plane/plane') #load the object #self.expPlane1.setScale(1,10,10) self.expPlane1.setPos(offset_x-8, offset_y+10, offset_z+3) #set the position self.expPlane1.reparentTo(render) #reparent to render self.expPlane1.setTransparency(1) self.expTexs1 = self.loadTextureMovie(50, 'explosion1/explosion','png', padding = 4) #create the animation task self.expTask1 = taskMgr.add(self.textureExplosion, "explosionTask") self.expTask1.fps = 30 #set framerate self.expTask1.obj = self.expPlane1 #set object self.expTask1.textures = self.expTexs1 #set texture list self.expPlane1.node().setEffect(BillboardEffect.makePointEye()) self.orientPlane = loader.loadModel('Models/plane/plane') #Load the object #self.orientPlane.setScale(1) self.orientTex = loader.loadTexture("Models/plane/textures/carpet.jpg") self.orientPlane.setTexture(self.orientTex, 1) #Set the texture self.orientPlane.reparentTo(render) #Parent to render #Set the position, orientation, and scale self.orientPlane.setPosHprScale(offset_x+0, offset_y+18, offset_z, 0, -90, 0, 20, 20, 20) def textureMovie(self, task): currentFrame = int(task.time * task.fps) task.obj.setTexture(task.textures[currentFrame % len(task.textures)], 1) return Task.cont def textureExplosion(self, task): currentFrame = int(task.time * task.fps) #print "curr " #print currentFrame%51 if((currentFrame%len(task.textures)) > 10): self.c1.hide() elif((currentFrame%len(task.textures)) <= 0): self.c1.show() task.obj.setTexture(task.textures[currentFrame % len(task.textures)], 1) return Task.cont def takeSnapShot(self, task): if (task.time > self.nextclick): self.nextclick += 1.0 / self.clickrate if (self.nextclick < task.time): self.nextclick = task.time base.win.triggerCopy() return Task.cont def loadTextureMovie(self, frames, name, suffix, padding = 1): return [loader.loadTexture((name+"%0"+str(padding)+"d."+suffix) % i) for i in range(frames)] def loadchar(self,main_char,txt): self.txt = txt if(txt == ''): self.t = loader.loadModel("Models/DJTable/DJTable") self.t.setPos(offset_x+0,offset_y+20,offset_z) self.t.setH(180) self.t.reparentTo(render) self.setupLights() self.loadParticleConfig('fountain2.ptf') else: self.t = main_char#loader.loadModel("Models/cat-vehicles-road/bvw-f2004--girlscar-egg/bvw-f2004--girlscar/girlcar")#loader.loadModel("Models/cat-vehicles-road/bvw-f2004--carnsx-egg/bvw-f2004--carnsx/carnsx") #self.t.setPos(0,20,0) #self.t.reparentTo(render) self.setupLights() self.loadParticleConfig('steam.ptf') def loadParticleConfig(self, file): #Start of the code from steam.ptf self.p.cleanup() self.p = ParticleEffect() if(self.txt == ''): self.txt = '' self.p.loadConfig(Filename(file)) self.p.setPos(0.000, 0, 2.500) elif(self.txt == 'blue'): self.txt = '' self.p.loadConfig(Filename('steam_front.ptf')) self.p.setPos(0.000, -1.8, -0.800) elif(self.txt == 'red'): self.txt = '' self.p.loadConfig(Filename(file)) self.p.setPos(0.000, 1.800, 0.250) self.p.start(self.t) def setupLights(self): ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.4, .4, .35, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3( 0, 8, -2.5 ) ) directionalLight.setColor(Vec4( 0.9, 0.8, 0.9, 1 ) ) self.t.setLight(self.t.attachNewNode(directionalLight)) self.t.setLight(self.t.attachNewNode(ambientLight)) #w = Effects() #run()
class Walker (PhysicalObject): collide_bits = SOLID_COLLIDE_BIT def __init__(self, incarnator, colordict=None, player=False): super(Walker, self).__init__() self.spawn_point = incarnator self.on_ground = False self.mass = 150.0 # 220.0 for heavy self.xz_velocity = Vec3(0, 0, 0) self.y_velocity = Vec3(0, 0, 0) self.factors = { 'forward': 7.5, 'backward': -7.5, 'left': 2.0, 'right': -2.0, 'crouch': 0.0, } self.movement = { 'forward': 0.0, 'backward': 0.0, 'left': 0.0, 'right': 0.0, 'crouch': 0.0, } self.head_height = Vec3(0, 1.5, 0) self.collides_with = MAP_COLLIDE_BIT | SOLID_COLLIDE_BIT self.grenade_loaded = False self.energy = 1.0 self.left_gun_charge = 1.0 self.right_gun_charge = 1.0 self.primary_color = [1,1,1,1] self.colordict = colordict if colordict else None self.crouching = False self.player = player self.can_jump = False self.crouch_impulse = 0 def get_model_part(self, obj_name): return self.actor.find("**/%s" % obj_name) def create_node(self): self.actor = Actor('walker.egg') if self.colordict: self.setup_color(self.colordict) self.actor.set_pos(*self.spawn_point.pos) self.actor.look_at(*self.spawn_point.heading) self.spawn_point.was_used() self.left_barrel_joint = self.actor.exposeJoint(None, 'modelRoot', 'left_barrel_bone') self.right_barrel_joint = self.actor.exposeJoint(None, 'modelRoot', 'right_barrel_bone') return self.actor def create_solid(self): walker_capsule = BulletGhostNode(self.name + "_walker_cap") self.walker_capsule_shape = BulletCylinderShape(.7, .2, YUp) walker_bullet_np = self.actor.attach_new_node(walker_capsule) walker_bullet_np.node().add_shape(self.walker_capsule_shape) walker_bullet_np.node().set_kinematic(True) walker_bullet_np.set_pos(0,1.5,0) walker_bullet_np.wrt_reparent_to(self.actor) self.world.physics.attach_ghost(walker_capsule) walker_bullet_np.node().setIntoCollideMask(GHOST_COLLIDE_BIT) return None def setup_shape(self, gnodepath, bone, pname): shape = BulletConvexHullShape() gnode = gnodepath.node() geom = gnode.get_geom(0) shape.add_geom(geom) node = BulletRigidBodyNode(self.name + pname) np = self.actor.attach_new_node(node) np.node().add_shape(shape) np.node().set_kinematic(True) np.wrt_reparent_to(bone) self.world.physics.attach_rigid_body(node) return np def setup_color(self, colordict): if colordict.has_key('barrel_color'): color = colordict['barrel_color'] self.get_model_part('left_barrel').setColor(*color) self.get_model_part('right_barrel').setColor(*color) if colordict.has_key('visor_color'): self.get_model_part('visor').setColor(*colordict['visor_color']) if colordict.has_key('body_primary_color'): color = colordict['body_primary_color'] self.primary_color = color for part in ['hull_primary', 'rt_leg_primary', 'lt_leg_primary', 'lb_leg_primary', 'rb_leg_primary', 'left_barrel_ring', 'right_barrel_ring', 'hull_bottom']: self.get_model_part(part).setColor(*color) if colordict.has_key('body_secondary_color'): color = colordict['body_secondary_color'] for part in ['hull_secondary', 'visor_stripe', 'rb_leg_secondary', 'rt_leg_secondary', 'lb_leg_secondary', 'lt_leg_secondary']: self.get_model_part(part).setColor(*color) return def attached(self): self.integrator = Integrator(self.world.gravity) #self.world.register_collider(self) self.world.register_updater(self) pelvis_bone = self.actor.controlJoint(None, 'modelRoot', 'pelvis_bone') left_foot_bone = self.actor.exposeJoint(None, 'modelRoot', 'left_foot_bone') left_foot_bone_origin_ref = self.actor.attach_new_node("left_foot_reference") left_foot_bone_origin_ref.set_pos(left_foot_bone.get_pos()) #pelvis_bone.attach_new_node(left_foot_bone_origin_ref) right_foot_bone = self.actor.exposeJoint(None, 'modelRoot', 'right_foot_bone') right_foot_bone_origin_ref = self.actor.attach_new_node("right_foot_reference") right_foot_bone_origin_ref.set_pos(right_foot_bone.get_pos()) #pelvis_bone.attach_new_node(right_foot_bone_origin_ref) left_bones = LegBones( self.world.scene, self.world.physics, self.actor.exposeJoint(None, 'modelRoot', 'left_hip_bone'), left_foot_bone, left_foot_bone_origin_ref, *[self.actor.controlJoint(None, 'modelRoot', name) for name in ['left_top_bone', 'left_bottom_bone']] ) right_bones = LegBones( self.world.scene, self.world.physics, self.actor.exposeJoint(None, 'modelRoot', 'right_hip_bone'), right_foot_bone, right_foot_bone_origin_ref, *[self.actor.controlJoint(None, 'modelRoot', name) for name in ['right_top_bone', 'right_bottom_bone']] ) self.skeleton = Skeleton(left_bones, right_bones, pelvis_bone) self.skeleton.setup_footsteps(self.world.audio3d) self.head_bone = self.actor.controlJoint(None, 'modelRoot', 'head_bone') self.head_bone_joint = self.actor.exposeJoint(None, 'modelRoot', 'head_bone') self.loaded_missile = LoadedMissile(self.head_bone_joint, self.primary_color) self.loaded_grenade = LoadedGrenade(self.head_bone_joint, self.primary_color) if self.player: self.sights = Sights(self.left_barrel_joint, self.right_barrel_joint, self.world) def collision(self, other, manifold, first): world_pt = manifold.get_position_world_on_a() if first else manifold.get_position_world_on_b() print self, 'HIT BY', other, 'AT', world_pt def handle_command(self, cmd, pressed): if cmd is 'crouch' and pressed: self.crouching = True if self.on_ground: self.can_jump = True if cmd is 'crouch' and not pressed and self.on_ground and self.can_jump: self.crouching = False self.y_velocity = Vec3(0, 6.8, 0) self.can_jump = False if cmd is 'fire' and pressed: self.handle_fire() return if cmd is 'missile' and pressed: if self.loaded_grenade.can_fire(): self.loaded_grenade.toggle_visibility() self.loaded_missile.toggle_visibility() return if cmd is 'grenade' and pressed: if self.loaded_missile.can_fire(): self.loaded_missile.toggle_visibility() self.loaded_grenade.toggle_visibility() return if cmd is 'grenade_fire' and pressed: if self.loaded_missile.can_fire(): self.loaded_missile.toggle_visibility() if not self.loaded_grenade.can_fire(): self.loaded_grenade.toggle_visibility() walker_v = Vec3(self.xz_velocity) walker_v.y = self.y_velocity.y self.loaded_grenade.fire(self.world, walker_v) return self.movement[cmd] = self.factors[cmd] if pressed else 0.0 def handle_fire(self): if self.loaded_missile.can_fire(): self.loaded_missile.fire(self.world) elif self.loaded_grenade.can_fire(): walker_v = self.xz_velocity walker_v.y = self.y_velocity.y self.loaded_grenade.fire(self.world, walker_v) else: p_energy = 0 hpr = 0 if self.left_gun_charge > self.right_gun_charge: origin = self.left_barrel_joint.get_pos(self.world.scene) hpr = self.left_barrel_joint.get_hpr(self.world.scene) p_energy = self.left_gun_charge if p_energy < MIN_PLASMA_CHARGE: return self.left_gun_charge = 0 else: origin = self.right_barrel_joint.get_pos(self.world.scene) hpr = self.right_barrel_joint.get_hpr(self.world.scene) p_energy = self.right_gun_charge if p_energy < MIN_PLASMA_CHARGE: return self.right_gun_charge = 0 hpr.y += 180 plasma = self.world.attach(Plasma(origin, hpr, p_energy)) def st_result(self, cur_pos, new_pos): return self.world.physics.sweepTestClosest(self.walker_capsule_shape, cur_pos, new_pos, self.collides_with, 0) def update(self, dt): dt = min(dt, 0.2) # let's just temporarily assume that if we're getting less than 5 fps, dt must be wrong. yaw = self.movement['left'] + self.movement['right'] self.rotate_by(yaw * dt * 60, 0, 0) walk = self.movement['forward'] + self.movement['backward'] start = self.position() cur_pos_ts = TransformState.make_pos(self.position() + self.head_height) if self.on_ground: friction = DEFAULT_FRICTION else: friction = AIR_FRICTION #to debug walk cycle (stay in place) #riction = 0 speed = walk pos = self.position() self.move_by(0, 0, speed) direction = self.position() - pos newpos, self.xz_velocity = Friction(direction, friction).integrate(pos, self.xz_velocity, dt) self.move(newpos) # Cast a ray from just above our feet to just below them, see if anything hits. pt_from = self.position() + Vec3(0, 1, 0) pt_to = pt_from + Vec3(0, -1.1, 0) result = self.world.physics.ray_test_closest(pt_from, pt_to, MAP_COLLIDE_BIT | SOLID_COLLIDE_BIT) # this should return 'on ground' information self.skeleton.update_legs(walk, dt, self.world.scene, self.world.physics) if self.y_velocity.get_y() <= 0 and result.has_hit(): self.on_ground = True self.crouch_impulse = self.y_velocity.y self.y_velocity = Vec3(0, 0, 0) self.move(result.get_hit_pos()) self.skeleton.left_leg_on_ground = True self.skeleton.right_leg_on_ground = True else: self.on_ground = False current_y = Point3(0, self.position().get_y(), 0) y, self.y_velocity = self.integrator.integrate(current_y, self.y_velocity, dt) self.move(self.position() + (y - current_y)) if self.crouching and self.skeleton.crouch_factor < 1: self.skeleton.crouch_factor += (dt*60)/10 self.skeleton.update_legs(0, dt, self.world.scene, self.world.physics) elif not self.crouching and self.skeleton.crouch_factor > 0: self.skeleton.crouch_factor -= (dt*60)/10 self.skeleton.update_legs(0, dt, self.world.scene, self.world.physics) #if self.crouch_impulse < 0: goal = self.position() adj_dist = abs((start - goal).length()) new_pos_ts = TransformState.make_pos(self.position() + self.head_height) sweep_result = self.st_result(cur_pos_ts, new_pos_ts) count = 0 while sweep_result.has_hit() and count < 10: moveby = sweep_result.get_hit_normal() self.xz_velocity = -self.xz_velocity.cross(moveby).cross(moveby) moveby.normalize() moveby *= adj_dist * (1 - sweep_result.get_hit_fraction()) self.move(self.position() + moveby) new_pos_ts = TransformState.make_pos(self.position() + self.head_height) sweep_result = self.st_result(cur_pos_ts, new_pos_ts) count += 1 if self.energy > WALKER_MIN_CHARGE_ENERGY: if self.left_gun_charge < 1: self.energy -= WALKER_ENERGY_TO_GUN_CHARGE[0] self.left_gun_charge += WALKER_ENERGY_TO_GUN_CHARGE[1] else: self.left_gun_charge = math.floor(self.left_gun_charge) if self.right_gun_charge < 1: self.energy -= WALKER_ENERGY_TO_GUN_CHARGE[0] self.right_gun_charge += WALKER_ENERGY_TO_GUN_CHARGE[1] else: self.right_gun_charge = math.floor(self.right_gun_charge) if self.energy < 1: self.energy += WALKER_RECHARGE_FACTOR * (dt) if self.player: self.sights.update(self.left_barrel_joint, self.right_barrel_joint)
class World(DirectObject): def __init__(self): #This code puts the standard title and instruction text on screen self.title = OnscreenText(text="", style=1, fg=(1,1,1,1), pos=(0.7,-0.95), scale = .07) self.onekeyText = genLabelText("ESC: Quit", 0) self.onekeyText = genLabelText("[1]: Calibrate", 1) #setup key input self.accept('escape', sys.exit) self.accept('1', self.calibrate) base.disableMouse() #Disable mouse-based camera-control camera.setPos(0,-15, 2) #Position the cameraffff self.eve = Actor("models/ralph") #Load our animated charachter self.eve.reparentTo(render) #Put it in the scene #Now we use controlJoint to get a NodePath that's in control of her neck #This must be done before any animations are played self.joints = dict() # mapping from names to NodePath objects self.modelQ = dict() # mapping from names to default joint orientations in the model self.jointCal = dict() # mapping from names to calibration quaternion self.jointCur = dict() # mapping from names to current device orientation for name in jointNames: self.joints[name] = self.eve.controlJoint(None, 'modelRoot', name) self.modelQ[name] = self.joints[name].getQuat() self.jointCal[name] = self.modelQ[name].identQuat() self.jointCur[name] = self.modelQ[name].identQuat() #We now play an animation. An animation must be played, or at least posed #for the nodepath we just got from controlJoint to actually effect the model #self.eve.actorInterval("walk", playRate = 2).loop() print self.eve.listJoints() self.setupLights() #Put in some default lighting # setup socket self.udpSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.udpSocket.bind(("localhost", 5555)) self.udpSocket.setblocking(0) taskMgr.add(self.checkSocket, "checkSocket") def checkSocket(self, task): r_read, r_write, r_error = select.select([self.udpSocket],[],[],0) while r_read: msg = self.udpSocket.recv(1024) #print msg msg_list = msg.split(',') node_id = int(msg_list[0]) [w, x, y, z] = [float(val) for val in msg_list[1:5]] seqNum = int(msg_list[5]) #print seqNum q = Quat() q.setR(w) q.setI(x) q.setJ(y) q.setK(z) self.jointCur[mapping[node_id]] = q # update root root = jointNames[0] self.joints[root].setQuat(self.modelQ[root]*(self.jointCal[root]*self.jointCur[root])) #other joints for name in jointNames[1:]: parentName = parents[name] _q = self.jointCal[parentName]*self.jointCur[parentName] _q = _q.conjugate() self.joints[name].setQuat((self.jointCal[name]*self.jointCur[name])*_q*self.modelQ[name]) r_read, r_write, r_error = select.select([self.udpSocket],[],[],0) return Task.cont def calibrate(self): for name in jointNames: self.jointCal[name] = self.jointCur[name].conjugate() def setupLights(self): #Sets up some default lighting ambientLight = AmbientLight( "ambientLight" ) ambientLight.setColor( Vec4(.4, .4, .35, 1) ) directionalLight = DirectionalLight( "directionalLight" ) directionalLight.setDirection( Vec3( 0, 8, -2.5 ) ) directionalLight.setColor( Vec4( 0.9, 0.8, 0.9, 1 ) ) render.setLight(render.attachNewNode( directionalLight ) ) render.setLight(render.attachNewNode( ambientLight ) )
class Grenade (Projectile): def __init__(self, pos, hpr, color, walker_v, name=None): super(Grenade, self).__init__(name) self.pos = Vec3(*pos) self.hpr = hpr self.move_divisor = 9 self.color = color self.forward_m = .25 self.walker_v = walker_v def create_node(self): self.model = Actor('grenade.egg') self.shell = self.model.find('**/shell') self.shell.set_color(*self.color) self.inner_top = self.model.find('**/inner_top') self.inner_bottom = self.model.find('**/inner_bottom') self.inner_top.set_color(*random.choice(ENGINE_COLORS)) self.inner_bottom.set_color(*random.choice(ENGINE_COLORS)) self.model.set_scale(GRENADE_SCALE) self.model.set_hpr(0,0,0) self.spin_bone = self.model.controlJoint(None, 'modelRoot', 'grenade_bone') return self.model def create_solid(self): node = BulletRigidBodyNode(self.name) node.set_angular_damping(.9) node_shape = BulletSphereShape(.08) node.add_shape(node_shape) node.set_mass(.5) return node def attached(self): self.node.set_pos(self.pos) self.node.set_hpr(self.hpr) self.world.register_updater(self) self.world.register_collider(self) self.solid.setIntoCollideMask(NO_COLLISION_BITS) self.solid.set_gravity(DEFAULT_GRAVITY*4.5) grenade_iv = self.world.scene.get_relative_vector(self.node, Vec3(0,8.5,13.5)) grenade_iv += (self.walker_v * 1/2) self.solid.apply_impulse(grenade_iv, Point3(*self.pos)) def decompose(self): clist = list(self.color) clist.extend([1]) expl_colors = [clist] expl_colors.extend(ENGINE_COLORS) expl_pos = self.node.get_pos(self.world.scene) for c in expl_colors: self.world.attach(TriangleExplosion(expl_pos, 1, size=.1, color=c, lifetime=40)) self.world.garbage.add(self) def update(self, dt): self.inner_top.set_color(*random.choice(ENGINE_COLORS)) self.inner_bottom.set_color(*random.choice(ENGINE_COLORS)) result = self.world.physics.contact_test(self.solid) self.spin_bone.set_hpr(self.spin_bone, 0,0,10) contacts = result.getContacts() if len(contacts) > 0: hit_node = contacts[0].get_node1().get_name() if hit_node.endswith("_walker_cap"): return clist = list(self.color) clist.extend([1]) expl_colors = [clist] expl_colors.extend(ENGINE_COLORS) expl_pos = self.node.get_pos(self.world.scene) for c in expl_colors: self.world.attach(TriangleExplosion(expl_pos, 3, size=.1, color=c, lifetime=80,)) self.world.do_explosion(self.node, 3, 100) self.world.garbage.add(self)
class World(DirectObject): def __init__(self): #This code puts the standard title and instuction text on screen self.title = OnscreenText(text="Panda3D: Embots - Joint Manipulation", style=1, fg=(1,1,1,1), pos=(0.8,-0.95), scale = .07) #setup key input self.accept('escape', sys.exit) #base.disableMouse() #Disable mouse-based camera-control camera.setPos(0,-20,0) #Position the camera self.teapot = loader.loadModel('models/teapot') self.teapot.reparentTo(render) self.teapot.setScale(0.2) self.tentacle = Actor("models/tentacle") #Load our animated charachter self.tentacle.reparentTo(render) #Put it in the scene self.tentacle.setScale(1.0) self.setupLights() #Put in some default lighting self.tentacleBase = self.tentacle.controlJoint(None, 'modelRoot', 'Bone') self.tentacleIK = SMRPy.SmrKinematicChain(True,True,'tentacle'); self.jointList = [] self.constraintList = [] self.createKinematicChain(self.tentacle, 'Bone', '', 0) myJoint = self.tentacleIK.getJointByName("Bone.006") self.myConstraint = SMRPy.SmrIKConstraint() self.myConstraint.setRelatedJointptr(myJoint) myConstraintPosition = SMRPy.SmrVector3(0.0,0.0,0.0) self.teapot.setPos(0.0,0.0,0.0) self.myConstraint.setPosition(myConstraintPosition) myConstraintPosition = SMRPy.SmrVector3(0.0,0.0,0.0) self.myConstraint.setOffset(myConstraintPosition) self.myKinematicSolver = SMRPy.SmrGSMMSolver(self.tentacleIK) self.myKinematicSolver.addConstraintPtr(self.myConstraint) taskMgr.add(self.ikStep, "ikStep") def ikStep(self, task): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.myConstraint.setPosition(SMRPy.SmrVector3(restrain(mpos.getX()) * 10, 0.0 , restrain(mpos.getY()) * 10 )) #self.tentacleBase.setR (restrain(mpos.getX()) * 20) self.teapot.setPos(restrain(mpos.getX()) * 10, 0.0 , restrain(mpos.getY()) * 10 ) self.myKinematicSolver.process() self.updatePandaSkeleton(self.tentacle, self.tentacleIK, 'Bone') return Task.cont def createKinematicChain(self, _tentacle, _initialJointName, _parentName, _weight): #get the tentacle's currentJoint currentPandaJoint = _tentacle.getJoints(_initialJointName) currentPandaCJoint = self.tentacle.controlJoint(None, 'modelRoot', _initialJointName) #get the first joint's position position = currentPandaCJoint.getPos() if (currentPandaJoint[0].getNumChildren() == 0): newJoint = SMRPy.SmrKinematicJoint(True) newJoint.setEndVect(position.getX(),position.getY(),position.getZ()); else: newJoint = SMRPy.SmrKinematicJoint(False) newJoint.setPos(position.getX(),position.getY(),position.getZ()) print "position", position.getX(), position.getY(), position.getZ() #newJoint.setRot(0,0,0) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) rotZ = (currentPandaCJoint.getH()/180.0)*3.14159; rotX = (currentPandaCJoint.getP()/180.0)*3.14159; rotY = (currentPandaCJoint.getR()/180.0)*3.14159; print rotX, rotY, rotZ, currentPandaCJoint.getName() # remove the setRot function veveal in C++, error prone newJoint.addDof(SMRPy.SmrVector3(0.0,0.0,1.0), rotZ - 1.0, rotZ + 1.0, rotZ, 0.01*_weight); newJoint.addDof(SMRPy.SmrVector3(1.0,0.0,0.0), rotX - 1.0, rotX + 1.0, rotX, 0.01*_weight); newJoint.addDof(SMRPy.SmrVector3(0.0,1.0,0.0), rotY, rotY, rotY, 0); _weight += 0.5 print newJoint.getName() print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren() self.jointList.append(newJoint) self.tentacleIK.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() print(childName) self.createKinematicChain(_tentacle, childName, _initialJointName, _weight) def updatePandaSkeleton(self, _pandaSkeleton, _smrSkeleton, _startJointName): currentPandaJoint = _pandaSkeleton.getJoints(_startJointName) currentPandaCJoint = _pandaSkeleton.controlJoint(None, 'modelRoot', _startJointName) currentSmrJoint = _smrSkeleton.getJointByName(_startJointName) self.synchronize(currentPandaCJoint, currentSmrJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() self.updatePandaSkeleton(_pandaSkeleton, _smrSkeleton, childName) def synchronize(self, _pandaCJoint, _smrJoint): #_smrJoint.setRot(3.14/20.0,0,0); smrQuaternion = _smrJoint.getRot() pandaQuaternion = Quat() pandaQuaternion.setI(smrQuaternion.getX()) pandaQuaternion.setJ(smrQuaternion.getY()) pandaQuaternion.setK(smrQuaternion.getZ()) pandaQuaternion.setR(smrQuaternion.getW()) _pandaCJoint.setQuat(pandaQuaternion) # def turnTentacle(self, task): #Check to make sure the mouse is readable # if base.mouseWatcherNode.hasMouse(): #get the mouse position as a Vec2. The values for each axis are from -1 to #1. The top-left is (-1,-1), the bottom rightis (1,1) # mpos = base.mouseWatcherNode.getMouse() #Here we multiply the values to get the amount of degrees to turn #Restrain is used to make sure the values returned by getMouse are in the #valid range. If this particular model were to turn more than this, #significant tearing would be visable #self.tentacleBase.setP(restrain(mpos.getY()) * -50) # self.tentacleBase.setR (restrain(mpos.getX()) * 20) # return Task.cont #Task continues infinitely def setupLights(self): #Sets up some default lighting lAttrib = LightAttrib.makeAllOff() ambientLight = AmbientLight( "ambientLight" ) ambientLight.setColor( Vec4(.4, .4, .35, 1) ) lAttrib = lAttrib.addLight( ambientLight ) directionalLight = DirectionalLight( "directionalLight" ) directionalLight.setDirection( Vec3( 0, 8, -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 )
class Agent: def __init__( self, _name ): print "Creating agent " + _name self.name = _name self.loadLightingFromConfig = 0 self.createShadowMap = 0 def setDataPath( self, _dataPath ): self.dataPath = _dataPath; def setActor( self, _modelFileName, _animationFileNames, _morphTargetsFileName ): self.modelFileName = _modelFileName; self.animationFileNames = _animationFileNames; self.morphTargetsFileName = _morphTargetsFileName; def setRealizer( self, _realizer ): self.realizer = _realizer; def setCameraMask( self, _mask ): self.cameraMask = _mask def setShadowMapParameters( self, _index, _distance ): self.createShadowMap = 1 self.shadowMapIndex = _index self.shadowMapDistance = _distance def setTransform( self, x, y, z, rx, ry, rz, scale ): self.agent.setPos( x, y, z ) self.agent.setScale( scale ) self.agent.setHpr( rx, ry, rz ) self.positionX = x self.positionY = y self.positionZ = z def getPosition( self ): return self.agent.getPos() def setLightingConfiguration( self, _config, _name ): self.lightingConfig = _config self.lightingConfigName = _name self.loadLightingFromConfig = 1 def init( self ): #load the agent and parent it to the world #The joints of this agent will reference Panda NodePaths, it will be possible to play animations on it self.animationAgent = Actor( self.modelFileName, self.animationFileNames ) self.agent = Actor( self.modelFileName, self.morphTargetsFileName ) self.targets = {#'Basis':[], 'ExpSmileClosed':[], 'ExpAnger':[], 'ExpDisgust':[], 'ExpFear':[], 'ExpSad':[], 'ExpSurprise':[], 'ExpSmileOpen':[], 'ModBlinkLeft':[], 'ModBlinkRight':[], 'ModBrowDownLeft':[], 'ModBrowDownRight':[], 'ModBlinkRight':[], 'ModBrowInRight':[], 'ModBrowInLeft':[], 'ModBrowUpLeft':[], 'ModBrowUpRight':[], 'ModEarsOut':[], 'ModEyeSquintLeft':[], 'ModEyeSquintRight':[], 'ModLookDown':[], 'ModLookLeft':[], 'ModLookRight':[], 'ModLookUp':[], 'ModBlinkLeft':[], 'Phonaah':[], 'PhonB,M,P':[], 'Phonbigaah':[], 'Phonch,J,sh':[], 'PhonD,S,T':[], 'Phonee':[], 'Phoneh':[], 'PhonF,V':[], 'Phoni':[], 'PhonK':[], 'PhonN':[], 'Phonoh':[], 'Phonooh,Q':[], 'PhonR':[], 'Phonth':[], 'PhonW':[]} iter = self.targets.iteritems() while True : try: morphsItem = iter.next() except StopIteration:break for i in range(2,7): #print (str(i)+'_'+morphsItem[0]) blendShape = self.agent.controlJoint(None, 'modelRoot', str(i)+'_'+morphsItem[0]) if(blendShape): morphsItem[1].append(blendShape) self.targets['inspire'] = [self.agent.controlJoint(None, 'modelRoot', 'inspire')] #instanciate a list in order to keep track of kinematic joints joints #in python runtime #if nothing points towards those joints, they get flushed by #python's garbage collector self.jointList = [] self.jointFKList = [] self.agentControlJoints = [] self.agentNodePaths = [] self.agentSMRSkel = SMRPy.SMRSkeleton(True,True,'agent') self.createSkel( self.agent, self.agentSMRSkel, 'root', '' ) #pascal: output of both skeletons amber and alfonse as chracter.bvh #SMRPy.exportSkeletonToBvh(self.name + '.bvh',self.agentSMRSkel); self.newSkeleton = SMRPy.SMRSkeleton(True,True,'pose') self.createFKSkel(self.animationAgent, self.newSkeleton, "root", '') self.realizer.addCharacter( self.name, self.agentSMRSkel ); for key in self.targets.keys(): self.realizer.addMorphTarget( self.name, key ) #TODO: declare morph targets into CharacterConfigurationFile self.realizer.addShaderParameter( self.name, 'blushing' ) #TODO: declare shader inputs into CharacterConfiguration file self.agent.reparentTo( render ) #self.agent.hide( BitMask32.bit( self.cameraMask ) ) #set lighting ambientColor = Vec4(0.0,0.0,0.0,0.0) self.lighting = shaders.Lighting( ambientColor ) if self.loadLightingFromConfig == 1: self.lighting.loadFromConfig( self.lightingConfig, self.lightingConfigName ) #shadow map if self.createShadowMap == 1: self.shadowMap = shadowmap.ShadowMap( self.shadowMapIndex, self.dataPath ) def setShaders( self, _shaders ): self.shaders = _shaders def update( self ): self.realizer.skeletonRequested() self.updatePandaSkeleton(self.agentControlJoints, self.agentSMRSkel) for key in self.targets.keys(): #print(key, "\n") weight = self.realizer.getMorphTargetWeight( self.name, key ) morphTargets = self.targets[key] for morphTarget in morphTargets : #print(weight, "\n") morphTarget.setX(weight) #blushingValue = self.realizer.getShaderParameterValue( self.name, 'blushing' ) #self.shaders.headShader.blushing.set( blushingValue ) self.lighting.update() if self.createShadowMap == 1: self.shaders.update() self.shadowMap.setLighting( self.lighting, Vec3( self.positionX, self.positionY, self.positionZ ), self.shadowMapDistance ) self.shaders.updateWithShadows( self.shadowMap ) else: self.shaders.update() def addAnimation(self,_actorName,_animationName): self.animationAgent.reparentTo(render) self.animationAgent.setScale(10) self.realizer.addAnimation(_actorName, _animationName) for i in range (self.animationAgent.getNumFrames(_animationName)): self.animationAgent.pose(_animationName,i) base.graphicsEngine.renderFrame() self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton) self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton) self.animationAgent.detachNode() print "animation",_animationName,"added" def addAnimationWE(self,_actorName,_animationName): self.animationAgent.reparentTo(render) self.animationAgent.setScale(10) agentSMRMotion = SMRPy.SMRMotion() agentSMRMotion.setTimeStep(0.04) self.realizer.addAnimation(_actorName, _animationName) for i in range (self.animationAgent.getNumFrames(_animationName)): self.animationAgent.pose(_animationName,i) base.graphicsEngine.renderFrame() self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton) self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton) agentSMRMotion.insertSkeleton(self.newSkeleton) self.animationAgent.detachNode() print "animation",_animationName,"added" SMRPy.exportMotionToBvh(_animationName+".bvh",agentSMRMotion) def createSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName): #get the agent's currentJoint currentPandaJoint = _pandaAgent.getJoints(None,_initialJointName) currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot', _initialJointName) self.agentControlJoints.append(currentPandaCJoint) #get the first joint's position position = currentPandaCJoint.getPos() if (currentPandaJoint[0].getNumChildren() == 0): newJoint = SMRPy.SMRJoint(True) newJoint.setEndVect(position.getX(),position.getY(),position.getZ()); else: newJoint = SMRPy.SMRJoint(False) rotZ = (currentPandaCJoint.getH()/180.0)*3.14159; rotX = (currentPandaCJoint.getP()/180.0)*3.14159; rotY = (currentPandaCJoint.getR()/180.0)*3.14159; quatZ = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0,0.0,1.0),rotZ) quatX = SMRPy.SMRQuaternion(SMRPy.SMRVector3(1.0,0.0,0.0),rotX) quatY = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0,1.0,0.0),rotY) quatRot = quatZ.multiply(quatX) quatRot = quatRot.multiply(quatY) quatRot.normalize(); #quatRot = currentPandaCJoint.getQuat() newJoint.setPos(position.getX(),position.getY(),position.getZ()) #newJoint.setRotQuat(quatRot.getR(),quatRot.getI(),quatRot.getJ(),quatRot.getK()) newJoint.setRotQuat(quatRot.getW(),quatRot.getX(),quatRot.getY(),quatRot.getZ()) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) #print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren() self.jointList.append(newJoint) _smrSkel.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() #print(childName) self.createSkel(_pandaAgent, _smrSkel, childName, _initialJointName) def createFKSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName): #get the agent's currentJoint currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName) currentPandaJointPath = _pandaAgent.exposeJoint(None, 'modelRoot', _initialJointName, "lodRoot", True) self.agentNodePaths.append(currentPandaJointPath) #get the first joint's position position = currentPandaJointPath.getPos() if (currentPandaJoint[0].getNumChildren() == 0): newJoint = SMRPy.SMRJoint(True) newJoint.setEndVect(position.getX(),position.getY(),position.getZ()); else: newJoint = SMRPy.SMRJoint(False) quatRot = currentPandaJointPath.getQuat() newJoint.setPos(position.getX(),position.getY(),position.getZ()) newJoint.setRotQuat(quatRot.getR(),quatRot.getI(),quatRot.getJ(),quatRot.getK()) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) #print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren() self.jointFKList.append(newJoint) _smrSkel.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() #print(childName) self.createFKSkel(_pandaAgent, _smrSkel, childName, _initialJointName) def updatePandaSkeleton(self, agentControlJoints, _smrSkeleton): #synchronize root joint SMRJoint = _smrSkeleton.getJoint(0) PANDAJoint = agentControlJoints[0] #position = SMRJoint.getPos() #PANDAJoint.setPos(position.X(),position.Y(),position.Z()); for i in range(_smrSkeleton.getNumjoints()): SMRJoint = _smrSkeleton.getJoint(i) PANDAJoint = agentControlJoints[i] self.synchronize(PANDAJoint,SMRJoint) def updateSMRSkeleton(self, agentNodePaths, _smrSkeleton): #synchronize root joint SMRJoint = _smrSkeleton.getJoint(0) PANDAJoint = agentNodePaths[0] position = PANDAJoint.getPos() SMRJoint.setPos(position.getX(),position.getY(),position.getZ()); for i in range(_smrSkeleton.getNumjoints()): SMRJoint = _smrSkeleton.getJoint(i) PANDAJoint = agentNodePaths[i] self.synchronizePandaToSMR(SMRJoint,PANDAJoint) def synchronizePandaToSMR(self, _SMRJoint, _PANDAJoint): pandaQuaternion = _PANDAJoint.getQuat() x = pandaQuaternion.getI() y = pandaQuaternion.getJ() z = pandaQuaternion.getK() w = pandaQuaternion.getR() _SMRJoint.setRotQuat(w,x,y,z) def synchronize(self, _pandaCJoint, _smrJoint): smrQuaternion = _smrJoint.getRot() pandaQuaternion = Quat() pandaQuaternion.setI(smrQuaternion.getX()) pandaQuaternion.setJ(smrQuaternion.getY()) pandaQuaternion.setK(smrQuaternion.getZ()) pandaQuaternion.setR(smrQuaternion.getW()) if not(pandaQuaternion.isNan()): _pandaCJoint.setQuat(pandaQuaternion)
class ArmatureUtils(): def __init__( self ): # Set up the components required to create joints: self.char = Character("IKChain") self.bundle = self.char.getBundle(0) self.skeleton = PartGroup(self.bundle, "<skeleton>") self.charNodePath = NodePath( self.char ) self.actor = None # Will be initialized after all the joints are created self.joints = {} self.controlNodes = {} def createJoint( self, name, parentJoint=None, rotMat=None, rotAxis=None, rotAngRad=0, translate=None, controlNode=None, static=False ): """ Utility function which helps to create a joint. """ if name in self.joints.keys(): raise sys.Exception( f"Cannot create joint with name {name}, already exists!" ) if rotAxis and rotMat: raise sys.Exception( "Only either rotMat or rotAxis can be used, not both!" ) if rotAxis: rotMat = Mat4.rotateMat( rotAngRad/math.pi*180, rotAxis ) if not rotMat: rotMat = Mat4.identMat() if translate: translateMat = Mat4.translateMat( translate ) else: translateMat = Mat4.identMat() transformMat = rotMat*translateMat if not parentJoint: joint = CharacterJoint( self.char, self.bundle, self.skeleton, name, transformMat ) else: joint = CharacterJoint( self.char, self.bundle, parentJoint, name, transformMat ) self.joints[name] = joint return joint def finalize( self ): self.actor = Actor( self.charNodePath ) for name, joint in self.joints.items(): controlNode = self.actor.controlJoint( None, "modelRoot", name ) self.controlNodes[name] = controlNode def getJoint( self, name ): return self.joints[name] def getControlNode( self, name ): return self.controlNodes[name] def getActor( self ): if not self.actor: raise sys.Exception( "Call 'finalize()' before calling 'getActor()'!" ) return self.actor
class Parcial(ShowBase): def __init__(self): ShowBase.__init__(self) self.disableMouse() # Instrucciones en pantalla self.Salir = addInstructions(.06, "[ESC]: Para Salir") self.Camara = addInstructions(.12, "[A]: Para Mover Cabeza") self.CabezaL = addInstructions(.18, "[S]: Para Mover Brazo Derecho") self.CabezaL = addInstructions(.24, "[D]: Para Mover Brazo Izquierdo") self.CaderaL = addInstructions(.30, "[F]: Para Mover Cadera") self.CaderaL = addInstructions(.36, "[G]: Para Mover Tronco") self.CaderaL = addInstructions(.42, "[H]: Para Girar") self.CaderaL = addInstructions(.48, "[Z]: Cabeza Cadera") self.CaderaL = addInstructions(.54, "[X]: Brazos") self.CaderaL = addInstructions(.60, "[C]: Giro Tronco") self.CaderaL = addInstructions(.66, "[V]: Todos a la vez") # Carga de un Actor self.Ralph = Actor("models/ralph", { "run": "models/ralph-run", "walk": "models/ralph-walk" }) self.Ralph.setScale(.5, .5, .5) self.Ralph.setPos( 0, 10, -1) #(x -IZQ +DER ,y PROFUNDIDAD ,z +ARRIBA -ABAJO ) self.Ralph.reparentTo(self.render) # Giro de ralph self.GiroTotal = self.Ralph.hprInterval(1.5, Point3(0, 359, 0)) # Declaración de partes del cuerpo self.Cabeza = self.Ralph.controlJoint(None, 'modelRoot', 'Neck') self.BrazoDerecho = self.Ralph.controlJoint(None, 'modelRoot', 'RightShoulder') self.BrazoIzquierdo = self.Ralph.controlJoint(None, 'modelRoot', 'LeftShoulder') self.CaderaDerecha = self.Ralph.controlJoint(None, 'modelRoot', 'RightHip') self.CaderaIzquierda = self.Ralph.controlJoint(None, 'modelRoot', 'LeftHip') self.Tronco = self.Ralph.controlJoint(None, 'modelRoot', 'Chest') # Movimiento de Cabeza self.CabezaAbajo = self.Cabeza.hprInterval(0.5, Point3(0, 0, 0)) self.CabezaArriba = self.Cabeza.hprInterval(0.5, Point3(20, 0, 0)) # Movimientos de brazo derecho self.BrazoDerechoAbajo = self.BrazoDerecho.hprInterval( 1.0, Point3(72.2059, 106.186, -45)) self.BrazoDerechoArriba = self.BrazoDerecho.hprInterval( 1.0, Point3(72.2059, 76.186, 6.02231)) # Movimientos de brazo izquierdo self.BrazoIzquierdoAbajo = self.BrazoIzquierdo.hprInterval( 1.0, Point3(160.1401, -22.1706, 6.55722)) self.BrazoIzquierdoArriba = self.BrazoIzquierdo.hprInterval( 1.0, Point3(80.1401, -52.1706, 6.55722)) # Movimientos de cadera derecha self.CaderaDerechaDerecha = self.CaderaDerecha.hprInterval( 0.5, Point3(4.9762, 0, 120)) self.CaderaDerechaNormal = self.CaderaDerecha.hprInterval( 0.5, Point3(4.9762, 0, 90)) # Movimientos de cadera derecha self.CaderaIzquierdaIzquierda = self.CaderaIzquierda.hprInterval( 0.5, Point3(5.02118, -0.862563, 62.9857)) self.CaderaIzquierdaNormal = self.CaderaIzquierda.hprInterval( 0.5, Point3(5.02118, -0.862563, 92.9857)) # Movimientos del tronco #self.Tronco.setHpr(0, 50, 0) self.TroncoIzquierda = self.Tronco.hprInterval(0.5, Point3(0, 50, 0)) self.TroncoDerecha = self.Tronco.hprInterval(0.5, Point3(0, -50, 0)) self.TroncoNormal = self.Tronco.hprInterval(0.5, Point3(0, 0, 0)) # Secuencias de movimientos self.MoverCabeza = Sequence(self.CabezaArriba, self.CabezaAbajo) self.MoverBrazoDerecho = Sequence(self.BrazoDerechoAbajo, self.BrazoDerechoArriba) self.MoverBrazoIzquierdo = Sequence(self.BrazoIzquierdoAbajo, self.BrazoIzquierdoArriba) self.MoverCaderaDerechaIzquierda = Sequence( self.CaderaDerechaDerecha, self.CaderaDerechaNormal, self.CaderaIzquierdaIzquierda, self.CaderaIzquierdaNormal) self.MoverTronco = Sequence(self.TroncoDerecha, self.TroncoNormal, self.TroncoIzquierda) self.Giro = Sequence(self.GiroTotal) # Paralelos self.CaderaCabeza = Parallel(self.MoverCabeza, self.MoverCaderaDerechaIzquierda) self.Brazos = Parallel(self.MoverBrazoDerecho, self.MoverBrazoIzquierdo) self.GiroTronco = Parallel(self.Giro, self.MoverTronco) self.Todos = Parallel(self.MoverCabeza, self.MoverCaderaDerechaIzquierda, self.MoverBrazoDerecho, self.MoverBrazoIzquierdo, self.Giro, self.MoverTronco) self.accept("escape", sys.exit) self.accept("a", self.eCabeza) self.accept("s", self.eBrazoDerecho) self.accept("d", self.eBrazoIzquierdo) self.accept("f", self.eCadera) self.accept("g", self.eTronco) self.accept("h", self.eGiro) self.accept("z", self.eCadCab) self.accept("x", self.eBrazos) self.accept("c", self.eGiroT) self.accept("v", self.eTodos) def eCabeza(self): self.MoverCabeza.start() def eBrazoDerecho(self): self.MoverBrazoDerecho.start() def eBrazoIzquierdo(self): self.MoverBrazoIzquierdo.start() def eCadera(self): self.MoverCaderaDerechaIzquierda.start() def eTronco(self): self.MoverTronco.start() def eGiro(self): self.Giro.start() def eCadCab(self): self.CaderaCabeza.start() def eBrazos(self): self.Brazos.start() def eGiroT(self): self.GiroTronco.start() def eTodos(self): self.Todos.loop()
class TccSample(ShowBase): def __init__(self): ShowBase.__init__(self) gltf.patch_loader(self.loader) self.disable_mouse() self.generateText() self.defineKeys() self.title = OnscreenText(text="Simulação do TCC", fg=(1, 1, 1, 1), parent=self.a2dBottomRight, align=TextNode.ARight, pos=(-0.1, 0.1), shadow=(0, 0, 0, .5), scale=.08) self.hand = Actor("models/Simple_Hand_AfterApply.gltf") self.hand.reparentTo(self.render) self.hand.setPos(0, 5, 0) self.loadHandJoints() self.taskMgr.add(self.setHandPostion, "HandTracking") print(self.camera.getPos()) print(self.hand.getPos()) def loadHandJoints(self): # Joints do dedo mindinho self.l2LittleFinger = self.hand.controlJoint(None, 'modelRoot', 'L2') self.l1LittleFinger = self.hand.controlJoint(None, 'modelRoot', 'L1') self.l0LittleFinger = self.hand.controlJoint(None, 'modelRoot', 'L0') # Joints do dedo anelar self.r2RingFinger = self.hand.controlJoint(None, 'modelRoot', 'R2') self.r1RingFinger = self.hand.controlJoint(None, 'modelRoot', 'R1') self.r0RingFinger = self.hand.controlJoint(None, 'modelRoot', 'R0') # Joints do dedo do meio self.m2MiddleFinger = self.hand.controlJoint(None, 'modelRoot', 'M2') self.m1MiddleFinger = self.hand.controlJoint(None, 'modelRoot', 'M1') self.m0MiddleFinger = self.hand.controlJoint(None, 'modelRoot', 'M0') # Joints do dedo indicador self.i2IndexFinger = self.hand.controlJoint(None, 'modelRoot', 'I2') self.i1IndexFinger = self.hand.controlJoint(None, 'modelRoot', 'I1') self.i0IndexFinger = self.hand.controlJoint(None, 'modelRoot', 'I0') # Joints do dedão da mão self.t2Thumb = self.hand.controlJoint(None, 'modelRoot', 'T2') self.t1Thumb = self.hand.controlJoint(None, 'modelRoot', 'T1') self.t0Thumb = self.hand.controlJoint(None, 'modelRoot', 'T0') def defineKeys(self): self.accept('escape', sys.exit) self.accept('1', self.changePerspective, [-60, -60]) self.accept('2', self.changePerspective, [-60, 60]) self.accept('3', self.moveFingers) self.accept('4', self.resetPerspective) self.accept('5', self.resetFinger) def generateText(self): self.onekeyText = genLabelText("ESC: Sair", 1, self) self.onekeyText = genLabelText("[1]: Muda a Perpectiva da câmera para o primeiro modo", 2, self) self.onekeyText = genLabelText("[2]: Muda a Perspectiva da câmera para o segundo modo", 3, self) self.onekeyText = genLabelText("[3]: Mexe os dedos", 4, self) self.onekeyText = genLabelText("[4]: Volta a perspectiva da mão para o formato original", 5, self) self.onekeyText = genLabelText("[5]: Volta os dedos para a posição inicial", 6, self) def setHandPostion(self, task): if self.mouseWatcherNode.hasMouse(): mousePosition = self.mouseWatcherNode.getMouse() self.hand.setX(mousePosition.getX() * 2) self.hand.setZ(mousePosition.getY() * 1.5) #print(self.hand.getPos()) return Task.cont def changePerspective(self, firstAngle, secondAngle): # Muda em Y e Z self.hand.setP(firstAngle) # Muda em X e Z self.hand.setR(secondAngle) # Muda em X e Y #self.hand.setH(60) def resetPerspective(self): self.hand.setP(0) self.hand.setR(0) def moveFingers(self): self.moveLittleFinger() self.moveRingFinger() self.moveMiddleFinger() self.moveIndexFinger() self.moveThumb() def moveLittleFinger(self): self.l0LittleFinger.setP(-20) self.l1LittleFinger.setP(-40) self.l2LittleFinger.setP(-30) def moveRingFinger(self): self.r0RingFinger.setP(-20) self.r1RingFinger.setP(-40) self.r2RingFinger.setP(-30) def moveMiddleFinger(self): self.m0MiddleFinger.setP(-20) self.m1MiddleFinger.setP(-40) self.m2MiddleFinger.setP(-30) def moveIndexFinger(self): self.i0IndexFinger.setP(-20) self.i1IndexFinger.setP(-40) self.i2IndexFinger.setP(-30) def moveThumb(self): self.t0Thumb.setP(-20) self.t1Thumb.setR(40) self.t2Thumb.setP(-30) self.t2Thumb.setR(40) def resetFinger(self): self.l0LittleFinger.setP(0) self.l1LittleFinger.setP(0) self.l2LittleFinger.setP(0) self.r0RingFinger.setP(0) self.r1RingFinger.setP(0) self.r2RingFinger.setP(0) self.m0MiddleFinger.setP(0) self.m1MiddleFinger.setP(0) self.m2MiddleFinger.setP(0) self.i0IndexFinger.setP(0) self.i1IndexFinger.setP(0) self.i2IndexFinger.setP(0) self.t0Thumb.setP(0) self.t1Thumb.setR(0) self.t2Thumb.setP(0) self.t2Thumb.setR(0)
class MyHand(ShowBase): def __init__(self, fingerInput): ShowBase.__init__(self) self.fingerPositions = fingerInput self.disableMouse() tex = loader.loadTexture('HandModel/HandTexture.png') self.Hand = Actor("HandModel/Hand.egg") self.Hand.setScale(1.5, 1.5, 1.5) self.Hand.setTexture(tex, 1) self.taskMgr.add(self.spinCameraTask, "SpinCameraTask") self.taskMgr.add(self.moveFingers, "MoveFingerTask") #self.taskMgr.add(self.updateFingers(fingerInput), "UpdateFingerTask") self.Hand.reparentTo(self.render) def moveFingers(self, task): #self.Hand.listJoints() angleDegrees = self.fingerPositions.get() #task.time * 100.0 #print(angleDegrees) if angleDegrees != "quit": angleDegrees *= 90 else: self.destroy() return task.done fingerList = ["pinky", "ring", "middle", "index", "thumb"] jointNumber = 3 for finger in fingerList: if finger == "thumb": NodePath = self.Hand.controlJoint(None, "modelRoot", finger + str(1)) Init_Rot = NodePath.getHpr() NodePath.setHpr( -15 * (sin(angleDegrees * pi / 180) + 1) + Init_Rot.getX(), -5 * (sin(angleDegrees * pi / 180) - 2) + Init_Rot.getY(), Init_Rot.getZ()) NodePath = self.Hand.controlJoint(None, "modelRoot", finger + str(2)) Init_Rot = NodePath.getHpr() NodePath.setHpr( Init_Rot.getX() + 15 * (sin(angleDegrees * pi / 180) - 1), Init_Rot.getY() - 15 * (sin(angleDegrees * pi / 180) - 1), Init_Rot.getZ()) NodePath = self.Hand.controlJoint(None, "modelRoot", finger + str(3)) Init_Rot = NodePath.getHpr() NodePath.setHpr( Init_Rot.getX() + 15 * (sin(angleDegrees * pi / 180) - 1), Init_Rot.getY() - 5 * (sin(angleDegrees * pi / 180) - 1), Init_Rot.getZ()) else: for i in range(1, jointNumber + 1): NodePath = self.Hand.controlJoint(None, "modelRoot", finger + str(i)) NodePath.setHpr(45 * (sin(angleDegrees * pi / 180) - 1), 0, 0) return task.cont #def updateFingers(self,task): # self.fingerPositions = input.get() # return task.cont def spinCameraTask(self, task): angleDegrees = 60 angleRadians = angleDegrees * (pi / 180.0) self.camera.setPos(20 * sin(angleRadians), -20 * cos(angleRadians), 4) self.camera.setHpr(angleDegrees, 0, 0) return Task.done
class DemoBase(ShowBase, ABC): def __init__(self): super().__init__() # Allow panda to synthesize shaders. Make sure hardware-animated-vertices is set # to true in panda config. render.setShaderAuto() # Show FPS self.setFrameRateMeter(True) # Load character self.character = Actor('data/character/character') self.character.reparentTo(self.render) self.joints = [] for name in JOINT_NAMES: j = self.character.controlJoint(None, 'modelRoot', name) j.reparentTo(self.render) self.joints.append(j) # Add lights dlight = core.DirectionalLight('DirectionalLight') dlight.setDirection(core.LVector3(2, 0, -1)) dlight.setColor(core.LColor(1, 1, 1, 1)) dlnp = self.render.attachNewNode(dlight) self.render.setLight(dlnp) alight = core.AmbientLight('AmbientLight') alight.setColor(core.LColor(0.6, 0.6, 0.6, 1)) alnp = self.render.attachNewNode(alight) self.render.setLight(alnp) # Camera angle in xy-plane (degrees) self.camera_angle = 0 # Camera control self.cam_left_pressed, self.cam_right_pressed = 0, 0 self.accept('a', self.set_cam_left_pressed, [1]) self.accept('a-up', self.set_cam_left_pressed, [0]) self.accept('d', self.set_cam_right_pressed, [1]) self.accept('d-up', self.set_cam_right_pressed, [0]) # Pad display self.pad_radius = 60 self.pad_outline = OnscreenImage('project/data/pad/pad_outline.png', (0, 0, 0)) self.pad_outline.setTransparency(core.TransparencyAttrib.MAlpha) self.pad_outline.hide() self.pad_response_circle = OnscreenImage( 'project/data/pad/pad_response_indicator.png', (0, 0, 0)) self.pad_response_circle.setTransparency( core.TransparencyAttrib.MAlpha) self.pad_response_circle.hide() self.accept('window-event', self.handle_window_event) # Pad control self.mouse1_pressed, self.controlling_pad = False, False self.accept('mouse1', self.set_mouse1_pressed, [True]) self.accept('mouse1-up', self.set_mouse1_pressed, [False]) # Load terrain self.heightmaps = {} self.set_heightmap('hmap2', 'project/data/heightmaps/hmap2.npy') # Heightmap choice self.accept('1', self.set_heightmap, ['hmap1', 'project/data/heightmaps/hmap1.npy']) self.accept('2', self.set_heightmap, ['hmap2', 'project/data/heightmaps/hmap2.npy']) self.accept('3', self.set_heightmap, ['hmap3', 'project/data/heightmaps/hmap3.npy']) self.accept('4', self.set_heightmap, ['hmap4', 'project/data/heightmaps/hmap4.npy']) self.accept('5', self.set_heightmap, ['hmap5', 'project/data/heightmaps/hmap5.npy']) # Tasks self.taskMgr.add(self.update_pad, 'UpdatePadTask', sort=1) self.last_update_char_time = 0 self.taskMgr.add(self.update_character, 'UpdateCharacterTask', sort=2) self.last_update_cam_time = 0 self.taskMgr.add(self.update_camera, 'UpdateCameraTask', sort=3) def set_cam_left_pressed(self, val): self.cam_left_pressed = val def set_cam_right_pressed(self, val): self.cam_right_pressed = val def set_mouse1_pressed(self, val): self.mouse1_pressed = val if self.mouse1_pressed and self.mouseWatcherNode.hasMouse(): mpos = self.screen_coords_to_pixels( self.mouseWatcherNode.getMouse()) diff = mpos - self.pad_center self.controlling_pad = diff.lengthSquared() <= self.pad_radius**2 else: self.controlling_pad = False def handle_window_event(self, window): self.window_w, self.window_h = window.getSize() min_dim = min(self.window_w, self.window_h) self.pad_radius = min_dim * 0.1 if self.window_w < 1300: self.pad_center = core.LVector2(min_dim * 0.15, min_dim * 0.15) else: self.pad_center = core.LVector2(self.window_w * 0.75, self.window_h * 0.5) self.pad_outline.setPos(self.pixels_to_im_coords(self.pad_center)) self.pad_outline.setScale(2 * self.pad_radius / min_dim) self.pad_outline.show() self.pad_response_circle.setScale(0.2 * self.pad_radius / min_dim) # Propagate event self.windowEvent(window) # Converts from screen coords in the [-1, 1] range to pixel coords def screen_coords_to_pixels(self, point): x_frac, y_frac = (point + 1.0) / 2.0 return core.LVector2(x_frac * self.window_w, (1 - y_frac) * self.window_h) # Converts from pixel coords to coords that can be passed in to OnscreenImage.setPos() def pixels_to_im_coords(self, point): px, py = point px, py = px - self.window_w / 2, py - self.window_h / 2 return core.LVector3(px, 0, -py) * (2.0 / min(self.window_w, self.window_h)) def update_pad(self, task): if self.controlling_pad and self.mouseWatcherNode.hasMouse(): mpos = self.screen_coords_to_pixels( self.mouseWatcherNode.getMouse()) pad_input = (mpos - self.pad_center) * PAD_SENSITIVITY if pad_input.lengthSquared() > 1: pad_input.normalize() resp_circle_pos = self.pad_center + pad_input * (self.pad_radius * 0.9) self.pad_response_circle.setPos( self.pixels_to_im_coords(resp_circle_pos)) self.pad_response_circle.show() else: pad_input = core.LVector2() self.pad_response_circle.hide() pad_input.setY(-pad_input.getY()) # flip y self.pad_input = pad_input return Task.cont def set_joint_global_xforms(self, global_xforms): # Invert global transforms inverse_global_xforms = [None] * NUM_JOINTS for i in PARENT_JOINTS: inverse_global_xforms[i] = core.LMatrix4() inverse_global_xforms[i].invertAffineFrom(global_xforms[i]) # Use each joint's global xform and the inverse of its parent's global xform to # compute and apply its local xform self.joints[0].setMat(global_xforms[0]) for i in range(1, NUM_JOINTS): local_xform = global_xforms[i] * inverse_global_xforms[ JOINT_PARENTS[i]] self.joints[i].setMat(local_xform) def update_character(self, task): dt = task.time - self.last_update_char_time self._update_character(task.time, dt) self.character.setPos(self.char_pos) self.set_joint_global_xforms([ core.LMatrix4(*m) for m in self.joint_global_xforms.reshape(31, 16) ]) self.last_update_char_time = task.time return Task.cont @abstractmethod def _update_character(self, t, dt): '''Should set self.char_pos and self.joint_global_xforms.''' raise NotImplementedError() def update_camera(self, task): dt = task.time - self.last_update_cam_time # Update camera angle self.camera_angle += 90 * (self.cam_right_pressed - self.cam_left_pressed) * dt # Reposition camera ang_rads = self.camera_angle * pi / 180 cam_offset = core.LVector3(300 * cos(ang_rads), 300 * sin(ang_rads), 320) self.camera.setPos(self.char_pos + cam_offset) self.camera.lookAt(self.char_pos + core.LVector3(0, 0, 80), core.LVector3(0, 0, 1)) self.last_update_cam_time = task.time return Task.cont def set_heightmap(self, name, fname): if name not in self.heightmaps: self.heightmaps[name] = Heightmap(name, fname, self.render) reset = False if hasattr(self, 'heightmap'): self.heightmap.model_np.stash() reset = True self.heightmap = self.heightmaps[name] self.heightmap.model_np.unstash() if reset: self.reset_level() def reset_level(self): self.camera_angle = 0 self.char_pos = core.LVector3()
class MayaDemo(ShowBase): R_LEG_JOINTS = ["joint6", "joint7", "joint8"] L_LEG_JOINTS = ["joint10", "joint11", "joint12"] def __init__(self): ShowBase.__init__(self) self.bandit = Actor("banditRiggedNoHat.egg") self.bandit.makeSubpart("r_leg", self.R_LEG_JOINTS) self.bandit.makeSubpart("l_leg", self.L_LEG_JOINTS) headJoint = self.bandit.exposeJoint(None, "modelRoot", "joint5") hat = loader.loadModel("{}_hat.egg".format(random.randint(0, 7))) hat.setPos(0, 0, -0.08) hat.setHpr(-90, 0, 0) hat.setScale(0.35) hat.reparentTo(headJoint) self.bandit.reparentTo(render) r_hip_ro = self.bandit.exposeJoint(None, "modelRoot", self.R_LEG_JOINTS[0]) r_hip_wo = self.bandit.controlJoint(None, "modelRoot", self.R_LEG_JOINTS[0]) r_knee_ro = self.bandit.exposeJoint(None, "modelRoot", self.R_LEG_JOINTS[1]) r_knee_wo = self.bandit.controlJoint(None, "modelRoot", self.R_LEG_JOINTS[1]) r_ankle_ro = self.bandit.exposeJoint(None, "modelRoot", self.R_LEG_JOINTS[2]) r_ankle_wo = self.bandit.controlJoint(None, "modelRoot", self.R_LEG_JOINTS[2]) distances = np.array([r_hip_ro.getDistance(r_knee_ro), r_knee_ro.getDistance(r_ankle_ro)]) self.r_leg = Leg.Leg(r_hip_ro, r_hip_wo, r_knee_ro, r_knee_wo, r_ankle_ro, r_ankle_wo, distances) l_hip = self.bandit.controlJoint(None, "modelRoot", self.L_LEG_JOINTS[0]) l_knee = self.bandit.controlJoint(None, "modelRoot", self.L_LEG_JOINTS[1]) l_ankle = self.bandit.exposeJoint(None, "modelRoot", self.L_LEG_JOINTS[2]) distances = np.array([l_hip.getDistance(l_knee), l_knee.getDistance(l_ankle)]) #self.l_leg = Leg.Leg(l_hip, l_knee, l_ankle, distances) self.accept("arrow_up", self.r_leg.moveAnkle, [(0, 0, 0.1)]) self.accept("arrow_down", self.r_leg.moveAnkle, [(0, 0, -0.1)]) self.accept("arrow_left", self.r_leg.rotateAnkle, [(0, 0, 10)]) self.accept("arrow_right", self.r_leg.rotateAnkle, [(0, 0, -10)]) # Draws debug skeleton self.bandit.setBin('background', 1) self.walkJointHierarchy(self.bandit, self.bandit.getPartBundle('modelRoot')) self.stream = StreamRead("/dev/input/smartshoes") self.last_t = time.time() taskMgr.add(self.getDeviceData, 'Stream reader') def getDeviceData(self, task): records = self.stream.readFromStream() if records and len(records[0]) == 10: records = map(float, records[0]) angular_velocity, acceleration, magnetic_field = [records[x:x+3] for x in range(0, 9, 3)] # Switch axis orientations angular_velocity[2], angular_velocity[0] = angular_velocity[0], angular_velocity[2] acceleration[2], acceleration[0] = acceleration[0], acceleration[2] magnetic_field[2], magnetic_field[0] = magnetic_field[0], magnetic_field[2] self.r_leg.ankle_rotation.rotationMagic(records[9], angular_velocity, acceleration, magnetic_field) self.r_leg.updateAnkleRotation() return task.again def walkJointHierarchy(self, actor, part, parentNode = None, indent = ""): if isinstance(part, CharacterJoint): np = actor.exposeJoint(None, 'modelRoot', part.getName()) if parentNode and parentNode.getName() != "root": lines = LineSegs() lines.setThickness(3.0) lines.setColor(random.random(), random.random(), random.random()) lines.moveTo(0, 0, 0) lines.drawTo(np.getPos(parentNode)) lnp = parentNode.attachNewNode(lines.create()) lnp.setBin("fixed", 40) lnp.setDepthWrite(False) lnp.setDepthTest(False) parentNode = np for child in part.getChildren(): self.walkJointHierarchy(actor, child, parentNode, indent + " ")
class LookingGrippingDemo(ShowBase): def __init__(self): # Initialize the ShowBase class from which we inherit, which will # create a window and set up everything we need for rendering into it. ShowBase.__init__(self) # This code puts the standard title and instruction text on screen self.title = OnscreenText(text="Panda3D: Tutorial - Joint Manipulation", fg=(1, 1, 1, 1), parent=base.a2dBottomRight, align=TextNode.ARight, pos=(-0.1, 0.1), shadow=(0, 0, 0, .5), scale=.08) self.onekeyText = genLabelText("ESC: Quit", 1) self.onekeyText = genLabelText("[1]: Teapot", 2) self.twokeyText = genLabelText("[2]: Candy cane", 3) self.threekeyText = genLabelText("[3]: Banana", 4) self.fourkeyText = genLabelText("[4]: Sword", 5) # Set up key input self.accept('escape', sys.exit) self.accept('1', self.switchObject, [0]) self.accept('2', self.switchObject, [1]) self.accept('3', self.switchObject, [2]) self.accept('4', self.switchObject, [3]) base.disableMouse() # Disable mouse-based camera-control camera.setPos(0, -15, 2) # Position the camera self.eve = Actor("models/eve", # Load our animated charachter {'walk': "models/eve_walk"}) self.eve.reparentTo(render) # Put it in the scene # Now we use controlJoint to get a NodePath that's in control of her neck # This must be done before any animations are played self.eveNeck = self.eve.controlJoint(None, 'modelRoot', 'Neck') # We now play an animation. An animation must be played, or at least posed # for the nodepath we just got from controlJoint to actually effect the # model self.eve.actorInterval("walk", playRate=2).loop() # Now we add a task that will take care of turning the head taskMgr.add(self.turnHead, "turnHead") # Now we will expose the joint the hand joint. ExposeJoint allows us to # get the position of a joint while it is animating. This is different than # controlJonit which stops that joint from animating but lets us move it. # This is particularly usefull for putting an object (like a weapon) in an # actor's hand self.rightHand = self.eve.exposeJoint(None, 'modelRoot', 'RightHand') # This is a table with models, positions, rotations, and scales of objects to # be attached to our exposed joint. These are stock models and so they needed # to be repositioned to look right. positions = [("teapot", (0, -.66, -.95), (90, 0, 90), .4), ("models/candycane", (.15, -.99, -.22), (90, 0, 90), 1), ("models/banana", (.08, -.1, .09), (0, -90, 0), 1.75), ("models/sword", (.11, .19, .06), (0, 0, 90), 1)] self.models = [] # A list that will store our models objects for row in positions: np = loader.loadModel(row[0]) # Load the model np.setPos(row[1][0], row[1][1], row[1][2]) # Position it np.setHpr(row[2][0], row[2][1], row[2][2]) # Rotate it np.setScale(row[3]) # Scale it # Reparent the model to the exposed joint. That way when the joint moves, # the model we just loaded will move with it. np.reparentTo(self.rightHand) self.models.append(np) # Add it to our models list self.switchObject(0) # Make object 0 the first shown self.setupLights() # Put in some default lighting # This is what we use to change which object it being held. It just hides all of # the objects and then unhides the one that was selected def switchObject(self, i): for np in self.models: np.hide() self.models[i].show() # This task gets the position of mouse each frame, and rotates the neck based # on it. def turnHead(self, task): # Check to make sure the mouse is readable if base.mouseWatcherNode.hasMouse(): # get the mouse position as a LVector2. The values for each axis are from -1 to # 1. The top-left is (-1,-1), the bottom right is (1,1) mpos = base.mouseWatcherNode.getMouse() # Here we multiply the values to get the amount of degrees to turn # Restrain is used to make sure the values returned by getMouse are in the # valid range. If this particular model were to turn more than this, # significant tearing would be visable self.eveNeck.setP(clamp(mpos.getX()) * 50) self.eveNeck.setH(clamp(mpos.getY()) * 20) return Task.cont # Task continues infinitely def setupLights(self): # Sets up some default lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.4, .4, .35, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(LVector3(0, 8, -2.5)) directionalLight.setColor((0.9, 0.8, 0.9, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight))
class Monster(): def __init__(self, setup_data, common, level=1.0, start_pos=(0,0,0)): common['monsterList'].append(self) id=len(common['monsterList'])-1 self.monsterList=common['monsterList'] self.waypoints_data=common['waypoints_data'] self.waypoints=common['waypoints'] self.audio3d=common['audio3d'] self.common=common #root node self.node=render.attachNewNode("monster") self.sound_node=None self.soundset=None self.actor=Actor(setup_data["model"],setup_data["anim"] ) self.actor.setBlend(frameBlend = True) self.actor.reparentTo(self.node) self.actor.setScale(setup_data["scale"]*random.uniform(0.9, 1.1)) self.actor.setH(setup_data["heading"]) self.actor.setBin("opaque", 10) self.rootBone=self.actor.exposeJoint(None, 'modelRoot', setup_data["root_bone"]) #sounds self.soundID=self.common['soundPool'].get_id() self.common['soundPool'].set_target(self.soundID, self.node) self.sound_names={"hit":setup_data["hit_sfx"], "arrow_hit":setup_data["arrowhit_sfx"], "attack":setup_data["attack_sfx"], "die":setup_data["die_sfx"]} self.vfx=setup_data["hit_vfx"] self.stats={"speed":setup_data["speed"], "hp":setup_data["hp"]*level, "armor":setup_data["armor"]*level, "dmg":setup_data["dmg"]*level } if self.stats['hp']>300: self.stats['hp']=300 self.maxHP=self.stats['hp'] self.HPring=Actor("models/ring_morph", {'anim' : 'models/ring_anim'}) self.HPring.setScale(0.07) self.HPring.setZ(0.4) self.HPring.setLightOff() self.HPring.reparentTo(self.node) self.HPvis=self.HPring.controlJoint(None, 'modelRoot', 'morph01') self.HPvis.setX(self.stats['hp']/300) self.HPring.hide(BitMask32.bit(1)) self.HPring.hide() #self.HPring.setColorScale(0.0, 1.0, 0.0, 1.0) #gamestate variables self.attack_pattern=setup_data["attack_pattern"] self.damage=setup_data["dmg"] #self.HP=setup_data["hp"] self.state="STOP" self.id=id self.nextWaypoint=None self.canSeePC=False self.PCisInRange=False self.PC=common['PC'] self.speed_mode=random.randrange(0+int(level),42+int(level), 7)/100.0 self.totalSpeed=self.stats['speed']+self.speed_mode self.sparkSum=0 self.lastMagmaDmg=0 self.DOT=0 self.arrows=set() self.traverser=CollisionTraverser("Trav"+str(self.id)) #self.traverser.showCollisions(render) self.queue = CollisionHandlerQueue() #bit masks: # 1 visibility polygons & coll-rays # 2 walls & radar-ray # 3 spheres #collision ray for testing visibility polygons coll=self.node.attachNewNode(CollisionNode('collRay')) coll.node().addSolid(CollisionRay(0, 0, 2, 0,0,-180)) coll.setTag("id", str(id)) coll.node().setIntoCollideMask(BitMask32.allOff()) coll.node().setFromCollideMask(BitMask32.bit(1)) self.traverser.addCollider(coll, self.queue) #radar collision ray self.radar=self.node.attachNewNode(CollisionNode('radarRay')) self.radar.node().addSolid(CollisionRay(0, 0, 1, 0,90,0)) self.radar.node().setIntoCollideMask(BitMask32.allOff()) self.radar.node().setFromCollideMask(BitMask32.bit(2)) self.radar.setTag("radar", str(id)) #self.radar.show() self.traverser.addCollider(self.radar, self.queue) #collision sphere self.coll_sphere=self.node.attachNewNode(CollisionNode('monsterSphere')) self.coll_sphere.node().addSolid(CollisionSphere(0, 0, 0.8, 0.8)) self.coll_sphere.setTag("id", str(id)) self.coll_sphere.node().setIntoCollideMask(BitMask32.bit(3)) #coll_sphere.show() #other monster blocking self.coll_quad=loader.loadModel("models/plane") self.coll_quad.reparentTo(self.node) #coll_quad=render.attachNewNode(CollisionNode('monsterSphere')) #coll_quad.node().addSolid(CollisionPolygon(Point3(-.5, -.5, 2), Point3(-.5, .5, 0), Point3(.5, .5, 0), Point3(.5, .5, 2))) #coll_quad.setTag("id", str(id)) #coll_quad.node().setIntoCollideMask(BitMask32.bit(2)) #coll_quad.reparentTo(self.node) #coll_quad.show() Sequence(Wait(random.uniform(.6, .8)), Func(self.restart)).start() self.node.setPos(render,start_pos) taskMgr.add(self.runAI, "AIfor"+str(self.id)) taskMgr.doMethodLater(.6, self.runCollisions,'collFor'+str(self.id)) taskMgr.doMethodLater(1.0, self.damageOverTime,'DOTfor'+str(self.id)) def damageOverTime(self, task): if self.state=="DIE": return task.done if self.DOT>0: self.doDamage(self.DOT) self.DOT=int((self.DOT*0.9)-1.0) if self.stats['hp']<1: self.actor.play("die") #self.common['soundPool'].play(self.soundID, self.sound_names["hit"]) self.common['soundPool'].play(self.soundID, self.sound_names["die"]) self.state="DIE" vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016, 24) return task.again def restart(self): self.state="SEEK" def check_stacking(self): for monster in self.monsterList: if monster and monster.id!=self.id : if self.node.getDistance(monster.node)< .8: if monster.state!="STOP" and self.state=="SEEK": if self.totalSpeed <= monster.totalSpeed: self.state="STOP" self.actor.stop() Sequence(Wait(1.5), Func(self.restart)).start() return True def doDamage(self, damage, igoreArmor=False): if self.state=="DIE": return if not igoreArmor: damage-=self.stats['armor'] if damage<1: damage=1 #print damage self.stats['hp']-=damage scale=self.stats['hp']/self.maxHP self.HPvis.setX(self.stats['hp']/300.0) #self.HPring.setColor(0.8*(1.0-scale), 0.8*scale, 0.0, 1.0) self.HPring.show() self.HPring.setColorScale((1.0-scale), scale, 0.0, 1.0) if self.stats['hp']<1: self.HPring.hide() def attack(self, pattern): if self.state=="DIE": return if not self.PC.node: return if pattern: next=pattern.pop() else: self.state="SEEK" self.PCisInRange=False return if self.PC.node and self.node: range= self.node.getDistance(self.PC.node) else: return #print range if range<1.8: self.PC.hit(self.damage) Sequence(Wait(next), Func(self.attack, pattern)).start() def onMagmaHit(self): if self.state=="DIE": return damage=self.lastMagmaDmg self.doDamage(damage) self.common['soundPool'].play(self.soundID, "onFire") vfx(self.node, texture="vfx/small_flame.png",scale=.6, Z=.7, depthTest=False, depthWrite=False).start(0.016, stopAtFrame=24) if self.stats['hp']<1: self.actor.play("die") self.common['soundPool'].play(self.soundID, "die3") self.state="DIE" vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016) def onPlasmaHit(self, damage): if self.state=="DIE": return self.doDamage(damage*1.5, True) #self.soundset["spark"].play() #self.common['soundPool'].play(self.soundID, "spark") if self.stats['hp']<1: self.actor.play("die") #self.soundset["die3"].play() self.common['soundPool'].play(self.soundID, "die3") self.state="DIE" vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016) #else: # short_vfx(self.node, texture="vfx/short_spark.png",scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.03) def onSparkHit(self, damage): if self.state=="DIE": return #print damage self.doDamage(damage) #self.soundset["spark"].play() self.common['soundPool'].play(self.soundID, "spark") if self.stats['hp']<1: self.actor.play("die") #self.soundset["die3"].play() self.common['soundPool'].play(self.soundID, "die3") self.state="DIE" vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016) else: short_vfx(self.node, texture="vfx/short_spark.png",scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.03) def onHit(self, damage, sound="hit"): if self.state=="DIE": return self.doDamage(damage) #print damage vfx(self.node, texture=self.vfx,scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016) if self.stats['hp']<1: self.actor.play("die") #self.sounds["die"].play() if sound: self.common['soundPool'].play(self.soundID, self.sound_names[sound]) self.common['soundPool'].play(self.soundID, self.sound_names["die"]) self.state="DIE" else: #self.sounds["hit"].play() if sound: self.common['soundPool'].play(self.soundID, self.sound_names[sound]) def findFirstWaypoint(self): min=100000 nearest=None for waypoint in self.waypoints: dist=self.node.getDistance(waypoint) if dist<min: min=dist nearest=waypoint return nearest def runCollisions(self, task): if self.state=="DIE": return task.done if self.node.getDistance(self.PC.node) >50.0: self.nextWaypoint=None return task.again if self.check_stacking(): return task.again self.radar.lookAt(self.PC.node) valid_waypoints=[] isFirstTest=True self.canSeePC=False self.traverser.traverse(render) self.queue.sortEntries() for entry in self.queue.getEntries(): if entry.getFromNodePath().hasTag("id"): #it's the monsters collRay valid_waypoints.append(int(entry.getIntoNodePath().getTag("index"))) #visibility polygons elif entry.getFromNodePath().hasTag("radar"): #it's the radar-ray #print "radar hit", entry.getIntoNodePath() if isFirstTest: isFirstTest=False #print "first hit!" #print "radar hit", entry.getIntoNodePath() if entry.getIntoNodePath().hasTag("player"): self.canSeePC=True '''distance={} for target in self.PC.myWaypoints: for waypoint in valid_waypoints: distance[target]=self.waypoints_data[target][waypoint] print(target, distance[target]) if distance: self.nextWaypoint=self.waypoints[min(distance, key=distance.get)] #print self.canSeePC''' if not valid_waypoints: #self.nextWaypoint=self.findFirstWaypoint() print(self.id, ": I'm lost!") valid_waypoints=[self.findFirstWaypoint()] #return task.again if self.state=="STOP": self.nextWaypoint=self.waypoints[random.choice(valid_waypoints)] return task.again best_distance=9000000 target_node=None for target in self.PC.myWaypoints: for valid in valid_waypoints: distance=self.waypoints_data[target][valid] #print "target->valid=",target, valid, distance if distance<best_distance: best_distance=distance target_node=valid if target_node: self.nextWaypoint=self.waypoints[target_node] else: #print "no target", valid_waypoints self.nextWaypoint=self.findFirstWaypoint() #self.waypoints[random.choice(valid_waypoints)] #print self.nextWaypoint return task.again def runAI(self, task): #print self.state if self.state=="DIE": self.coll_sphere.node().setIntoCollideMask(BitMask32.allOff()) self.coll_quad.removeNode() self.actor.play("die") self.common["kills"]-=1 if self.common["kills"]==0: Interactive(self.common, data.items['key'], self.node.getPos(render)) elif random.randrange(10)==0: Interactive(self.common, data.items['potion'], self.node.getPos(render)) Sequence(Wait(2.0),LerpPosInterval(self.node, 2.0, VBase3(self.node.getX(),self.node.getY(),self.node.getZ()-5)),Func(self.destroy)).start() return task.done elif self.state=="STOP": target=self.nextWaypoint if not target: return task.again self.node.headsUp(target) if self.node.getDistance(target)>0.3: self.node.setY(self.node, self.totalSpeed*globalClock.getDt()) if(self.actor.getCurrentAnim()!="walk"): self.actor.loop("walk") return task.again elif self.state=="ATTACK": self.node.headsUp(self.PC.node) if(self.actor.getCurrentAnim()!="attack"): self.actor.play("attack") #Sequence(Wait(self.attack_pattern[-1]+self.speed_mode), Func(self.attack, list(self.attack_pattern))).start() Sequence(Wait(self.attack_pattern[-1]), Func(self.attack, list(self.attack_pattern))).start() return task.again elif self.state=="SEEK": if self.PCisInRange: self.state="ATTACK" return task.again target=self.nextWaypoint if self.canSeePC and self.PC.HP>0: target=self.PC.node #print "target pc!" if not target: return task.again self.node.headsUp(target) if self.node.getDistance(target)>0.3: self.node.setY(self.node, self.totalSpeed*globalClock.getDt()) if(self.actor.getCurrentAnim()!="walk"): self.actor.loop("walk") return task.again else: #print "I'm stuck?" #print target #print self.canSeePC self.nextWaypoint=self.PC.node return task.again def destroy(self): #for sound in self.soundset: # self.soundset[sound].stop() #print "destroy:", #self.sound_node.reparentTo(render) #self.common['soundPool'].append([self.sound_node,self.soundset]) self.common['soundPool'].set_free(self.soundID) #self.sounds=None #print " sounds", self.arrows=None if self.actor: self.actor.cleanup() self.actor.removeNode() #print " actor", if taskMgr.hasTaskNamed("AIfor"+str(self.id)): taskMgr.remove("AIfor"+str(self.id)) #print " AI", if taskMgr.hasTaskNamed('collFor'+str(self.id)): taskMgr.remove('collFor'+str(self.id)) #print " collision", if taskMgr.hasTaskNamed('DOTfor'+str(self.id)): taskMgr.remove('DOTfor'+str(self.id)) if self.node: self.node.removeNode() #print " node", self.monsterList[self.id]=None self.traverser=None self.queue=None
class Agent: def __init__(self, _name): print "Creating agent " + _name self.name = _name self.loadLightingFromConfig = 0 self.createShadowMap = 0 def setDataPath(self, _dataPath): self.dataPath = _dataPath def setActor(self, _modelFileName, _animationFileNames, _morphTargetsFileName): self.modelFileName = _modelFileName self.animationFileNames = _animationFileNames self.morphTargetsFileName = _morphTargetsFileName def setRealizer(self, _realizer): self.realizer = _realizer def setCameraMask(self, _mask): self.cameraMask = _mask def setShadowMapParameters(self, _index, _distance): self.createShadowMap = 1 self.shadowMapIndex = _index self.shadowMapDistance = _distance def setTransform(self, x, y, z, rx, ry, rz, scale): self.agent.setPos(x, y, z) self.agent.setScale(scale) self.agent.setHpr(rx, ry, rz) self.positionX = x self.positionY = y self.positionZ = z def getPosition(self): return self.agent.getPos() def setLightingConfiguration(self, _config, _name): self.lightingConfig = _config self.lightingConfigName = _name self.loadLightingFromConfig = 1 def init(self): # load the agent and parent it to the world # The joints of this agent will reference Panda NodePaths, it will be possible to play animations on it self.animationAgent = Actor(self.modelFileName, self.animationFileNames) self.agent = Actor(self.modelFileName, self.morphTargetsFileName) self.targets = { #'Basis':[], "ExpSmileClosed": [], "ExpAnger": [], "ExpDisgust": [], "ExpFear": [], "ExpSad": [], "ExpSurprise": [], "ExpSmileOpen": [], "ModBlinkLeft": [], "ModBlinkRight": [], "ModBrowDownLeft": [], "ModBrowDownRight": [], "ModBlinkRight": [], "ModBrowInRight": [], "ModBrowInLeft": [], "ModBrowUpLeft": [], "ModBrowUpRight": [], "ModEarsOut": [], "ModEyeSquintLeft": [], "ModEyeSquintRight": [], "ModLookDown": [], "ModLookLeft": [], "ModLookRight": [], "ModLookUp": [], "ModBlinkLeft": [], "Phonaah": [], "PhonB,M,P": [], "Phonbigaah": [], "Phonch,J,sh": [], "PhonD,S,T": [], "Phonee": [], "Phoneh": [], "PhonF,V": [], "Phoni": [], "PhonK": [], "PhonN": [], "Phonoh": [], "Phonooh,Q": [], "PhonR": [], "Phonth": [], "PhonW": [], } iter = self.targets.iteritems() while True: try: morphsItem = iter.next() except StopIteration: break for i in range(2, 7): # print (str(i)+'_'+morphsItem[0]) blendShape = self.agent.controlJoint(None, "modelRoot", str(i) + "_" + morphsItem[0]) if blendShape: morphsItem[1].append(blendShape) self.targets["inspire"] = [self.agent.controlJoint(None, "modelRoot", "inspire")] # instanciate a list in order to keep track of kinematic joints joints # in python runtime # if nothing points towards those joints, they get flushed by # python's garbage collector self.jointList = [] self.jointFKList = [] self.agentControlJoints = [] self.agentNodePaths = [] self.agentSMRSkel = SMRPy.SMRSkeleton(True, True, "agent") self.createSkel(self.agent, self.agentSMRSkel, "root", "") # SMRPy.exportSkeletonToBvh('exportedPose.bvh',self.agentSMRSkel); self.newSkeleton = SMRPy.SMRSkeleton(True, True, "pose") self.createFKSkel(self.animationAgent, self.newSkeleton, "root", "") self.realizer.addCharacter(self.name, self.agentSMRSkel) for key in self.targets.keys(): self.realizer.addMorphTarget(self.name, key) self.realizer.addShaderParameter(self.name, "blushing") self.addAnimation(self.name, "breathing") self.addAnimation(self.name, "hands_claw") self.addAnimation(self.name, "hands_fist") self.addAnimation(self.name, "hands_index") self.addAnimation(self.name, "hands_open-relaxed") self.addAnimation(self.name, "hands_open-spread") self.addAnimation(self.name, "hands_open-straight") self.addAnimation(self.name, "hands_purse") self.addAnimation(self.name, "hands_ring") self.addAnimation(self.name, "poseNeutral") # self.addAnimation(self.name,'endian') if "default" in self.animationFileNames: self.addAnimation(self.name, "default") # self.realizer.addCharacterSkeleton( self.name, ); self.agent.reparentTo(render) self.agent.hide(BitMask32.bit(self.cameraMask)) # set lighting ambientColor = Vec4(0.0, 0.0, 0.0, 0.0) self.lighting = shaders.Lighting(ambientColor, self.agent) if self.loadLightingFromConfig == 1: self.lighting.loadFromConfig(self.lightingConfig, self.lightingConfigName) # shadow map if self.createShadowMap == 1: self.shadowMap = shadowmap.ShadowMap(self.shadowMapIndex, self.dataPath) def setShaders(self, _shaders): self.shaders = _shaders def update(self): self.realizer.skeletonRequested() self.updatePandaSkeleton(self.agentControlJoints, self.agentSMRSkel) for key in self.targets.keys(): # print(key, "\n") weight = self.realizer.getMorphTargetWeight(self.name, key) morphTargets = self.targets[key] for morphTarget in morphTargets: # print(weight, "\n") morphTarget.setX(weight) # blushingValue = self.realizer.getShaderParameterValue( self.name, 'blushing' ) # self.shaders.headShader.blushing.set( blushingValue ) self.lighting.update() if self.createShadowMap == 1: self.shadowMap.setLighting( self.lighting, Vec3(self.positionX, self.positionY, self.positionZ), self.shadowMapDistance ) self.shaders.updateWithShadows(self.shadowMap) else: self.shaders.update() def addAnimation(self, _actorName, _animationName): self.animationAgent.reparentTo(render) self.animationAgent.setScale(10) self.realizer.addAnimation(_actorName, _animationName) for i in range(self.animationAgent.getNumFrames(_animationName)): self.animationAgent.pose(_animationName, i) base.graphicsEngine.renderFrame() self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton) self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton) self.animationAgent.detachNode() print "animation", _animationName, "added" def createSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName): # get the agent's currentJoint currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName) currentPandaCJoint = _pandaAgent.controlJoint(None, "modelRoot", _initialJointName) self.agentControlJoints.append(currentPandaCJoint) # get the first joint's position position = currentPandaCJoint.getPos() if currentPandaJoint[0].getNumChildren() == 0: newJoint = SMRPy.SMRJoint(True) newJoint.setEndVect(position.getX(), position.getY(), position.getZ()) else: newJoint = SMRPy.SMRJoint(False) rotZ = (currentPandaCJoint.getH() / 180.0) * 3.14159 rotX = (currentPandaCJoint.getP() / 180.0) * 3.14159 rotY = (currentPandaCJoint.getR() / 180.0) * 3.14159 quatZ = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 0.0, 1.0), rotZ) quatX = SMRPy.SMRQuaternion(SMRPy.SMRVector3(1.0, 0.0, 0.0), rotX) quatY = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 1.0, 0.0), rotY) quatRot = quatZ.multiply(quatX) quatRot = quatRot.multiply(quatY) quatRot.normalize() newJoint.setPos(position.getX(), position.getY(), position.getZ()) newJoint.setRotQuat(quatRot.getW(), quatRot.getX(), quatRot.getY(), quatRot.getZ()) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) # print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren() self.jointList.append(newJoint) _smrSkel.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() # print(childName) self.createSkel(_pandaAgent, _smrSkel, childName, _initialJointName) def createFKSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName): # get the agent's currentJoint currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName) currentPandaJointPath = _pandaAgent.exposeJoint(None, "modelRoot", _initialJointName, "lodRoot", True) # currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot', _initialJointName) # if (_parentName == 'root' or _parentName == '' or _parentName == 'Bone.001'): # currentPandaJointPath = _pandaAgent.exposeJoint(None, 'modelRoot', _initialJointName) # else: # print(_parentName) # currentPandaJointPath = _pandaAgent.exposeJoint(None, _parentName, _initialJointName) # if (_initialJointName == "lhand"): # self.rhand = currentPandaJointPath self.agentNodePaths.append(currentPandaJointPath) # get the first joint's position position = currentPandaJointPath.getPos() if currentPandaJoint[0].getNumChildren() == 0: newJoint = SMRPy.SMRJoint(True) newJoint.setEndVect(position.getX(), position.getY(), position.getZ()) else: newJoint = SMRPy.SMRJoint(False) quatRot = currentPandaJointPath.getQuat() newJoint.setPos(position.getX(), position.getY(), position.getZ()) newJoint.setRotQuat(quatRot.getR(), quatRot.getI(), quatRot.getJ(), quatRot.getK()) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) # print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren() self.jointFKList.append(newJoint) _smrSkel.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() # print(childName) self.createFKSkel(_pandaAgent, _smrSkel, childName, _initialJointName) def updatePandaSkeleton(self, agentControlJoints, _smrSkeleton): # synchronize root joint SMRJoint = _smrSkeleton.getJoint(0) PANDAJoint = agentControlJoints[0] position = SMRJoint.getPos() # PANDAJoint.setPos(position.X() + 0.65 ,position.Y()-0.35,position.Z() - 1.4); PANDAJoint.setPos(position.X(), position.Y(), position.Z()) for i in range(_smrSkeleton.getNumjoints()): SMRJoint = _smrSkeleton.getJoint(i) PANDAJoint = agentControlJoints[i] self.synchronize(PANDAJoint, SMRJoint) def updateSMRSkeleton(self, agentNodePaths, _smrSkeleton): # synchronize root joint SMRJoint = _smrSkeleton.getJoint(0) PANDAJoint = agentNodePaths[0] position = PANDAJoint.getPos() SMRJoint.setPos(position.getX(), position.getY(), position.getZ()) for i in range(_smrSkeleton.getNumjoints()): SMRJoint = _smrSkeleton.getJoint(i) PANDAJoint = agentNodePaths[i] self.synchronizePandaToSMR(SMRJoint, PANDAJoint) def synchronizePandaToSMR(self, _SMRJoint, _PANDAJoint): pandaQuaternion = _PANDAJoint.getQuat() x = pandaQuaternion.getI() y = pandaQuaternion.getJ() z = pandaQuaternion.getK() w = pandaQuaternion.getR() _SMRJoint.setRotQuat(w, x, y, z) def synchronize(self, _pandaCJoint, _smrJoint): smrQuaternion = _smrJoint.getRot() pandaQuaternion = Quat() pandaQuaternion.setI(smrQuaternion.getX()) pandaQuaternion.setJ(smrQuaternion.getY()) pandaQuaternion.setK(smrQuaternion.getZ()) pandaQuaternion.setR(smrQuaternion.getW()) if not (pandaQuaternion.isNan()): _pandaCJoint.setQuat(pandaQuaternion)
class PlayerBase(DirectObject): def __init__(self): # Player Model setup self.player = Actor("Player", {"Run":"Player-Run", "Sidestep":"Player-Sidestep", "Idle":"Player-Idle"}) self.player.setBlend(frameBlend = True) self.player.setPos(0, 0, 0) self.player.pose("Idle", 0) self.player.reparentTo(render) self.player.hide() self.footstep = base.audio3d.loadSfx('footstep.ogg') self.footstep.setLoop(True) base.audio3d.attachSoundToObject(self.footstep, self.player) # Create a brush to paint on the texture splat = PNMImage("../data/Splat.png") self.colorBrush = PNMBrush.makeImage(splat, 6, 6, 1) CamMask = BitMask32.bit(0) AvBufMask = BitMask32.bit(1) self.avbuf = None if base.win: self.avbufTex = Texture('avbuf') self.avbuf = base.win.makeTextureBuffer('avbuf', 256, 256, self.avbufTex, True) cam = Camera('avbuf') cam.setLens(base.camNode.getLens()) self.avbufCam = base.cam.attachNewNode(cam) dr = self.avbuf.makeDisplayRegion() dr.setCamera(self.avbufCam) self.avbuf.setActive(False) self.avbuf.setClearColor((1, 0, 0, 1)) cam.setCameraMask(AvBufMask) base.camNode.setCameraMask(CamMask) # avbuf renders everything it sees with the gradient texture. tex = loader.loadTexture('gradient.png') np = NodePath('np') np.setTexture(tex, 100) np.setColor((1, 1, 1, 1), 100) np.setColorScaleOff(100) np.setTransparency(TransparencyAttrib.MNone, 100) np.setLightOff(100) cam.setInitialState(np.getState()) #render.hide(AvBufMask) # Setup a texture stage to paint on the player self.paintTs = TextureStage('paintTs') self.paintTs.setMode(TextureStage.MDecal) self.paintTs.setSort(10) self.paintTs.setPriority(10) self.tex = Texture('paint_av_%s'%id(self)) # Setup a PNMImage that will hold the paintable texture of the player self.imageSizeX = 64 self.imageSizeY = 64 self.p = PNMImage(self.imageSizeX, self.imageSizeY, 4) self.p.fill(1) self.p.alphaFill(0) self.tex.load(self.p) self.tex.setWrapU(self.tex.WMClamp) self.tex.setWrapV(self.tex.WMClamp) # Apply the paintable texture to the avatar self.player.setTexture(self.paintTs, self.tex) # team self.playerTeam = "" # A lable that will display the players team self.lblTeam = DirectLabel( scale = 1, pos = (0, 0, 3), frameColor = (0, 0, 0, 0), text = "TEAM", text_align = TextNode.ACenter, text_fg = (0,0,0,1)) self.lblTeam.reparentTo(self.player) self.lblTeam.setBillboardPointEye() # basic player values self.maxHits = 3 self.currentHits = 0 self.isOut = False self.TorsorControl = self.player.controlJoint(None,"modelRoot","Torsor") # setup the collision detection # wall and object collision self.playerSphere = CollisionSphere(0, 0, 1, 1) self.playerCollision = self.player.attachNewNode(CollisionNode("playerCollision%d"%id(self))) self.playerCollision.node().addSolid(self.playerSphere) base.pusher.addCollider(self.playerCollision, self.player) base.cTrav.addCollider(self.playerCollision, base.pusher) # foot (walk) collision self.playerFootRay = self.player.attachNewNode(CollisionNode("playerFootCollision%d"%id(self))) self.playerFootRay.node().addSolid(CollisionRay(0, 0, 2, 0, 0, -1)) self.playerFootRay.node().setIntoCollideMask(0) self.lifter = CollisionHandlerFloor() self.lifter.addCollider(self.playerFootRay, self.player) base.cTrav.addCollider(self.playerFootRay, self.lifter) # Player weapon setup self.gunAttach = self.player.exposeJoint(None, "modelRoot", "WeaponSlot_R") self.color = LPoint3f(1, 1, 1) self.gun = Gun(id(self)) self.gun.reparentTo(self.gunAttach) self.gun.hide() self.gun.setColor(self.color) self.hud = None # Player controls setup self.keyMap = {"left":0, "right":0, "forward":0, "backward":0} # screen sizes self.winXhalf = base.win.getXSize() / 2 self.winYhalf = base.win.getYSize() / 2 self.mouseSpeedX = 0.1 self.mouseSpeedY = 0.1 # AI controllable variables self.AIP = 0.0 self.AIH = 0.0 self.movespeed = 5.0 self.userControlled = False self.accept("Bulet-hit-playerCollision%d" % id(self), self.hit) self.accept("window-event", self.recalcAspectRatio) def runBase(self): self.player.show() self.gun.show() taskMgr.add(self.move, "moveTask%d"%id(self), priority=-4) def stopBase(self): taskMgr.remove("moveTask%d"%id(self)) self.ignoreAll() self.gun.remove() self.footstep.stop() base.audio3d.detachSound(self.footstep) self.player.delete() def setKey(self, key, value): self.keyMap[key] = value def setPos(self, pos): self.player.setPos(pos) def setColor(self, color=LPoint3f(0,0,0)): self.color = color self.gun.setColor(color) c = (color[0], color[1], color[2], 1.0) self.lblTeam["text_fg"] = c def setTeam(self, team): self.playerTeam = team self.lblTeam["text"] = team def shoot(self, shotVec=None): self.gun.shoot(shotVec) if self.hud != None: self.hud.updateAmmo(self.gun.maxAmmunition, self.gun.ammunition) def reload(self): self.gun.reload() if self.hud != None: self.hud.updateAmmo(self.gun.maxAmmunition, self.gun.ammunition) def recalcAspectRatio(self, window): self.winXhalf = window.getXSize() / 2 self.winYhalf = window.getYSize() / 2 def hit(self, entry, color): self.currentHits += 1 # Create a brush to paint on the texture splat = PNMImage("../data/Splat.png") splat = splat * LColorf(color[0], color[1], color[2], 1.0) self.colorBrush = PNMBrush.makeImage(splat, 6, 6, 1) self.paintAvatar(entry) if self.currentHits >= self.maxHits: base.messenger.send("GameOver-player%d" % id(self)) self.isOut = True def __paint(self, s, t): """ Paints a point on the avatar at texture coordinates (s, t). """ x = (s * self.p.getXSize()) y = ((1.0 - t) * self.p.getYSize()) # Draw in color directly on the avatar p1 = PNMPainter(self.p) p1.setPen(self.colorBrush) p1.drawPoint(x, y) self.tex.load(self.p) self.tex.setWrapU(self.tex.WMClamp) self.tex.setWrapV(self.tex.WMClamp) self.paintDirty = True def paintAvatar(self, entry): """ Paints onto an avatar. Returns true on success, false on failure (because there are no avatar pixels under the mouse, for instance). """ # First, we have to render the avatar in its false-color # image, to determine which part of its texture is under the # mouse. if not self.avbuf: return False #mpos = base.mouseWatcherNode.getMouse() mpos = entry.getSurfacePoint(self.player) ppos = entry.getSurfacePoint(render) self.player.showThrough(BitMask32.bit(1)) self.avbuf.setActive(True) base.graphicsEngine.renderFrame() self.player.show(BitMask32.bit(1)) self.avbuf.setActive(False) # Now we have the rendered image in self.avbufTex. if not self.avbufTex.hasRamImage(): print "Weird, no image in avbufTex." return False p = PNMImage() self.avbufTex.store(p) ix = int((1 + mpos.getX()) * p.getXSize() * 0.5) iy = int((1 - mpos.getY()) * p.getYSize() * 0.5) x = 1 if ix >= 0 and ix < p.getXSize() and iy >= 0 and iy < p.getYSize(): s = p.getBlue(ix, iy) t = p.getGreen(ix, iy) x = p.getRed(ix, iy) if x > 0.5: # Off the avatar. return False # At point (s, t) on the avatar's map. self.__paint(s, t) return True def move(self, task): if self is None: return task.done if self.userControlled: if not base.mouseWatcherNode.hasMouse(): return task.cont self.pointer = base.win.getPointer(0) mouseX = self.pointer.getX() mouseY = self.pointer.getY() if base.win.movePointer(0, self.winXhalf, self.winYhalf): p = self.TorsorControl.getP() + (mouseY - self.winYhalf) * self.mouseSpeedY if p <-80: p = -80 elif p > 90: p = 90 self.TorsorControl.setP(p) h = self.player.getH() - (mouseX - self.winXhalf) * self.mouseSpeedX if h <-360: h = 360 elif h > 360: h = -360 self.player.setH(h) else: self.TorsorControl.setP(self.AIP) self.player.setH(self.AIH) forward = self.keyMap["forward"] != 0 backward = self.keyMap["backward"] != 0 if self.keyMap["left"] != 0: if self.player.getCurrentAnim() != "Sidestep" and not (forward or backward): self.player.loop("Sidestep") self.player.setPlayRate(5, "Sidestep") self.player.setX(self.player, self.movespeed * globalClock.getDt()) elif self.keyMap["right"] != 0: if self.player.getCurrentAnim() != "Sidestep" and not (forward or backward): self.player.loop("Sidestep") self.player.setPlayRate(5, "Sidestep") self.player.setX(self.player, -self.movespeed * globalClock.getDt()) else: self.player.stop("Sidestep") if forward: if self.player.getCurrentAnim() != "Run": self.player.loop("Run") self.player.setPlayRate(5, "Run") self.player.setY(self.player, -self.movespeed * globalClock.getDt()) elif backward: if self.player.getCurrentAnim() != "Run": self.player.loop("Run") self.player.setPlayRate(-5, "Run") self.player.setY(self.player, self.movespeed * globalClock.getDt()) else: self.player.stop("Run") if not (self.keyMap["left"] or self.keyMap["right"] or self.keyMap["forward"] or self.keyMap["backward"] or self.player.getCurrentAnim() == "Idle"): self.player.loop("Idle") self.footstep.stop() else: self.footstep.play() return task.cont
class Agent: def __init__(self, _name): print "Creating agent " + _name self.name = _name def setDataPath(self, _dataPath): self.dataPath = _dataPath def setActor(self, _modelFileName, _animationFileNames, _morphTargetsFileName): self.modelFileName = _modelFileName self.animationFileNames = _animationFileNames self.morphTargetsFileName = _morphTargetsFileName def setRealizer(self, _realizer): self.realizer = _realizer def setTransform(self, x, y, z, rx, ry, rz, scale): self.agent.setPos(x, y, z) self.agent.setScale(scale) self.agent.setHpr(rx, ry, rz) self.positionX = x self.positionY = y self.positionZ = z def getPosition(self): return self.agent.getPos() def init(self): #load the agent and parent it to the world #The joints of this agent will reference Panda NodePaths, it will be possible to play animations on it self.animationAgent = Actor(self.modelFileName, self.animationFileNames) self.agent = Actor(self.modelFileName, self.morphTargetsFileName) maxMorphTargets = { 'MT_Jaw_Open': self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_Open'), 'MT_Jaw_L': self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_L'), 'MT_Jaw_R': self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_R'), 'MT_Jaw_Fwd': self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_Fwd'), 'MT_WideL': self.agent.controlJoint(None, 'modelRoot', 'MT_WideL'), 'MT_WideR': self.agent.controlJoint(None, 'modelRoot', 'MT_WideR'), 'MT_NarrowL': self.agent.controlJoint(None, 'modelRoot', 'MT_NarrowL'), 'MT_NarrowR': self.agent.controlJoint(None, 'modelRoot', 'MT_NarrowR'), 'MT_FrownL': self.agent.controlJoint(None, 'modelRoot', 'MT_FrownL'), 'MT_FrownR': self.agent.controlJoint(None, 'modelRoot', 'MT_FrownR'), 'MT_SneerL': self.agent.controlJoint(None, 'modelRoot', 'MT_SneerL'), 'MT_SneerR': self.agent.controlJoint(None, 'modelRoot', 'MT_SneerR'), 'MT_SquintL': self.agent.controlJoint(None, 'modelRoot', 'MT_SquintL'), 'MT_SquintR': self.agent.controlJoint(None, 'modelRoot', 'MT_SquintR'), 'MT_BrowUpL': self.agent.controlJoint(None, 'modelRoot', 'MT_BrowUpL'), 'MT_BrowUpR': self.agent.controlJoint(None, 'modelRoot', 'MT_BrowUpR'), 'MT_BrowDnL': self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnL'), 'MT_BrowDnR': self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnR'), 'MT_MBrowUp': self.agent.controlJoint(None, 'modelRoot', 'MT_MBrowUp'), 'MT_BrowDnR': self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnR'), 'MT_BrowDnL': self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnL'), 'MT_MBrowDn': self.agent.controlJoint(None, 'modelRoot', 'MT_MBrowDn'), 'MT_BrowSqueeze': self.agent.controlJoint(None, 'modelRoot', 'MT_BrowSqueeze'), 'MT_MouthL': self.agent.controlJoint(None, 'modelRoot', 'MT_MouthL'), 'MT_MouthR': self.agent.controlJoint(None, 'modelRoot', 'MT_MouthR'), 'MT_UprLipUpL': self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipUpL'), 'MT_UprLipUpR': self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipUpR'), 'MT_UprLipDnL': self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipDnL'), 'MT_UprLipDnR': self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipDnR'), 'MT_LwrLipUpL': self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipUpL'), 'MT_LwrLipUpR': self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipUpR'), 'MT_LwrLipDnL': self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipDnL'), 'MT_LwrLipDnR': self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipDnR'), 'MT_BlowCheeksL': self.agent.controlJoint(None, 'modelRoot', 'MT_BlowCheeksL'), 'MT_BlowCheeksR': self.agent.controlJoint(None, 'modelRoot', 'MT_BlowCheeksR'), 'MT_TongueOut': self.agent.controlJoint(None, 'modelRoot', 'MT_TongueOut'), 'MT_TongueUp': self.agent.controlJoint(None, 'modelRoot', 'MT_TongueUp'), 'MT_TongueTipUp': self.agent.controlJoint(None, 'modelRoot', 'MT_TongueTipUp'), 'MT_TongueL': self.agent.controlJoint(None, 'modelRoot', 'MT_TongueL'), 'MT_TongueR': self.agent.controlJoint(None, 'modelRoot', 'MT_TongueR'), 'MT_Blink_L': self.agent.controlJoint(None, 'modelRoot', 'MT_Blink_L'), 'MT_Blink_R': self.agent.controlJoint(None, 'modelRoot', 'MT_Blink_R') } self.targets = { #'Basis':[], 'ExpSmileClosed': { maxMorphTargets['MT_WideR']: 1.0, maxMorphTargets['MT_WideL']: 1.0 }, 'ExpAnger': { maxMorphTargets['MT_Jaw_Open']: -0.07, maxMorphTargets['MT_Jaw_Fwd']: 0.25, maxMorphTargets['MT_NarrowL']: 0.30, maxMorphTargets['MT_NarrowR']: 0.30, maxMorphTargets['MT_SquintL']: 0.60, maxMorphTargets['MT_SquintR']: 0.60, maxMorphTargets['MT_MBrowDn']: 1.0, maxMorphTargets['MT_BrowDnL']: 0.7, maxMorphTargets['MT_BrowDnR']: 0.7, maxMorphTargets['MT_SneerL']: 0.8, maxMorphTargets['MT_SneerR']: 0.8, maxMorphTargets['MT_FrownL']: 0.2, maxMorphTargets['MT_FrownR']: 0.2, maxMorphTargets['MT_UprLipDnL']: 0.45, maxMorphTargets['MT_UprLipDnR']: 0.45, maxMorphTargets['MT_LwrLipUpL']: 1.0, maxMorphTargets['MT_LwrLipUpR']: 1.0 }, 'ExpDisgust': { maxMorphTargets['MT_WideL']: 0.25, maxMorphTargets['MT_WideR']: 0.15, maxMorphTargets['MT_SquintL']: 0.40, maxMorphTargets['MT_SquintR']: 0.40, maxMorphTargets['MT_MBrowDn']: 0.25, maxMorphTargets['MT_BrowSqueeze']: 0.45, maxMorphTargets['MT_WideL']: 0.25, maxMorphTargets['MT_BrowDnL']: 0.50, maxMorphTargets['MT_BrowDnR']: 0.50, maxMorphTargets['MT_SneerL']: 2.0, maxMorphTargets['MT_SneerR']: 2.0, maxMorphTargets['MT_FrownL']: 0.25, maxMorphTargets['MT_FrownR']: 0.25, maxMorphTargets['MT_UprLipUpL']: 0.66, maxMorphTargets['MT_UprLipUpR']: 0.33, maxMorphTargets['MT_LwrLipUpL']: 0.40, maxMorphTargets['MT_LwrLipUpR']: 0.40 }, 'ExpFear': { maxMorphTargets['MT_Jaw_Open']: 0.15, maxMorphTargets['MT_Jaw_Fwd']: -0.3, maxMorphTargets['MT_NarrowL']: 0.24, maxMorphTargets['MT_NarrowR']: 0.24, maxMorphTargets['MT_SquintL']: -0.4, maxMorphTargets['MT_SquintR']: -0.4, maxMorphTargets['MT_BrowUpL']: 0.36, maxMorphTargets['MT_BrowUpR']: 0.36, maxMorphTargets['MT_MBrowUp']: 1.30, maxMorphTargets['MT_BrowSqueeze']: 0.40, maxMorphTargets['MT_FrownL']: 0.35, maxMorphTargets['MT_FrownR']: 0.35, maxMorphTargets['MT_UprLipDnL']: 0.25, maxMorphTargets['MT_UprLipDnR']: 0.25, maxMorphTargets['MT_LwrLipUpL']: 0.35, maxMorphTargets['MT_LwrLipUpR']: 0.35 }, 'ExpSad': { maxMorphTargets['MT_NarrowL']: 0.20, maxMorphTargets['MT_NarrowR']: 0.20, maxMorphTargets['MT_SquintL']: 0.20, maxMorphTargets['MT_SquintR']: 0.20, maxMorphTargets['MT_MBrowUp']: 0.40, maxMorphTargets['MT_BrowSqueeze']: 0.66, maxMorphTargets['MT_BrowDnL']: 0.66, maxMorphTargets['MT_BrowDnR']: 0.66, maxMorphTargets['MT_BlowCheeksL']: -0.25, maxMorphTargets['MT_BlowCheeksR']: -0.25, maxMorphTargets['MT_FrownL']: 0.66, maxMorphTargets['MT_FrownR']: 0.66, maxMorphTargets['MT_UprLipDnL']: 0.50, maxMorphTargets['MT_UprLipDnR']: 0.50, maxMorphTargets['MT_LwrLipUpL']: 0.66, maxMorphTargets['MT_LwrLipUpR']: 0.66 }, 'ExpSurprise': { maxMorphTargets['MT_Jaw_Open']: 0.25, maxMorphTargets['MT_NarrowL']: 0.24, maxMorphTargets['MT_NarrowR']: 0.24, maxMorphTargets['MT_SquintL']: -0.20, maxMorphTargets['MT_SquintR']: -0.20, maxMorphTargets['MT_BrowUpL']: 0.92, maxMorphTargets['MT_BrowUpR']: 0.92, maxMorphTargets['MT_MBrowUp']: 0.66 }, 'ExpSmileOpen': { maxMorphTargets['MT_Jaw_Open']: 0.16, maxMorphTargets['MT_WideL']: 0.740, maxMorphTargets['MT_WideR']: 0.740, maxMorphTargets['MT_SneerL']: 0.280, maxMorphTargets['MT_SneerR']: 0.280, maxMorphTargets['MT_BrowUpL']: 0.360, maxMorphTargets['MT_BrowUpR']: 0.360 }, 'ExpHappy': { maxMorphTargets['MT_Jaw_Open']: 0.22, maxMorphTargets['MT_WideL']: 0.75, maxMorphTargets['MT_WideR']: 0.75, maxMorphTargets['MT_SquintL']: 0.35, maxMorphTargets['MT_SquintR']: 0.35, maxMorphTargets['MT_BrowDnL']: 0.08, maxMorphTargets['MT_BrowDnR']: 0.08, maxMorphTargets['MT_UprLipUpL']: 0.15, maxMorphTargets['MT_UprLipUpR']: 0.15, maxMorphTargets['MT_LwrLipUpL']: 0.15, maxMorphTargets['MT_LwrLipUpR']: 0.15, maxMorphTargets['MT_BrowUpL']: 0.360, maxMorphTargets['MT_BrowUpR']: 0.360 }, 'ModBlinkLeft': { maxMorphTargets['MT_Blink_L']: 1.0 }, 'ModBlinkRight': { maxMorphTargets['MT_Blink_R']: 1.0 }, 'ModBrowDownLeft': { maxMorphTargets['MT_BrowDnL']: 1.0 }, 'ModBrowDownRight': { maxMorphTargets['MT_BrowDnR']: 1.0 }, 'ModBrowInRight': { maxMorphTargets['MT_BrowSqueeze']: 1.0 }, 'ModBrowInLeft': { maxMorphTargets['MT_BrowSqueeze']: 1.0 }, 'ModBrowUpLeft': { maxMorphTargets['MT_BrowUpL']: 1.0 }, 'ModBrowUpRight': { maxMorphTargets['MT_BrowUpR']: 1.0 }, #'ModEarsOut':[], 'ModEyeSquintLeft': { maxMorphTargets['MT_SquintL']: 1.0 }, 'ModEyeSquintRight': { maxMorphTargets['MT_SquintR']: 1.0 }, 'Phonaah': { maxMorphTargets['MT_Jaw_Open']: 1.0 }, 'PhonB,M,P': { maxMorphTargets['MT_WideL']: 0.5, maxMorphTargets['MT_WideR']: 0.5 }, 'Phonbigaah': { maxMorphTargets['MT_Jaw_Open']: 1.0 }, 'Phonch,J,sh': { maxMorphTargets['MT_WideL']: 0.5, maxMorphTargets['MT_WideR']: 0.5 }, 'PhonD,S,T': { maxMorphTargets['MT_WideL']: 0.5, maxMorphTargets['MT_WideR']: 0.5, maxMorphTargets['MT_Jaw_Open']: 0.2 }, 'Phonee': { maxMorphTargets['MT_WideL']: 0.5, maxMorphTargets['MT_WideR']: 0.5 }, 'Phoneh': { maxMorphTargets['MT_WideL']: 0.5, maxMorphTargets['MT_WideR']: 0.5, maxMorphTargets['MT_Jaw_Open']: 0.2 }, 'PhonF,V': { maxMorphTargets['MT_WideL']: 0.2, maxMorphTargets['MT_WideR']: 0.2, maxMorphTargets['MT_Jaw_Open']: 0.3, maxMorphTargets['MT_UprLipDnL']: 0.3, maxMorphTargets['MT_UprLipDnR']: 0.3 }, 'Phoni': { maxMorphTargets['MT_WideL']: 0.2, maxMorphTargets['MT_WideR']: 0.2, maxMorphTargets['MT_Jaw_Open']: 0.3 }, 'PhonK': { maxMorphTargets['MT_Jaw_Open']: 0.4 }, 'PhonN': { maxMorphTargets['MT_WideL']: 0.5, maxMorphTargets['MT_WideR']: 0.5 }, 'Phonoh': { maxMorphTargets['MT_Jaw_Open']: 0.4, maxMorphTargets['MT_NarrowL']: 0.55, maxMorphTargets['MT_NarrowR']: 0.55 }, 'Phonooh,Q': { maxMorphTargets['MT_Jaw_Open']: 0.4, maxMorphTargets['MT_NarrowL']: 0.55, maxMorphTargets['MT_NarrowR']: 0.55 }, 'PhonR': { maxMorphTargets['MT_WideL']: 0.5, maxMorphTargets['MT_WideR']: 0.5, maxMorphTargets['MT_Jaw_Open']: 0.2 }, 'Phonth': { maxMorphTargets['MT_WideL']: 0.5, maxMorphTargets['MT_WideR']: 0.5, maxMorphTargets['MT_Jaw_Open']: 0.2 }, 'PhonW': { maxMorphTargets['MT_Jaw_Open']: 0.3, maxMorphTargets['MT_NarrowL']: 0.7, maxMorphTargets['MT_NarrowR']: 0.7 }, 'AU26_MT_Jaw_Open': { maxMorphTargets['MT_Jaw_Open']: 1.0 }, 'AU30_MT_Jaw_L': { maxMorphTargets['MT_Jaw_L']: 1.0 }, 'AU30_MT_Jaw_R': { maxMorphTargets['MT_Jaw_R']: 1.0 }, 'AU31_MT_Jaw_Fwd': { maxMorphTargets['MT_Jaw_Fwd']: 1.0 }, 'AU27_MT_WideL': { maxMorphTargets['MT_WideL']: 1.0 }, 'AU27_MT_WideR': { maxMorphTargets['MT_WideR']: 1.0 }, 'AU18_MT_NarrowL': { maxMorphTargets['MT_NarrowL']: 1.0 }, 'AU18_MT_NarrowR': { maxMorphTargets['MT_NarrowL']: 1.0 }, 'AU42_MT_FrownL': { maxMorphTargets['MT_FrownL']: 1.0 }, 'AU42_MT_FrownR': { maxMorphTargets['MT_FrownR']: 1.0 }, 'AU9_MT_SneerL': { maxMorphTargets['MT_SneerL']: 1.0 }, 'AU9_MT_SneerR': { maxMorphTargets['MT_SneerR']: 1.0 }, 'AU46_MT_SquintL': { maxMorphTargets['MT_SquintL']: 1.0 }, 'AU46_MT_SquintR': { maxMorphTargets['MT_SquintR']: 1.0 }, 'AU2_MT_BrowUpL': { maxMorphTargets['MT_BrowUpL']: 1.0 }, 'AU2_MT_BrowUpR': { maxMorphTargets['MT_BrowUpR']: 1.0 }, 'AU4_MT_BrowDnL': { maxMorphTargets['MT_BrowDnL']: 1.0 }, 'AU4_MT_BrowDnR': { maxMorphTargets['MT_BrowDnR']: 1.0 }, 'AU4_MT_MBrowUp': { maxMorphTargets['MT_MBrowUp']: 1.0 }, 'AU1_MT_BrowDnR': { maxMorphTargets['MT_BrowDnR']: 1.0 }, 'AU1_MT_BrowDnL': { maxMorphTargets['MT_BrowDnL']: 1.0 }, 'AU1_MT_MBrowDn': { maxMorphTargets['MT_MBrowDn']: 1.0 }, 'AU44_MT_BrowSqueeze': { maxMorphTargets['MT_BrowSqueeze']: 1.0 }, 'AU12_MT_MouthL': { maxMorphTargets['MT_MouthL']: 1.0 }, 'AU12_MT_MouthR': { maxMorphTargets['MT_MouthR']: 1.0 }, 'AU5_MT_UprLipUpL': { maxMorphTargets['MT_UprLipUpL']: 1.0 }, 'AU5_MT_UprLipUpR': { maxMorphTargets['MT_UprLipUpR']: 1.0 }, 'MT_UprLipDnL': { maxMorphTargets['MT_UprLipDnL']: 1.0 }, 'MT_UprLipDnR': { maxMorphTargets['MT_UprLipDnR']: 1.0 }, 'MT_LwrLipUpL': { maxMorphTargets['MT_LwrLipUpL']: 1.0 }, 'MT_LwrLipUpR': { maxMorphTargets['MT_LwrLipUpR']: 1.0 }, 'MT_LwrLipDnL': { maxMorphTargets['MT_LwrLipDnL']: 1.0 }, 'MT_LwrLipDnR': { maxMorphTargets['MT_LwrLipDnR']: 1.0 }, 'AU33_MT_BlowCheeksL': { maxMorphTargets['MT_BlowCheeksL']: 1.0 }, 'AU33_MT_BlowCheeksR': { maxMorphTargets['MT_BlowCheeksR']: 1.0 }, 'AU36_MT_TongueOut': { maxMorphTargets['MT_TongueOut']: 1.0 }, 'AU36_MT_TongueUp': { maxMorphTargets['MT_TongueUp']: 1.0 }, 'AU36_MT_TongueTipUp': { maxMorphTargets['MT_TongueTipUp']: 1.0 }, 'AU36_MT_TongueL': { maxMorphTargets['MT_TongueL']: 1.0 }, 'AU36_MT_TongueR': { maxMorphTargets['MT_TongueR']: 1.0 }, 'AU45_MT_Blink_L': { maxMorphTargets['MT_Blink_L']: 1.0 }, 'AU45_MT_Blink_R': { maxMorphTargets['MT_Blink_R']: 1.0 } } #instanciate a list in order to keep track of kinematic joints joints #in python runtime #if nothing points towards those joints, they get flushed by #python's garbage collector self.jointList = [] self.jointFKList = [] self.agentControlJoints = [] self.agentNodePaths = [] self.agentSMRSkel = SMRPy.SMRSkeleton(True, True, 'agent') self.createSkel(self.agent, self.agentSMRSkel, 'root', '') #Pascal: output of both skeletons amber and alfonse as chracter.bvh #SMRPy.exportSkeletonToBvh(self.name + '.bvh',self.agentSMRSkel); self.newSkeleton = SMRPy.SMRSkeleton(True, True, 'pose') self.createFKSkel(self.animationAgent, self.newSkeleton, "root", '') self.realizer.addCharacter(self.name, self.agentSMRSkel) for key in self.targets.keys(): self.realizer.addMorphTarget( self.name, key ) #TODO: declare morph targets into CharacterConfigurationFile #self.realizer.addShaderParameter( self.name, 'blushing' ) #TODO: declare shader inputs into CharacterConfiguration file self.realizer.addBVHMotionToCharacter( self.name, 'hands_claw', open('./animations/hands_claw.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_index', open('./animations/hands_index.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_open-relaxed', open('./animations/hands_open-relaxed.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_open-spread', open('./animations/hands_open-spread.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_open-straight', open('./animations/hands_open-straight.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_purse', open('./animations/hands_purse.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ring', open('./animations/hands_ring.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'poseNeutral', open('./animations/poseNeutral.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'shrug', open('./animations/shrug.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_A', open('./animations/hands_DGS_A.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_B', open('./animations/hands_DGS_B.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_C', open('./animations/hands_DGS_C.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_D', open('./animations/hands_DGS_D.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_E', open('./animations/hands_DGS_E.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_F', open('./animations/hands_DGS_F.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_G', open('./animations/hands_DGS_G.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_H', open('./animations/hands_DGS_H.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_I', open('./animations/hands_DGS_I.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_J', open('./animations/hands_DGS_J.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_K', open('./animations/hands_DGS_K.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_L', open('./animations/hands_DGS_L.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_M', open('./animations/hands_DGS_M.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_N', open('./animations/hands_DGS_N.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_O', open('./animations/hands_DGS_O.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_P', open('./animations/hands_DGS_P.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_Q', open('./animations/hands_DGS_Q.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_R', open('./animations/hands_DGS_R.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_T', open('./animations/hands_DGS_T.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_U', open('./animations/hands_DGS_U.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_W', open('./animations/hands_DGS_W.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_X', open('./animations/hands_DGS_X.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_Y', open('./animations/hands_DGS_Y.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_Z', open('./animations/hands_DGS_Z.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_DGS_SCH', open('./animations/hands_DGS_SCH.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_A', open('./animations/hands_ASL_A.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_B', open('./animations/hands_ASL_B.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_C', open('./animations/hands_ASL_C.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_D', open('./animations/hands_ASL_D.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_E', open('./animations/hands_ASL_E.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_F', open('./animations/hands_ASL_F.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_G', open('./animations/hands_ASL_G.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_H', open('./animations/hands_ASL_H.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_I', open('./animations/hands_ASL_I.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_J', open('./animations/hands_ASL_J.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_K', open('./animations/hands_ASL_K.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_L', open('./animations/hands_ASL_L.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_M', open('./animations/hands_ASL_M.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_N', open('./animations/hands_ASL_N.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_O', open('./animations/hands_ASL_O.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_P', open('./animations/hands_ASL_P.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_Q', open('./animations/hands_ASL_Q.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_R', open('./animations/hands_ASL_R.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_T', open('./animations/hands_ASL_T.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_U', open('./animations/hands_ASL_U.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_V', open('./animations/hands_ASL_V.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_W', open('./animations/hands_ASL_W.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_X', open('./animations/hands_ASL_X.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_Y', open('./animations/hands_ASL_Y.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_Z', open('./animations/hands_ASL_Z.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_1CL', open('./animations/hands_ASL_1CL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_2CL', open('./animations/hands_ASL_2CL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_3CL', open('./animations/hands_ASL_3CL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_4CL', open('./animations/hands_ASL_4CL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_5aCL', open('./animations/hands_ASL_5aCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_5bCL', open('./animations/hands_ASL_5bCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_ACL', open('./animations/hands_ASL_ACL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_BCL', open('./animations/hands_ASL_BCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_CCL', open('./animations/hands_ASL_CCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_FCL', open('./animations/hands_ASL_FCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_ICL', open('./animations/hands_ASL_ICL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_ILYCL', open('./animations/hands_ASL_ILYCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_SCL', open('./animations/hands_ASL_SCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_VaCL', open('./animations/hands_ASL_VaCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_VbCL', open('./animations/hands_ASL_VbCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_YCL', open('./animations/hands_ASL_YCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_CbCL', open('./animations/hands_ASL_CbCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter( self.name, 'hands_ASL_TCL', open('./animations/hands_ASL_TCL.bvh', "r").read()) firingstevenhigh = open('./animations/alfonse-FiringStevenHigh.bvh', "r").read() self.realizer.addBVHMotionToCharacter(self.name, 'FiringStevenHigh', firingstevenhigh) print("done") self.agent.reparentTo(render) def update(self): self.realizer.skeletonRequested() skeletonHasBeenUpdated = False while (not skeletonHasBeenUpdated): #wait until skeleton can be displayed if (self.realizer.skeletonIsReadyToBeDisplayed(self.name)): self.updatePandaSkeleton(self.agentControlJoints, self.agentSMRSkel) skeletonHasBeenUpdated = True for key in self.realizer.getModifiedMorphTargets( self.name ): #self.targets.keys(): # Only update the targets that have actually changed here #print key, "\n" weight = self.realizer.getMorphTargetWeight(self.name, key) morphTargets = self.targets[key] for morphTargetKey in morphTargets.keys(): #print(weight*morphTargets[morphTargetKey]) morphTargetKey.setX(weight * morphTargets[morphTargetKey]) #blushingValue = self.realizer.getShaderParameterValue( self.name, 'blushing' ) #self.shaders.headShader.blushing.set( blushingValue ) def addAnimation(self, _actorName, _animationName): self.animationAgent.reparentTo(render) self.animationAgent.setScale(10) self.realizer.addAnimation(_actorName, _animationName) for i in range(self.animationAgent.getNumFrames(_animationName)): self.animationAgent.pose(_animationName, i) base.graphicsEngine.renderFrame() self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton) self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton) self.animationAgent.detachNode() print "animation", _animationName, "added" def addAnimationWE(self, _actorName, _animationName): self.animationAgent.reparentTo(render) self.animationAgent.setScale(10) agentSMRMotion = SMRPy.SMRMotion() agentSMRMotion.setTimeStep(0.04) self.realizer.addAnimation(_actorName, _animationName) for i in range(self.animationAgent.getNumFrames(_animationName)): self.animationAgent.pose(_animationName, i) base.graphicsEngine.renderFrame() self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton) self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton) agentSMRMotion.insertSkeleton(self.newSkeleton) self.animationAgent.detachNode() print "animation", _animationName, "added" SMRPy.exportMotionToBvh(_animationName + ".bvh", agentSMRMotion) def createSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName): #get the agent's currentJoint currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName) currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot', _initialJointName) self.agentControlJoints.append(currentPandaCJoint) #get the first joint's position position = currentPandaCJoint.getPos() if (currentPandaJoint[0].getNumChildren() == 0): newJoint = SMRPy.SMRJoint(True) newJoint.setEndVect(position.getX(), position.getY(), position.getZ()) else: newJoint = SMRPy.SMRJoint(False) rotZ = (currentPandaCJoint.getH() / 180.0) * 3.14159 rotX = (currentPandaCJoint.getP() / 180.0) * 3.14159 rotY = (currentPandaCJoint.getR() / 180.0) * 3.14159 quatZ = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 0.0, 1.0), rotZ) quatX = SMRPy.SMRQuaternion(SMRPy.SMRVector3(1.0, 0.0, 0.0), rotX) quatY = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 1.0, 0.0), rotY) quatRot = quatZ.multiply(quatX) quatRot = quatRot.multiply(quatY) quatRot.normalize() newJoint.setPos(position.getX(), position.getY(), position.getZ()) newJoint.setRotQuat(quatRot.getW(), quatRot.getX(), quatRot.getY(), quatRot.getZ()) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) self.jointList.append(newJoint) _smrSkel.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() #print(childName) self.createSkel(_pandaAgent, _smrSkel, childName, _initialJointName) def createFKSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName): #get the agent's currentJoint currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName) currentPandaJointPath = _pandaAgent.exposeJoint( None, 'modelRoot', _initialJointName, "lodRoot", True) self.agentNodePaths.append(currentPandaJointPath) #get the first joint's position position = currentPandaJointPath.getPos() if (currentPandaJoint[0].getNumChildren() == 0): newJoint = SMRPy.SMRJoint(True) newJoint.setEndVect(position.getX(), position.getY(), position.getZ()) else: newJoint = SMRPy.SMRJoint(False) quatRot = currentPandaJointPath.getQuat() newJoint.setPos(position.getX(), position.getY(), position.getZ()) newJoint.setRotQuat(quatRot.getR(), quatRot.getI(), quatRot.getJ(), quatRot.getK()) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) self.jointFKList.append(newJoint) _smrSkel.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() #print(childName) self.createFKSkel(_pandaAgent, _smrSkel, childName, _initialJointName) def updatePandaSkeleton(self, agentControlJoints, _smrSkeleton): #synchronize root joint SMRJoint = _smrSkeleton.getJoint(0) PANDAJoint = agentControlJoints[0] position = SMRJoint.getPos() PANDAJoint.setPos(position.X(), position.Y(), position.Z()) for i in range(_smrSkeleton.getNumjoints()): SMRJoint = _smrSkeleton.getJoint(i) PANDAJoint = agentControlJoints[i] self.synchronize(PANDAJoint, SMRJoint) def updateSMRSkeleton(self, agentNodePaths, _smrSkeleton): #synchronize root joint SMRJoint = _smrSkeleton.getJoint(0) PANDAJoint = agentNodePaths[0] position = PANDAJoint.getPos() SMRJoint.setPos(position.getX(), position.getY(), position.getZ()) for i in range(_smrSkeleton.getNumjoints()): SMRJoint = _smrSkeleton.getJoint(i) PANDAJoint = agentNodePaths[i] self.synchronizePandaToSMR(SMRJoint, PANDAJoint) def synchronizePandaToSMR(self, _SMRJoint, _PANDAJoint): pandaQuaternion = _PANDAJoint.getQuat() x = pandaQuaternion.getI() y = pandaQuaternion.getJ() z = pandaQuaternion.getK() w = pandaQuaternion.getR() _SMRJoint.setRotQuat(w, x, y, z) def synchronize(self, _pandaCJoint, _smrJoint): smrQuaternion = _smrJoint.getRot() pandaQuaternion = Quat() pandaQuaternion.setI(smrQuaternion.getX()) pandaQuaternion.setJ(smrQuaternion.getY()) pandaQuaternion.setK(smrQuaternion.getZ()) pandaQuaternion.setR(smrQuaternion.getW()) if not (pandaQuaternion.isNan()): _pandaCJoint.setQuat(pandaQuaternion)
class Grenade (Projectile): def __init__(self, pos, hpr, color, walker_v, name=None): super(Grenade, self).__init__(name) self.pos = Vec3(*pos) self.hpr = hpr self.move_divisor = 9 self.color = color self.forward_m = .25 self.walker_v = walker_v def create_node(self): self.model = Actor('grenade.egg') self.shell = self.model.find('**/shell') self.shell.set_color(*self.color) self.inner_top = self.model.find('**/inner_top') self.inner_bottom = self.model.find('**/inner_bottom') self.inner_top.set_color(*random.choice(ENGINE_COLORS)) self.inner_bottom.set_color(*random.choice(ENGINE_COLORS)) self.model.set_scale(GRENADE_SCALE) self.model.set_hpr(0,0,0) self.spin_bone = self.model.controlJoint(None, 'modelRoot', 'grenade_bone') return self.model def create_solid(self): node = BulletRigidBodyNode(self.name) node.set_angular_damping(.9) node_shape = BulletSphereShape(.08) node.add_shape(node_shape) node.set_mass(.5) return node def attached(self): self.node.set_pos(self.pos) self.node.set_hpr(self.hpr) self.world.register_updater(self) self.world.register_collider(self) self.solid.setIntoCollideMask(NO_COLLISION_BITS) self.solid.set_gravity(DEFAULT_GRAVITY*4.5) grenade_iv = render.get_relative_vector(self.node, Vec3(0,8.5,13.5)) grenade_iv += (self.walker_v * 1/2) self.solid.apply_impulse(grenade_iv, Point3(*self.pos)) def decompose(self): clist = list(self.color) clist.extend([1]) expl_colors = [clist] expl_colors.extend(ENGINE_COLORS) expl_pos = self.node.get_pos(self.world.render) for c in expl_colors: self.world.attach(TriangleExplosion(expl_pos, 1, size=.1, color=c, lifetime=40)) self.world.garbage.add(self) def update(self, dt): self.inner_top.set_color(*random.choice(ENGINE_COLORS)) self.inner_bottom.set_color(*random.choice(ENGINE_COLORS)) result = self.world.physics.contact_test(self.solid) self.spin_bone.set_hpr(self.spin_bone, 0,0,10) contacts = result.getContacts() if len(contacts) > 0: hit_node = contacts[0].get_node1().get_name() if hit_node.endswith("_walker_cap"): return clist = list(self.color) clist.extend([1]) expl_colors = [clist] expl_colors.extend(ENGINE_COLORS) expl_pos = self.node.get_pos(self.world.render) for c in expl_colors: self.world.attach(TriangleExplosion(expl_pos, 3, size=.1, color=c, lifetime=80,)) self.world.do_explosion(self.node, 3, 100) self.world.garbage.add(self)
class WatchMe(ShowBase): def __init__(self): # Initialize the ShowBase class from which we inherit, which will # create a window and set up everything we need for rendering into it. ShowBase.__init__(self) # Put the standard title and instruction text on screen self.modeText = OnscreenText(text="Optical Flow", fg=(1, 1, 1, 1), parent=base.a2dBottomRight, align=TextNode.ARight, pos=(-0.1, 0.1), shadow=(0, 0, 0, .5), scale=.08) instr0 = addInstructions(0.06, "Press ESC to exit") instr1 = addInstructions(0.12, "Press 1: Facial Recognition") instr1 = addInstructions(0.18, "Press 2: Optical Flow") # Set up key input self.accept('escape', self.destroy) self.accept('1', self.chooseFacialRec) self.accept('2', self.chooseOpticalFlow) self.mode = 'opticalFlow' self.environ = loader.loadModel("models/world") self.environ.reparentTo(render) # Disable mouse-based camera-control base.disableMouse() self.eve = Actor("models/eve") self.eve.setScale(.7) self.eve.setPos(5, 5, 3) # Put it in the scene self.eve.reparentTo(render) self.camDistance = 15 self.camHeight = 5 # Position the camera camera.setPos(self.eve.getPos() + (0, -1 * self.camDistance, self.camHeight)) # Now we use controlJoint to get a NodePath that's in control of her neck # This must be done before any animations are played self.eveNeck = self.eve.controlJoint(None, 'modelRoot', 'Neck') self.camera.lookAt(self.eve) self.camBaseZ = self.camera.getZ() self.camBaseX = self.camera.getX() self.pitchOffset = self.camDistance self.headingOffset = self.camDistance # Now we add a task that will take care of turning the head taskMgr.add(self.turnHead, "turnHead") # Put in some default lighting self.setupLights() self.video = cv2.VideoCapture(0) check, self.prev_frame = self.video.read() self.prev_frame = downsample(self.prev_frame) self.total_displacement = [0, 0] self.prev_face_x = None self.prev_face_y = None self.total_face_displacement = [0, 0] # Moving averages self.xQueueSize = 20 self.xQueue = collections.deque([0, 0, 0, 0, 0], self.xQueueSize) self.xQueueSum = 0 self.yQueueSize = 20 self.yQueue = collections.deque([0, 0, 0, 0, 0], self.yQueueSize) self.yQueueSum = 0 def updateModeText(self, text): self.modeText.setText(text) def chooseFacialRec(self): self.mode = 'face' self.updateModeText('Facial Recognition') def chooseOpticalFlow(self): self.mode = 'opticalFlow' self.updateModeText('Optical Flow') # Clean up def destroy(self): self.video.release() cv2.destroyAllWindows sys.exit # Move camera based on displacement # Turn eve's head to look at new camera position def turnHead(self, task): # Move camera up and down relative to displacement # between frames (scaled arbitrarily for good practical results) # Move eve's head to look at camera if self.mode == 'opticalFlow': self.getDisplacement() self.camera.setX(self.camBaseX + self.total_displacement[0] * -0.35) self.eveNeck.setP(self.getP()) self.camera.setZ(self.camBaseZ + self.total_displacement[1] * -0.35) self.eveNeck.setH(self.getH()) elif self.mode == 'face': self.getFaces() self.camera.setX(self.camBaseX + self.total_face_displacement[0] * -0.1) self.eveNeck.setP(self.getP()) self.camera.setZ(self.camBaseZ + self.total_face_displacement[1] * -0.1) self.eveNeck.setH(self.getH()) else: print('Unrecognized mode') # Rotate camera to center on eve self.camera.lookAt(self.eve) # Task continues infinitely return Task.cont # Trig to get heading of eve's head, looking at camera def getH(self): A = self.pitchOffset O = self.camera.getZ() - self.camBaseZ + self.camHeight H = math.sqrt(A**2 + O**2) self.headingOffset = H return np.degrees(np.arctan(O / A)) # Trig to get pitch of eve's head, looking at camera def getP(self): A = self.headingOffset O = self.camera.getX() - self.camBaseX H = math.sqrt(A**2 + O**2) self.headingOffset = H return np.degrees(np.arctan(O / A)) def getFaces(self): check, frame = self.video.read() f = faces(frame) # Only use the first detected face if (len(f) > 0): x = f[0][0] y = f[0][1] w = f[0][2] h = f[0][3] frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) if not self.prev_face_x is None: delta = self.prev_face_x - x minus = self.xQueue.popleft() self.xQueue.append(delta) self.xQueueSum -= minus self.xQueueSum += delta average = self.xQueueSum / self.xQueueSize self.total_face_displacement[0] -= average self.prev_face_x = x if not self.prev_face_y is None: delta = self.prev_face_y - y minus = self.yQueue.popleft() self.yQueue.append(delta) self.yQueueSum -= minus self.yQueueSum += delta average = self.yQueueSum / self.yQueueSize self.total_face_displacement[1] -= average self.prev_face_y = y cv2.imshow("Faces", frame) return f def getDisplacement(self): check, frame = self.video.read() frame = downsample(frame) # Compute displacement between current and previous frame d = displacement(np.array([self.prev_frame, frame])) self.total_displacement += d self.prev_frame = frame cv2.imshow("Capturing", frame) return d # Sets up some default lighting def setupLights(self): ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.4, .4, .35, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(LVector3(0, 8, -2.5)) directionalLight.setColor((0.9, 0.8, 0.9, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight))
class Monster(): def __init__(self, setup_data, common, level=1.0, start_pos=(0, 0, 0)): common['monsterList'].append(self) id = len(common['monsterList']) - 1 self.monsterList = common['monsterList'] self.waypoints_data = common['waypoints_data'] self.waypoints = common['waypoints'] self.audio3d = common['audio3d'] self.common = common #root node self.node = render.attachNewNode("monster") self.sound_node = None self.soundset = None self.actor = Actor(setup_data["model"], setup_data["anim"]) self.actor.setBlend(frameBlend=True) self.actor.reparentTo(self.node) self.actor.setScale(setup_data["scale"] * random.uniform(0.9, 1.1)) self.actor.setH(setup_data["heading"]) self.actor.setBin("opaque", 10) self.rootBone = self.actor.exposeJoint(None, 'modelRoot', setup_data["root_bone"]) #sounds self.soundID = self.common['soundPool'].get_id() self.common['soundPool'].set_target(self.soundID, self.node) self.sound_names = { "hit": setup_data["hit_sfx"], "arrow_hit": setup_data["arrowhit_sfx"], "attack": setup_data["attack_sfx"], "die": setup_data["die_sfx"] } self.vfx = setup_data["hit_vfx"] self.stats = { "speed": setup_data["speed"], "hp": setup_data["hp"] * level, "armor": setup_data["armor"] * level, "dmg": setup_data["dmg"] * level } if self.stats['hp'] > 300: self.stats['hp'] = 300 self.maxHP = self.stats['hp'] self.HPring = Actor("models/ring_morph", {'anim': 'models/ring_anim'}) self.HPring.setScale(0.07) self.HPring.setZ(0.4) self.HPring.setLightOff() self.HPring.reparentTo(self.node) self.HPvis = self.HPring.controlJoint(None, 'modelRoot', 'morph01') self.HPvis.setX(self.stats['hp'] / 300) self.HPring.hide(BitMask32.bit(1)) self.HPring.hide() #self.HPring.setColorScale(0.0, 1.0, 0.0, 1.0) #gamestate variables self.attack_pattern = setup_data["attack_pattern"] self.damage = setup_data["dmg"] #self.HP=setup_data["hp"] self.state = "STOP" self.id = id self.nextWaypoint = None self.canSeePC = False self.PCisInRange = False self.PC = common['PC'] self.speed_mode = random.randrange(0 + int(level), 42 + int(level), 7) / 100.0 self.totalSpeed = self.stats['speed'] + self.speed_mode self.sparkSum = 0 self.lastMagmaDmg = 0 self.DOT = 0 self.arrows = set() self.traverser = CollisionTraverser("Trav" + str(self.id)) #self.traverser.showCollisions(render) self.queue = CollisionHandlerQueue() #bit masks: # 1 visibility polygons & coll-rays # 2 walls & radar-ray # 3 spheres #collision ray for testing visibility polygons coll = self.node.attachNewNode(CollisionNode('collRay')) coll.node().addSolid(CollisionRay(0, 0, 2, 0, 0, -180)) coll.setTag("id", str(id)) coll.node().setIntoCollideMask(BitMask32.allOff()) coll.node().setFromCollideMask(BitMask32.bit(1)) self.traverser.addCollider(coll, self.queue) #radar collision ray self.radar = self.node.attachNewNode(CollisionNode('radarRay')) self.radar.node().addSolid(CollisionRay(0, 0, 1, 0, 90, 0)) self.radar.node().setIntoCollideMask(BitMask32.allOff()) self.radar.node().setFromCollideMask(BitMask32.bit(2)) self.radar.setTag("radar", str(id)) #self.radar.show() self.traverser.addCollider(self.radar, self.queue) #collision sphere self.coll_sphere = self.node.attachNewNode( CollisionNode('monsterSphere')) self.coll_sphere.node().addSolid(CollisionSphere(0, 0, 0.8, 0.8)) self.coll_sphere.setTag("id", str(id)) self.coll_sphere.node().setIntoCollideMask(BitMask32.bit(3)) #coll_sphere.show() #other monster blocking self.coll_quad = loader.loadModel("models/plane") self.coll_quad.reparentTo(self.node) #coll_quad=render.attachNewNode(CollisionNode('monsterSphere')) #coll_quad.node().addSolid(CollisionPolygon(Point3(-.5, -.5, 2), Point3(-.5, .5, 0), Point3(.5, .5, 0), Point3(.5, .5, 2))) #coll_quad.setTag("id", str(id)) #coll_quad.node().setIntoCollideMask(BitMask32.bit(2)) #coll_quad.reparentTo(self.node) #coll_quad.show() Sequence(Wait(random.uniform(.6, .8)), Func(self.restart)).start() self.node.setPos(render, start_pos) taskMgr.add(self.runAI, "AIfor" + str(self.id)) taskMgr.doMethodLater(.6, self.runCollisions, 'collFor' + str(self.id)) taskMgr.doMethodLater(1.0, self.damageOverTime, 'DOTfor' + str(self.id)) def damageOverTime(self, task): if self.state == "DIE": return task.done if self.DOT > 0: self.doDamage(self.DOT) self.DOT = int((self.DOT * 0.9) - 1.0) if self.stats['hp'] < 1: self.actor.play("die") #self.common['soundPool'].play(self.soundID, self.sound_names["hit"]) self.common['soundPool'].play(self.soundID, self.sound_names["die"]) self.state = "DIE" vfx(self.node, texture=self.vfx, scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016, 24) return task.again def restart(self): self.state = "SEEK" def check_stacking(self): for monster in self.monsterList: if monster and monster.id != self.id: if self.node.getDistance(monster.node) < .8: if monster.state != "STOP" and self.state == "SEEK": if self.totalSpeed <= monster.totalSpeed: self.state = "STOP" self.actor.stop() Sequence(Wait(1.5), Func(self.restart)).start() return True def doDamage(self, damage, igoreArmor=False): if self.state == "DIE": return if not igoreArmor: damage -= self.stats['armor'] if damage < 1: damage = 1 #print damage self.stats['hp'] -= damage scale = self.stats['hp'] / self.maxHP self.HPvis.setX(self.stats['hp'] / 300.0) #self.HPring.setColor(0.8*(1.0-scale), 0.8*scale, 0.0, 1.0) self.HPring.show() self.HPring.setColorScale((1.0 - scale), scale, 0.0, 1.0) if self.stats['hp'] < 1: self.HPring.hide() def attack(self, pattern): if self.state == "DIE": return if not self.PC.node: return if pattern: next = pattern.pop() else: self.state = "SEEK" self.PCisInRange = False return if self.PC.node and self.node: range = self.node.getDistance(self.PC.node) else: return #print range if range < 1.8: self.PC.hit(self.damage) Sequence(Wait(next), Func(self.attack, pattern)).start() def onMagmaHit(self): if self.state == "DIE": return damage = self.lastMagmaDmg self.doDamage(damage) self.common['soundPool'].play(self.soundID, "onFire") vfx(self.node, texture="vfx/small_flame.png", scale=.6, Z=.7, depthTest=False, depthWrite=False).start(0.016, stopAtFrame=24) if self.stats['hp'] < 1: self.actor.play("die") self.common['soundPool'].play(self.soundID, "die3") self.state = "DIE" vfx(self.node, texture=self.vfx, scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016) def onPlasmaHit(self, damage): if self.state == "DIE": return self.doDamage(damage * 1.5, True) #self.soundset["spark"].play() #self.common['soundPool'].play(self.soundID, "spark") if self.stats['hp'] < 1: self.actor.play("die") #self.soundset["die3"].play() self.common['soundPool'].play(self.soundID, "die3") self.state = "DIE" vfx(self.node, texture=self.vfx, scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016) #else: # short_vfx(self.node, texture="vfx/short_spark.png",scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.03) def onSparkHit(self, damage): if self.state == "DIE": return #print damage self.doDamage(damage) #self.soundset["spark"].play() self.common['soundPool'].play(self.soundID, "spark") if self.stats['hp'] < 1: self.actor.play("die") #self.soundset["die3"].play() self.common['soundPool'].play(self.soundID, "die3") self.state = "DIE" vfx(self.node, texture=self.vfx, scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016) else: short_vfx(self.node, texture="vfx/short_spark.png", scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.03) def onHit(self, damage, sound="hit"): if self.state == "DIE": return self.doDamage(damage) #print damage vfx(self.node, texture=self.vfx, scale=.5, Z=1.0, depthTest=True, depthWrite=True).start(0.016) if self.stats['hp'] < 1: self.actor.play("die") #self.sounds["die"].play() if sound: self.common['soundPool'].play(self.soundID, self.sound_names[sound]) self.common['soundPool'].play(self.soundID, self.sound_names["die"]) self.state = "DIE" else: #self.sounds["hit"].play() if sound: self.common['soundPool'].play(self.soundID, self.sound_names[sound]) def findFirstWaypoint(self): min = 100000 nearest = None for waypoint in self.waypoints: dist = self.node.getDistance(waypoint) if dist < min: min = dist nearest = waypoint return nearest def runCollisions(self, task): if self.state == "DIE": return task.done if self.node.getDistance(self.PC.node) > 50.0: self.nextWaypoint = None return task.again if self.check_stacking(): return task.again self.radar.lookAt(self.PC.node) valid_waypoints = [] isFirstTest = True self.canSeePC = False self.traverser.traverse(render) self.queue.sortEntries() for entry in self.queue.getEntries(): if entry.getFromNodePath().hasTag( "id"): #it's the monsters collRay valid_waypoints.append( int(entry.getIntoNodePath().getTag( "index"))) #visibility polygons elif entry.getFromNodePath().hasTag("radar"): #it's the radar-ray #print "radar hit", entry.getIntoNodePath() if isFirstTest: isFirstTest = False #print "first hit!" #print "radar hit", entry.getIntoNodePath() if entry.getIntoNodePath().hasTag("player"): self.canSeePC = True '''distance={} for target in self.PC.myWaypoints: for waypoint in valid_waypoints: distance[target]=self.waypoints_data[target][waypoint] print(target, distance[target]) if distance: self.nextWaypoint=self.waypoints[min(distance, key=distance.get)] #print self.canSeePC''' if not valid_waypoints: #self.nextWaypoint=self.findFirstWaypoint() print(self.id, ": I'm lost!") valid_waypoints = [self.findFirstWaypoint()] #return task.again if self.state == "STOP": self.nextWaypoint = self.waypoints[random.choice(valid_waypoints)] return task.again best_distance = 9000000 target_node = None for target in self.PC.myWaypoints: for valid in valid_waypoints: distance = self.waypoints_data[target][valid] #print "target->valid=",target, valid, distance if distance < best_distance: best_distance = distance target_node = valid if target_node: self.nextWaypoint = self.waypoints[target_node] else: #print "no target", valid_waypoints self.nextWaypoint = self.findFirstWaypoint() #self.waypoints[random.choice(valid_waypoints)] #print self.nextWaypoint return task.again def runAI(self, task): #print self.state if self.state == "DIE": self.coll_sphere.node().setIntoCollideMask(BitMask32.allOff()) self.coll_quad.removeNode() self.actor.play("die") self.common["kills"] -= 1 if self.common["kills"] == 0: Interactive(self.common, data.items['key'], self.node.getPos(render)) elif random.randrange(10) == 0: Interactive(self.common, data.items['potion'], self.node.getPos(render)) Sequence( Wait(2.0), LerpPosInterval( self.node, 2.0, VBase3(self.node.getX(), self.node.getY(), self.node.getZ() - 5)), Func(self.destroy)).start() return task.done elif self.state == "STOP": target = self.nextWaypoint if not target: return task.again self.node.headsUp(target) if self.node.getDistance(target) > 0.3: self.node.setY(self.node, self.totalSpeed * globalClock.getDt()) if (self.actor.getCurrentAnim() != "walk"): self.actor.loop("walk") return task.again elif self.state == "ATTACK": self.node.headsUp(self.PC.node) if (self.actor.getCurrentAnim() != "attack"): self.actor.play("attack") #Sequence(Wait(self.attack_pattern[-1]+self.speed_mode), Func(self.attack, list(self.attack_pattern))).start() Sequence(Wait(self.attack_pattern[-1]), Func(self.attack, list(self.attack_pattern))).start() return task.again elif self.state == "SEEK": if self.PCisInRange: self.state = "ATTACK" return task.again target = self.nextWaypoint if self.canSeePC and self.PC.HP > 0: target = self.PC.node #print "target pc!" if not target: return task.again self.node.headsUp(target) if self.node.getDistance(target) > 0.3: self.node.setY(self.node, self.totalSpeed * globalClock.getDt()) if (self.actor.getCurrentAnim() != "walk"): self.actor.loop("walk") return task.again else: #print "I'm stuck?" #print target #print self.canSeePC self.nextWaypoint = self.PC.node return task.again def destroy(self): #for sound in self.soundset: # self.soundset[sound].stop() #print "destroy:", #self.sound_node.reparentTo(render) #self.common['soundPool'].append([self.sound_node,self.soundset]) self.common['soundPool'].set_free(self.soundID) #self.sounds=None #print " sounds", self.arrows = None if self.actor: self.actor.cleanup() self.actor.removeNode() #print " actor", if taskMgr.hasTaskNamed("AIfor" + str(self.id)): taskMgr.remove("AIfor" + str(self.id)) #print " AI", if taskMgr.hasTaskNamed('collFor' + str(self.id)): taskMgr.remove('collFor' + str(self.id)) #print " collision", if taskMgr.hasTaskNamed('DOTfor' + str(self.id)): taskMgr.remove('DOTfor' + str(self.id)) if self.node: self.node.removeNode() #print " node", self.monsterList[self.id] = None self.traverser = None self.queue = None
class World(DirectObject): def __init__(self): #This code puts the standard title and instuction text on screen self.title = OnscreenText(text="Panda3D: Embots - Joint Manipulation", style=1, fg=(1, 1, 1, 1), pos=(0.8, -0.95), scale=.07) #setup key input self.accept('escape', sys.exit) #base.disableMouse() #Disable mouse-based camera-control camera.setPos(0, -20, 0) #Position the camera self.teapot = loader.loadModel('models/teapot') self.teapot.reparentTo(render) self.teapot.setScale(0.2) self.tentacle = Actor("models/tentacle") #Load our animated charachter self.tentacle.reparentTo(render) #Put it in the scene self.tentacle.setScale(1.0) self.setupLights() #Put in some default lighting self.tentacleBase = self.tentacle.controlJoint(None, 'modelRoot', 'Bone') self.tentacleIK = SMRPy.SmrKinematicChain(True, True, 'tentacle') self.jointList = [] self.constraintList = [] self.createKinematicChain(self.tentacle, 'Bone', '', 0) myJoint = self.tentacleIK.getJointByName("Bone.006") self.myConstraint = SMRPy.SmrIKConstraint() self.myConstraint.setRelatedJointptr(myJoint) myConstraintPosition = SMRPy.SmrVector3(0.0, 0.0, 0.0) self.teapot.setPos(0.0, 0.0, 0.0) self.myConstraint.setPosition(myConstraintPosition) myConstraintPosition = SMRPy.SmrVector3(0.0, 0.0, 0.0) self.myConstraint.setOffset(myConstraintPosition) self.myKinematicSolver = SMRPy.SmrGSMMSolver(self.tentacleIK) self.myKinematicSolver.addConstraintPtr(self.myConstraint) taskMgr.add(self.ikStep, "ikStep") def ikStep(self, task): if base.mouseWatcherNode.hasMouse(): mpos = base.mouseWatcherNode.getMouse() self.myConstraint.setPosition( SMRPy.SmrVector3( restrain(mpos.getX()) * 10, 0.0, restrain(mpos.getY()) * 10)) #self.tentacleBase.setR (restrain(mpos.getX()) * 20) self.teapot.setPos( restrain(mpos.getX()) * 10, 0.0, restrain(mpos.getY()) * 10) self.myKinematicSolver.process() self.updatePandaSkeleton(self.tentacle, self.tentacleIK, 'Bone') return Task.cont def createKinematicChain(self, _tentacle, _initialJointName, _parentName, _weight): #get the tentacle's currentJoint currentPandaJoint = _tentacle.getJoints(_initialJointName) currentPandaCJoint = self.tentacle.controlJoint( None, 'modelRoot', _initialJointName) #get the first joint's position position = currentPandaCJoint.getPos() if (currentPandaJoint[0].getNumChildren() == 0): newJoint = SMRPy.SmrKinematicJoint(True) newJoint.setEndVect(position.getX(), position.getY(), position.getZ()) else: newJoint = SMRPy.SmrKinematicJoint(False) newJoint.setPos(position.getX(), position.getY(), position.getZ()) print "position", position.getX(), position.getY(), position.getZ() #newJoint.setRot(0,0,0) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) rotZ = (currentPandaCJoint.getH() / 180.0) * 3.14159 rotX = (currentPandaCJoint.getP() / 180.0) * 3.14159 rotY = (currentPandaCJoint.getR() / 180.0) * 3.14159 print rotX, rotY, rotZ, currentPandaCJoint.getName() # remove the setRot function veveal in C++, error prone newJoint.addDof(SMRPy.SmrVector3(0.0, 0.0, 1.0), rotZ - 1.0, rotZ + 1.0, rotZ, 0.01 * _weight) newJoint.addDof(SMRPy.SmrVector3(1.0, 0.0, 0.0), rotX - 1.0, rotX + 1.0, rotX, 0.01 * _weight) newJoint.addDof(SMRPy.SmrVector3(0.0, 1.0, 0.0), rotY, rotY, rotY, 0) _weight += 0.5 print newJoint.getName() print _initialJointName, 'numchildren : ', currentPandaJoint[ 0].getNumChildren() self.jointList.append(newJoint) self.tentacleIK.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() print(childName) self.createKinematicChain(_tentacle, childName, _initialJointName, _weight) def updatePandaSkeleton(self, _pandaSkeleton, _smrSkeleton, _startJointName): currentPandaJoint = _pandaSkeleton.getJoints(_startJointName) currentPandaCJoint = _pandaSkeleton.controlJoint( None, 'modelRoot', _startJointName) currentSmrJoint = _smrSkeleton.getJointByName(_startJointName) self.synchronize(currentPandaCJoint, currentSmrJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() self.updatePandaSkeleton(_pandaSkeleton, _smrSkeleton, childName) def synchronize(self, _pandaCJoint, _smrJoint): #_smrJoint.setRot(3.14/20.0,0,0); smrQuaternion = _smrJoint.getRot() pandaQuaternion = Quat() pandaQuaternion.setI(smrQuaternion.getX()) pandaQuaternion.setJ(smrQuaternion.getY()) pandaQuaternion.setK(smrQuaternion.getZ()) pandaQuaternion.setR(smrQuaternion.getW()) _pandaCJoint.setQuat(pandaQuaternion) # def turnTentacle(self, task): #Check to make sure the mouse is readable # if base.mouseWatcherNode.hasMouse(): #get the mouse position as a Vec2. The values for each axis are from -1 to #1. The top-left is (-1,-1), the bottom rightis (1,1) # mpos = base.mouseWatcherNode.getMouse() #Here we multiply the values to get the amount of degrees to turn #Restrain is used to make sure the values returned by getMouse are in the #valid range. If this particular model were to turn more than this, #significant tearing would be visable #self.tentacleBase.setP(restrain(mpos.getY()) * -50) # self.tentacleBase.setR (restrain(mpos.getX()) * 20) # return Task.cont #Task continues infinitely def setupLights(self): #Sets up some default lighting lAttrib = LightAttrib.makeAllOff() ambientLight = AmbientLight("ambientLight") ambientLight.setColor(Vec4(.4, .4, .35, 1)) lAttrib = lAttrib.addLight(ambientLight) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(Vec3(0, 8, -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)
class MayaDemo(ShowBase): R_LEG_JOINTS = ["joint6", "joint7", "joint8"] L_LEG_JOINTS = ["joint10", "joint11", "joint12"] def __init__(self): ShowBase.__init__(self) self.bandit = Actor("banditRiggedNoHat.egg") self.bandit.makeSubpart("r_leg", self.R_LEG_JOINTS) self.bandit.makeSubpart("l_leg", self.L_LEG_JOINTS) headJoint = self.bandit.exposeJoint(None, "modelRoot", "joint5") hat = loader.loadModel("{}_hat.egg".format(random.randint(0, 7))) hat.setPos(0, 0, -0.08) hat.setHpr(-90, 0, 0) hat.setScale(0.35) hat.reparentTo(headJoint) self.bandit.reparentTo(render) r_hip_ro = self.bandit.exposeJoint(None, "modelRoot", self.R_LEG_JOINTS[0]) r_hip_wo = self.bandit.controlJoint(None, "modelRoot", self.R_LEG_JOINTS[0]) r_knee_ro = self.bandit.exposeJoint(None, "modelRoot", self.R_LEG_JOINTS[1]) r_knee_wo = self.bandit.controlJoint(None, "modelRoot", self.R_LEG_JOINTS[1]) r_ankle_ro = self.bandit.exposeJoint(None, "modelRoot", self.R_LEG_JOINTS[2]) r_ankle_wo = self.bandit.controlJoint(None, "modelRoot", self.R_LEG_JOINTS[2]) distances = np.array([ r_hip_ro.getDistance(r_knee_ro), r_knee_ro.getDistance(r_ankle_ro) ]) self.r_leg = Leg.Leg(r_hip_ro, r_hip_wo, r_knee_ro, r_knee_wo, r_ankle_ro, r_ankle_wo, distances) l_hip = self.bandit.controlJoint(None, "modelRoot", self.L_LEG_JOINTS[0]) l_knee = self.bandit.controlJoint(None, "modelRoot", self.L_LEG_JOINTS[1]) l_ankle = self.bandit.exposeJoint(None, "modelRoot", self.L_LEG_JOINTS[2]) distances = np.array( [l_hip.getDistance(l_knee), l_knee.getDistance(l_ankle)]) #self.l_leg = Leg.Leg(l_hip, l_knee, l_ankle, distances) self.accept("arrow_up", self.r_leg.moveAnkle, [(0, 0, 0.1)]) self.accept("arrow_down", self.r_leg.moveAnkle, [(0, 0, -0.1)]) self.accept("arrow_left", self.r_leg.rotateAnkle, [(0, 0, 10)]) self.accept("arrow_right", self.r_leg.rotateAnkle, [(0, 0, -10)]) # Draws debug skeleton self.bandit.setBin('background', 1) self.walkJointHierarchy(self.bandit, self.bandit.getPartBundle('modelRoot')) self.stream = StreamRead("/dev/input/smartshoes") self.last_t = time.time() taskMgr.add(self.getDeviceData, 'Stream reader') def getDeviceData(self, task): records = self.stream.readFromStream() if records and len(records[0]) == 10: records = map(float, records[0]) angular_velocity, acceleration, magnetic_field = [ records[x:x + 3] for x in range(0, 9, 3) ] # Switch axis orientations angular_velocity[2], angular_velocity[0] = angular_velocity[ 0], angular_velocity[2] acceleration[2], acceleration[0] = acceleration[0], acceleration[2] magnetic_field[2], magnetic_field[0] = magnetic_field[ 0], magnetic_field[2] self.r_leg.ankle_rotation.rotationMagic(records[9], angular_velocity, acceleration, magnetic_field) self.r_leg.updateAnkleRotation() return task.again def walkJointHierarchy(self, actor, part, parentNode=None, indent=""): if isinstance(part, CharacterJoint): np = actor.exposeJoint(None, 'modelRoot', part.getName()) if parentNode and parentNode.getName() != "root": lines = LineSegs() lines.setThickness(3.0) lines.setColor(random.random(), random.random(), random.random()) lines.moveTo(0, 0, 0) lines.drawTo(np.getPos(parentNode)) lnp = parentNode.attachNewNode(lines.create()) lnp.setBin("fixed", 40) lnp.setDepthWrite(False) lnp.setDepthTest(False) parentNode = np for child in part.getChildren(): self.walkJointHierarchy(actor, child, parentNode, indent + " ")
class Walker (PhysicalObject): collide_bits = SOLID_COLLIDE_BIT def __init__(self, incarnator, colordict=None, player=False): super(Walker, self).__init__() self.spawn_point = incarnator self.on_ground = False self.mass = 150.0 # 220.0 for heavy self.xz_velocity = Vec3(0, 0, 0) self.y_velocity = Vec3(0, 0, 0) self.factors = { 'forward': 7.5, 'backward': -7.5, 'left': 2.0, 'right': -2.0, 'crouch': 0.0, } self.movement = { 'forward': 0.0, 'backward': 0.0, 'left': 0.0, 'right': 0.0, 'crouch': 0.0, } self.head_height = Vec3(0, 1.5, 0) self.collides_with = MAP_COLLIDE_BIT | SOLID_COLLIDE_BIT self.grenade_loaded = False self.energy = 1.0 self.left_gun_charge = 1.0 self.right_gun_charge = 1.0 self.primary_color = [1,1,1,1] self.colordict = colordict if colordict else None self.crouching = False self.player = player self.can_jump = False self.crouch_impulse = 0 def get_model_part(self, obj_name): return self.actor.find("**/%s" % obj_name) def create_node(self): self.actor = Actor('walker.egg') if self.colordict: self.setup_color(self.colordict) self.actor.set_pos(*self.spawn_point.pos) self.actor.look_at(*self.spawn_point.heading) self.spawn_point.was_used() self.left_barrel_joint = self.actor.exposeJoint(None, 'modelRoot', 'left_barrel_bone') self.right_barrel_joint = self.actor.exposeJoint(None, 'modelRoot', 'right_barrel_bone') return self.actor def create_solid(self): walker_capsule = BulletGhostNode(self.name + "_walker_cap") self.walker_capsule_shape = BulletCylinderShape(.7, .2, YUp) walker_bullet_np = self.actor.attach_new_node(walker_capsule) walker_bullet_np.node().add_shape(self.walker_capsule_shape) walker_bullet_np.node().set_kinematic(True) walker_bullet_np.set_pos(0,1.5,0) walker_bullet_np.wrt_reparent_to(self.actor) self.world.physics.attach_ghost(walker_capsule) walker_bullet_np.node().setIntoCollideMask(GHOST_COLLIDE_BIT) return None def setup_shape(self, gnodepath, bone, pname): shape = BulletConvexHullShape() gnode = gnodepath.node() geom = gnode.get_geom(0) shape.add_geom(geom) node = BulletRigidBodyNode(self.name + pname) np = self.actor.attach_new_node(node) np.node().add_shape(shape) np.node().set_kinematic(True) np.wrt_reparent_to(bone) self.world.physics.attach_rigid_body(node) return np def setup_color(self, colordict): if colordict.has_key('barrel_color'): color = colordict['barrel_color'] self.get_model_part('left_barrel').setColor(*color) self.get_model_part('right_barrel').setColor(*color) if colordict.has_key('visor_color'): self.get_model_part('visor').setColor(*colordict['visor_color']) if colordict.has_key('body_primary_color'): color = colordict['body_primary_color'] self.primary_color = color for part in ['hull_primary', 'rt_leg_primary', 'lt_leg_primary', 'lb_leg_primary', 'rb_leg_primary', 'left_barrel_ring', 'right_barrel_ring', 'hull_bottom']: self.get_model_part(part).setColor(*color) if colordict.has_key('body_secondary_color'): color = colordict['body_secondary_color'] for part in ['hull_secondary', 'visor_stripe', 'rb_leg_secondary', 'rt_leg_secondary', 'lb_leg_secondary', 'lt_leg_secondary']: self.get_model_part(part).setColor(*color) return def attached(self): self.integrator = Integrator(self.world.gravity) self.world.register_collider(self) self.world.register_updater(self) left_bones = LegBones( self.world.render, self.world.physics, self.actor.exposeJoint(None, 'modelRoot', 'left_hip_bone'), self.actor.exposeJoint(None, 'modelRoot', 'left_foot_bone'), *[self.actor.controlJoint(None, 'modelRoot', name) for name in ['left_top_bone', 'left_bottom_bone']] ) right_bones = LegBones( self.world.render, self.world.physics, self.actor.exposeJoint(None, 'modelRoot', 'right_hip_bone'), self.actor.exposeJoint(None, 'modelRoot', 'right_foot_bone'), *[self.actor.controlJoint(None, 'modelRoot', name) for name in ['right_top_bone', 'right_bottom_bone']] ) self.skeleton = Skeleton(left_bones, right_bones, self.actor.controlJoint(None, 'modelRoot', 'pelvis_bone')) self.skeleton.setup_footsteps(self.world.audio3d) self.head_bone = self.actor.controlJoint(None, 'modelRoot', 'head_bone') self.head_bone_joint = self.actor.exposeJoint(None, 'modelRoot', 'head_bone') self.loaded_missile = Hat(self.head_bone_joint, self.primary_color) self.loaded_grenade = Sack(self.head_bone_joint, self.primary_color) if self.player: self.sights = Sights(self.left_barrel_joint, self.right_barrel_joint, self.world.render, self.world.physics) def collision(self, other, manifold, first): world_pt = manifold.get_position_world_on_a() if first else manifold.get_position_world_on_b() print self, 'HIT BY', other, 'AT', world_pt def handle_command(self, cmd, pressed): if cmd is 'crouch' and pressed: self.crouching = True if self.on_ground: self.can_jump = True if cmd is 'crouch' and not pressed and self.on_ground and self.can_jump: self.crouching = False self.y_velocity = Vec3(0, 6.8, 0) self.can_jump = False if cmd is 'fire' and pressed: self.handle_fire() return if cmd is 'missile' and pressed: if self.loaded_grenade.can_fire(): self.loaded_grenade.toggle_visibility() self.loaded_missile.toggle_visibility() return if cmd is 'grenade' and pressed: if self.loaded_missile.can_fire(): self.loaded_missile.toggle_visibility() self.loaded_grenade.toggle_visibility() return if cmd is 'grenade_fire' and pressed: if self.loaded_missile.can_fire(): self.loaded_missile.toggle_visibility() if not self.loaded_grenade.can_fire(): self.loaded_grenade.toggle_visibility() walker_v = Vec3(self.xz_velocity) walker_v.y = self.y_velocity.y self.loaded_grenade.fire(self.world, walker_v) return self.movement[cmd] = self.factors[cmd] if pressed else 0.0 def handle_fire(self): if self.loaded_missile.can_fire(): self.loaded_missile.fire(self.world) elif self.loaded_grenade.can_fire(): walker_v = self.xz_velocity walker_v.y = self.y_velocity.y self.loaded_grenade.fire(self.world, walker_v) else: p_energy = 0 hpr = 0 if self.left_gun_charge > self.right_gun_charge: origin = self.left_barrel_joint.get_pos(self.world.render) hpr = self.left_barrel_joint.get_hpr(self.world.render) p_energy = self.left_gun_charge if p_energy < MIN_PLASMA_CHARGE: return self.left_gun_charge = 0 else: origin = self.right_barrel_joint.get_pos(self.world.render) hpr = self.right_barrel_joint.get_hpr(self.world.render) p_energy = self.right_gun_charge if p_energy < MIN_PLASMA_CHARGE: return self.right_gun_charge = 0 hpr.y += 180 plasma = self.world.attach(Plasma(origin, hpr, p_energy)) def st_result(self, cur_pos, new_pos): return self.world.physics.sweepTestClosest(self.walker_capsule_shape, cur_pos, new_pos, self.collides_with, 0) def update(self, dt): dt = min(dt, 0.2) # let's just temporarily assume that if we're getting less than 5 fps, dt must be wrong. yaw = self.movement['left'] + self.movement['right'] self.rotate_by(yaw * dt * 60, 0, 0) walk = self.movement['forward'] + self.movement['backward'] start = self.position() cur_pos_ts = TransformState.make_pos(self.position() + self.head_height) if self.on_ground: friction = DEFAULT_FRICTION else: friction = AIR_FRICTION speed = walk pos = self.position() self.move_by(0, 0, speed) direction = self.position() - pos newpos, self.xz_velocity = Friction(direction, friction).integrate(pos, self.xz_velocity, dt) self.move(newpos) # Cast a ray from just above our feet to just below them, see if anything hits. pt_from = self.position() + Vec3(0, 1, 0) pt_to = pt_from + Vec3(0, -1.1, 0) result = self.world.physics.ray_test_closest(pt_from, pt_to, MAP_COLLIDE_BIT | SOLID_COLLIDE_BIT) #this should return 'on ground' information self.skeleton.update_legs(walk, dt, self.world.render, self.world.physics) if self.y_velocity.get_y() <= 0 and result.has_hit(): self.on_ground = True self.crouch_impulse = self.y_velocity.y self.y_velocity = Vec3(0, 0, 0) self.move(result.get_hit_pos()) else: self.on_ground = False current_y = Point3(0, self.position().get_y(), 0) y, self.y_velocity = self.integrator.integrate(current_y, self.y_velocity, dt) self.move(self.position() + (y - current_y)) if self.crouching and self.skeleton.crouch_factor < 1: self.skeleton.crouch_factor += (dt*60)/10 self.skeleton.update_legs(0, dt, self.world.render, self.world.physics) elif not self.crouching and self.skeleton.crouch_factor > 0: self.skeleton.crouch_factor -= (dt*60)/10 self.skeleton.update_legs(0, dt, self.world.render, self.world.physics) #if self.crouch_impulse < 0: goal = self.position() adj_dist = abs((start - goal).length()) new_pos_ts = TransformState.make_pos(self.position() + self.head_height) sweep_result = self.st_result(cur_pos_ts, new_pos_ts) count = 0 while sweep_result.has_hit() and count < 10: moveby = sweep_result.get_hit_normal() self.xz_velocity = -self.xz_velocity.cross(moveby).cross(moveby) moveby.normalize() moveby *= adj_dist * (1 - sweep_result.get_hit_fraction()) self.move(self.position() + moveby) new_pos_ts = TransformState.make_pos(self.position() + self.head_height) sweep_result = self.st_result(cur_pos_ts, new_pos_ts) count += 1 if self.energy > WALKER_MIN_CHARGE_ENERGY: if self.left_gun_charge < 1: self.energy -= WALKER_ENERGY_TO_GUN_CHARGE[0] self.left_gun_charge += WALKER_ENERGY_TO_GUN_CHARGE[1] else: self.left_gun_charge = math.floor(self.left_gun_charge) if self.right_gun_charge < 1: self.energy -= WALKER_ENERGY_TO_GUN_CHARGE[0] self.right_gun_charge += WALKER_ENERGY_TO_GUN_CHARGE[1] else: self.right_gun_charge = math.floor(self.right_gun_charge) if self.energy < 1: self.energy += WALKER_RECHARGE_FACTOR * (dt) if self.player: self.sights.update(self.left_barrel_joint, self.right_barrel_joint)
class RoamingRalphDemo(ShowBase): def __init__(self): # Set up the window, camera, etc. ShowBase.__init__(self) # Set the background color to black self.win.setClearColor((0, 0, 0, 1)) # This is used to store which keys are currently pressed. self.keyMap = { "left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0} # Post the instructions self.title = addTitle( "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.06, "[ESC]: Quit") self.inst2 = addInstructions(0.12, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.18, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.24, "[Up Arrow]: Run Ralph Forward") self.inst6 = addInstructions(0.30, "[A]: Rotate Camera Left") self.inst7 = addInstructions(0.36, "[S]: Rotate Camera Right") self.dirText = addInstructions(0.42, "pos") self.anglesText = addInstructions(0.48, "angle") # 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.createArm() # Create the main character, Ralph #ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("models/ralph", {"run": "models/ralph-run", "walk": "models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) #self.ralph.setPos(ralphStartPos + (0, 0, 0.5)) # Create a floater object, which floats 2 units above ralph. We # use this as a target for the camera to look at. self.floater = NodePath(PandaNode("floater")) self.floater.reparentTo(self.ralph) self.floater.setZ(2.0) # Accept the control keys for movement and rotation self.accept("escape", self.exitButton) self.accept("arrow_left", self.setKey, ["left", True]) self.accept("arrow_right", self.setKey, ["right", True]) self.accept("arrow_up", self.setKey, ["forward", True]) self.accept("a", self.setKey, ["cam-left", True]) self.accept("s", self.setKey, ["cam-right", True]) self.accept("arrow_left-up", self.setKey, ["left", False]) self.accept("arrow_right-up", self.setKey, ["right", False]) self.accept("arrow_up-up", self.setKey, ["forward", False]) self.accept("a-up", self.setKey, ["cam-left", False]) self.accept("s-up", self.setKey, ["cam-right", False]) taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera self.disableMouse() self.camera.setPos(15, 0, 3)#self.ralph.getX(), self.ralph.getY() + 10, 2) self.camera.setHpr(90, -5, 0) # 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, 9) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(CollideMask.bit(0)) self.ralphGroundCol.setIntoCollideMask(CollideMask.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, 9) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(CollideMask.bit(0)) self.camGroundCol.setIntoCollideMask(CollideMask.allOff()) self.camGroundColNp = self.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((.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection((-5, -5, -5)) directionalLight.setColor((1, 1, 1, 1)) directionalLight.setSpecularColor((1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) def exitButton(self): servos.exit() __import__('sys').exit() def createArm(self): self.robotarm = Actor("models/robotarm") self.robotarm.reparentTo(render) self.robotarm.setPos(0,0,0) self.robotarm.setScale(.2) self.jointForearm = self.robotarm.controlJoint(None, "modelRoot", "forearm") self.jointBase = self.robotarm.controlJoint(None, "modelRoot", "base") taskMgr.add(self.monitorArm, "robot arm") inc = 15 self.accept("i", self.setForearm, [inc]) self.accept("u", self.setForearm, [-inc]) self.accept("j", self.setBase, [inc]) self.accept("k", self.setBase, [-inc]) def monitorArm(self, task): def clamp1(x): return min(1, max(-1, x)) direction = self.ralph.get_pos() - self.robotarm.get_pos() direction.z += 1 direction.normalize() # camera starts facing along x dec = math.asin(direction.x) cosdec = math.cos(dec) if cosdec > 1e-05: ra = math.asin(clamp1(direction.z / cosdec)) ra2 = math.acos(clamp1(direction.y / cosdec)) else: ra = ra2 = math.pi/2#float('nan') #print(cosdec, direction) #print(dec, ra, ra2, cosdec) if direction.z < 0: if ra2 < math.pi/2: ra2 = 0 else: ra2 = math.pi self.jointForearm.setH(-dec * 180/math.pi) self.jointBase.setP(ra2 * 180/math.pi) self.dirText.setText(str(direction)) self.anglesText.setText(str((dec, ra, ra2, cosdec))) a = self.jointForearm.getH() / 90.0 * 300 + 512 b = self.jointBase.getP() / 90.0 * 300 + 212 #print(a, b) baseID = 9 servos.setAngle({baseID:int(round(b)), (baseID+1):int(round(a))}) return task.again def monitorArmServos(self, task): baseID = 9 a = self.jointForearm.getH() / 90.0 * 300 + 512 b = self.jointBase.getP() / 90.0 * 300 + 212 #print(a, b) servos.setAngle({baseID:int(round(a)), (baseID+1):int(round(b))}) # frac = task.time - int(task.time) # if frac > .9 and frac < .99: #print(self.jointForearm.getH(), self.jointBase.getP()) return task.again def setForearm(self, inc): #self.jointForearm.setH(random.random()*180-90) self.jointForearm.setH(self.jointForearm.getH() + inc) def setBase(self, inc): #self.jointBase.setP(random.random()*180) self.jointBase.setP(self.jointBase.getP() + inc) # Records the state of the arrow keys def setKey(self, key, value): self.keyMap[key] = value # Accepts arrow keys to move either the player or the menu cursor, # Also deals with grid checking and collision detection def move(self, task): # Get the time that elapsed since last frame. We multiply this with # the desired speed in order to find out with which distance to move # in order to achieve that desired speed. dt = globalClock.getDt() # If the camera-left key is pressed, move camera left. # If the camera-right key is pressed, move camera right. if self.keyMap["cam-left"]: self.camera.setX(self.camera, -20 * dt) if self.keyMap["cam-right"]: self.camera.setX(self.camera, +20 * dt) # save ralph's initial position so that we can restore it, # in case he falls off the map or runs into something. startpos = self.ralph.getPos() # If a move-key is pressed, move ralph in the specified direction. if self.keyMap["left"]: self.ralph.setH(self.ralph.getH() + 300 * dt) if self.keyMap["right"]: self.ralph.setH(self.ralph.getH() - 300 * dt) if self.keyMap["forward"]: self.ralph.setY(self.ralph, -25 * dt) # If ralph is moving, loop the run animation. # If he is standing still, stop the animation. if self.keyMap["forward"] or self.keyMap["left"] or self.keyMap["right"]: if self.isMoving is False: self.ralph.loop("run") self.isMoving = True else: if self.isMoving: self.ralph.stop() self.ralph.pose("walk", 5) self.isMoving = False # 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() - self.camera.getPos() camvec.setZ(0) camdist = camvec.length() camvec.normalize() if camdist > 10.0: self.camera.setPos(self.camera.getPos() + camvec * (camdist - 10)) camdist = 10.0 if camdist < 5.0: self.camera.setPos(self.camera.getPos() - camvec * (5 - camdist)) camdist = 5.0 # Normally, we would have to call traverse() to check for collisions. # However, the class ShowBase that we inherit from has a task to do # this for us, if we assign a CollisionTraverser to self.cTrav. #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 = list(self.ralphGroundHandler.getEntries()) entries.sort(key=lambda x: 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(startpos) # Keep the camera at one foot above the terrain, # or two feet above ralph, whichever is greater. entries = list(self.camGroundHandler.getEntries()) entries.sort(key=lambda x: x.getSurfacePoint(render).getZ()) if len(entries) > 0 and entries[0].getIntoNode().getName() == "terrain": self.camera.setZ(entries[0].getSurfacePoint(render).getZ() + 1.0) if self.camera.getZ() < self.ralph.getZ() + 2.0: self.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.camera.lookAt(self.floater)""" return task.cont
class DistributedPartyTrampolineActivity(DistributedPartyActivity): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyTrampolineActivity') def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None): DistributedPartyTrampolineActivity.notify.debug('__init__') DistributedPartyActivity.__init__(self, cr, PartyGlobals.ActivityIds.PartyTrampoline, PartyGlobals.ActivityTypes.GuestInitiated, wantLever=False, wantRewardGui=True) self.doJellyBeans = doJellyBeans self.doTricks = doTricks self.texture = texture self.toon = None self.trampHeight = 3.6 self.trampK = 400.0 self.normalTrampB = 2.5 self.leavingTrampB = 8.0 self.trampB = self.normalTrampB self.g = -32.0 self.jumpBoost = 330.0 self.beginningBoost = 500.0 self.beginningBoostThreshold = self.trampHeight + 1.5 self.earlyJumpThreshold = 75.0 self.boingThreshold = 300.0 self.turnFactor = 120.0 self.stepDT = 0.001 self.targetCameraPos = Point3(0.0, 40.0, 10.0) self.cameraSpeed = 2.0 self.hopOffPos = Point3(16.0, 0.0, 0.0) self.indicatorFactor = 0.0095 self.dropShadowCutoff = 15.0 self.minHeightForText = 15.0 self.heightTextOffset = -0.065 self.beanOffset = 0.5 self.guiBeanOffset = -0.02 self.jumpTextShown = False self.toonJumped = False self.turnLeft = False self.turnRight = False self.leavingTrampoline = False self.toonVelocity = 0.0 self.topHeight = 0.0 self.lastPeak = 0.0 self.beginRoundInterval = None self.hopOnAnim = None self.hopOffAnim = None self.flashTextInterval = None self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus self.jellyBeanStartHeight = 20.0 self.jellyBeanStopHeight = 90.0 self.jellyBeanColors = [VBase4(1.0, 0.5, 0.5, 1.0), VBase4(0.5, 1.0, 0.5, 1.0), VBase4(0.5, 1.0, 1.0, 1.0), VBase4(1.0, 1.0, 0.4, 1.0), VBase4(0.4, 0.4, 1.0, 1.0), VBase4(1.0, 0.5, 1.0, 1.0)] delta = (self.jellyBeanStopHeight - self.jellyBeanStartHeight) / (self.numJellyBeans - 1) self.jellyBeanPositions = [ self.jellyBeanStartHeight + n * delta for n in xrange(self.numJellyBeans) ] self.doSimulateStep = False return def load(self): DistributedPartyTrampolineActivity.notify.debug('load') DistributedPartyActivity.load(self) self.loadModels() self.loadCollision() self.loadGUI() self.loadSounds() self.loadIntervals() self.activityFSM = TrampolineActivityFSM(self) self.activityFSM.request('Idle') self.animFSM = TrampolineAnimFSM(self) self.setBestHeightInfo('', 0) def loadModels(self): self.tramp = self.root.attachNewNode(self.uniqueName('tramp')) self.trampActor = Actor('phase_13/models/parties/trampoline_model', {'emptyAnim': 'phase_13/models/parties/trampoline_anim'}) self.trampActor.reparentTo(self.tramp) if self.texture: reskinNode = self.tramp.find('**/trampoline/__Actor_modelRoot/-GeomNode') reskinNode.setTexture(loader.loadTexture(self.texture), 100) self.surface = NodePath(self.uniqueName('trampSurface')) self.surface.reparentTo(self.tramp) self.surface.setZ(self.trampHeight) self.trampActor.controlJoint(self.surface, 'modelRoot', 'trampoline_joint1') self.sign.setPos(PartyGlobals.TrampolineSignOffset) self.beans = [ loader.loadModelCopy('phase_4/models/props/jellybean4') for i in xrange(self.numJellyBeans) ] for bean in self.beans: bean.find('**/jellybean').setP(-35.0) bean.setScale(3.0) bean.setTransparency(True) bean.reparentTo(self.tramp) bean.stash() self.beans[-1].setScale(8.0) def loadCollision(self): collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4) collTube.setTangible(True) self.trampolineCollision = CollisionNode(self.uniqueName('TrampolineCollision')) self.trampolineCollision.addSolid(collTube) self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask) self.trampolineCollisionNP = self.tramp.attachNewNode(self.trampolineCollision) collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0) collSphere.setTangible(False) self.trampolineTrigger = CollisionNode(self.uniqueName('TrampolineTrigger')) self.trampolineTrigger.addSolid(collSphere) self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask) self.trampolineTriggerNP = self.tramp.attachNewNode(self.trampolineTrigger) self.accept('enter%s' % self.uniqueName('TrampolineTrigger'), self.onTrampolineTrigger) def loadGUI(self): self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI') self.gui.reparentTo(base.a2dTopLeft) self.gui.setPos(0.115, 0, -1) self.gui.hide() self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar') jumpLineLocator = self.gui.find('**/jumpLine_locator') guiBean = self.gui.find('**/trampolineGUI_GreenJellyBean') self.gui.find('**/trampolineGUI_GreenJellyBean').stash() self.guiBeans = [ guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName('guiBean%d' % i)) for i in xrange(self.numJellyBeans) ] self.guiBeans[-1].setScale(1.5) heightTextNode = TextNode(self.uniqueName('TrampolineActivity.heightTextNode')) heightTextNode.setFont(ToontownGlobals.getSignFont()) heightTextNode.setAlign(TextNode.ALeft) heightTextNode.setText('0.0') heightTextNode.setShadow(0.05, 0.05) heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0) heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.heightText = jumpLineLocator.attachNewNode(heightTextNode) self.heightText.setX(0.15) self.heightText.setScale(0.1) self.heightText.setAlphaScale(0.0) self.quitEarlyButtonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp') quitEarlyDown = self.quitEarlyButtonModels.find('**/InventoryButtonDown') quitEarlyRollover = self.quitEarlyButtonModels.find('**/InventoryButtonRollover') self.quitEarlyButton = DirectButton(parent=base.a2dTopRight, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-0.183, 0, -0.4), scale=0.09, command=self.leaveTrampoline) self.quitEarlyButton.stash() self.flashText = OnscreenText(text='', pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True) self.timer = PartyUtils.getNewToontownTimer() self.timer.posInTopRightCorner() return def loadSounds(self): self.jellyBeanSound = base.loadSfx('phase_4/audio/sfx/sparkly.ogg') self.boingSound = base.loadSfx('phase_4/audio/sfx/target_trampoline_2.ogg') self.whistleSound = base.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg') def loadIntervals(self): def prepareHeightText(): self.heightText.node().setText(TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ())) self.heightText.setZ(self.indicatorFactor * self.toon.getZ() + self.heightTextOffset) self.heightTextInterval = Sequence(Func(prepareHeightText), LerpFunc(self.heightText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0)) def unload(self): DistributedPartyTrampolineActivity.notify.debug('unload') if self.hopOnAnim and self.hopOnAnim.isPlaying(): self.hopOnAnim.finish() if self.hopOffAnim and self.hopOffAnim.isPlaying(): self.hopOffAnim.finish() if self.beginRoundInterval and self.beginRoundInterval.isPlaying(): self.beginRoundInterval.finish() if self.flashTextInterval and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() if self.heightTextInterval and self.heightTextInterval.isPlaying(): self.heightTextInterval.finish() self.timer.stop() DistributedPartyActivity.unload(self) taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.ignoreAll() del self.heightTextInterval del self.beginRoundInterval del self.hopOnAnim del self.hopOffAnim del self.flashTextInterval if hasattr(self, 'beanAnims'): self.cleanupJellyBeans() self.quitEarlyButton.destroy() del self.quitEarlyButton del self.gui del self.activityFSM del self.animFSM return def setBestHeightInfo(self, toonName, height): self.bestHeightInfo = (toonName, height) DistributedPartyTrampolineActivity.notify.debug('%s has the best height of %d' % (toonName, height)) if height > 0: self.setSignNote(TTLocalizer.PartyTrampolineBestHeight % self.bestHeightInfo) else: self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet) def leaveTrampoline(self): if self.toon != None and self.toon.doId == base.localAvatar.doId: self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp) self.leavingTrampoline = True self.timer.reset() self.trampB = self.leavingTrampB self.ignore('control') self.quitEarlyButton.stash() self.gui.hide() return def requestAnim(self, request): self.animFSM.request(request) def b_requestAnim(self, request): self.requestAnim(request) self.sendUpdate('requestAnim', [request]) def requestAnimEcho(self, request): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.requestAnim(request) return def removeBeans(self, beansToRemove): for i in beansToRemove: height, bean, guiBean, beanAnim = self.beanDetails[i] guiBean.stash() if i in self.beansToCollect: self.beansToCollect.remove(i) else: self.notify.warning('removeBeans avoided a crash, %d not in self.beansToCollect' % i) self.poofBean(bean, beanAnim) def b_removeBeans(self, beansToRemove): self.removeBeans(beansToRemove) self.sendUpdate('removeBeans', [beansToRemove]) def removeBeansEcho(self, beansToRemove): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.removeBeans(beansToRemove) return def joinRequestDenied(self, reason): DistributedPartyActivity.joinRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny) base.cr.playGame.getPlace().fsm.request('walk') def exitRequestDenied(self, reason): DistributedPartyActivity.exitRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny) def setState(self, newState, timestamp): DistributedPartyTrampolineActivity.notify.debug('setState( newState=%s, ... )' % newState) DistributedPartyActivity.setState(self, newState, timestamp) self.activityFSM.request(newState) def startIdle(self): DistributedPartyTrampolineActivity.notify.debug('startIdle') def finishIdle(self): DistributedPartyTrampolineActivity.notify.debug('finishIdle') def startRules(self): DistributedPartyTrampolineActivity.notify.debug('startRules') if self.doJellyBeans: self.setupJellyBeans() if self.toon != None and self.toon.doId == base.localAvatar.doId: self.acquireToon() return def startActive(self): DistributedPartyTrampolineActivity.notify.debug('startActive') if self.toon != None and self.toon.doId == base.localAvatar.doId: base.setCellsActive(base.bottomCells, True) self.accept('arrow_left', self.onLeft) self.accept('arrow_left-up', self.onLeftUp) self.accept('arrow_right', self.onRight) self.accept('arrow_right-up', self.onRightUp) self.beginRoundInterval = Sequence(Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady), Wait(1.2), Func(self.flashMessage, TTLocalizer.PartyTrampolineGo), Func(self.beginRound)) self.beginRoundInterval.start() return def finishActive(self): DistributedPartyTrampolineActivity.notify.debug('finishActive') if self.doJellyBeans: self.cleanupJellyBeans() def setupJellyBeans(self): self.beanAnims = [] self.beansToCollect = [] self.beanDetails = [] self.numBeansCollected = 0 for i in xrange(self.numJellyBeans): bean = self.beans[i] guiBean = self.guiBeans[i] height = self.jellyBeanPositions[i] color = random.choice(self.jellyBeanColors) bean.find('**/jellybean').setColor(color) if self.toon.doId == base.localAvatar.doId: bean.setAlphaScale(1.0) else: bean.setAlphaScale(0.5) guiBean.setColor(color) bean.setZ(height + self.toon.getHeight() + self.beanOffset) guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset) bean.setH(0.0) bean.unstash() guiBean.unstash() beanAnim = bean.hprInterval(1.5, VBase3((i % 2 * 2 - 1) * 360.0, 0.0, 0.0)) beanAnim.loop() self.beanAnims.append(beanAnim) self.beanDetails.append((height, bean, guiBean, beanAnim)) self.beansToCollect = range(self.numJellyBeans) def cleanupJellyBeans(self): for bean in self.beans: bean.stash() for guiBean in self.guiBeans: guiBean.stash() if hasattr(self, 'beanAnims'): for beanAnim in self.beanAnims: beanAnim.finish() del self.beanAnims del self.beansToCollect def beginRound(self): base.playSfx(self.whistleSound) self.timer.setTime(PartyGlobals.TrampolineDuration) self.timer.countdown(PartyGlobals.TrampolineDuration) self.timer.show() self.gui.show() self.quitEarlyButton.unstash() self.notify.debug('Accepting contorl') self.accept('control', self.onJump) self.notify.debug('setting simulate step to true') self.doSimulateStep = True def acquireToon(self): self.toon.disableSmartCameraViews() self.toon.stopUpdateSmartCamera() camera.wrtReparentTo(render) self.toon.dropShadow.reparentTo(hidden) self.toon.startPosHprBroadcast(period=0.2) self.toonAcceleration = 0.0 self.toonVelocity = 0.0 self.topHeight = 0.0 self.trampB = self.normalTrampB self.leavingTrampoline = False self.hopOnAnim = Sequence(Func(self.toon.b_setAnimState, 'jump', 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, Point3(0.0, 0.0, self.trampHeight), 5.0, self.tramp), Func(self.postHopOn)) self.hopOnAnim.start() def postHopOn(self): self.toon.setH(self.toon.getH() + 90.0) self.toon.dropShadow.reparentTo(self.surface) self.timeLeftToSimulate = 0.0 self.doSimulateStep = False taskMgr.add(self.updateTask, self.uniqueName('TrampolineActivity.updateTask')) base.setCellsActive(base.leftCells, False) base.setCellsActive(base.bottomCells, False) DistributedPartyActivity.startRules(self) def releaseToon(self): self._hideFlashMessage() self.ignore('arrow_left') self.ignore('arrow_left-up') self.ignore('arrow_right') self.ignore('arrow_right-up') taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) self.hopOffAnim = Sequence(self.toon.hprInterval(0.5, VBase3(-90.0, 0.0, 0.0), other=self.tramp), Func(self.toon.b_setAnimState, 'jump', 1.0), Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0, self.tramp), Func(self.postHopOff)) self.hopOffAnim.start() def postHopOff(self): base.setCellsActive(base.leftCells, True) self.timer.stop() self.timer.hide() self.toon.dropShadow.reparentTo(self.toon.getShadowJoint()) self.toon.dropShadow.setAlphaScale(1.0) self.toon.dropShadow.setScale(1.0) self.b_requestAnim('Off') camera.reparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() base.localAvatar.enableSmartCameraViews() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) place = base.cr.playGame.getPlace() if self.doJellyBeans: self.sendUpdate('awardBeans', [self.numBeansCollected, int(self.topHeight)]) if int(self.topHeight) > self.bestHeightInfo[1]: self.sendUpdate('reportHeightInformation', [int(self.topHeight)]) self.d_toonExitDemand() def onTrampolineTrigger(self, collEntry): if self.activityFSM.state == 'Idle' and self.toon == None and base.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'walk': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() else: self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied, duration=2.0) return def onJump(self): self.notify.debug('got onJump') if self.toon != None and self.toon.getZ() < self.trampHeight: self.toonJumped = True self.b_requestAnim('Jump') else: self.notify.debug('z is less than tramp height') return def onLeft(self): self.turnLeft = True def onLeftUp(self): self.turnLeft = False def onRight(self): self.turnRight = True def onRightUp(self): self.turnRight = False def handleToonJoined(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonJoined') self.toon = self.getAvatar(toonId) if self.toon != None and not self.toon.isEmpty(): self.oldJumpSquatPlayRate = self.toon.getPlayRate('jump-squat') self.oldJumpLandPlayRate = self.toon.getPlayRate('jump-land') self.toon.setPlayRate(2.5, 'jump-squat') self.toon.setPlayRate(2.0, 'jump-land') self.turnLeft = False self.turnRight = False self.activityFSM.request('Rules') if self.toon.doId != base.localAvatar.doId: taskMgr.add(self.remoteUpdateTask, self.uniqueName('TrampolineActivity.remoteUpdateTask')) else: self.notify.warning('handleToonJoined could not get toon %d' % toonId) return def handleToonExited(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonExited') if self.toon != None: if self.toon.doId != base.localAvatar.doId: taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.surface.setZ(self.trampHeight) self.toon.setPlayRate(self.oldJumpSquatPlayRate, 'jump-squat') self.toon.setPlayRate(self.oldJumpLandPlayRate, 'jump-land') self.toon = None return def handleToonDisabled(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonDisabled') DistributedPartyTrampolineActivity.notify.debug('avatar ' + str(toonId) + ' disabled') if base.localAvatar.doId == toonId: self.releaseToon() def handleRulesDone(self): self.sendUpdate('toonReady') self.finishRules() def getTitle(self): if self.doJellyBeans: return TTLocalizer.PartyTrampolineJellyBeanTitle elif self.doTricks: return TTLocalizer.PartyTrampolineTricksTitle else: return DistributedPartyActivity.getTitle(self) def getInstructions(self): return TTLocalizer.PartyTrampolineActivityInstructions def updateTask(self, task): z = self.toon.getZ() dt = globalClock.getDt() if self.doSimulateStep: self.timeLeftToSimulate += dt while self.timeLeftToSimulate >= self.stepDT: z, a = self.simulateStep(z) self.timeLeftToSimulate -= self.stepDT self.toon.setZ(z) if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor) if self.turnLeft: self.toon.setH(self.toon.getH() + self.turnFactor * dt) if self.turnRight: self.toon.setH(self.toon.getH() - self.turnFactor * dt) currentPos = base.camera.getPos(self.toon) vec = self.targetCameraPos - currentPos newPos = currentPos + vec * (dt * self.cameraSpeed) base.camera.setPos(self.toon, newPos) base.camera.lookAt(self.toon) #if z > self.trampHeight: # heightFactor = 1.0 - min(1.0, (z - self.trampHeight) / self.dropShadowCutoff) # self.toon.dropShadow.setAlphaScale(heightFactor) # self.toon.dropShadow.setScale(max(0.1, heightFactor)) #else: # self.toon.dropShadow.setAlphaScale(1.0) # self.toon.dropShadow.setScale(1.0) if self.leavingTrampoline and z < self.trampHeight and abs(a) < 0.1: self.releaseToon() return Task.cont def simulateStep(self, z): if z >= self.trampHeight: a = self.g self.toonJumped = False else: a = self.g + self.trampK * (self.trampHeight - z) - self.trampB * self.toonVelocity if self.toonJumped: if self.lastPeak > self.earlyJumpThreshold or self.toonVelocity >= -300000.0: a += self.jumpBoost if self.lastPeak < self.beginningBoostThreshold: a += self.beginningBoost lastVelocity = self.toonVelocity self.toonVelocity += a * self.stepDT if lastVelocity > 0.0 and self.toonVelocity <= 0.0: topOfJump = True bottomOfJump = False elif lastVelocity < 0.0 and self.toonVelocity >= 0.0: topOfJump = False bottomOfJump = True else: topOfJump = False bottomOfJump = False newZ = z + self.toonVelocity * self.stepDT if newZ > self.topHeight: self.topHeight = newZ if self.doJellyBeans: self.collectJellyBeans(newZ) if topOfJump: self.lastPeak = newZ if newZ >= self.minHeightForText: self.heightTextInterval.start() if topOfJump: if newZ > self.trampHeight + 20.0: self.b_requestAnim('Falling') elif self.animFSM.state == 'Jump': self.b_requestAnim('Falling') if newZ <= self.trampHeight and z > self.trampHeight: if self.animFSM.state == 'Falling': self.b_requestAnim('Land') elif self.animFSM.state != 'Neutral': self.b_requestAnim('Neutral') if bottomOfJump and a > self.boingThreshold: base.playSfx(self.boingSound) return (newZ, a) def collectJellyBeans(self, z): beansToRemove = [] for i in self.beansToCollect: height = self.beanDetails[i][0] if height <= z: beansToRemove.append(i) if len(beansToRemove) > 0: base.playSfx(self.jellyBeanSound) self.numBeansCollected += len(beansToRemove) self.b_removeBeans(beansToRemove) def remoteUpdateTask(self, task): if self.toon != None and not self.toon.isEmpty(): z = self.toon.getZ() if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) return Task.cont def poofBean(self, bean, beanAnim): if bean == None: self.notify.warning('poofBean, returning immediately as bean is None') return if bean.isEmpty(): self.notify.warning('poofBean, returning immediately as bean is empty') return currentAlpha = bean.getColorScale()[3] currentScale = bean.getScale() poofAnim = Sequence(Parallel(LerpFunc(bean.setAlphaScale, fromData=currentAlpha, toData=0.0, duration=0.25), LerpFunc(bean.setScale, fromData=currentScale, toData=currentScale * 5.0, duration=0.25)), Func(bean.stash), Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha), Func(bean.setScale, currentScale)) poofAnim.start() return def _showFlashMessage(self, message): if self.isDisabled(): return if self.flashTextInterval is not None and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() self.flashText.setText(message) self.flashText.setAlphaScale(1.0) self.flashText.unstash() return def _hideFlashMessage(self, duration = 0.0): if self.isDisabled(): pass self.flashTextInterval = Sequence(Wait(duration), LerpFunc(self.flashText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), Func(self.flashText.stash)) self.flashTextInterval.start() def flashMessage(self, message, duration = 0.5): self._showFlashMessage(message) self._hideFlashMessage(duration)
class Agent: def __init__( self, _name ): print "Creating agent " + _name self.name = _name def setDataPath( self, _dataPath ): self.dataPath = _dataPath; def setActor( self, _modelFileName, _animationFileNames, _morphTargetsFileName ): self.modelFileName = _modelFileName; self.animationFileNames = _animationFileNames; self.morphTargetsFileName = _morphTargetsFileName; def setRealizer( self, _realizer ): self.realizer = _realizer; def setTransform( self, x, y, z, rx, ry, rz, scale ): self.agent.setPos( x, y, z ) self.agent.setScale( scale ) self.agent.setHpr( rx, ry, rz ) self.positionX = x self.positionY = y self.positionZ = z def getPosition( self ): return self.agent.getPos() def init( self ): #load the agent and parent it to the world #The joints of this agent will reference Panda NodePaths, it will be possible to play animations on it self.animationAgent = Actor( self.modelFileName, self.animationFileNames ) self.agent = Actor( self.modelFileName, self.morphTargetsFileName ) maxMorphTargets={'MT_Jaw_Open':self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_Open'), 'MT_Jaw_L':self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_L'), 'MT_Jaw_R':self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_R'), 'MT_Jaw_Fwd':self.agent.controlJoint(None, 'modelRoot', 'MT_Jaw_Fwd'), 'MT_WideL':self.agent.controlJoint(None, 'modelRoot', 'MT_WideL'), 'MT_WideR':self.agent.controlJoint(None, 'modelRoot', 'MT_WideR'), 'MT_NarrowL':self.agent.controlJoint(None, 'modelRoot', 'MT_NarrowL'), 'MT_NarrowR':self.agent.controlJoint(None, 'modelRoot', 'MT_NarrowR'), 'MT_FrownL':self.agent.controlJoint(None, 'modelRoot', 'MT_FrownL'), 'MT_FrownR':self.agent.controlJoint(None, 'modelRoot', 'MT_FrownR'), 'MT_SneerL':self.agent.controlJoint(None, 'modelRoot', 'MT_SneerL'), 'MT_SneerR':self.agent.controlJoint(None, 'modelRoot', 'MT_SneerR'), 'MT_SquintL':self.agent.controlJoint(None, 'modelRoot', 'MT_SquintL'), 'MT_SquintR':self.agent.controlJoint(None, 'modelRoot', 'MT_SquintR'), 'MT_BrowUpL':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowUpL'), 'MT_BrowUpR':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowUpR'), 'MT_BrowDnL':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnL'), 'MT_BrowDnR':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnR'), 'MT_MBrowUp':self.agent.controlJoint(None, 'modelRoot', 'MT_MBrowUp'), 'MT_BrowDnR':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnR'), 'MT_BrowDnL':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowDnL'), 'MT_MBrowDn':self.agent.controlJoint(None, 'modelRoot', 'MT_MBrowDn'), 'MT_BrowSqueeze':self.agent.controlJoint(None, 'modelRoot', 'MT_BrowSqueeze'), 'MT_MouthL':self.agent.controlJoint(None, 'modelRoot', 'MT_MouthL'), 'MT_MouthR':self.agent.controlJoint(None, 'modelRoot', 'MT_MouthR'), 'MT_UprLipUpL':self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipUpL'), 'MT_UprLipUpR':self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipUpR'), 'MT_UprLipDnL':self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipDnL'), 'MT_UprLipDnR':self.agent.controlJoint(None, 'modelRoot', 'MT_UprLipDnR'), 'MT_LwrLipUpL':self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipUpL'), 'MT_LwrLipUpR':self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipUpR'), 'MT_LwrLipDnL':self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipDnL'), 'MT_LwrLipDnR':self.agent.controlJoint(None, 'modelRoot', 'MT_LwrLipDnR'), 'MT_BlowCheeksL':self.agent.controlJoint(None, 'modelRoot', 'MT_BlowCheeksL'), 'MT_BlowCheeksR':self.agent.controlJoint(None, 'modelRoot', 'MT_BlowCheeksR'), 'MT_TongueOut':self.agent.controlJoint(None, 'modelRoot', 'MT_TongueOut'), 'MT_TongueUp':self.agent.controlJoint(None, 'modelRoot', 'MT_TongueUp'), 'MT_TongueTipUp':self.agent.controlJoint(None, 'modelRoot', 'MT_TongueTipUp'), 'MT_TongueL':self.agent.controlJoint(None, 'modelRoot', 'MT_TongueL'), 'MT_TongueR':self.agent.controlJoint(None, 'modelRoot', 'MT_TongueR'), 'MT_Blink_L':self.agent.controlJoint(None, 'modelRoot', 'MT_Blink_L'), 'MT_Blink_R':self.agent.controlJoint(None, 'modelRoot', 'MT_Blink_R')} self.targets = {#'Basis':[], 'ExpSmileClosed':{maxMorphTargets['MT_WideR']:1.0,maxMorphTargets['MT_WideL']:1.0}, 'ExpAnger':{maxMorphTargets['MT_Jaw_Open']:-0.07,maxMorphTargets['MT_Jaw_Fwd']:0.25,maxMorphTargets['MT_NarrowL']:0.30,maxMorphTargets['MT_NarrowR']:0.30,maxMorphTargets['MT_SquintL']:0.60,maxMorphTargets['MT_SquintR']:0.60,maxMorphTargets['MT_MBrowDn']:1.0,maxMorphTargets['MT_BrowDnL']:0.7,maxMorphTargets['MT_BrowDnR']:0.7,maxMorphTargets['MT_SneerL']:0.8,maxMorphTargets['MT_SneerR']:0.8,maxMorphTargets['MT_FrownL']:0.2,maxMorphTargets['MT_FrownR']:0.2,maxMorphTargets['MT_UprLipDnL']:0.45,maxMorphTargets['MT_UprLipDnR']:0.45,maxMorphTargets['MT_LwrLipUpL']:1.0,maxMorphTargets['MT_LwrLipUpR']:1.0}, 'ExpDisgust':{maxMorphTargets['MT_WideL']:0.25,maxMorphTargets['MT_WideR']:0.15,maxMorphTargets['MT_SquintL']:0.40,maxMorphTargets['MT_SquintR']:0.40,maxMorphTargets['MT_MBrowDn']:0.25,maxMorphTargets['MT_BrowSqueeze']:0.45,maxMorphTargets['MT_WideL']:0.25,maxMorphTargets['MT_BrowDnL']:0.50,maxMorphTargets['MT_BrowDnR']:0.50,maxMorphTargets['MT_SneerL']:2.0,maxMorphTargets['MT_SneerR']:2.0,maxMorphTargets['MT_FrownL']:0.25,maxMorphTargets['MT_FrownR']:0.25,maxMorphTargets['MT_UprLipUpL']:0.66,maxMorphTargets['MT_UprLipUpR']:0.33,maxMorphTargets['MT_LwrLipUpL']:0.40,maxMorphTargets['MT_LwrLipUpR']:0.40 }, 'ExpFear':{maxMorphTargets['MT_Jaw_Open']:0.15,maxMorphTargets['MT_Jaw_Fwd']:-0.3,maxMorphTargets['MT_NarrowL']:0.24,maxMorphTargets['MT_NarrowR']:0.24,maxMorphTargets['MT_SquintL']:-0.4,maxMorphTargets['MT_SquintR']:-0.4,maxMorphTargets['MT_BrowUpL']:0.36,maxMorphTargets['MT_BrowUpR']:0.36,maxMorphTargets['MT_MBrowUp']:1.30,maxMorphTargets['MT_BrowSqueeze']:0.40,maxMorphTargets['MT_FrownL']:0.35,maxMorphTargets['MT_FrownR']:0.35,maxMorphTargets['MT_UprLipDnL']:0.25,maxMorphTargets['MT_UprLipDnR']:0.25,maxMorphTargets['MT_LwrLipUpL']:0.35,maxMorphTargets['MT_LwrLipUpR']:0.35}, 'ExpSad':{maxMorphTargets['MT_NarrowL']:0.20,maxMorphTargets['MT_NarrowR']:0.20,maxMorphTargets['MT_SquintL']:0.20,maxMorphTargets['MT_SquintR']:0.20,maxMorphTargets['MT_MBrowUp']:0.40,maxMorphTargets['MT_BrowSqueeze']:0.66,maxMorphTargets['MT_BrowDnL']:0.66,maxMorphTargets['MT_BrowDnR']:0.66,maxMorphTargets['MT_BlowCheeksL']:-0.25,maxMorphTargets['MT_BlowCheeksR']:-0.25,maxMorphTargets['MT_FrownL']:0.66,maxMorphTargets['MT_FrownR']:0.66,maxMorphTargets['MT_UprLipDnL']:0.50,maxMorphTargets['MT_UprLipDnR']:0.50,maxMorphTargets['MT_LwrLipUpL']:0.66,maxMorphTargets['MT_LwrLipUpR']:0.66}, 'ExpSurprise':{maxMorphTargets['MT_Jaw_Open']:0.25,maxMorphTargets['MT_NarrowL']:0.24,maxMorphTargets['MT_NarrowR']:0.24,maxMorphTargets['MT_SquintL']:-0.20,maxMorphTargets['MT_SquintR']:-0.20,maxMorphTargets['MT_BrowUpL']:0.92,maxMorphTargets['MT_BrowUpR']:0.92,maxMorphTargets['MT_MBrowUp']:0.66}, 'ExpSmileOpen':{maxMorphTargets['MT_Jaw_Open']:0.16,maxMorphTargets['MT_WideL']:0.740,maxMorphTargets['MT_WideR']:0.740,maxMorphTargets['MT_SneerL']:0.280,maxMorphTargets['MT_SneerR']:0.280,maxMorphTargets['MT_BrowUpL']:0.360,maxMorphTargets['MT_BrowUpR']:0.360}, 'ExpHappy':{maxMorphTargets['MT_Jaw_Open']:0.22,maxMorphTargets['MT_WideL']:0.75,maxMorphTargets['MT_WideR']:0.75,maxMorphTargets['MT_SquintL']:0.35,maxMorphTargets['MT_SquintR']:0.35,maxMorphTargets['MT_BrowDnL']:0.08,maxMorphTargets['MT_BrowDnR']:0.08,maxMorphTargets['MT_UprLipUpL']:0.15,maxMorphTargets['MT_UprLipUpR']:0.15,maxMorphTargets['MT_LwrLipUpL']:0.15,maxMorphTargets['MT_LwrLipUpR']:0.15,maxMorphTargets['MT_BrowUpL']:0.360,maxMorphTargets['MT_BrowUpR']:0.360}, 'ModBlinkLeft':{maxMorphTargets['MT_Blink_L']:1.0}, 'ModBlinkRight':{maxMorphTargets['MT_Blink_R']:1.0}, 'ModBrowDownLeft':{maxMorphTargets['MT_BrowDnL']:1.0}, 'ModBrowDownRight':{maxMorphTargets['MT_BrowDnR']:1.0}, 'ModBrowInRight':{maxMorphTargets['MT_BrowSqueeze']:1.0}, 'ModBrowInLeft':{maxMorphTargets['MT_BrowSqueeze']:1.0}, 'ModBrowUpLeft':{maxMorphTargets['MT_BrowUpL']:1.0}, 'ModBrowUpRight':{maxMorphTargets['MT_BrowUpR']:1.0}, #'ModEarsOut':[], 'ModEyeSquintLeft':{maxMorphTargets['MT_SquintL']:1.0}, 'ModEyeSquintRight':{maxMorphTargets['MT_SquintR']:1.0}, 'Phonaah':{maxMorphTargets['MT_Jaw_Open']:1.0}, 'PhonB,M,P':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5}, 'Phonbigaah':{maxMorphTargets['MT_Jaw_Open']:1.0}, 'Phonch,J,sh':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5}, 'PhonD,S,T':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5,maxMorphTargets['MT_Jaw_Open']:0.2 }, 'Phonee':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5}, 'Phoneh':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5,maxMorphTargets['MT_Jaw_Open']:0.2 }, 'PhonF,V':{maxMorphTargets['MT_WideL']:0.2,maxMorphTargets['MT_WideR']:0.2,maxMorphTargets['MT_Jaw_Open']:0.3,maxMorphTargets['MT_UprLipDnL']:0.3,maxMorphTargets['MT_UprLipDnR']:0.3}, 'Phoni':{maxMorphTargets['MT_WideL']:0.2,maxMorphTargets['MT_WideR']:0.2,maxMorphTargets['MT_Jaw_Open']:0.3 }, 'PhonK':{maxMorphTargets['MT_Jaw_Open']:0.4}, 'PhonN':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5}, 'Phonoh':{maxMorphTargets['MT_Jaw_Open']:0.4,maxMorphTargets['MT_NarrowL']:0.55,maxMorphTargets['MT_NarrowR']:0.55}, 'Phonooh,Q':{maxMorphTargets['MT_Jaw_Open']:0.4,maxMorphTargets['MT_NarrowL']:0.55,maxMorphTargets['MT_NarrowR']:0.55}, 'PhonR':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5,maxMorphTargets['MT_Jaw_Open']:0.2 }, 'Phonth':{maxMorphTargets['MT_WideL']:0.5,maxMorphTargets['MT_WideR']:0.5,maxMorphTargets['MT_Jaw_Open']:0.2 }, 'PhonW':{maxMorphTargets['MT_Jaw_Open']:0.3,maxMorphTargets['MT_NarrowL']:0.7,maxMorphTargets['MT_NarrowR']:0.7}, 'AU26_MT_Jaw_Open':{maxMorphTargets['MT_Jaw_Open']:1.0}, 'AU30_MT_Jaw_L':{maxMorphTargets['MT_Jaw_L']:1.0}, 'AU30_MT_Jaw_R':{maxMorphTargets['MT_Jaw_R']:1.0}, 'AU31_MT_Jaw_Fwd':{maxMorphTargets['MT_Jaw_Fwd']:1.0}, 'AU27_MT_WideL':{maxMorphTargets['MT_WideL']:1.0}, 'AU27_MT_WideR':{maxMorphTargets['MT_WideR']:1.0}, 'AU18_MT_NarrowL':{maxMorphTargets['MT_NarrowL']:1.0}, 'AU18_MT_NarrowR':{maxMorphTargets['MT_NarrowL']:1.0}, 'AU42_MT_FrownL':{maxMorphTargets['MT_FrownL']:1.0}, 'AU42_MT_FrownR':{maxMorphTargets['MT_FrownR']:1.0}, 'AU9_MT_SneerL':{maxMorphTargets['MT_SneerL']:1.0}, 'AU9_MT_SneerR':{maxMorphTargets['MT_SneerR']:1.0}, 'AU46_MT_SquintL':{maxMorphTargets['MT_SquintL']:1.0}, 'AU46_MT_SquintR':{maxMorphTargets['MT_SquintR']:1.0}, 'AU2_MT_BrowUpL':{maxMorphTargets['MT_BrowUpL']:1.0}, 'AU2_MT_BrowUpR':{maxMorphTargets['MT_BrowUpR']:1.0}, 'AU4_MT_BrowDnL':{maxMorphTargets['MT_BrowDnL']:1.0}, 'AU4_MT_BrowDnR':{maxMorphTargets['MT_BrowDnR']:1.0}, 'AU4_MT_MBrowUp':{maxMorphTargets['MT_MBrowUp']:1.0}, 'AU1_MT_BrowDnR':{maxMorphTargets['MT_BrowDnR']:1.0}, 'AU1_MT_BrowDnL':{maxMorphTargets['MT_BrowDnL']:1.0}, 'AU1_MT_MBrowDn':{maxMorphTargets['MT_MBrowDn']:1.0}, 'AU44_MT_BrowSqueeze':{maxMorphTargets['MT_BrowSqueeze']:1.0}, 'AU12_MT_MouthL':{maxMorphTargets['MT_MouthL']:1.0}, 'AU12_MT_MouthR':{maxMorphTargets['MT_MouthR']:1.0}, 'AU5_MT_UprLipUpL':{maxMorphTargets['MT_UprLipUpL']:1.0}, 'AU5_MT_UprLipUpR':{maxMorphTargets['MT_UprLipUpR']:1.0}, 'MT_UprLipDnL':{maxMorphTargets['MT_UprLipDnL']:1.0}, 'MT_UprLipDnR':{maxMorphTargets['MT_UprLipDnR']:1.0}, 'MT_LwrLipUpL':{maxMorphTargets['MT_LwrLipUpL']:1.0}, 'MT_LwrLipUpR':{maxMorphTargets['MT_LwrLipUpR']:1.0}, 'MT_LwrLipDnL':{maxMorphTargets['MT_LwrLipDnL']:1.0}, 'MT_LwrLipDnR':{maxMorphTargets['MT_LwrLipDnR']:1.0}, 'AU33_MT_BlowCheeksL':{maxMorphTargets['MT_BlowCheeksL']:1.0}, 'AU33_MT_BlowCheeksR':{maxMorphTargets['MT_BlowCheeksR']:1.0}, 'AU36_MT_TongueOut':{maxMorphTargets['MT_TongueOut']:1.0}, 'AU36_MT_TongueUp':{maxMorphTargets['MT_TongueUp']:1.0}, 'AU36_MT_TongueTipUp':{maxMorphTargets['MT_TongueTipUp']:1.0}, 'AU36_MT_TongueL':{maxMorphTargets['MT_TongueL']:1.0}, 'AU36_MT_TongueR':{maxMorphTargets['MT_TongueR']:1.0}, 'AU45_MT_Blink_L':{maxMorphTargets['MT_Blink_L']:1.0}, 'AU45_MT_Blink_R':{maxMorphTargets['MT_Blink_R']:1.0} } #instanciate a list in order to keep track of kinematic joints joints #in python runtime #if nothing points towards those joints, they get flushed by #python's garbage collector self.jointList = [] self.jointFKList = [] self.agentControlJoints = [] self.agentNodePaths = [] self.agentSMRSkel = SMRPy.SMRSkeleton(True,True,'agent') self.createSkel( self.agent, self.agentSMRSkel, 'root', '' ) #Pascal: output of both skeletons amber and alfonse as chracter.bvh #SMRPy.exportSkeletonToBvh(self.name + '.bvh',self.agentSMRSkel); self.newSkeleton = SMRPy.SMRSkeleton(True,True,'pose') self.createFKSkel(self.animationAgent, self.newSkeleton, "root", '') self.realizer.addCharacter( self.name, self.agentSMRSkel ); for key in self.targets.keys(): self.realizer.addMorphTarget( self.name, key ) #TODO: declare morph targets into CharacterConfigurationFile #self.realizer.addShaderParameter( self.name, 'blushing' ) #TODO: declare shader inputs into CharacterConfiguration file self.realizer.addBVHMotionToCharacter(self.name, 'hands_claw', open('./animations/hands_claw.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_index', open('./animations/hands_index.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_open-relaxed', open('./animations/hands_open-relaxed.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_open-spread', open('./animations/hands_open-spread.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_open-straight', open('./animations/hands_open-straight.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_purse', open('./animations/hands_purse.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ring', open('./animations/hands_ring.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'poseNeutral', open('./animations/poseNeutral.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'shrug', open('./animations/shrug.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_A', open('./animations/hands_DGS_A.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_B', open('./animations/hands_DGS_B.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_C', open('./animations/hands_DGS_C.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_D', open('./animations/hands_DGS_D.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_E', open('./animations/hands_DGS_E.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_F', open('./animations/hands_DGS_F.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_G', open('./animations/hands_DGS_G.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_H', open('./animations/hands_DGS_H.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_I', open('./animations/hands_DGS_I.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_J', open('./animations/hands_DGS_J.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_K', open('./animations/hands_DGS_K.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_L', open('./animations/hands_DGS_L.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_M', open('./animations/hands_DGS_M.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_N', open('./animations/hands_DGS_N.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_O', open('./animations/hands_DGS_O.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_P', open('./animations/hands_DGS_P.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_Q', open('./animations/hands_DGS_Q.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_R', open('./animations/hands_DGS_R.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_T', open('./animations/hands_DGS_T.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_U', open('./animations/hands_DGS_U.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_W', open('./animations/hands_DGS_W.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_X', open('./animations/hands_DGS_X.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_Y', open('./animations/hands_DGS_Y.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_Z', open('./animations/hands_DGS_Z.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_DGS_SCH', open('./animations/hands_DGS_SCH.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_A', open('./animations/hands_ASL_A.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_B', open('./animations/hands_ASL_B.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_C', open('./animations/hands_ASL_C.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_D', open('./animations/hands_ASL_D.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_E', open('./animations/hands_ASL_E.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_F', open('./animations/hands_ASL_F.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_G', open('./animations/hands_ASL_G.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_H', open('./animations/hands_ASL_H.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_I', open('./animations/hands_ASL_I.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_J', open('./animations/hands_ASL_J.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_K', open('./animations/hands_ASL_K.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_L', open('./animations/hands_ASL_L.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_M', open('./animations/hands_ASL_M.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_N', open('./animations/hands_ASL_N.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_O', open('./animations/hands_ASL_O.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_P', open('./animations/hands_ASL_P.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_Q', open('./animations/hands_ASL_Q.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_R', open('./animations/hands_ASL_R.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_T', open('./animations/hands_ASL_T.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_U', open('./animations/hands_ASL_U.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_V', open('./animations/hands_ASL_V.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_W', open('./animations/hands_ASL_W.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_X', open('./animations/hands_ASL_X.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_Y', open('./animations/hands_ASL_Y.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_Z', open('./animations/hands_ASL_Z.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_1CL', open('./animations/hands_ASL_1CL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_2CL', open('./animations/hands_ASL_2CL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_3CL', open('./animations/hands_ASL_3CL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_4CL', open('./animations/hands_ASL_4CL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_5aCL', open('./animations/hands_ASL_5aCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_5bCL', open('./animations/hands_ASL_5bCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_ACL', open('./animations/hands_ASL_ACL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_BCL', open('./animations/hands_ASL_BCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_CCL', open('./animations/hands_ASL_CCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_FCL', open('./animations/hands_ASL_FCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_ICL', open('./animations/hands_ASL_ICL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_ILYCL', open('./animations/hands_ASL_ILYCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_SCL', open('./animations/hands_ASL_SCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_VaCL', open('./animations/hands_ASL_VaCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_VbCL', open('./animations/hands_ASL_VbCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_YCL', open('./animations/hands_ASL_YCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_CbCL', open('./animations/hands_ASL_CbCL.bvh', "r").read()) self.realizer.addBVHMotionToCharacter(self.name, 'hands_ASL_TCL', open('./animations/hands_ASL_TCL.bvh', "r").read()) firingstevenhigh = open('./animations/alfonse-FiringStevenHigh.bvh', "r").read() self.realizer.addBVHMotionToCharacter(self.name, 'FiringStevenHigh', firingstevenhigh ) print("done") self.agent.reparentTo( render ) def update( self ): self.realizer.skeletonRequested() skeletonHasBeenUpdated = False while(not skeletonHasBeenUpdated): #wait until skeleton can be displayed if(self.realizer.skeletonIsReadyToBeDisplayed(self.name)): self.updatePandaSkeleton(self.agentControlJoints, self.agentSMRSkel) skeletonHasBeenUpdated = True for key in self.realizer.getModifiedMorphTargets(self.name): #self.targets.keys(): # Only update the targets that have actually changed here #print key, "\n" weight = self.realizer.getMorphTargetWeight( self.name, key ) morphTargets = self.targets[key] for morphTargetKey in morphTargets.keys() : #print(weight*morphTargets[morphTargetKey]) morphTargetKey.setX(weight*morphTargets[morphTargetKey]) #blushingValue = self.realizer.getShaderParameterValue( self.name, 'blushing' ) #self.shaders.headShader.blushing.set( blushingValue ) def addAnimation(self,_actorName,_animationName): self.animationAgent.reparentTo(render) self.animationAgent.setScale(10) self.realizer.addAnimation(_actorName, _animationName) for i in range (self.animationAgent.getNumFrames(_animationName)): self.animationAgent.pose(_animationName,i) base.graphicsEngine.renderFrame() self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton) self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton) self.animationAgent.detachNode() print "animation",_animationName,"added" def addAnimationWE(self,_actorName,_animationName): self.animationAgent.reparentTo(render) self.animationAgent.setScale(10) agentSMRMotion = SMRPy.SMRMotion() agentSMRMotion.setTimeStep(0.04) self.realizer.addAnimation(_actorName, _animationName) for i in range (self.animationAgent.getNumFrames(_animationName)): self.animationAgent.pose(_animationName,i) base.graphicsEngine.renderFrame() self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton) self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton) agentSMRMotion.insertSkeleton(self.newSkeleton) self.animationAgent.detachNode() print "animation",_animationName,"added" SMRPy.exportMotionToBvh(_animationName+".bvh",agentSMRMotion) def createSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName): #get the agent's currentJoint currentPandaJoint = _pandaAgent.getJoints(None,_initialJointName) currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot', _initialJointName) self.agentControlJoints.append(currentPandaCJoint) #get the first joint's position position = currentPandaCJoint.getPos() if (currentPandaJoint[0].getNumChildren() == 0): newJoint = SMRPy.SMRJoint(True) newJoint.setEndVect(position.getX(),position.getY(),position.getZ()); else: newJoint = SMRPy.SMRJoint(False) rotZ = (currentPandaCJoint.getH()/180.0)*3.14159; rotX = (currentPandaCJoint.getP()/180.0)*3.14159; rotY = (currentPandaCJoint.getR()/180.0)*3.14159; quatZ = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0,0.0,1.0),rotZ) quatX = SMRPy.SMRQuaternion(SMRPy.SMRVector3(1.0,0.0,0.0),rotX) quatY = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0,1.0,0.0),rotY) quatRot = quatZ.multiply(quatX) quatRot = quatRot.multiply(quatY) quatRot.normalize(); newJoint.setPos(position.getX(),position.getY(),position.getZ()) newJoint.setRotQuat(quatRot.getW(),quatRot.getX(),quatRot.getY(),quatRot.getZ()) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) self.jointList.append(newJoint) _smrSkel.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() #print(childName) self.createSkel(_pandaAgent, _smrSkel, childName, _initialJointName) def createFKSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName): #get the agent's currentJoint currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName) currentPandaJointPath = _pandaAgent.exposeJoint(None, 'modelRoot', _initialJointName, "lodRoot", True) self.agentNodePaths.append(currentPandaJointPath) #get the first joint's position position = currentPandaJointPath.getPos() if (currentPandaJoint[0].getNumChildren() == 0): newJoint = SMRPy.SMRJoint(True) newJoint.setEndVect(position.getX(),position.getY(),position.getZ()); else: newJoint = SMRPy.SMRJoint(False) quatRot = currentPandaJointPath.getQuat() newJoint.setPos(position.getX(),position.getY(),position.getZ()) newJoint.setRotQuat(quatRot.getR(),quatRot.getI(),quatRot.getJ(),quatRot.getK()) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) self.jointFKList.append(newJoint) _smrSkel.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() #print(childName) self.createFKSkel(_pandaAgent, _smrSkel, childName, _initialJointName) def updatePandaSkeleton(self, agentControlJoints, _smrSkeleton): #synchronize root joint SMRJoint = _smrSkeleton.getJoint(0) PANDAJoint = agentControlJoints[0] position = SMRJoint.getPos() PANDAJoint.setPos(position.X(),position.Y(),position.Z()); for i in range(_smrSkeleton.getNumjoints()): SMRJoint = _smrSkeleton.getJoint(i) PANDAJoint = agentControlJoints[i] self.synchronize(PANDAJoint,SMRJoint) def updateSMRSkeleton(self, agentNodePaths, _smrSkeleton): #synchronize root joint SMRJoint = _smrSkeleton.getJoint(0) PANDAJoint = agentNodePaths[0] position = PANDAJoint.getPos() SMRJoint.setPos(position.getX(),position.getY(),position.getZ()); for i in range(_smrSkeleton.getNumjoints()): SMRJoint = _smrSkeleton.getJoint(i) PANDAJoint = agentNodePaths[i] self.synchronizePandaToSMR(SMRJoint,PANDAJoint) def synchronizePandaToSMR(self, _SMRJoint, _PANDAJoint): pandaQuaternion = _PANDAJoint.getQuat() x = pandaQuaternion.getI() y = pandaQuaternion.getJ() z = pandaQuaternion.getK() w = pandaQuaternion.getR() _SMRJoint.setRotQuat(w,x,y,z) def synchronize(self, _pandaCJoint, _smrJoint): smrQuaternion = _smrJoint.getRot() pandaQuaternion = Quat() pandaQuaternion.setI(smrQuaternion.getX()) pandaQuaternion.setJ(smrQuaternion.getY()) pandaQuaternion.setK(smrQuaternion.getZ()) pandaQuaternion.setR(smrQuaternion.getW()) if not(pandaQuaternion.isNan()): _pandaCJoint.setQuat(pandaQuaternion)
class Character: """A character with an animated avatar that moves left, right or forward according to the controls turned on or off in self.controlMap. Public fields: self.controlMap -- The character's movement controls self.actor -- The character's Actor (3D animated model) Public functions: __init__ -- Initialise the character move -- Move and animate the character for one frame. This is a task function that is called every frame by Panda3D. setControl -- Set one of the character's controls on or off. """ def __init__(self, agent_simulator, model, actions, startPos, scale): """Initialize the character. Arguments: model -- The path to the character's model file (string) run : The path to the model's run animation (string) walk : The path to the model's walk animation (string) startPos : Where in the world the character will begin (pos) scale : The amount by which the size of the model will be scaled (float) """ self.agent_simulator = agent_simulator self.controlMap = {"turn_left":0, "turn_right":0, "move_forward":0, "move_backward":0,\ "look_up":0, "look_down":0, "look_left":0, "look_right":0} self.actor = Actor(model,actions) self.actor.reparentTo(render) self.actor.setScale(scale) self.actor.setPos(startPos) self.actor.setHpr(0,0,0) # Expose agent's right hand joint to attach objects to self.actor_right_hand = self.actor.exposeJoint(None, 'modelRoot', 'RightHand') self.actor_left_hand = self.actor.exposeJoint(None, 'modelRoot', 'LeftHand') self.right_hand_holding_object = False self.left_hand_holding_object = False # speech bubble self.last_spoke = 0 self.speech_bubble=DirectLabel(parent=self.actor, text="", text_wordwrap=10, pad=(3,3), relief=None, text_scale=(.5,.5), pos = (0,0,6), frameColor=(.6,.2,.1,.5), textMayChange=1, text_frame=(0,0,0,1), text_bg=(1,1,1,1)) self.speech_bubble.component('text0').textNode.setCardDecal(1) self.speech_bubble.setBillboardAxis() # visual processing self.actor_eye = self.actor.exposeJoint(None, 'modelRoot', 'LeftEyeLid') # put a camera on ralph self.fov = NodePath(Camera('RaphViz')) self.fov.reparentTo(self.actor_eye) self.fov.setHpr(180,0,0) #lens = OrthographicLens() #lens.setFilmSize(20,15) #self.fov.node().setLens(lens) lens = self.fov.node().getLens() lens.setFov(60) # degree field of view (expanded from 40) lens.setNear(0.2) #self.fov.node().showFrustum() # displays a box around his head self.actor_neck = self.actor.controlJoint(None, 'modelRoot', 'Neck') # Define subpart of agent for when he's standing around self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"]) taskMgr.add(self.move,"moveTask") # Note: deriving classes DO NOT need # to add their own move tasks to the # task manager. If they override # self.move, then their own self.move # function will get called by the # task manager (they must then # explicitly call Character.move in # that function if they want it). self.prevtime = 0 self.isMoving = False self.current_frame_count = 0.0 # 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.initialize_collision_handling() def initialize_collision_handling(self): self.collision_handling_mutex = Lock() self.cTrav = CollisionTraverser() self.groundRay = CollisionRay() self.groundRay.setOrigin(0,0,1000) self.groundRay.setDirection(0,0,-1) self.groundCol = CollisionNode('ralphRay') self.groundCol.setIntoCollideMask(BitMask32.bit(0)) self.groundCol.setFromCollideMask(BitMask32.bit(0)) self.groundCol.addSolid(self.groundRay) self.groundColNp = self.actor.attachNewNode(self.groundCol) self.groundHandler = CollisionHandlerQueue() self.cTrav.addCollider(self.groundColNp, self.groundHandler) # Uncomment this line to see the collision rays # self.groundColNp.show() #Uncomment this line to show a visual representation of the #collisions occuring # self.cTrav.showCollisions(render) def destroy_collision_handling(self): self.collision_handling_mutex.acquire() def handle_collisions(self): self.collision_handling_mutex.acquire() self.groundCol.setIntoCollideMask(BitMask32.bit(0)) self.groundCol.setFromCollideMask(BitMask32.bit(1)) # Now check for collisions. self.cTrav.traverse(render) # Adjust the character's Z coordinate. If the character'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.groundHandler.getNumEntries()): entry = self.groundHandler.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.actor.setZ(entries[0].getSurfacePoint(render).getZ()) else: self.actor.setPos(self.startpos) self.groundCol.setIntoCollideMask(BitMask32.bit(0)) self.groundCol.setFromCollideMask(BitMask32.bit(0)) self.collision_handling_mutex.release() def position(self): return self.actor.getPos() def forward_normal_vector(self): backward = self.actor.getNetTransform().getMat().getRow3(1) backward.setZ(0) backward.normalize() return -backward def step_simulation_time(self, seconds): # save the character's initial position so that we can restore it, # in case he falls off the map or runs into something. self.startpos = self.actor.getPos() def bound(i, mn = -1, mx = 1): return min(max(i, mn), mx) # enforces bounds on a numeric value # move the character if any of the move controls are activated. if (self.controlMap["turn_left"]!=0): self.actor.setH(self.actor.getH() + seconds*30) if (self.controlMap["turn_right"]!=0): self.actor.setH(self.actor.getH() - seconds*30) if (self.controlMap["move_forward"]!=0): self.actor.setPos(self.actor.getPos() + self.forward_normal_vector() * (seconds*0.5)) if (self.controlMap["move_backward"]!=0): self.actor.setPos(self.actor.getPos() - self.forward_normal_vector() * (seconds*0.5)) if (self.controlMap["look_left"]!=0): self.actor_neck.setP(bound(self.actor_neck.getP(),-60,60)+1*(seconds*50)) if (self.controlMap["look_right"]!=0): self.actor_neck.setP(bound(self.actor_neck.getP(),-60,60)-1*(seconds*50)) if (self.controlMap["look_up"]!=0): self.actor_neck.setH(bound(self.actor_neck.getH(),-60,80)+1*(seconds*50)) if (self.controlMap["look_down"]!=0): self.actor_neck.setH(bound(self.actor_neck.getH(),-60,80)-1*(seconds*50)) # allow dialogue window to gradually decay (changing transparancy) and then disappear self.last_spoke += seconds self.speech_bubble['text_bg']=(1,1,1,1/(2*self.last_spoke+0.01)) self.speech_bubble['frameColor']=(.6,.2,.1,.5/(2*self.last_spoke+0.01)) if self.last_spoke > 2: self.speech_bubble['text'] = "" # If the character is moving, loop the run animation. # If he is standing still, stop the animation. if (self.controlMap["move_forward"]!=0) or (self.controlMap["move_backward"]!=0): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.current_frame_count = 5.0 self.isMoving = False total_frame_num = self.actor.getNumFrames('walk') if self.isMoving: self.current_frame_count = self.current_frame_count + (seconds*10.0) while (self.current_frame_count >= total_frame_num + 1): self.current_frame_count -= total_frame_num while (self.current_frame_count < 0): self.current_frame_count += total_frame_num self.actor.pose('walk', self.current_frame_count) self.handle_collisions() def move(self, task): """Move and animate the character for one frame. This is a task function that is called every frame by Panda3D. The character is moved according to which of it's movement controls are set, and the function keeps the character's feet on the ground and stops the character from moving if a collision is detected. This function also handles playing the characters movement animations. Arguments: task -- A direct.task.Task object passed to this function by Panda3D. Return: Task.cont -- To tell Panda3D to call this task function again next frame. """ elapsed = task.time - self.prevtime # Store the task time and continue. self.prevtime = task.time return Task.cont def setControl(self, control, value): """Set the state of one of the character's movement controls. Arguments See self.controlMap in __init__. control -- The control to be set, must be a string matching one of the strings in self.controlMap. value -- The value to set the control to. """ # FIXME: this function is duplicated in Camera and Character, and # keyboard control settings are spread throughout the code. Maybe # add a Controllable class? self.controlMap[control] = value # these are simple commands that can be exported over xml-rpc (or attached to the keyboard) def get_objects(self): """ Looks up all of the model nodes that are 'isInView' of the camera and returns them in the in_view dictionary (as long as they are also in the self.world_objects -- otherwise this includes points defined within the environment/terrain). TODO: 1) include more geometric information about the object (size, mass, etc) """ def map3dToAspect2d(node, point): """Maps the indicated 3-d point (a Point3), which is relative to the indicated NodePath, to the corresponding point in the aspect2d scene graph. Returns the corresponding Point3 in aspect2d. Returns None if the point is not onscreen. """ # Convert the point to the 3-d space of the camera p3 = self.fov.getRelativePoint(node, point) # Convert it through the lens to render2d coordinates p2 = Point2() if not self.fov.node().getLens().project(p3, p2): return None r2d = Point3(p2[0], 0, p2[1]) # And then convert it to aspect2d coordinates a2d = aspect2d.getRelativePoint(render2d, r2d) return a2d objs = render.findAllMatches("**/+ModelNode") in_view = {} for o in objs: o.hideBounds() # in case previously turned on o_pos = o.getPos(self.fov) if self.fov.node().isInView(o_pos): if self.agent_simulator.world_objects.has_key(o.getName()): b_min, b_max = o.getTightBounds() a_min = map3dToAspect2d(render, b_min) a_max = map3dToAspect2d(render, b_max) if a_min == None or a_max == None: continue x_diff = math.fabs(a_max[0]-a_min[0]) y_diff = math.fabs(a_max[2]-a_min[2]) area = 100*x_diff*y_diff # percentage of screen object_dict = {'x_pos': (a_min[2]+a_max[2])/2.0,\ 'y_pos': (a_min[0]+a_max[0])/2.0,\ 'distance':o.getDistance(self.fov), \ 'area':area,\ 'orientation': o.getH(self.fov)} in_view[o.getName()]=object_dict print o.getName(), object_dict return in_view def control__turn_left__start(self): self.setControl("turn_left", 1) self.setControl("turn_right", 0) def control__turn_left__stop(self): self.setControl("turn_left", 0) def control__turn_right__start(self): self.setControl("turn_left", 0) self.setControl("turn_right", 1) def control__turn_right__stop(self): self.setControl("turn_right", 0) def control__move_forward__start(self): self.setControl("move_forward", 1) self.setControl("move_backward", 0) def control__move_forward__stop(self): self.setControl("move_forward", 0) def control__move_backward__start(self): self.setControl("move_forward", 0) self.setControl("move_backward", 1) def control__move_backward__stop(self): self.setControl("move_backward", 0) def control__look_left__start(self): self.setControl("look_left", 1) self.setControl("look_right", 0) def control__look_left__stop(self): self.setControl("look_left", 0) def control__look_right__start(self): self.setControl("look_right", 1) self.setControl("look_left", 0) def control__look_right__stop(self): self.setControl("look_right", 0) def control__look_up__start(self): self.setControl("look_up", 1) self.setControl("look_down", 0) def control__look_up__stop(self): self.setControl("look_up", 0) def control__look_down__start(self): self.setControl("look_down", 1) self.setControl("look_up", 0) def control__look_down__stop(self): self.setControl("look_down", 0) def can_grasp(self, object_name): objects = self.get_objects() if objects.has_key(object_name): object_view = objects[object_name] distance = object_view['distance'] if (distance < 5.0): return True return False def control__say(self, message): self.speech_bubble['text'] = message self.last_spoke = 0 def control__pick_up_with_right_hand(self, pick_up_object): print "attempting to pick up " + pick_up_object + " with right hand.\n" if self.right_hand_holding_object: return 'right hand is already holding ' + self.right_hand_holding_object.getName() + '.' if self.can_grasp(pick_up_object): world_object = self.agent_simulator.world_objects[pick_up_object] object_parent = world_object.getParent() if (object_parent == self.agent_simulator.env): world_object.wrtReparentTo(self.actor_right_hand) world_object.setPos(0, 0, 0) world_object.setHpr(0, 0, 0) self.right_hand_holding_object = world_object return 'success' else: return 'object (' + pick_up_object + ') is already held by something or someone.' else: return 'object (' + pick_up_object + ') is not graspable (i.e. in view and close enough).' def put_object_in_empty_left_hand(self, object_name): if (self.left_hand_holding_object is not False): return False world_object = self.agent_simulator.world_objects[object_name] world_object.wrtReparentTo(self.actor_left_hand) world_object.setPos(0, 0, 0) world_object.setHpr(0, 0, 0) self.left_hand_holding_object = world_object return True def control__pick_up_with_left_hand(self, pick_up_object): print "attempting to pick up " + pick_up_object + " with left hand.\n" if self.left_hand_holding_object: return 'left hand is already holding ' + self.left_hand_holding_object.getName() + '.' if self.can_grasp(pick_up_object): world_object = self.agent_simulator.world_objects[pick_up_object] object_parent = world_object.getParent() if (object_parent == self.agent_simulator.env): self.put_object_in_empty_left_hand(pick_up_object) return 'success' else: return 'object (' + pick_up_object + ') is already held by something or someone.' else: return 'object (' + pick_up_object + ') is not graspable (i.e. in view and close enough).' def control__drop_from_right_hand(self): print "attempting to drop object from right hand.\n" if self.right_hand_holding_object is False: return 'right hand is not holding an object.' world_object = self.right_hand_holding_object self.right_hand_holding_object = False world_object.wrtReparentTo(self.agent_simulator.env) world_object.setHpr(0, 0, 0) world_object.setPos(self.position() + self.forward_normal_vector() * 0.5) world_object.setZ(world_object.getZ() + 1.0) return 'success' def control__drop_from_left_hand(self): print "attempting to drop object from left hand.\n" if self.left_hand_holding_object is False: return 'left hand is not holding an object.' world_object = self.left_hand_holding_object self.left_hand_holding_object = False world_object.wrtReparentTo(self.agent_simulator.env) world_object.setHpr(0, 0, 0) world_object.setPos(self.position() + self.forward_normal_vector() * 0.5) world_object.setZ(world_object.getZ() + 1.0) return 'success' def is_holding(self, object_name): return ((self.left_hand_holding_object and (self.left_hand_holding_object.getName() == object_name)) or (self.right_hand_holding_object and (self.right_hand_holding_object.getName() == object_name))) def empty_hand(self): if (self.left_hand_holding_object is False): return self.actor_left_hand elif (self.right_hand_holding_object is False): return self.actor_right_hand return False def has_empty_hand(self): return (self.empty_hand() is not False) def control__use_object_with_object(self, use_object, with_object): if ((use_object == 'knife') and (with_object == 'loaf_of_bread')): if self.is_holding('knife'): if self.can_grasp('loaf_of_bread'): if self.has_empty_hand(): empty_hand = self.empty_hand() new_object_name = self.agent_simulator.create_object__slice_of_bread([float(x) for x in empty_hand.getPos()]) if (empty_hand == self.actor_left_hand): self.put_object_in_empty_left_hand(new_object_name) elif (empty_hand == self.actor_right_hand): self.put_object_in_empty_right_hand(new_object_name) else: return "simulator error: empty hand is not left or right. (are there others?)" return 'success' else: return 'failure: one hand must be empty to hold loaf_of_bread in place while using knife.' else: return 'failure: loaf of bread is not graspable (in view and close enough)' else: return 'failure: must be holding knife object to use it.' return 'failure: don\'t know how to use ' + use_object + ' with ' + with_object + '.'
class LookingGrippingDemo(ShowBase): def __init__(self): # Initialize the ShowBase class from which we inherit, which will # create a window and set up everything we need for rendering into it. ShowBase.__init__(self) # This code puts the standard title and instruction text on screen self.title = OnscreenText( text="Panda3D: Tutorial - Joint Manipulation", fg=(1, 1, 1, 1), parent=base.a2dBottomRight, align=TextNode.ARight, pos=(-0.1, 0.1), shadow=(0, 0, 0, .5), scale=.08) self.onekeyText = genLabelText("ESC: Quit", 1) self.onekeyText = genLabelText("[1]: Teapot", 2) self.twokeyText = genLabelText("[2]: Candy cane", 3) self.threekeyText = genLabelText("[3]: Banana", 4) self.fourkeyText = genLabelText("[4]: Sword", 5) # Set up key input self.accept('escape', sys.exit) self.accept('1', self.switchObject, [0]) self.accept('2', self.switchObject, [1]) self.accept('3', self.switchObject, [2]) self.accept('4', self.switchObject, [3]) base.disableMouse() # Disable mouse-based camera-control camera.setPos(0, -15, 2) # Position the camera self.eve = Actor( "models/eve", # Load our animated charachter {'walk': "models/eve_walk"}) self.eve.reparentTo(render) # Put it in the scene # Now we use controlJoint to get a NodePath that's in control of her neck # This must be done before any animations are played self.eveNeck = self.eve.controlJoint(None, 'modelRoot', 'Neck') # We now play an animation. An animation must be played, or at least posed # for the nodepath we just got from controlJoint to actually effect the # model self.eve.actorInterval("walk", playRate=2).loop() # Now we add a task that will take care of turning the head taskMgr.add(self.turnHead, "turnHead") # Now we will expose the joint the hand joint. ExposeJoint allows us to # get the position of a joint while it is animating. This is different than # controlJonit which stops that joint from animating but lets us move it. # This is particularly usefull for putting an object (like a weapon) in an # actor's hand self.rightHand = self.eve.exposeJoint(None, 'modelRoot', 'RightHand') # This is a table with models, positions, rotations, and scales of objects to # be attached to our exposed joint. These are stock models and so they needed # to be repositioned to look right. positions = [("teapot", (0, -.66, -.95), (90, 0, 90), .4), ("models/candycane", (.15, -.99, -.22), (90, 0, 90), 1), ("models/banana", (.08, -.1, .09), (0, -90, 0), 1.75), ("models/sword", (.11, .19, .06), (0, 0, 90), 1)] self.models = [] # A list that will store our models objects for row in positions: np = loader.loadModel(row[0]) # Load the model np.setPos(row[1][0], row[1][1], row[1][2]) # Position it np.setHpr(row[2][0], row[2][1], row[2][2]) # Rotate it np.setScale(row[3]) # Scale it # Reparent the model to the exposed joint. That way when the joint moves, # the model we just loaded will move with it. np.reparentTo(self.rightHand) self.models.append(np) # Add it to our models list self.switchObject(0) # Make object 0 the first shown self.setupLights() # Put in some default lighting # This is what we use to change which object it being held. It just hides all of # the objects and then unhides the one that was selected def switchObject(self, i): for np in self.models: np.hide() self.models[i].show() # This task gets the position of mouse each frame, and rotates the neck based # on it. def turnHead(self, task): # Check to make sure the mouse is readable if base.mouseWatcherNode.hasMouse(): # get the mouse position as a LVector2. The values for each axis are from -1 to # 1. The top-left is (-1,-1), the bottom right is (1,1) mpos = base.mouseWatcherNode.getMouse() # Here we multiply the values to get the amount of degrees to turn # Restrain is used to make sure the values returned by getMouse are in the # valid range. If this particular model were to turn more than this, # significant tearing would be visable self.eveNeck.setP(clamp(mpos.getX()) * 50) self.eveNeck.setH(clamp(mpos.getY()) * 20) return Task.cont # Task continues infinitely def setupLights(self): # Sets up some default lighting ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.4, .4, .35, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection(LVector3(0, 8, -2.5)) directionalLight.setColor((0.9, 0.8, 0.9, 1)) render.setLight(render.attachNewNode(directionalLight)) render.setLight(render.attachNewNode(ambientLight))
def __init__(self): ShowBase.__init__(self) self.dirTypes = ['heading', 'pitch', 'roll'] self.dirType = 0 # Display instructions add_title("Panda3D Tutorial: Portal Culling") add_instructions(0.06, "[Esc]: Quit") self.posText = add_instructions(0.12, "pos") self.anglesText = add_instructions(0.18, "angle") self.armHprText = add_instructions(0.24, "hpr") self.dirText = add_instructions(.30, self.dirTypes[0]) self.forearmText = add_instructions(0.36, "angle") self.baseText = add_instructions(0.42, "angle") """add_instructions(0.12, "[W]: Move Forward") add_instructions(0.18, "[A]: Move Left") add_instructions(0.24, "[S]: Move Right") add_instructions(0.30, "[D]: Move Back") add_instructions(0.36, "Arrow Keys: Look Around") add_instructions(0.42, "[F]: Toggle Wireframe") add_instructions(0.48, "[X]: Toggle X-Ray Mode") add_instructions(0.54, "[B]: Toggle Bounding Volumes")""" # Setup controls self.keys = {} for key in ['arrow_left', 'arrow_right', 'arrow_up', 'arrow_down', 'a', 'd', 'w', 's', 'q', 'e']: self.keys[key] = 0 self.accept(key, self.push_key, [key, 1]) self.accept('shift-%s' % key, self.push_key, [key, 1]) self.accept('%s-up' % key, self.push_key, [key, 0]) self.accept("b", self.push_key, ["Rleft", True]) self.accept("b-up", self.push_key, ["Rleft", False]) self.accept("n", self.push_key, ["Rright", True]) self.accept("n-up", self.push_key, ["Rright", False]) self.accept("h", self.push_key, ["Rforward", True]) self.accept("h-up", self.push_key, ["Rforward", False]) self.keys['Rleft'] = self.keys['Rright'] = self.keys['Rforward'] = 0 self.accept('escape', self.exitButton) self.accept('p', self.selectDir) self.accept('[', self.incDir, [-15]) self.accept(']', self.incDir, [15]) #self.disableMouse() # Setup camera lens = PerspectiveLens() lens.setFov(60) lens.setNear(0.01) lens.setFar(1000.0) self.cam.node().setLens(lens) self.camera.setPos(-50, 0, 0) self.pitch = 0.0 self.heading = 0 ambientLight = AmbientLight("ambientLight") ambientLight.setColor((.3, .3, .3, 1)) directionalLight = DirectionalLight("directionalLight") directionalLight.setDirection((-5, -5, -5)) directionalLight.setColor((1, 1, 1, 1)) directionalLight.setSpecularColor((1, 1, 1, 1)) render.setLight(render.attachNewNode(ambientLight)) render.setLight(render.attachNewNode(directionalLight)) # Load level geometry self.level = self.loader.loadModel('models/theater') self.level.reparentTo(self.render) self.isMoving = False self.ralph = Actor("models/ralph", {"run": "models/ralph-run", "walk": "models/ralph-walk"}) self.ralph.reparentTo(render) self.ralph.setScale(.2) self.arms = [] idMap = {0:9, 1:11, 2:17, 3:27, 4:29} for node in self.level.get_children(): if not node.getName().startswith('arm'): continue arm = Actor("models/robotarm") self.arms.append(arm) arm.reparentTo(render) arm.setName(node.getName()) arm.setPos(node.getPos()) arm.setHpr(node.getHpr()) #arm.setScale(.2) tokens = node.getName().split('.') try: id = int(tokens[1]) except: id = 0 arm.baseID = idMap[id] arm.jointForearm = arm.controlJoint(None, "modelRoot", "forearm") arm.jointBase = arm.controlJoint(None, "modelRoot", "base") print node.getName(), str(node.getPos()), str(node.getHpr()) taskMgr.add(self.printLoc, "printLoc") taskMgr.add(self.monitorArms, "robot arms") self.taskMgr.add(self.update, 'main loop')
class DistributedPartyTrampolineActivity(DistributedPartyActivity): notify = DirectNotifyGlobal.directNotify.newCategory( "DistributedPartyTrampolineActivity") def __init__(self, cr, doJellyBeans=True, doTricks=False, texture=None): DistributedPartyTrampolineActivity.notify.debug("__init__") DistributedPartyActivity.__init__( self, cr, PartyGlobals.ActivityIds.PartyTrampoline, PartyGlobals.ActivityTypes.GuestInitiated, wantLever=False, wantRewardGui=True, ) self.doJellyBeans = doJellyBeans self.doTricks = doTricks self.texture = texture self.toon = None self.trampHeight = 3.6 self.trampK = 400.0 # spring constant self.normalTrampB = 2.5 # spring damping self.leavingTrampB = 8.0 # increase damping to slow toon faster when leaving self.trampB = self.normalTrampB self.g = -32.0 # acceleration due to gravity self.jumpBoost = 330.0 self.beginningBoost = 500.0 self.beginningBoostThreshold = self.trampHeight + 1.5 self.earlyJumpThreshold = 75.0 self.boingThreshold = 300.0 self.turnFactor = 120.0 self.stepDT = 0.001 self.targetCameraPos = Point3(0.0, 40.0, 10.0) # relative to toon self.cameraSpeed = 2.0 self.hopOffPos = Point3(16.0, 0.0, 0.0) # relative to tramp self.indicatorFactor = 0.0095 self.dropShadowCutoff = 15.0 self.minHeightForText = 15.0 self.heightTextOffset = -0.065 self.beanOffset = 0.5 self.guiBeanOffset = -0.02 self.jumpTextShown = False self.toonJumped = False self.turnLeft = False self.turnRight = False self.leavingTrampoline = False self.toonVelocity = 0.0 self.topHeight = 0.0 self.lastPeak = 0.0 self.beginRoundInterval = None self.hopOnAnim = None self.hopOffAnim = None self.flashTextInterval = None # Jelly Beans self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans # These are in PartyGlobals so they can be available to the AI. self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus self.jellyBeanStartHeight = 20.0 self.jellyBeanStopHeight = 90.0 self.jellyBeanColors = [ VBase4(1.0, 0.5, 0.5, 1.0), VBase4(0.5, 1.0, 0.5, 1.0), VBase4(0.5, 1.0, 1.0, 1.0), VBase4(1.0, 1.0, 0.4, 1.0), VBase4(0.4, 0.4, 1.0, 1.0), VBase4(1.0, 0.5, 1.0, 1.0), ] delta = (self.jellyBeanStopHeight - self.jellyBeanStartHeight) / (self.numJellyBeans - 1) self.jellyBeanPositions = [ self.jellyBeanStartHeight + n * delta for n in range(self.numJellyBeans) ] self.doSimulateStep = False # import sys # sys.path.append( "C:\\pratt\\SchellGames\\perforce\\depot\\Tools\\PandaMisc" ) # from Reloader import Reloader # self.reloader = Reloader( "C:\\cygwin\\home\\pratt\\player_working\\toontown\\src\\parties" ) #--------------------------------------------------- # Loading #--------------------------------------------------- def load(self): DistributedPartyTrampolineActivity.notify.debug("load") DistributedPartyActivity.load(self) self.loadModels() self.loadCollision() self.loadGUI() self.loadSounds() self.loadIntervals() self.activityFSM = TrampolineActivityFSM(self) self.activityFSM.request("Idle") self.animFSM = TrampolineAnimFSM(self) self.setBestHeightInfo("", 0) def loadModels(self): self.tramp = self.root.attachNewNode(self.uniqueName("tramp")) self.screenPlaneElements = NodePath(self.uniqueName("screenPlane")) self.trampActor = Actor( "phase_13/models/parties/trampoline_model", {"emptyAnim": "phase_13/models/parties/trampoline_anim"}, ) self.trampActor.reparentTo(self.tramp) # Allow reskinning. if self.texture: reskinNode = self.tramp.find( "**/trampoline/__Actor_modelRoot/-GeomNode") reskinNode.setTexture(loader.loadTexture(self.texture), 100) self.surface = NodePath(self.uniqueName("trampSurface")) self.surface.reparentTo(self.tramp) self.surface.setZ(self.trampHeight) self.trampActor.controlJoint(self.surface, "modelRoot", "trampoline_joint1") self.sign.setPos(PartyGlobals.TrampolineSignOffset) self.beans = [ loader.loadModelCopy("phase_4/models/props/jellybean4") for i in range(self.numJellyBeans) ] for bean in self.beans: bean.find("**/jellybean").setP(-35.0) bean.setScale(3.0) bean.setTransparency(True) bean.reparentTo(self.tramp) bean.stash() self.beans[-1].setScale(8.0) def loadCollision(self): collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4) collTube.setTangible(True) self.trampolineCollision = CollisionNode( self.uniqueName("TrampolineCollision")) self.trampolineCollision.addSolid(collTube) self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask) self.trampolineCollisionNP = self.tramp.attachNewNode( self.trampolineCollision) collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0) collSphere.setTangible(False) self.trampolineTrigger = CollisionNode( self.uniqueName("TrampolineTrigger")) self.trampolineTrigger.addSolid(collSphere) self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask) self.trampolineTriggerNP = self.tramp.attachNewNode( self.trampolineTrigger) self.accept("enter%s" % self.uniqueName("TrampolineTrigger"), self.onTrampolineTrigger) def loadGUI(self): self.gui = loader.loadModel("phase_13/models/parties/trampolineGUI") self.gui.reparentTo(base.a2dTopLeft) self.gui.setPos(0.115, 0, -1) self.gui.hide() self.toonIndicator = self.gui.find("**/trampolineGUI_MovingBar") jumpLineLocator = self.gui.find("**/jumpLine_locator") guiBean = self.gui.find("**/trampolineGUI_GreenJellyBean") self.gui.find("**/trampolineGUI_GreenJellyBean").stash( ) # sadly, the white jelly bean is named GreenJellyBean self.guiBeans = [ guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName("guiBean%d" % i)) for i in range(self.numJellyBeans) ] self.guiBeans[-1].setScale(1.5) heightTextNode = TextNode( self.uniqueName("TrampolineActivity.heightTextNode")) heightTextNode.setFont(ToontownGlobals.getSignFont()) heightTextNode.setAlign(TextNode.ALeft) heightTextNode.setText("0.0") heightTextNode.setShadow(0.05, 0.05) heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0) heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.heightText = jumpLineLocator.attachNewNode(heightTextNode) self.heightText.setX(0.15) self.heightText.setScale(0.1) self.heightText.setAlphaScale(0.0) self.quitEarlyButtonModels = loader.loadModel( "phase_3.5/models/gui/inventory_gui") quitEarlyUp = self.quitEarlyButtonModels.find("**//InventoryButtonUp") quitEarlyDown = self.quitEarlyButtonModels.find( "**/InventoryButtonDown") quitEarlyRollover = self.quitEarlyButtonModels.find( "**/InventoryButtonRollover") self.quitEarlyButton = DirectButton( parent=base.a2dTopRight, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-0.183, 0, -0.4), scale=0.09, command=self.leaveTrampoline, ) self.quitEarlyButton.stash() self.flashText = OnscreenText( text="", pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True, ) self.timer = PartyUtils.getNewToontownTimer() self.timer.reparentTo(self.screenPlaneElements) def loadSounds(self): self.jellyBeanSound = base.loader.loadSfx( "phase_4/audio/sfx/sparkly.mp3") self.boingSound = base.loader.loadSfx( "phase_4/audio/sfx/target_trampoline_2.mp3") self.whistleSound = base.loader.loadSfx( "phase_4/audio/sfx/AA_sound_whistle.mp3") def loadIntervals(self): def prepareHeightText(): self.heightText.node().setText( TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ())) self.heightText.setZ(self.indicatorFactor * self.toon.getZ() + self.heightTextOffset) self.heightTextInterval = Sequence( Func(prepareHeightText), LerpFunc(self.heightText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), ) def unload(self): DistributedPartyTrampolineActivity.notify.debug("unload") if self.hopOnAnim and self.hopOnAnim.isPlaying(): self.hopOnAnim.finish() if self.hopOffAnim and self.hopOffAnim.isPlaying(): self.hopOffAnim.finish() if self.beginRoundInterval and self.beginRoundInterval.isPlaying(): self.beginRoundInterval.finish() if self.flashTextInterval and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() if self.heightTextInterval and self.heightTextInterval.isPlaying(): self.heightTextInterval.finish() self.timer.stop() DistributedPartyActivity.unload(self) # Unload tasks taskMgr.remove(self.uniqueName("TrampolineActivity.updateTask")) taskMgr.remove(self.uniqueName("TrampolineActivity.remoteUpdateTask")) # Unload events self.ignoreAll() # Unload intervals del self.heightTextInterval del self.beginRoundInterval del self.hopOnAnim del self.hopOffAnim del self.flashTextInterval if hasattr(self, 'beanAnims'): # we need to cleanup the jelly bean interval self.cleanupJellyBeans() # Unload gui stuff self.quitEarlyButton.destroy() del self.quitEarlyButton if self.screenPlaneElements: self.screenPlaneElements.removeNode() self.screenPlaneElements = None # Unload fsms del self.activityFSM del self.animFSM #--------------------------------------------------- # Distributed #--------------------------------------------------- def setBestHeightInfo(self, toonName, height): if GMUtils.testGMIdentity(toonName): toonName = GMUtils.handleGMName(toonName) self.bestHeightInfo = (toonName, height) DistributedPartyTrampolineActivity.notify.debug( "%s has the best height of %d" % (toonName, height)) if height > 0: self.setSignNote(TTLocalizer.PartyTrampolineBestHeight % self.bestHeightInfo) else: self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet) def leaveTrampoline(self): if self.toon != None and self.toon.doId == base.localAvatar.doId: self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp) self.leavingTrampoline = True self.timer.reset() self.trampB = self.leavingTrampB self.ignore("control") self.quitEarlyButton.stash() self.gui.hide() def requestAnim(self, request): self.animFSM.request(request) def b_requestAnim(self, request): self.requestAnim(request) self.sendUpdate("requestAnim", [request]) def requestAnimEcho(self, request): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.requestAnim(request) def removeBeans(self, beansToRemove): for i in beansToRemove: height, bean, guiBean, beanAnim = self.beanDetails[i] guiBean.stash() if i in self.beansToCollect: self.beansToCollect.remove(i) else: self.notify.warning( "removeBeans avoided a crash, %d not in self.beansToCollect" % i) self.poofBean(bean, beanAnim) # bean.stash() # beanAnim.finish() def b_removeBeans(self, beansToRemove): self.removeBeans(beansToRemove) self.sendUpdate("removeBeans", [beansToRemove]) def removeBeansEcho(self, beansToRemove): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.removeBeans(beansToRemove) def joinRequestDenied(self, reason): DistributedPartyActivity.joinRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny) base.cr.playGame.getPlace().fsm.request("walk") def exitRequestDenied(self, reason): DistributedPartyActivity.exitRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny) def setState(self, newState, timestamp): DistributedPartyTrampolineActivity.notify.debug( "setState( newState=%s, ... )" % newState) DistributedPartyActivity.setState(self, newState, timestamp) self.activityFSM.request(newState) #--------------------------------------------------- # FSM handling #--------------------------------------------------- def startIdle(self): DistributedPartyTrampolineActivity.notify.debug("startIdle") def finishIdle(self): DistributedPartyTrampolineActivity.notify.debug("finishIdle") def startRules(self): DistributedPartyTrampolineActivity.notify.debug("startRules") if self.doJellyBeans: self.setupJellyBeans() if self.toon != None and self.toon.doId == base.localAvatar.doId: self.acquireToon() def startActive(self): DistributedPartyTrampolineActivity.notify.debug("startActive") if self.toon != None and self.toon.doId == base.localAvatar.doId: base.setCellsAvailable(base.bottomCells, True) self.accept("arrow_left", self.onLeft) self.accept("arrow_left-up", self.onLeftUp) self.accept("arrow_right", self.onRight) self.accept("arrow_right-up", self.onRightUp) self.beginRoundInterval = Sequence( Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady), Wait(1.2), Func(self.flashMessage, TTLocalizer.PartyTrampolineGo), Func(self.beginRound)) self.beginRoundInterval.start() def finishActive(self): DistributedPartyTrampolineActivity.notify.debug("finishActive") if self.doJellyBeans: self.cleanupJellyBeans() #--------------------------------------------------- # FSM extras #--------------------------------------------------- def setupJellyBeans(self): self.beanAnims = [] self.beansToCollect = [] self.beanDetails = [] self.numBeansCollected = 0 for i in range(self.numJellyBeans): bean = self.beans[i] guiBean = self.guiBeans[i] height = self.jellyBeanPositions[i] color = random.choice(self.jellyBeanColors) bean.find("**/jellybean").setColor(color) if self.toon.doId == base.localAvatar.doId: bean.setAlphaScale(1.0) else: bean.setAlphaScale(0.5) guiBean.setColor(color) bean.setZ(height + self.toon.getHeight() + self.beanOffset) guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset) bean.setH(0.0) bean.unstash() guiBean.unstash() beanAnim = bean.hprInterval( 1.5, VBase3((((i % 2) * 2) - 1) * 360.0, 0.0, 0.0) ) # the (((i % 2)*2) - 1) makes adjacent beans spin opposite directions beanAnim.loop() self.beanAnims.append(beanAnim) self.beanDetails.append((height, bean, guiBean, beanAnim)) self.beansToCollect = list(range(self.numJellyBeans)) def cleanupJellyBeans(self): for bean in self.beans: bean.stash() for guiBean in self.guiBeans: guiBean.stash() # If handleToonJoined hasn't been sent toonId on some clients if hasattr(self, 'beanAnims'): for beanAnim in self.beanAnims: beanAnim.finish() del self.beanAnims del self.beansToCollect def beginRound(self): base.playSfx(self.whistleSound) self.timer.setTime(PartyGlobals.TrampolineDuration) self.timer.countdown(PartyGlobals.TrampolineDuration) self.timer.show() self.gui.show() self.quitEarlyButton.unstash() self.notify.debug("Accepting contorl") self.accept("control", self.onJump) self.notify.debug("setting simulate step to true") self.doSimulateStep = True def acquireToon(self): # self.dataLog = open( "dataLog.txt", "w" ) self.toon.disableSmartCameraViews() self.toon.stopUpdateSmartCamera() camera.wrtReparentTo(render) self.toon.dropShadow.reparentTo(hidden) self.toon.startPosHprBroadcast(period=0.2) self.toonAcceleration = 0.0 self.toonVelocity = 0.0 self.topHeight = 0.0 self.trampB = self.normalTrampB self.leavingTrampoline = False self.hopOnAnim = Sequence( Func(self.toon.b_setAnimState, "jump", 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, Point3(0.0, 0.0, self.trampHeight), 5.0, self.tramp), Func(self.postHopOn), ) self.hopOnAnim.start() def postHopOn(self): self.toon.setH(self.toon.getH() + 90.0) # makes camera adjustment less jarring self.toon.dropShadow.reparentTo(self.surface) self.screenPlaneElements.reparentTo(aspect2d) self.timeLeftToSimulate = 0.0 self.doSimulateStep = False taskMgr.add(self.updateTask, self.uniqueName("TrampolineActivity.updateTask")) base.setCellsAvailable(base.leftCells, False) base.setCellsAvailable(base.bottomCells, False) DistributedPartyActivity.startRules(self) def releaseToon(self): self._hideFlashMessage() self.ignore("arrow_left") self.ignore("arrow_left-up") self.ignore("arrow_right") self.ignore("arrow_right-up") taskMgr.remove(self.uniqueName("TrampolineActivity.updateTask")) self.hopOffAnim = Sequence( self.toon.hprInterval(0.5, VBase3(-90.0, 0.0, 0.0), other=self.tramp), Func(self.toon.b_setAnimState, "jump", 1.0), Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0, self.tramp), Func(self.postHopOff), ) self.hopOffAnim.start() def postHopOff(self): self.screenPlaneElements.reparentTo(hidden) base.setCellsAvailable(base.leftCells, True) self.timer.stop() self.timer.hide() self.toon.dropShadow.reparentTo(self.toon.getShadowJoint()) self.toon.dropShadow.setAlphaScale(1.0) self.toon.dropShadow.setScale(1.0) # Continue broadcasting so remote toons see us reach the final hop off position. #self.toon.stopPosHprBroadcast() self.b_requestAnim("Off") camera.reparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() base.localAvatar.enableSmartCameraViews() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) place = base.cr.playGame.getPlace() if self.doJellyBeans: self.sendUpdate("awardBeans", [self.numBeansCollected, int(self.topHeight)]) if int(self.topHeight) > self.bestHeightInfo[1]: self.sendUpdate("reportHeightInformation", [int(self.topHeight)]) self.d_toonExitDemand() #--------------------------------------------------- # Event Handling #--------------------------------------------------- def onTrampolineTrigger(self, collEntry): if (self.activityFSM._state == "Idle") and (self.toon == None) and ( base.cr.playGame.getPlace().fsm.getCurrentState().getName() == "walk"): base.cr.playGame.getPlace().fsm.request("activity") self.d_toonJoinRequest() else: self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied, duration=2.0) def onJump(self): self.notify.debug("got onJump") if self.toon != None and self.toon.getZ() < self.trampHeight: # Have to be on the trampoline self.toonJumped = True self.b_requestAnim("Jump") else: self.notify.debug("z is less than tramp height") def onLeft(self): self.turnLeft = True def onLeftUp(self): self.turnLeft = False def onRight(self): self.turnRight = True def onRightUp(self): self.turnRight = False #--------------------------------------------------- # Super class functionality #--------------------------------------------------- def handleToonJoined(self, toonId): DistributedPartyTrampolineActivity.notify.debug("handleToonJoined") self.toon = self.getAvatar(toonId) if self.toon != None and not self.toon.isEmpty(): self.oldJumpSquatPlayRate = self.toon.getPlayRate("jump-squat") self.oldJumpLandPlayRate = self.toon.getPlayRate("jump-land") self.toon.setPlayRate(2.5, "jump-squat") self.toon.setPlayRate(2.0, "jump-land") self.turnLeft = False self.turnRight = False self.activityFSM.request("Rules") if self.toon.doId != base.localAvatar.doId: taskMgr.add( self.remoteUpdateTask, self.uniqueName("TrampolineActivity.remoteUpdateTask")) else: self.notify.warning("handleToonJoined could not get toon %d" % toonId) def handleToonExited(self, toonId): DistributedPartyTrampolineActivity.notify.debug("handleToonExited") if self.toon != None: if self.toon.doId != base.localAvatar.doId: taskMgr.remove( self.uniqueName("TrampolineActivity.remoteUpdateTask")) self.surface.setZ(self.trampHeight) self.toon.setPlayRate(self.oldJumpSquatPlayRate, "jump-squat") self.toon.setPlayRate(self.oldJumpLandPlayRate, "jump-land") self.toon = None def handleToonDisabled(self, toonId): """ A toon dropped unexpectedly from the game. Handle it! """ DistributedPartyTrampolineActivity.notify.debug("handleToonDisabled") DistributedPartyTrampolineActivity.notify.debug("avatar " + str(toonId) + " disabled") if base.localAvatar.doId == toonId: self.releaseToon() def handleRulesDone(self): self.sendUpdate("toonReady") self.finishRules() def getTitle(self): if self.doJellyBeans: return TTLocalizer.PartyTrampolineJellyBeanTitle elif self.doTricks: return TTLocalizer.PartyTrampolineTricksTitle else: return DistributedPartyActivity.getTitle(self) def getInstructions(self): return TTLocalizer.PartyTrampolineActivityInstructions #--------------------------------------------------- # Simulation #--------------------------------------------------- def updateTask(self, task): # Only run on local client z = self.toon.getZ() dt = globalClock.getDt() if self.doSimulateStep: self.timeLeftToSimulate += dt while self.timeLeftToSimulate >= self.stepDT: z, a = self.simulateStep(z) self.timeLeftToSimulate -= self.stepDT self.toon.setZ(z) # Move tramp surface if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) # Move toon indicator self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor) # Turn left or right if self.turnLeft: self.toon.setH(self.toon.getH() + self.turnFactor * dt) if self.turnRight: self.toon.setH(self.toon.getH() - self.turnFactor * dt) # Update camera currentPos = base.camera.getPos(self.toon) vec = self.targetCameraPos - currentPos newPos = currentPos + vec * (dt * self.cameraSpeed) base.camera.setPos(self.toon, newPos) base.camera.lookAt(self.toon) # Fade and scale drop shadow if z > self.trampHeight: heightFactor = 1.0 - min( 1.0, (z - self.trampHeight) / self.dropShadowCutoff) self.toon.dropShadow.setAlphaScale(heightFactor) self.toon.dropShadow.setScale(max(0.1, heightFactor)) else: self.toon.dropShadow.setAlphaScale(1.0) self.toon.dropShadow.setScale(1.0) # Leave trampoline if necessary if self.leavingTrampoline and (z < self.trampHeight) and (abs(a) < 0.1): self.releaseToon() # Simulate poor framerate # time.sleep( 0.03 ) return Task.cont def simulateStep(self, z): # Calculate acceleration if z >= self.trampHeight: # Above the trampoline; only use gravity. a = self.g # Clear jumped flag self.toonJumped = False else: # On the trampoline; use gravity + spring + damping a = self.g + self.trampK * (self.trampHeight - z) - self.trampB * self.toonVelocity # Add jump acceleration if necessary if self.toonJumped: # Don't penalize early jumps. # If we're above the earlyJumpThreshold, go ahead and add jump # acceleration, even if the toon hasn't bottomed out (which # will reduce the effectiveness of the jump). # Otherwise, only add jump acceleration, if the toon has # bottomed out (toonVelocity >= 0.0). #self.notify.debug("self.lastPeak=%s earlyJumpThreshold=%s toonVelocity=%s" %(self.lastPeak, self.earlyJumpThreshold, self.toonVelocity )) if (self.lastPeak > self.earlyJumpThreshold) or ( self.toonVelocity >= -3E5): a += self.jumpBoost # Add beginning boost if necessary. if self.lastPeak < self.beginningBoostThreshold: a += self.beginningBoost # Calculate velocity #import pdb; pdb.set_trace() lastVelocity = self.toonVelocity self.toonVelocity += a * self.stepDT if (lastVelocity > 0.0) and (self.toonVelocity <= 0.0): topOfJump = True bottomOfJump = False elif (lastVelocity < 0.0) and (self.toonVelocity >= 0.0): topOfJump = False bottomOfJump = True else: topOfJump = False bottomOfJump = False # optimal jumping # if bottomOfJump and self.isAccepting( "control" ): # self.toonJumped = True # print z # Calculate position newZ = z + self.toonVelocity * self.stepDT if newZ > self.topHeight: self.topHeight = newZ if self.doJellyBeans: self.collectJellyBeans(newZ) if topOfJump: # Set lastPeak self.lastPeak = newZ # Show height text if necessary if newZ >= self.minHeightForText: self.heightTextInterval.start() # Set anim state if topOfJump: if newZ > (self.trampHeight + 20.0): self.b_requestAnim("Falling") elif self.animFSM._state == "Jump": self.b_requestAnim("Falling") if (newZ <= self.trampHeight) and (z > self.trampHeight): if self.animFSM._state == "Falling": self.b_requestAnim("Land") elif self.animFSM._state != "Neutral": self.b_requestAnim("Neutral") # Play "boing" sound. if bottomOfJump and (a > self.boingThreshold): base.playSfx(self.boingSound) return newZ, a def collectJellyBeans(self, z): beansToRemove = [] for i in self.beansToCollect: height = self.beanDetails[i][0] if height <= z: beansToRemove.append(i) if len(beansToRemove) > 0: base.playSfx(self.jellyBeanSound) self.numBeansCollected += len(beansToRemove) self.b_removeBeans(beansToRemove) def remoteUpdateTask(self, task): # Only run on remote clients # Move tramp surface if self.toon != None and not self.toon.isEmpty(): z = self.toon.getZ() if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) return Task.cont #--------------------------------------------------- # Misc #--------------------------------------------------- def poofBean(self, bean, beanAnim): if bean == None: self.notify.warning( "poofBean, returning immediately as bean is None") return if bean.isEmpty(): self.notify.warning( "poofBean, returning immediately as bean is empty") return currentAlpha = bean.getColorScale()[3] currentScale = bean.getScale() poofAnim = Sequence( Parallel( LerpFunc(bean.setAlphaScale, fromData=currentAlpha, toData=0.0, duration=0.25), LerpFunc(bean.setScale, fromData=currentScale, toData=currentScale * 5.0, duration=0.25), ), Func(bean.stash), Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha), Func(bean.setScale, currentScale), ) poofAnim.start() def _showFlashMessage(self, message): if self.isDisabled(): assert self.notify.debug( "_showFlasMessage disabled, not showing %s" % message) return if (self.flashTextInterval is not None) and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() self.flashText.setText(message) self.flashText.setAlphaScale(1.0) self.flashText.unstash() def _hideFlashMessage(self, duration=0.0): if self.isDisabled(): assert self.notify.debug( "_hideFlashMessage we're disabled, but still hiding self.flashText" ) # return self.flashTextInterval = Sequence( Wait(duration), LerpFunc(self.flashText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), Func(self.flashText.stash), ) self.flashTextInterval.start() def flashMessage(self, message, duration=0.5): self._showFlashMessage(message) self._hideFlashMessage(duration)
class IsisAgent(kinematicCharacterController, DirectObject): @classmethod def setPhysics(cls, physics): """ This method is set in src.loader when the generators are loaded into the namespace. This frees the environment definitions (in scenario files) from having to pass around the physics parameter that is required for all IsisObjects """ cls.physics = physics def __init__(self, name, queueSize=100): # load the model and the different animations for the model into an Actor object. self.actor = Actor( "media/models/boxman", {"walk": "media/models/boxman-walk", "idle": "media/models/boxman-idle"} ) self.actor.setScale(1.0) self.actor.setH(0) # self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params self.actor.setColorScale(random.random(), random.random(), random.random(), 1.0) self.actorNodePath = NodePath("agent-%s" % name) self.activeModel = self.actorNodePath self.actorNodePath.reparentTo(render) self.actor.reparentTo(self.actorNodePath) self.name = name self.isMoving = False # initialize ODE controller kinematicCharacterController.__init__(self, IsisAgent.physics, self.actorNodePath) self.setGeomPos(self.actorNodePath.getPos(render)) """ Additional Direct Object that I use for convenience. """ self.specialDirectObject = DirectObject() """ How high above the center of the capsule you want the camera to be when walking and when crouching. It's related to the values in KCC. """ self.walkCamH = 0.7 self.crouchCamH = 0.2 self.camH = self.walkCamH """ This tells the Player Controller what we're aiming at. """ self.aimed = None self.isSitting = False self.isDisabled = False """ The special direct object is used for trigger messages and the like. """ # self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True]) # self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False]) self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"]) # Expose agent's right hand joint to attach objects to self.player_right_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.R") self.player_left_hand = self.actor.exposeJoint(None, "modelRoot", "Hand.L") self.right_hand_holding_object = None self.left_hand_holding_object = None # don't change the color of things you pick up self.player_right_hand.setColorScaleOff() self.player_left_hand.setColorScaleOff() self.player_head = self.actor.exposeJoint(None, "modelRoot", "Head") self.neck = self.actor.controlJoint(None, "modelRoot", "Head") self.controlMap = { "turn_left": 0, "turn_right": 0, "move_forward": 0, "move_backward": 0, "move_right": 0, "move_left": 0, "look_up": 0, "look_down": 0, "look_left": 0, "look_right": 0, "jump": 0, } # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left] # turns are in degrees per second, moves are in units per second self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60] self.originalPos = self.actor.getPos() bubble = loader.loadTexture("media/textures/thought_bubble.png") # bubble.setTransparency(TransparencyAttrib.MAlpha) self.speech_bubble = DirectLabel( parent=self.actor, text="", text_wordwrap=10, pad=(3, 3), relief=None, text_scale=(0.3, 0.3), pos=(0, 0, 3.6), frameColor=(0.6, 0.2, 0.1, 0.5), textMayChange=1, text_frame=(0, 0, 0, 1), text_bg=(1, 1, 1, 1), ) # self.myImage= self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.speech_bubble.setColorScaleOff() self.speech_bubble.component("text0").textNode.setCardDecal(1) self.speech_bubble.setBillboardAxis() # hide the speech bubble from IsisAgent's own camera self.speech_bubble.hide(BitMask32.bit(1)) self.thought_bubble = DirectLabel( parent=self.actor, text="", text_wordwrap=9, text_frame=(1, 0, -2, 1), text_pos=(0, 0.5), text_bg=(1, 1, 1, 0), relief=None, frameSize=(0, 1.5, -2, 3), text_scale=(0.18, 0.18), pos=(0, 0.2, 3.6), textMayChange=1, image=bubble, image_pos=(0, 0.1, 0), sortOrder=5, ) self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.thought_bubble.setColorScaleOff() self.thought_bubble.component("text0").textNode.setFrameColor(1, 1, 1, 0) self.thought_bubble.component("text0").textNode.setFrameAsMargin(0.1, 0.1, 0.1, 0.1) self.thought_bubble.component("text0").textNode.setCardDecal(1) self.thought_bubble.setBillboardAxis() # hide the thought bubble from IsisAgent's own camera self.thought_bubble.hide(BitMask32.bit(1)) # disable by default self.thought_bubble.hide() self.thought_filter = {} # only show thoughts whose values are in here self.last_spoke = 0 # timers to keep track of last thought/speech and self.last_thought = 0 # hide visualizations # put a camera on ralph self.fov = NodePath(Camera("RaphViz")) self.fov.node().setCameraMask(BitMask32.bit(1)) # position the camera to be infront of Boxman's face. self.fov.reparentTo(self.player_head) # x,y,z are not in standard orientation when parented to player-Head self.fov.setPos(0, 0.2, 0) # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face. self.fov.setHpr(0, -90, 0) lens = self.fov.node().getLens() lens.setFov(60) # degree field of view (expanded from 40) lens.setNear(0.2) # self.fov.node().showFrustum() # displays a box around his head # self.fov.place() self.prevtime = 0 self.current_frame_count = 0 self.isSitting = False self.isDisabled = False self.msg = None self.actorNodePath.setPythonTag("agent", self) # Initialize the action queue, with a maximum length of queueSize self.queue = [] self.queueSize = queueSize self.lastSense = 0 def setLayout(self, layout): """ Dummy method called by spatial methods for use with objects. Doesn't make sense for an agent that can move around.""" pass def setPos(self, pos): """ Wrapper to set the position of the ODE geometry, which in turn sets the visual model's geometry the next time the update() method is called. """ self.setGeomPos(pos) def setPosition(self, pos): self.setPos(pos) def reparentTo(self, parent): self.actorNodePath.reparentTo(parent) def setControl(self, control, value): """Set the state of one of the character's movement controls. """ self.controlMap[control] = value def get_objects_in_field_of_vision(self, exclude=["isisobject"]): """ This works in an x-ray style. Fast. Works best if you listen to http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while you use it. needs to exclude isisobjects since they cannot be serialized """ objects = {} for obj in base.render.findAllMatches("**/IsisObject*"): if not obj.hasPythonTag("isisobj"): continue o = obj.getPythonTag("isisobj") bounds = o.activeModel.getBounds() bounds.xform(o.activeModel.getMat(self.fov)) if self.fov.node().isInView(o.activeModel.getPos(self.fov)): pos = o.activeModel.getPos(render) pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2) p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) object_dict = {} if "x_pos" not in exclude: object_dict["x_pos"] = p3[0] if "y_pos" not in exclude: object_dict["y_pos"] = p3[2] if "distance" not in exclude: object_dict["distance"] = o.activeModel.getDistance(self.fov) if "orientation" not in exclude: object_dict["orientation"] = o.activeModel.getH(self.fov) if "actions" not in exclude: object_dict["actions"] = o.list_actions() if "isisobject" not in exclude: object_dict["isisobject"] = o # add item to dinctionary objects[o] = object_dict return objects def get_agents_in_field_of_vision(self): """ This works in an x-ray vision style as well""" agents = {} for agent in base.render.findAllMatches("**/agent-*"): if not agent.hasPythonTag("agent"): continue a = agent.getPythonTag("agent") bounds = a.actorNodePath.getBounds() bounds.xform(a.actorNodePath.getMat(self.fov)) pos = a.actorNodePath.getPos(self.fov) if self.fov.node().isInView(pos): p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) agentDict = { "x_pos": p3[0], "y_pos": p3[2], "distance": a.actorNodePath.getDistance(self.fov), "orientation": a.actorNodePath.getH(self.fov), } agents[a] = agentDict return agents def in_view(self, isisobj): """ Returns true iff a particular isisobject is in view """ return len( filter(lambda x: x["isisobject"] == isisobj, self.get_objects_in_field_of_vision(exclude=[]).values()) ) def get_objects_in_view(self): """ Gets objects through ray tracing. Slow""" return self.picker.get_objects_in_view() def control__turn_left__start(self, speed=None): self.setControl("turn_left", 1) self.setControl("turn_right", 0) if speed: self.speeds[0] = speed return "success" def control__turn_left__stop(self): self.setControl("turn_left", 0) return "success" def control__turn_right__start(self, speed=None): self.setControl("turn_left", 0) self.setControl("turn_right", 1) if speed: self.speeds[1] = speed return "success" def control__turn_right__stop(self): self.setControl("turn_right", 0) return "success" def control__move_forward__start(self, speed=None): self.setControl("move_forward", 1) self.setControl("move_backward", 0) if speed: self.speeds[2] = speed return "success" def control__move_forward__stop(self): self.setControl("move_forward", 0) return "success" def control__move_backward__start(self, speed=None): self.setControl("move_forward", 0) self.setControl("move_backward", 1) if speed: self.speeds[3] = speed return "success" def control__move_backward__stop(self): self.setControl("move_backward", 0) return "success" def control__move_left__start(self, speed=None): self.setControl("move_left", 1) self.setControl("move_right", 0) if speed: self.speeds[4] = speed return "success" def control__move_left__stop(self): self.setControl("move_left", 0) return "success" def control__move_right__start(self, speed=None): self.setControl("move_right", 1) self.setControl("move_left", 0) if speed: self.speeds[5] = speed return "success" def control__move_right__stop(self): self.setControl("move_right", 0) return "success" def control__look_left__start(self, speed=None): self.setControl("look_left", 1) self.setControl("look_right", 0) if speed: self.speeds[9] = speed return "success" def control__look_left__stop(self): self.setControl("look_left", 0) return "success" def control__look_right__start(self, speed=None): self.setControl("look_right", 1) self.setControl("look_left", 0) if speed: self.speeds[8] = speed return "success" def control__look_right__stop(self): self.setControl("look_right", 0) return "success" def control__look_up__start(self, speed=None): self.setControl("look_up", 1) self.setControl("look_down", 0) if speed: self.speeds[6] = speed return "success" def control__look_up__stop(self): self.setControl("look_up", 0) return "success" def control__look_down__start(self, speed=None): self.setControl("look_down", 1) self.setControl("look_up", 0) if speed: self.speeds[7] = speed return "success" def control__look_down__stop(self): self.setControl("look_down", 0) return "success" def control__jump(self): self.setControl("jump", 1) return "success" def control__view_objects(self): """ calls a raytrace to to all objects in view """ objects = self.get_objects_in_field_of_vision() self.control__say("If I were wearing x-ray glasses, I could see %i items" % len(objects)) print "Objects in view:", objects return objects def control__sense(self): """ perceives the world, returns percepts dict """ percepts = dict() # eyes: visual matricies # percepts['vision'] = self.sense__get_vision() # objects in purview (cheating object recognition) percepts["objects"] = self.sense__get_objects() # global position in environment - our robots can have GPS :) percepts["position"] = self.sense__get_position() # language: get last utterances that were typed percepts["language"] = self.sense__get_utterances() # agents: returns a map of agents to a list of actions that have been sensed percepts["agents"] = self.sense__get_agents() print percepts return percepts def control__think(self, message, layer=0): """ Changes the contents of an agent's thought bubble""" # only say things that are checked in the controller if self.thought_filter.has_key(layer): self.thought_bubble.show() self.thought_bubble["text"] = message # self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05) # self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer]) self.last_thought = 0 return "success" def control__say(self, message="Hello!"): self.speech_bubble["text"] = message self.last_spoke = 0 return "success" """ Methods explicitly for IsisScenario files """ def put_in_front_of(self, isisobj): # find open direction pos = isisobj.getGeomPos() direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom]) print "CLOSEST", closestEntry, closestObject if closestObject == None: self.setPosition(pos + Vec3(0, 2, 0)) else: print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(0, -2, 0)) else: print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % (isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( "aimRay", 5, [pos, direction], [isisobj.geom] ) if closestEntry == None: self.setPosition(pos + Vec3(2, 0, 0)) else: print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % (isisobj, closestObject) # there's only one option left, do it anyway self.setPosition(pos + Vec3(-2, 0, 0)) # rotate agent to look at it self.actorNodePath.setPos(self.getGeomPos()) self.actorNodePath.lookAt(pos) self.setH(self.actorNodePath.getH()) def put_in_right_hand(self, target): return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) def put_in_left_hand(self, target): return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) def __get_object_in_center_of_view(self): direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.fov.getPos(render) exclude = [] # [base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom] closestEntry, closestObject = IsisAgent.physics.doRaycastNew("aimRay", 5, [pos, direction], exclude) return closestObject def pick_object_up_with(self, target, hand_slot, hand_joint): """ Attaches an IsisObject, target, to the hand joint. Does not check anything first, other than the fact that the hand joint is not currently holding something else.""" if hand_slot != None: print "already holding " + hand_slot.getName() + "." return None else: if target.layout: target.layout.remove(target) target.layout = None # store original position target.originalHpr = target.getHpr(render) target.disable() # turn off physics if target.body: target.body.setGravityMode(0) target.reparentTo(hand_joint) target.setPosition(hand_joint.getPos(render)) target.setTag("heldBy", self.name) if hand_joint == self.player_right_hand: self.right_hand_holding_object = target elif hand_joint == self.player_left_hand: self.left_hand_holding_object = target hand_slot = target return target def control__pick_up_with_right_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return "error: no target in reach" else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with right hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) else: print "object (" + target.name + ") is not graspable (i.e. in view and close enough)." return "error: object not graspable" def control__pick_up_with_left_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with left hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) else: print "object (" + target.name + ") is not graspable (i.e. in view and close enough)." return "error: object not graspable" def control__drop_from_right_hand(self): print "attempting to drop object from right hand.\n" if self.right_hand_holding_object is None: print "right hand is not holding an object." return False if self.right_hand_holding_object.getNetTag("heldBy") == self.name: self.right_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_right_hand.getPos(render) heldPos = self.right_hand_holding_object.geom.getPosition() self.right_hand_holding_object.setPosition(pos) self.right_hand_holding_object.synchPosQuatToNode() self.right_hand_holding_object.setTag("heldBy", "") self.right_hand_holding_object.setRotation(self.right_hand_holding_object.originalHpr) self.right_hand_holding_object.enable() if self.right_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.right_hand_holding_object.body.setGravityMode(1) self.right_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0))) self.right_hand_holding_object = None return "success" else: return "Error: not being held by agent %s" % (self.name) def control__drop_from_left_hand(self): print "attempting to drop object from left hand.\n" if self.left_hand_holding_object is None: return "left hand is not holding an object." if self.left_hand_holding_object.getNetTag("heldBy") == self.name: self.left_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_left_hand.getPos(render) heldPos = self.left_hand_holding_object.geom.getPosition() self.left_hand_holding_object.setPosition(pos) self.left_hand_holding_object.synchPosQuatToNode() self.left_hand_holding_object.setTag("heldBy", "") self.left_hand_holding_object.setRotation(self.left_hand_holding_object.originalHpr) self.left_hand_holding_object.enable() if self.left_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.left_hand_holding_object.body.setGravityMode(1) self.left_hand_holding_object.getBody().setForce(quat.xform(Vec3(0, force, 0))) self.left_hand_holding_object = None return "success" else: return "Error: not being held by agent %s" % (self.name) def control__use_right_hand(self, target=None, action=None): # TODO, rename this to use object with if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "Trying to use object", target if self.can_grasp(target): if target.call(self, action, self.right_hand_holding_object) or ( self.right_hand_holding_object and self.right_hand_holding_object.call(self, action, target) ): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def control__use_left_hand(self, target=None, action=None): if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") if self.can_grasp(target): if target.call(self, action, self.left_hand_holding_object) or ( self.left_hand_holding_object and self.left_hand_holding_object.call(self, action, target) ): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def can_grasp(self, isisobject): distance = isisobject.activeModel.getDistance(self.fov) print "distance = ", distance return distance < 5.0 def is_holding(self, object_name): return ( self.left_hand_holding_object and (self.left_hand_holding_object.getPythonTag("isisobj").name == object_name) ) or ( self.right_hand_holding_object and (self.right_hand_holding_object.getPythonTag("isisobj").name == object_name) ) def empty_hand(self): if self.left_hand_holding_object is None: return self.player_left_hand elif self.right_hand_holding_object is None: return self.player_right_hand return False def has_empty_hand(self): return self.empty_hand() is not False def control__use_aimed(self): """ Try to use the object that we aim at, by calling its callback method. """ target = self.__get_object_in_center_of_view() if target.selectionCallback: target.selectionCallback(self, dir) return "success" def sense__get_position(self): x, y, z = self.actorNodePath.getPos() h, p, r = self.actorNodePath.getHpr() # FIXME # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr() left_hand_obj = "" right_hand_obj = "" if self.left_hand_holding_object: left_hand_obj = self.left_hand_holding_object.getName() if self.right_hand_holding_object: right_hand_obj = self.right_hand_holding_object.getName() return { "body_x": x, "body_y": y, "body_z": z, "body_h": h, "body_p": p, "body_r": r, "in_left_hand": left_hand_obj, "in_right_hand": right_hand_obj, } def sense__get_vision(self): self.fov.node().saveScreenshot("temp.jpg") image = Image.open("temp.jpg") os.remove("temp.jpg") return image def sense__get_objects(self): return dict([x.getName(), y] for (x, y) in self.get_objects_in_field_of_vision().items()) def sense__get_agents(self): curSense = time() agents = {} for k, v in self.get_agents_in_field_of_vision().items(): v["actions"] = k.get_other_agents_actions(self.lastSense, curSense) agents[k.name] = v self.lastSense = curSense return agents def sense__get_utterances(self): """ Clear out the buffer of things that the teacher has typed, FIXME: this doesn't work right now """ return [] utterances = self.teacher_utterances self.teacher_utterances = [] return utterances def debug__print_objects(self): text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys()) print text def add_action_to_history(self, action, args, result=0): self.queue.append((time(), action, args, result)) if len(self.queue) > self.queueSize: self.queue.pop(0) def get_other_agents_actions(self, start=0, end=None): if not end: end = time() actions = [] for act in self.queue: if act[0] >= start: if act[0] < end: actions.append(act) else: break return actions def update(self, stepSize=0.1): self.speed = [0.0, 0.0] self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70)) self.actorNodePath.setQuat(self.getQuat()) # the values in self.speeds are used as coefficientes for turns and movements if self.controlMap["turn_left"] != 0: self.addToH(stepSize * self.speeds[0]) if self.controlMap["turn_right"] != 0: self.addToH(-stepSize * self.speeds[1]) if self.verticalState == "ground": # these actions require contact with the ground if self.controlMap["move_forward"] != 0: self.speed[1] = self.speeds[2] if self.controlMap["move_backward"] != 0: self.speed[1] = -self.speeds[3] if self.controlMap["move_left"] != 0: self.speed[0] = -self.speeds[4] if self.controlMap["move_right"] != 0: self.speed[0] = self.speeds[5] if self.controlMap["jump"] != 0: kinematicCharacterController.jump(self) # one jump at a time! self.controlMap["jump"] = 0 if self.controlMap["look_left"] != 0: self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80) if self.controlMap["look_right"] != 0: self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80) if self.controlMap["look_up"] != 0: self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80) if self.controlMap["look_down"] != 0: self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80) kinematicCharacterController.update(self, stepSize) """ Update the held object position to be in the hands """ if self.right_hand_holding_object != None: self.right_hand_holding_object.setPosition(self.player_right_hand.getPos(render)) if self.left_hand_holding_object != None: self.left_hand_holding_object.setPosition(self.player_left_hand.getPos(render)) # Update the dialog box and thought windows # This allows dialogue window to gradually decay (changing transparancy) and then disappear self.last_spoke += stepSize / 2 self.last_thought += stepSize / 2 self.speech_bubble["text_bg"] = (1, 1, 1, 1 / (self.last_spoke + 0.01)) self.speech_bubble["frameColor"] = (0.6, 0.2, 0.1, 0.5 / (self.last_spoke + 0.01)) if self.last_spoke > 2: self.speech_bubble["text"] = "" if self.last_thought > 1: self.thought_bubble.hide() # If the character is moving, loop the run animation. # If he is standing still, stop the animation. if ( (self.controlMap["move_forward"] != 0) or (self.controlMap["move_backward"] != 0) or (self.controlMap["move_left"] != 0) or (self.controlMap["move_right"] != 0) ): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.current_frame_count = 5.0 self.isMoving = False total_frame_num = self.actor.getNumFrames("walk") if self.isMoving: self.current_frame_count = self.current_frame_count + (stepSize * 250.0) if self.current_frame_count > total_frame_num: self.current_frame_count = self.current_frame_count % total_frame_num self.actor.pose("walk", self.current_frame_count) elif self.current_frame_count != 0: self.current_frame_count = 0 self.actor.pose("idle", 0) return Task.cont def destroy(self): self.disable() self.specialDirectObject.ignoreAll() self.actorNodePath.removeNode() del self.specialDirectObject kinematicCharacterController.destroy(self) def disable(self): self.isDisabled = True self.geom.disable() self.footRay.disable() def enable(self): self.footRay.enable() self.geom.enable() self.isDisabled = False """ Set camera to correct height above the center of the capsule when crouching and when standing up. """ def crouch(self): kinematicCharacterController.crouch(self) self.camH = self.crouchCamH def crouchStop(self): """ Only change the camera's placement when the KCC allows standing up. See the KCC to find out why it might not allow it. """ if kinematicCharacterController.crouchStop(self): self.camH = self.walkCamH
class Agent: def __init__(self, _name): print "Creating agent " + _name self.name = _name self.loadLightingFromConfig = 0 self.createShadowMap = 0 def setDataPath(self, _dataPath): self.dataPath = _dataPath def setActor(self, _modelFileName, _animationFileNames, _morphTargetsFileName): self.modelFileName = _modelFileName self.animationFileNames = _animationFileNames self.morphTargetsFileName = _morphTargetsFileName def setRealizer(self, _realizer): self.realizer = _realizer def setCameraMask(self, _mask): self.cameraMask = _mask def setShadowMapParameters(self, _index, _distance): self.createShadowMap = 1 self.shadowMapIndex = _index self.shadowMapDistance = _distance def setTransform(self, x, y, z, rx, ry, rz, scale): self.agent.setPos(x, y, z) self.agent.setScale(scale) self.agent.setHpr(rx, ry, rz) self.positionX = x self.positionY = y self.positionZ = z def getPosition(self): return self.agent.getPos() def setLightingConfiguration(self, _config, _name): self.lightingConfig = _config self.lightingConfigName = _name self.loadLightingFromConfig = 1 def init(self): #load the agent and parent it to the world #The joints of this agent will reference Panda NodePaths, it will be possible to play animations on it self.animationAgent = Actor(self.modelFileName, self.animationFileNames) self.agent = Actor(self.modelFileName, self.morphTargetsFileName) self.targets = { #'Basis':[], 'ExpSmileClosed': [], 'ExpAnger': [], 'ExpDisgust': [], 'ExpFear': [], 'ExpSad': [], 'ExpSurprise': [], 'ExpSmileOpen': [], 'ModBlinkLeft': [], 'ModBlinkRight': [], 'ModBrowDownLeft': [], 'ModBrowDownRight': [], 'ModBlinkRight': [], 'ModBrowInRight': [], 'ModBrowInLeft': [], 'ModBrowUpLeft': [], 'ModBrowUpRight': [], 'ModEarsOut': [], 'ModEyeSquintLeft': [], 'ModEyeSquintRight': [], 'ModLookDown': [], 'ModLookLeft': [], 'ModLookRight': [], 'ModLookUp': [], 'ModBlinkLeft': [], 'Phonaah': [], 'PhonB,M,P': [], 'Phonbigaah': [], 'Phonch,J,sh': [], 'PhonD,S,T': [], 'Phonee': [], 'Phoneh': [], 'PhonF,V': [], 'Phoni': [], 'PhonK': [], 'PhonN': [], 'Phonoh': [], 'Phonooh,Q': [], 'PhonR': [], 'Phonth': [], 'PhonW': [] } iter = self.targets.iteritems() while True: try: morphsItem = iter.next() except StopIteration: break for i in range(2, 7): #print (str(i)+'_'+morphsItem[0]) blendShape = self.agent.controlJoint( None, 'modelRoot', str(i) + '_' + morphsItem[0]) if (blendShape): morphsItem[1].append(blendShape) self.targets['inspire'] = [ self.agent.controlJoint(None, 'modelRoot', 'inspire') ] #instanciate a list in order to keep track of kinematic joints joints #in python runtime #if nothing points towards those joints, they get flushed by #python's garbage collector self.jointList = [] self.jointFKList = [] self.agentControlJoints = [] self.agentNodePaths = [] self.agentSMRSkel = SMRPy.SMRSkeleton(True, True, 'agent') self.createSkel(self.agent, self.agentSMRSkel, 'root', '') #SMRPy.exportSkeletonToBvh('exportedPose.bvh',self.agentSMRSkel); self.newSkeleton = SMRPy.SMRSkeleton(True, True, 'pose') self.createFKSkel(self.animationAgent, self.newSkeleton, "root", '') self.realizer.addCharacter(self.name, self.agentSMRSkel) for key in self.targets.keys(): self.realizer.addMorphTarget(self.name, key) self.realizer.addShaderParameter(self.name, 'blushing') self.addAnimation(self.name, 'breathing') self.addAnimation(self.name, 'hands_claw') self.addAnimation(self.name, 'hands_fist') self.addAnimation(self.name, 'hands_index') self.addAnimation(self.name, 'hands_open-relaxed') self.addAnimation(self.name, 'hands_open-spread') self.addAnimation(self.name, 'hands_open-straight') self.addAnimation(self.name, 'hands_purse') self.addAnimation(self.name, 'hands_ring') self.addAnimation(self.name, 'poseNeutral') #self.addAnimation(self.name,'endian') if 'default' in self.animationFileNames: self.addAnimation(self.name, 'default') #self.realizer.addCharacterSkeleton( self.name, ); self.agent.reparentTo(render) self.agent.hide(BitMask32.bit(self.cameraMask)) #set lighting ambientColor = Vec4(0.0, 0.0, 0.0, 0.0) self.lighting = shaders.Lighting(ambientColor, self.agent) if self.loadLightingFromConfig == 1: self.lighting.loadFromConfig(self.lightingConfig, self.lightingConfigName) #shadow map if self.createShadowMap == 1: self.shadowMap = shadowmap.ShadowMap(self.shadowMapIndex, self.dataPath) def setShaders(self, _shaders): self.shaders = _shaders def update(self): self.realizer.skeletonRequested() self.updatePandaSkeleton(self.agentControlJoints, self.agentSMRSkel) for key in self.targets.keys(): #print(key, "\n") weight = self.realizer.getMorphTargetWeight(self.name, key) morphTargets = self.targets[key] for morphTarget in morphTargets: #print(weight, "\n") morphTarget.setX(weight) #blushingValue = self.realizer.getShaderParameterValue( self.name, 'blushing' ) #self.shaders.headShader.blushing.set( blushingValue ) self.lighting.update() if self.createShadowMap == 1: self.shadowMap.setLighting( self.lighting, Vec3(self.positionX, self.positionY, self.positionZ), self.shadowMapDistance) self.shaders.updateWithShadows(self.shadowMap) else: self.shaders.update() def addAnimation(self, _actorName, _animationName): self.animationAgent.reparentTo(render) self.animationAgent.setScale(10) self.realizer.addAnimation(_actorName, _animationName) for i in range(self.animationAgent.getNumFrames(_animationName)): self.animationAgent.pose(_animationName, i) base.graphicsEngine.renderFrame() self.updateSMRSkeleton(self.agentNodePaths, self.newSkeleton) self.realizer.addPoseToAnimation(_actorName, _animationName, self.newSkeleton) self.animationAgent.detachNode() print "animation", _animationName, "added" def createSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName): #get the agent's currentJoint currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName) currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot', _initialJointName) self.agentControlJoints.append(currentPandaCJoint) #get the first joint's position position = currentPandaCJoint.getPos() if (currentPandaJoint[0].getNumChildren() == 0): newJoint = SMRPy.SMRJoint(True) newJoint.setEndVect(position.getX(), position.getY(), position.getZ()) else: newJoint = SMRPy.SMRJoint(False) rotZ = (currentPandaCJoint.getH() / 180.0) * 3.14159 rotX = (currentPandaCJoint.getP() / 180.0) * 3.14159 rotY = (currentPandaCJoint.getR() / 180.0) * 3.14159 quatZ = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 0.0, 1.0), rotZ) quatX = SMRPy.SMRQuaternion(SMRPy.SMRVector3(1.0, 0.0, 0.0), rotX) quatY = SMRPy.SMRQuaternion(SMRPy.SMRVector3(0.0, 1.0, 0.0), rotY) quatRot = quatZ.multiply(quatX) quatRot = quatRot.multiply(quatY) quatRot.normalize() newJoint.setPos(position.getX(), position.getY(), position.getZ()) newJoint.setRotQuat(quatRot.getW(), quatRot.getX(), quatRot.getY(), quatRot.getZ()) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) #print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren() self.jointList.append(newJoint) _smrSkel.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() #print(childName) self.createSkel(_pandaAgent, _smrSkel, childName, _initialJointName) def createFKSkel(self, _pandaAgent, _smrSkel, _initialJointName, _parentName): #get the agent's currentJoint currentPandaJoint = _pandaAgent.getJoints(None, _initialJointName) currentPandaJointPath = _pandaAgent.exposeJoint( None, 'modelRoot', _initialJointName, "lodRoot", True) #currentPandaCJoint = _pandaAgent.controlJoint(None, 'modelRoot', _initialJointName) #if (_parentName == 'root' or _parentName == '' or _parentName == 'Bone.001'): # currentPandaJointPath = _pandaAgent.exposeJoint(None, 'modelRoot', _initialJointName) #else: # print(_parentName) # currentPandaJointPath = _pandaAgent.exposeJoint(None, _parentName, _initialJointName) #if (_initialJointName == "lhand"): # self.rhand = currentPandaJointPath self.agentNodePaths.append(currentPandaJointPath) #get the first joint's position position = currentPandaJointPath.getPos() if (currentPandaJoint[0].getNumChildren() == 0): newJoint = SMRPy.SMRJoint(True) newJoint.setEndVect(position.getX(), position.getY(), position.getZ()) else: newJoint = SMRPy.SMRJoint(False) quatRot = currentPandaJointPath.getQuat() newJoint.setPos(position.getX(), position.getY(), position.getZ()) newJoint.setRotQuat(quatRot.getR(), quatRot.getI(), quatRot.getJ(), quatRot.getK()) newJoint.setParentName(_parentName) newJoint.setName(_initialJointName) #print _initialJointName, 'numchildren : ', currentPandaJoint[0].getNumChildren() self.jointFKList.append(newJoint) _smrSkel.insertJoint(newJoint) for i in range(currentPandaJoint[0].getNumChildren()): childJoint = currentPandaJoint[0].getChild(i) childName = childJoint.getName() #print(childName) self.createFKSkel(_pandaAgent, _smrSkel, childName, _initialJointName) def updatePandaSkeleton(self, agentControlJoints, _smrSkeleton): #synchronize root joint SMRJoint = _smrSkeleton.getJoint(0) PANDAJoint = agentControlJoints[0] position = SMRJoint.getPos() #PANDAJoint.setPos(position.X() + 0.65 ,position.Y()-0.35,position.Z() - 1.4); PANDAJoint.setPos(position.X(), position.Y(), position.Z()) for i in range(_smrSkeleton.getNumjoints()): SMRJoint = _smrSkeleton.getJoint(i) PANDAJoint = agentControlJoints[i] self.synchronize(PANDAJoint, SMRJoint) def updateSMRSkeleton(self, agentNodePaths, _smrSkeleton): #synchronize root joint SMRJoint = _smrSkeleton.getJoint(0) PANDAJoint = agentNodePaths[0] position = PANDAJoint.getPos() SMRJoint.setPos(position.getX(), position.getY(), position.getZ()) for i in range(_smrSkeleton.getNumjoints()): SMRJoint = _smrSkeleton.getJoint(i) PANDAJoint = agentNodePaths[i] self.synchronizePandaToSMR(SMRJoint, PANDAJoint) def synchronizePandaToSMR(self, _SMRJoint, _PANDAJoint): pandaQuaternion = _PANDAJoint.getQuat() x = pandaQuaternion.getI() y = pandaQuaternion.getJ() z = pandaQuaternion.getK() w = pandaQuaternion.getR() _SMRJoint.setRotQuat(w, x, y, z) def synchronize(self, _pandaCJoint, _smrJoint): smrQuaternion = _smrJoint.getRot() pandaQuaternion = Quat() pandaQuaternion.setI(smrQuaternion.getX()) pandaQuaternion.setJ(smrQuaternion.getY()) pandaQuaternion.setK(smrQuaternion.getZ()) pandaQuaternion.setR(smrQuaternion.getW()) if not (pandaQuaternion.isNan()): _pandaCJoint.setQuat(pandaQuaternion)
class IKChain(): def __init__(self, parent): # Create a character. self.char = Character('IKChain') self.bundle = self.char.getBundle(0) self.skeleton = PartGroup(self.bundle, '<skeleton>') self.root = CharacterJoint(self.char, self.bundle, self.skeleton, 'root', Mat4.identMat()) self.bones = [] self.target = None self.targetReached = False self.parent = parent def addBone(self, offset, rotAxis=None, minAng=0, maxAng=0, parentBone=None): name = "joint" + str(len(self.bones)) if parentBone is None: transform = Mat4.identMat() joint = CharacterJoint(self.char, self.bundle, self.root, name, transform) else: transform = Mat4.translateMat(parentBone.offset) joint = CharacterJoint(self.char, self.bundle, parentBone.joint, name, transform) if rotAxis: rotAxis = rotAxis.normalized() bone = Bone(offset, rotAxis, minAng, maxAng, joint, parent=parentBone) self.bones.append(bone) return bone def finalize(self): self.charNodePath = NodePath(self.char) self.actor = Actor(self.charNodePath) #, {'simplechar' : anim}) self.actor.reparentTo(self.parent) self.rootExposedNode = self.actor.exposeJoint(None, "modelRoot", self.root.getName()) # Root of the chain parentIKNode = self.rootExposedNode # For each bone, create: # - a control node which will be used to update the bone position after IK solving # - an exposed node which we can attach things to, to render them # - a normal NodePath node called ikNode, which we'll use during IK solving for bone in self.bones: name = bone.joint.getName() controlNode = self.actor.controlJoint(None, "modelRoot", name) bone.controlNode = controlNode exposedNode = self.actor.exposeJoint(None, "modelRoot", name) bone.exposedNode = exposedNode # Separate nodes for IK: ikNode = parentIKNode.attachNewNode(name) # Same local pos as the exposed joints: ikNode.setPos(controlNode.getPos()) bone.ikNode = ikNode parentIKNode = ikNode self.endEffector = self.bones[-1].ikNode.attachNewNode("EndEffector") self.endEffector.setPos(self.bones[-1].offset) def updateIK(self): # Solve the IK chain for the IK nodes: if self.target: self.inverseKinematicsCCD() # Copy the data from the IK chain to the actual bones. # This will end up affecting the actual mesh. for bone in self.bones: bone.controlNode.setQuat(bone.ikNode.getQuat()) def inverseKinematicsCCD(self, threshold=1e-2, minIterations=1, maxIterations=10): self.targetReached = False for i in range(maxIterations): if i >= minIterations: err = (self.target.getPos(render) - self.endEffector.getPos(render)).lengthSquared() if err < threshold: self.targetReached = True break for j in range(len(self.bones)): bone = self.bones[-j - 1] boneNode = bone.ikNode if bone.parent: parentNode = bone.parent.ikNode else: parentNode = self.rootExposedNode target = self.target.getPos(boneNode) pos = LPoint3.zero() ee = self.endEffector.getPos(boneNode) d1 = target - pos d2 = ee - pos cross = d1.cross(d2).normalized() if cross.lengthSquared() < 1e-9: continue ang = d2.normalized().signedAngleRad(d1.normalized(), cross) q = Quat() q.setFromAxisAngleRad(ang, cross) # Add this rotation to the current rotation: qOld = boneNode.getQuat() qNew = q * qOld qNew.normalize() #boneNode.setQuat( qNew ) # Correct rotation for hinge: if bone.axis: #qInv = boneNode.getQuat() #qInv.invertInPlace() #myAxisInParentSpace = qInv.xform( bone.axis ) myAxisInParentSpace = bone.axis swing, twist = swingTwistDecomposition( qNew, -myAxisInParentSpace) qNew = twist rotAxis = qNew.getAxis() rotAxis.normalize() ang = qNew.getAngleRad() if rotAxis.lengthSquared() > 1e-3 and not math.isnan( ang) and abs(ang) > 0: # valid rotation axis? # reduce the angle ang = ang % (math.pi * 2) # force into the minimum absolute value residue class, so that -180 < angle <= 180 if ang > math.pi: ang -= 2 * math.pi if abs(ang) > 1e-6 and abs(ang) < math.pi * 2: if bone.axis and (rotAxis - bone.axis).lengthSquared() > 0.5: # Clamp the rotation value: ang = max(-bone.maxAng, min(-bone.minAng, ang)) else: # Clamp the rotation value: ang = max(bone.minAng, min(bone.maxAng, ang)) #ang = -ang #rotAxis = -rotAxis #annealing = (j+1)/len(self.bones) #print("annealing", annealing) #q = qOld + (qNew-qOld)*annealing qNew.setFromAxisAngleRad(ang, rotAxis) boneNode.setQuat(qNew) def setTarget(self, node): self.target = node def debugDisplay(self): for bone in self.bones: col = (random.random(), random.random(), random.random()) #col = (0,0,0) lines = LineSegs() lines.setThickness(6) lines.setColor(col[0], col[1], col[2]) lines.moveTo(0, 0, 0) #lines.drawTo(np.getPos(parentNode)) lnp = bone.exposedNode.attachNewNode(lines.create()) lnp.setBin("fixed", 40) #lnp.setDepthWrite(False) #lnp.setDepthTest(False) lines = LineSegs() lines.setThickness(12) lines.setColor(col[0], col[1], col[2]) lines.moveTo(0, 0, 0) lines.drawTo(bone.offset) #lines.drawTo(np.getPos(parentNode)) lnp = bone.exposedNode.attachNewNode(lines.create()) lnp.setBin("fixed", 40) #lnp.setDepthWrite(False) #lnp.setDepthTest(False) if bone.parent: parentNode = bone.parent.exposedNode else: parentNode = self.rootExposedNode lines = LineSegs() lines.setColor(0.6, 0.2, 0.2) #lines.setColor( 0.02, 0.02, 0.02 ) myPos = bone.exposedNode.getPos(parentNode) if bone.axis: qMin = Quat() qMin.setFromAxisAngleRad(bone.minAng, bone.axis) qMax = Quat() qMax.setFromAxisAngleRad(bone.maxAng, bone.axis) l = bone.offset.normalized() * 0.3 lines.moveTo(myPos) lines.drawTo(myPos + qMin.xform(l)) lines.moveTo(myPos) lines.drawTo(myPos + qMax.xform(l)) else: qMin = Quat() qMin.setFromAxisAngleRad(bone.minAng, LVector3f.unitY()) qMax = Quat() qMax.setFromAxisAngleRad(bone.maxAng, LVector3f.unitY()) l = bone.offset.normalized() * 0.3 lines.moveTo(myPos) lines.drawTo(myPos + qMin.xform(l)) lines.moveTo(myPos) lines.drawTo(myPos + qMax.xform(l)) qMin = Quat() qMin.setFromAxisAngleRad(bone.minAng, LVector3f.unitZ()) qMax = Quat() qMax.setFromAxisAngleRad(bone.maxAng, LVector3f.unitZ()) lines.moveTo(myPos) lines.drawTo(myPos + qMin.xform(l)) lines.moveTo(myPos) lines.drawTo(myPos + qMax.xform(l)) lnp = parentNode.attachNewNode(lines.create()) lnp.setBin("fixed", 40) #lnp.setDepthWrite(False) #lnp.setDepthTest(False) if bone.axis: lines = LineSegs() lines.setColor(0.6, 0.6, 0.6) lines.setThickness(3) lines.moveTo(myPos) lines.drawTo(myPos + bone.axis.normalized() * 0.3) lnp = parentNode.attachNewNode(lines.create()) lnp.setBin("fixed", 40)
class DistributedPartyTrampolineActivity(DistributedPartyActivity): notify = DirectNotifyGlobal.directNotify.newCategory('DistributedPartyTrampolineActivity') def __init__(self, cr, doJellyBeans = True, doTricks = False, texture = None): DistributedPartyTrampolineActivity.notify.debug('__init__') DistributedPartyActivity.__init__(self, cr, PartyGlobals.ActivityIds.PartyTrampoline, PartyGlobals.ActivityTypes.GuestInitiated, wantLever=False, wantRewardGui=True) self.doJellyBeans = doJellyBeans self.doTricks = doTricks self.texture = texture self.toon = None self.trampHeight = 3.6 self.trampK = 400.0 self.normalTrampB = 2.5 self.leavingTrampB = 8.0 self.trampB = self.normalTrampB self.g = -32.0 self.jumpBoost = 330.0 self.beginningBoost = 500.0 self.beginningBoostThreshold = self.trampHeight + 1.5 self.earlyJumpThreshold = 75.0 self.boingThreshold = 300.0 self.turnFactor = 120.0 self.stepDT = 0.001 self.targetCameraPos = Point3(0.0, 40.0, 10.0) self.cameraSpeed = 2.0 self.hopOffPos = Point3(16.0, 0.0, 0.0) self.indicatorFactor = 0.0095 self.dropShadowCutoff = 15.0 self.minHeightForText = 15.0 self.heightTextOffset = -0.065 self.beanOffset = 0.5 self.guiBeanOffset = -0.02 self.jumpTextShown = False self.toonJumped = False self.turnLeft = False self.turnRight = False self.leavingTrampoline = False self.toonVelocity = 0.0 self.topHeight = 0.0 self.lastPeak = 0.0 self.beginRoundInterval = None self.hopOnAnim = None self.hopOffAnim = None self.flashTextInterval = None self.numJellyBeans = PartyGlobals.TrampolineNumJellyBeans self.jellyBeanBonus = PartyGlobals.TrampolineJellyBeanBonus self.jellyBeanStartHeight = 20.0 self.jellyBeanStopHeight = 90.0 self.jellyBeanColors = [VBase4(1.0, 0.5, 0.5, 1.0), VBase4(0.5, 1.0, 0.5, 1.0), VBase4(0.5, 1.0, 1.0, 1.0), VBase4(1.0, 1.0, 0.4, 1.0), VBase4(0.4, 0.4, 1.0, 1.0), VBase4(1.0, 0.5, 1.0, 1.0)] delta = (self.jellyBeanStopHeight - self.jellyBeanStartHeight) / (self.numJellyBeans - 1) self.jellyBeanPositions = [ self.jellyBeanStartHeight + n * delta for n in xrange(self.numJellyBeans) ] self.doSimulateStep = False return def load(self): DistributedPartyTrampolineActivity.notify.debug('load') DistributedPartyActivity.load(self) self.loadModels() self.loadCollision() self.loadGUI() self.loadSounds() self.loadIntervals() self.activityFSM = TrampolineActivityFSM(self) self.activityFSM.request('Idle') self.animFSM = TrampolineAnimFSM(self) self.setBestHeightInfo('', 0) def loadModels(self): self.tramp = self.root.attachNewNode(self.uniqueName('tramp')) self.trampActor = Actor('phase_13/models/parties/trampoline_model', {'emptyAnim': 'phase_13/models/parties/trampoline_anim'}) self.trampActor.reparentTo(self.tramp) if self.texture: reskinNode = self.tramp.find('**/trampoline/__Actor_modelRoot/-GeomNode') reskinNode.setTexture(loader.loadTexture(self.texture), 100) self.surface = NodePath(self.uniqueName('trampSurface')) self.surface.reparentTo(self.tramp) self.surface.setZ(self.trampHeight) self.trampActor.controlJoint(self.surface, 'modelRoot', 'trampoline_joint1') self.sign.setPos(PartyGlobals.TrampolineSignOffset) self.beans = [ loader.loadModelCopy('phase_4/models/props/jellybean4') for i in xrange(self.numJellyBeans) ] for bean in self.beans: bean.find('**/jellybean').setP(-35.0) bean.setScale(3.0) bean.setTransparency(True) bean.reparentTo(self.tramp) bean.stash() self.beans[-1].setScale(8.0) def loadCollision(self): collTube = CollisionTube(0.0, 0.0, 0.0, 0.0, 0.0, 6.0, 5.4) collTube.setTangible(True) self.trampolineCollision = CollisionNode(self.uniqueName('TrampolineCollision')) self.trampolineCollision.addSolid(collTube) self.trampolineCollision.setCollideMask(OTPGlobals.CameraBitmask | OTPGlobals.WallBitmask) self.trampolineCollisionNP = self.tramp.attachNewNode(self.trampolineCollision) collSphere = CollisionSphere(0.0, 0.0, 0.0, 7.0) collSphere.setTangible(False) self.trampolineTrigger = CollisionNode(self.uniqueName('TrampolineTrigger')) self.trampolineTrigger.addSolid(collSphere) self.trampolineTrigger.setIntoCollideMask(OTPGlobals.WallBitmask) self.trampolineTriggerNP = self.tramp.attachNewNode(self.trampolineTrigger) self.accept('enter%s' % self.uniqueName('TrampolineTrigger'), self.onTrampolineTrigger) def loadGUI(self): self.gui = loader.loadModel('phase_13/models/parties/trampolineGUI') self.gui.reparentTo(base.a2dTopLeft) self.gui.setPos(0.115, 0, -1) self.gui.hide() self.toonIndicator = self.gui.find('**/trampolineGUI_MovingBar') jumpLineLocator = self.gui.find('**/jumpLine_locator') guiBean = self.gui.find('**/trampolineGUI_GreenJellyBean') self.gui.find('**/trampolineGUI_GreenJellyBean').stash() self.guiBeans = [ guiBean.instanceUnderNode(jumpLineLocator, self.uniqueName('guiBean%d' % i)) for i in xrange(self.numJellyBeans) ] self.guiBeans[-1].setScale(1.5) heightTextNode = TextNode(self.uniqueName('TrampolineActivity.heightTextNode')) heightTextNode.setFont(ToontownGlobals.getSignFont()) heightTextNode.setAlign(TextNode.ALeft) heightTextNode.setText('0.0') heightTextNode.setShadow(0.05, 0.05) heightTextNode.setShadowColor(0.0, 0.0, 0.0, 1.0) heightTextNode.setTextColor(1.0, 1.0, 1.0, 1.0) self.heightText = jumpLineLocator.attachNewNode(heightTextNode) self.heightText.setX(0.15) self.heightText.setScale(0.1) self.heightText.setAlphaScale(0.0) self.quitEarlyButtonModels = loader.loadModel('phase_3.5/models/gui/inventory_gui') quitEarlyUp = self.quitEarlyButtonModels.find('**//InventoryButtonUp') quitEarlyDown = self.quitEarlyButtonModels.find('**/InventoryButtonDown') quitEarlyRollover = self.quitEarlyButtonModels.find('**/InventoryButtonRollover') self.quitEarlyButton = DirectButton(parent=base.a2dTopRight, relief=None, text=TTLocalizer.PartyTrampolineQuitEarlyButton, text_fg=(1, 1, 0.65, 1), text_pos=(0, -0.23), text_scale=0.7, image=(quitEarlyUp, quitEarlyDown, quitEarlyRollover), image_color=(1, 0, 0, 1), image_scale=(20, 1, 11), pos=(-0.183, 0, -0.4), scale=0.09, command=self.leaveTrampoline) self.quitEarlyButton.stash() self.flashText = OnscreenText(text='', pos=(0.0, -0.45), scale=0.2, fg=(1.0, 1.0, 0.65, 1.0), align=TextNode.ACenter, font=ToontownGlobals.getSignFont(), mayChange=True) self.timer = PartyUtils.getNewToontownTimer() self.timer.posInTopRightCorner() return def loadSounds(self): self.jellyBeanSound = base.loader.loadSfx('phase_4/audio/sfx/sparkly.ogg') self.boingSound = base.loader.loadSfx('phase_4/audio/sfx/target_trampoline_2.ogg') self.whistleSound = base.loader.loadSfx('phase_4/audio/sfx/AA_sound_whistle.ogg') def loadIntervals(self): def prepareHeightText(): self.heightText.node().setText(TTLocalizer.PartyTrampolineGetHeight % int(self.toon.getZ())) self.heightText.setZ(self.indicatorFactor * self.toon.getZ() + self.heightTextOffset) self.heightTextInterval = Sequence(Func(prepareHeightText), LerpFunc(self.heightText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0)) def unload(self): DistributedPartyTrampolineActivity.notify.debug('unload') if self.hopOnAnim and self.hopOnAnim.isPlaying(): self.hopOnAnim.finish() if self.hopOffAnim and self.hopOffAnim.isPlaying(): self.hopOffAnim.finish() if self.beginRoundInterval and self.beginRoundInterval.isPlaying(): self.beginRoundInterval.finish() if self.flashTextInterval and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() if self.heightTextInterval and self.heightTextInterval.isPlaying(): self.heightTextInterval.finish() self.timer.stop() DistributedPartyActivity.unload(self) taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.ignoreAll() del self.heightTextInterval del self.beginRoundInterval del self.hopOnAnim del self.hopOffAnim del self.flashTextInterval if hasattr(self, 'beanAnims'): self.cleanupJellyBeans() self.quitEarlyButton.destroy() del self.quitEarlyButton del self.gui del self.activityFSM del self.animFSM return def setBestHeightInfo(self, toonName, height): self.bestHeightInfo = (toonName, height) DistributedPartyTrampolineActivity.notify.debug('%s has the best height of %d' % (toonName, height)) if height > 0: self.setSignNote(TTLocalizer.PartyTrampolineBestHeight % self.bestHeightInfo) else: self.setSignNote(TTLocalizer.PartyTrampolineNoHeightYet) def leaveTrampoline(self): if self.toon != None and self.toon.doId == base.localAvatar.doId: self._showFlashMessage(TTLocalizer.PartyTrampolineTimesUp) self.leavingTrampoline = True self.timer.reset() self.trampB = self.leavingTrampB self.ignore('control') self.quitEarlyButton.stash() self.gui.hide() return def requestAnim(self, request): self.animFSM.request(request) def b_requestAnim(self, request): self.requestAnim(request) self.sendUpdate('requestAnim', [request]) def requestAnimEcho(self, request): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.requestAnim(request) return def removeBeans(self, beansToRemove): for i in beansToRemove: height, bean, guiBean, beanAnim = self.beanDetails[i] guiBean.stash() if i in self.beansToCollect: self.beansToCollect.remove(i) else: self.notify.warning('removeBeans avoided a crash, %d not in self.beansToCollect' % i) self.poofBean(bean, beanAnim) def b_removeBeans(self, beansToRemove): self.removeBeans(beansToRemove) self.sendUpdate('removeBeans', [beansToRemove]) def removeBeansEcho(self, beansToRemove): if self.toon != None and self.toon.doId != base.localAvatar.doId: self.removeBeans(beansToRemove) return def joinRequestDenied(self, reason): DistributedPartyActivity.joinRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultJoinDeny) base.cr.playGame.getPlace().fsm.request('walk') def exitRequestDenied(self, reason): DistributedPartyActivity.exitRequestDenied(self, reason) self.showMessage(TTLocalizer.PartyActivityDefaultExitDeny) def setState(self, newState, timestamp): DistributedPartyTrampolineActivity.notify.debug('setState( newState=%s, ... )' % newState) DistributedPartyActivity.setState(self, newState, timestamp) self.activityFSM.request(newState) def startIdle(self): DistributedPartyTrampolineActivity.notify.debug('startIdle') def finishIdle(self): DistributedPartyTrampolineActivity.notify.debug('finishIdle') def startRules(self): DistributedPartyTrampolineActivity.notify.debug('startRules') if self.doJellyBeans: self.setupJellyBeans() if self.toon != None and self.toon.doId == base.localAvatar.doId: self.acquireToon() return def startActive(self): DistributedPartyTrampolineActivity.notify.debug('startActive') if self.toon != None and self.toon.doId == base.localAvatar.doId: base.setCellsActive(base.bottomCells, True) self.accept('arrow_left', self.onLeft) self.accept('arrow_left-up', self.onLeftUp) self.accept('arrow_right', self.onRight) self.accept('arrow_right-up', self.onRightUp) self.beginRoundInterval = Sequence(Func(self._showFlashMessage, TTLocalizer.PartyTrampolineReady), Wait(1.2), Func(self.flashMessage, TTLocalizer.PartyTrampolineGo), Func(self.beginRound)) self.beginRoundInterval.start() return def finishActive(self): DistributedPartyTrampolineActivity.notify.debug('finishActive') if self.doJellyBeans: self.cleanupJellyBeans() def setupJellyBeans(self): self.beanAnims = [] self.beansToCollect = [] self.beanDetails = [] self.numBeansCollected = 0 for i in xrange(self.numJellyBeans): bean = self.beans[i] guiBean = self.guiBeans[i] height = self.jellyBeanPositions[i] color = random.choice(self.jellyBeanColors) bean.find('**/jellybean').setColor(color) if self.toon.doId == base.localAvatar.doId: bean.setAlphaScale(1.0) else: bean.setAlphaScale(0.5) guiBean.setColor(color) bean.setZ(height + self.toon.getHeight() + self.beanOffset) guiBean.setZ(height * self.indicatorFactor + self.guiBeanOffset) bean.setH(0.0) bean.unstash() guiBean.unstash() beanAnim = bean.hprInterval(1.5, VBase3((i % 2 * 2 - 1) * 360.0, 0.0, 0.0)) beanAnim.loop() self.beanAnims.append(beanAnim) self.beanDetails.append((height, bean, guiBean, beanAnim)) self.beansToCollect = range(self.numJellyBeans) def cleanupJellyBeans(self): for bean in self.beans: bean.stash() for guiBean in self.guiBeans: guiBean.stash() if hasattr(self, 'beanAnims'): for beanAnim in self.beanAnims: beanAnim.finish() del self.beanAnims del self.beansToCollect def beginRound(self): base.playSfx(self.whistleSound) self.timer.setTime(PartyGlobals.TrampolineDuration) self.timer.countdown(PartyGlobals.TrampolineDuration) self.timer.show() self.gui.show() self.quitEarlyButton.unstash() self.notify.debug('Accepting contorl') self.accept('control', self.onJump) self.notify.debug('setting simulate step to true') self.doSimulateStep = True def acquireToon(self): self.toon.disableSmartCameraViews() self.toon.stopUpdateSmartCamera() camera.wrtReparentTo(render) self.toon.dropShadow.reparentTo(hidden) self.toon.startPosHprBroadcast(period=0.2) self.toonAcceleration = 0.0 self.toonVelocity = 0.0 self.topHeight = 0.0 self.trampB = self.normalTrampB self.leavingTrampoline = False self.hopOnAnim = Sequence(Func(self.toon.b_setAnimState, 'jump', 1.0), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, Point3(0.0, 0.0, self.trampHeight), 5.0, self.tramp), Func(self.postHopOn)) self.hopOnAnim.start() def postHopOn(self): self.toon.setH(self.toon.getH() + 90.0) self.toon.dropShadow.reparentTo(self.surface) self.timeLeftToSimulate = 0.0 self.doSimulateStep = False taskMgr.add(self.updateTask, self.uniqueName('TrampolineActivity.updateTask')) base.setCellsActive(base.leftCells, False) base.setCellsActive(base.bottomCells, False) DistributedPartyActivity.startRules(self) def releaseToon(self): self._hideFlashMessage() self.ignore('arrow_left') self.ignore('arrow_left-up') self.ignore('arrow_right') self.ignore('arrow_right-up') taskMgr.remove(self.uniqueName('TrampolineActivity.updateTask')) self.hopOffAnim = Sequence(self.toon.hprInterval(0.5, VBase3(-90.0, 0.0, 0.0), other=self.tramp), Func(self.toon.b_setAnimState, 'jump', 1.0), Func(self.toon.dropShadow.reparentTo, hidden), Wait(0.4), PartyUtils.arcPosInterval(0.75, self.toon, self.hopOffPos, 5.0, self.tramp), Func(self.postHopOff)) self.hopOffAnim.start() def postHopOff(self): base.setCellsActive(base.leftCells, True) self.timer.stop() self.timer.hide() self.toon.dropShadow.reparentTo(self.toon.getShadowJoint()) self.toon.dropShadow.setAlphaScale(1.0) self.toon.dropShadow.setScale(1.0) self.b_requestAnim('Off') camera.reparentTo(base.localAvatar) base.localAvatar.startUpdateSmartCamera() base.localAvatar.enableSmartCameraViews() base.localAvatar.setCameraPositionByIndex(base.localAvatar.cameraIndex) place = base.cr.playGame.getPlace() if self.doJellyBeans: self.sendUpdate('awardBeans', [self.numBeansCollected, int(self.topHeight)]) if int(self.topHeight) > self.bestHeightInfo[1]: self.sendUpdate('reportHeightInformation', [int(self.topHeight)]) self.d_toonExitDemand() def onTrampolineTrigger(self, collEntry): if self.activityFSM.state == 'Idle' and self.toon == None and base.cr.playGame.getPlace().fsm.getCurrentState().getName() == 'walk': base.cr.playGame.getPlace().fsm.request('activity') self.d_toonJoinRequest() else: self.flashMessage(TTLocalizer.PartyTrampolineActivityOccupied, duration=2.0) return def onJump(self): self.notify.debug('got onJump') if self.toon != None and self.toon.getZ() < self.trampHeight: self.toonJumped = True self.b_requestAnim('Jump') else: self.notify.debug('z is less than tramp height') return def onLeft(self): self.turnLeft = True def onLeftUp(self): self.turnLeft = False def onRight(self): self.turnRight = True def onRightUp(self): self.turnRight = False def handleToonJoined(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonJoined') self.toon = self.getAvatar(toonId) if self.toon != None and not self.toon.isEmpty(): self.oldJumpSquatPlayRate = self.toon.getPlayRate('jump-squat') self.oldJumpLandPlayRate = self.toon.getPlayRate('jump-land') self.toon.setPlayRate(2.5, 'jump-squat') self.toon.setPlayRate(2.0, 'jump-land') self.turnLeft = False self.turnRight = False self.activityFSM.request('Rules') if self.toon.doId != base.localAvatar.doId: taskMgr.add(self.remoteUpdateTask, self.uniqueName('TrampolineActivity.remoteUpdateTask')) else: self.notify.warning('handleToonJoined could not get toon %d' % toonId) return def handleToonExited(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonExited') if self.toon != None: if self.toon.doId != base.localAvatar.doId: taskMgr.remove(self.uniqueName('TrampolineActivity.remoteUpdateTask')) self.surface.setZ(self.trampHeight) self.toon.setPlayRate(self.oldJumpSquatPlayRate, 'jump-squat') self.toon.setPlayRate(self.oldJumpLandPlayRate, 'jump-land') self.toon = None return def handleToonDisabled(self, toonId): DistributedPartyTrampolineActivity.notify.debug('handleToonDisabled') DistributedPartyTrampolineActivity.notify.debug('avatar ' + str(toonId) + ' disabled') if base.localAvatar.doId == toonId: self.releaseToon() def handleRulesDone(self): self.sendUpdate('toonReady') self.finishRules() def getTitle(self): if self.doJellyBeans: return TTLocalizer.PartyTrampolineJellyBeanTitle elif self.doTricks: return TTLocalizer.PartyTrampolineTricksTitle else: return DistributedPartyActivity.getTitle(self) def getInstructions(self): return TTLocalizer.PartyTrampolineActivityInstructions def updateTask(self, task): z = self.toon.getZ() dt = globalClock.getDt() if self.doSimulateStep: self.timeLeftToSimulate += dt while self.timeLeftToSimulate >= self.stepDT: z, a = self.simulateStep(z) self.timeLeftToSimulate -= self.stepDT self.toon.setZ(z) if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) self.toonIndicator.setZ((z - self.trampHeight) * self.indicatorFactor) if self.turnLeft: self.toon.setH(self.toon.getH() + self.turnFactor * dt) if self.turnRight: self.toon.setH(self.toon.getH() - self.turnFactor * dt) currentPos = base.camera.getPos(self.toon) vec = self.targetCameraPos - currentPos newPos = currentPos + vec * (dt * self.cameraSpeed) base.camera.setPos(self.toon, newPos) base.camera.lookAt(self.toon) #if z > self.trampHeight: # heightFactor = 1.0 - min(1.0, (z - self.trampHeight) / self.dropShadowCutoff) # self.toon.dropShadow.setAlphaScale(heightFactor) # self.toon.dropShadow.setScale(max(0.1, heightFactor)) #else: # self.toon.dropShadow.setAlphaScale(1.0) # self.toon.dropShadow.setScale(1.0) if self.leavingTrampoline and z < self.trampHeight and abs(a) < 0.1: self.releaseToon() return Task.cont def simulateStep(self, z): if z >= self.trampHeight: a = self.g self.toonJumped = False else: a = self.g + self.trampK * (self.trampHeight - z) - self.trampB * self.toonVelocity if self.toonJumped: if self.lastPeak > self.earlyJumpThreshold or self.toonVelocity >= -300000.0: a += self.jumpBoost if self.lastPeak < self.beginningBoostThreshold: a += self.beginningBoost lastVelocity = self.toonVelocity self.toonVelocity += a * self.stepDT if lastVelocity > 0.0 and self.toonVelocity <= 0.0: topOfJump = True bottomOfJump = False elif lastVelocity < 0.0 and self.toonVelocity >= 0.0: topOfJump = False bottomOfJump = True else: topOfJump = False bottomOfJump = False newZ = z + self.toonVelocity * self.stepDT if newZ > self.topHeight: self.topHeight = newZ if self.doJellyBeans: self.collectJellyBeans(newZ) if topOfJump: self.lastPeak = newZ if newZ >= self.minHeightForText: self.heightTextInterval.start() if topOfJump: if newZ > self.trampHeight + 20.0: self.b_requestAnim('Falling') elif self.animFSM.state == 'Jump': self.b_requestAnim('Falling') if newZ <= self.trampHeight and z > self.trampHeight: if self.animFSM.state == 'Falling': self.b_requestAnim('Land') elif self.animFSM.state != 'Neutral': self.b_requestAnim('Neutral') if bottomOfJump and a > self.boingThreshold: base.playSfx(self.boingSound) return (newZ, a) def collectJellyBeans(self, z): beansToRemove = [] for i in self.beansToCollect: height = self.beanDetails[i][0] if height <= z: beansToRemove.append(i) if len(beansToRemove) > 0: base.playSfx(self.jellyBeanSound) self.numBeansCollected += len(beansToRemove) self.b_removeBeans(beansToRemove) def remoteUpdateTask(self, task): if self.toon != None and not self.toon.isEmpty(): z = self.toon.getZ() if z <= self.trampHeight: self.surface.setZ(z) else: self.surface.setZ(self.trampHeight) return Task.cont def poofBean(self, bean, beanAnim): if bean == None: self.notify.warning('poofBean, returning immediately as bean is None') return if bean.isEmpty(): self.notify.warning('poofBean, returning immediately as bean is empty') return currentAlpha = bean.getColorScale()[3] currentScale = bean.getScale() poofAnim = Sequence(Parallel(LerpFunc(bean.setAlphaScale, fromData=currentAlpha, toData=0.0, duration=0.25), LerpFunc(bean.setScale, fromData=currentScale, toData=currentScale * 5.0, duration=0.25)), Func(bean.stash), Func(beanAnim.finish), Func(bean.setAlphaScale, currentAlpha), Func(bean.setScale, currentScale)) poofAnim.start() return def _showFlashMessage(self, message): if self.isDisabled(): return if self.flashTextInterval is not None and self.flashTextInterval.isPlaying(): self.flashTextInterval.finish() self.flashText.setText(message) self.flashText.setAlphaScale(1.0) self.flashText.unstash() return def _hideFlashMessage(self, duration = 0.0): if self.isDisabled(): pass self.flashTextInterval = Sequence(Wait(duration), LerpFunc(self.flashText.setAlphaScale, fromData=1.0, toData=0.0, duration=1.0), Func(self.flashText.stash)) self.flashTextInterval.start() def flashMessage(self, message, duration = 0.5): self._showFlashMessage(message) self._hideFlashMessage(duration)
class IsisAgent(kinematicCharacterController, DirectObject): @classmethod def setPhysics(cls, physics): """ This method is set in src.loader when the generators are loaded into the namespace. This frees the environment definitions (in scenario files) from having to pass around the physics parameter that is required for all IsisObjects """ cls.physics = physics def __init__(self, name, queueSize=100): # load the model and the different animations for the model into an Actor object. self.actor = Actor("media/models/boxman", { "walk": "media/models/boxman-walk", "idle": "media/models/boxman-idle" }) self.actor.setScale(1.0) self.actor.setH(0) #self.actor.setLODAnimation(10,5,2) # slows animation framerate when actor is far from camera, if you can figure out reasonable params self.actor.setColorScale(random.random(), random.random(), random.random(), 1.0) self.actorNodePath = NodePath('agent-%s' % name) self.activeModel = self.actorNodePath self.actorNodePath.reparentTo(render) self.actor.reparentTo(self.actorNodePath) self.name = name self.isMoving = False # initialize ODE controller kinematicCharacterController.__init__(self, IsisAgent.physics, self.actorNodePath) self.setGeomPos(self.actorNodePath.getPos(render)) """ Additional Direct Object that I use for convenience. """ self.specialDirectObject = DirectObject() """ How high above the center of the capsule you want the camera to be when walking and when crouching. It's related to the values in KCC. """ self.walkCamH = 0.7 self.crouchCamH = 0.2 self.camH = self.walkCamH """ This tells the Player Controller what we're aiming at. """ self.aimed = None self.isSitting = False self.isDisabled = False """ The special direct object is used for trigger messages and the like. """ #self.specialDirectObject.accept("ladder_trigger_enter", self.setFly, [True]) #self.specialDirectObject.accept("ladder_trigger_exit", self.setFly, [False]) self.actor.makeSubpart("arms", ["LeftShoulder", "RightShoulder"]) # Expose agent's right hand joint to attach objects to self.player_right_hand = self.actor.exposeJoint( None, 'modelRoot', 'Hand.R') self.player_left_hand = self.actor.exposeJoint(None, 'modelRoot', 'Hand.L') self.right_hand_holding_object = None self.left_hand_holding_object = None # don't change the color of things you pick up self.player_right_hand.setColorScaleOff() self.player_left_hand.setColorScaleOff() self.player_head = self.actor.exposeJoint(None, 'modelRoot', 'Head') self.neck = self.actor.controlJoint(None, 'modelRoot', 'Head') self.controlMap = { "turn_left": 0, "turn_right": 0, "move_forward": 0, "move_backward": 0, "move_right": 0, "move_left": 0, "look_up": 0, "look_down": 0, "look_left": 0, "look_right": 0, "jump": 0 } # see update method for uses, indices are [turn left, turn right, move_forward, move_back, move_right, move_left, look_up, look_down, look_right, look_left] # turns are in degrees per second, moves are in units per second self.speeds = [270, 270, 5, 5, 5, 5, 60, 60, 60, 60] self.originalPos = self.actor.getPos() bubble = loader.loadTexture("media/textures/thought_bubble.png") #bubble.setTransparency(TransparencyAttrib.MAlpha) self.speech_bubble = DirectLabel(parent=self.actor, text="", text_wordwrap=10, pad=(3, 3), relief=None, text_scale=(.3, .3), pos=(0, 0, 3.6), frameColor=(.6, .2, .1, .5), textMayChange=1, text_frame=(0, 0, 0, 1), text_bg=(1, 1, 1, 1)) #self.myImage= self.speech_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.speech_bubble.setColorScaleOff() self.speech_bubble.component('text0').textNode.setCardDecal(1) self.speech_bubble.setBillboardAxis() # hide the speech bubble from IsisAgent's own camera self.speech_bubble.hide(BitMask32.bit(1)) self.thought_bubble = DirectLabel(parent=self.actor, text="", text_wordwrap=9, text_frame=(1, 0, -2, 1), text_pos=(0, .5), text_bg=(1, 1, 1, 0), relief=None, frameSize=(0, 1.5, -2, 3), text_scale=(.18, .18), pos=(0, 0.2, 3.6), textMayChange=1, image=bubble, image_pos=(0, 0.1, 0), sortOrder=5) self.thought_bubble.setTransparency(TransparencyAttrib.MAlpha) # stop the speech bubble from being colored like the agent self.thought_bubble.setColorScaleOff() self.thought_bubble.component('text0').textNode.setFrameColor( 1, 1, 1, 0) self.thought_bubble.component('text0').textNode.setFrameAsMargin( 0.1, 0.1, 0.1, 0.1) self.thought_bubble.component('text0').textNode.setCardDecal(1) self.thought_bubble.setBillboardAxis() # hide the thought bubble from IsisAgent's own camera self.thought_bubble.hide(BitMask32.bit(1)) # disable by default self.thought_bubble.hide() self.thought_filter = {} # only show thoughts whose values are in here self.last_spoke = 0 # timers to keep track of last thought/speech and self.last_thought = 0 # hide visualizations # put a camera on ralph self.fov = NodePath(Camera('RaphViz')) self.fov.node().setCameraMask(BitMask32.bit(1)) # position the camera to be infront of Boxman's face. self.fov.reparentTo(self.player_head) # x,y,z are not in standard orientation when parented to player-Head self.fov.setPos(0, 0.2, 0) # if P=0, canrea is looking directly up. 90 is back of head. -90 is on face. self.fov.setHpr(0, -90, 0) lens = self.fov.node().getLens() lens.setFov(60) # degree field of view (expanded from 40) lens.setNear(0.2) #self.fov.node().showFrustum() # displays a box around his head #self.fov.place() self.prevtime = 0 self.current_frame_count = 0 self.isSitting = False self.isDisabled = False self.msg = None self.actorNodePath.setPythonTag("agent", self) # Initialize the action queue, with a maximum length of queueSize self.queue = [] self.queueSize = queueSize self.lastSense = 0 def setLayout(self, layout): """ Dummy method called by spatial methods for use with objects. Doesn't make sense for an agent that can move around.""" pass def setPos(self, pos): """ Wrapper to set the position of the ODE geometry, which in turn sets the visual model's geometry the next time the update() method is called. """ self.setGeomPos(pos) def setPosition(self, pos): self.setPos(pos) def reparentTo(self, parent): self.actorNodePath.reparentTo(parent) def setControl(self, control, value): """Set the state of one of the character's movement controls. """ self.controlMap[control] = value def get_objects_in_field_of_vision(self, exclude=['isisobject']): """ This works in an x-ray style. Fast. Works best if you listen to http://en.wikipedia.org/wiki/Rock_Art_and_the_X-Ray_Style while you use it. needs to exclude isisobjects since they cannot be serialized """ objects = {} for obj in base.render.findAllMatches("**/IsisObject*"): if not obj.hasPythonTag("isisobj"): continue o = obj.getPythonTag("isisobj") bounds = o.activeModel.getBounds() bounds.xform(o.activeModel.getMat(self.fov)) if self.fov.node().isInView(o.activeModel.getPos(self.fov)): pos = o.activeModel.getPos(render) pos = (pos[0], pos[1], pos[2] + o.getHeight() / 2) p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) object_dict = {} if 'x_pos' not in exclude: object_dict['x_pos'] = p3[0] if 'y_pos' not in exclude: object_dict['y_pos'] = p3[2] if 'distance' not in exclude: object_dict['distance'] = o.activeModel.getDistance( self.fov) if 'orientation' not in exclude: object_dict['orientation'] = o.activeModel.getH(self.fov) if 'actions' not in exclude: object_dict['actions'] = o.list_actions() if 'isisobject' not in exclude: object_dict['isisobject'] = o # add item to dinctionary objects[o] = object_dict return objects def get_agents_in_field_of_vision(self): """ This works in an x-ray vision style as well""" agents = {} for agent in base.render.findAllMatches("**/agent-*"): if not agent.hasPythonTag("agent"): continue a = agent.getPythonTag("agent") bounds = a.actorNodePath.getBounds() bounds.xform(a.actorNodePath.getMat(self.fov)) pos = a.actorNodePath.getPos(self.fov) if self.fov.node().isInView(pos): p1 = self.fov.getRelativePoint(render, pos) p2 = Point2() self.fov.node().getLens().project(p1, p2) p3 = aspect2d.getRelativePoint(render2d, Point3(p2[0], 0, p2[1])) agentDict = {'x_pos': p3[0],\ 'y_pos': p3[2],\ 'distance':a.actorNodePath.getDistance(self.fov),\ 'orientation': a.actorNodePath.getH(self.fov)} agents[a] = agentDict return agents def in_view(self, isisobj): """ Returns true iff a particular isisobject is in view """ return len( filter(lambda x: x['isisobject'] == isisobj, self.get_objects_in_field_of_vision(exclude=[]).values())) def get_objects_in_view(self): """ Gets objects through ray tracing. Slow""" return self.picker.get_objects_in_view() def control__turn_left__start(self, speed=None): self.setControl("turn_left", 1) self.setControl("turn_right", 0) if speed: self.speeds[0] = speed return "success" def control__turn_left__stop(self): self.setControl("turn_left", 0) return "success" def control__turn_right__start(self, speed=None): self.setControl("turn_left", 0) self.setControl("turn_right", 1) if speed: self.speeds[1] = speed return "success" def control__turn_right__stop(self): self.setControl("turn_right", 0) return "success" def control__move_forward__start(self, speed=None): self.setControl("move_forward", 1) self.setControl("move_backward", 0) if speed: self.speeds[2] = speed return "success" def control__move_forward__stop(self): self.setControl("move_forward", 0) return "success" def control__move_backward__start(self, speed=None): self.setControl("move_forward", 0) self.setControl("move_backward", 1) if speed: self.speeds[3] = speed return "success" def control__move_backward__stop(self): self.setControl("move_backward", 0) return "success" def control__move_left__start(self, speed=None): self.setControl("move_left", 1) self.setControl("move_right", 0) if speed: self.speeds[4] = speed return "success" def control__move_left__stop(self): self.setControl("move_left", 0) return "success" def control__move_right__start(self, speed=None): self.setControl("move_right", 1) self.setControl("move_left", 0) if speed: self.speeds[5] = speed return "success" def control__move_right__stop(self): self.setControl("move_right", 0) return "success" def control__look_left__start(self, speed=None): self.setControl("look_left", 1) self.setControl("look_right", 0) if speed: self.speeds[9] = speed return "success" def control__look_left__stop(self): self.setControl("look_left", 0) return "success" def control__look_right__start(self, speed=None): self.setControl("look_right", 1) self.setControl("look_left", 0) if speed: self.speeds[8] = speed return "success" def control__look_right__stop(self): self.setControl("look_right", 0) return "success" def control__look_up__start(self, speed=None): self.setControl("look_up", 1) self.setControl("look_down", 0) if speed: self.speeds[6] = speed return "success" def control__look_up__stop(self): self.setControl("look_up", 0) return "success" def control__look_down__start(self, speed=None): self.setControl("look_down", 1) self.setControl("look_up", 0) if speed: self.speeds[7] = speed return "success" def control__look_down__stop(self): self.setControl("look_down", 0) return "success" def control__jump(self): self.setControl("jump", 1) return "success" def control__view_objects(self): """ calls a raytrace to to all objects in view """ objects = self.get_objects_in_field_of_vision() self.control__say( "If I were wearing x-ray glasses, I could see %i items" % len(objects)) print "Objects in view:", objects return objects def control__sense(self): """ perceives the world, returns percepts dict """ percepts = dict() # eyes: visual matricies #percepts['vision'] = self.sense__get_vision() # objects in purview (cheating object recognition) percepts['objects'] = self.sense__get_objects() # global position in environment - our robots can have GPS :) percepts['position'] = self.sense__get_position() # language: get last utterances that were typed percepts['language'] = self.sense__get_utterances() # agents: returns a map of agents to a list of actions that have been sensed percepts['agents'] = self.sense__get_agents() print percepts return percepts def control__think(self, message, layer=0): """ Changes the contents of an agent's thought bubble""" # only say things that are checked in the controller if self.thought_filter.has_key(layer): self.thought_bubble.show() self.thought_bubble['text'] = message #self.thought_bubble.component('text0').textNode.setShadow(0.05, 0.05) #self.thought_bubble.component('text0').textNode.setShadowColor(self.thought_filter[layer]) self.last_thought = 0 return "success" def control__say(self, message="Hello!"): self.speech_bubble['text'] = message self.last_spoke = 0 return "success" """ Methods explicitly for IsisScenario files """ def put_in_front_of(self, isisobj): # find open direction pos = isisobj.getGeomPos() direction = render.getRelativeVector(isisobj, Vec3(0, 1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) print "CLOSEST", closestEntry, closestObject if closestObject == None: self.setPosition(pos + Vec3(0, 2, 0)) else: print "CANNOT PLACE IN FRONT OF %s BECAUSE %s IS THERE" % ( isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(0, -1.0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(0, -2, 0)) else: print "CANNOT PLACE BEHIND %s BECAUSE %s IS THERE" % ( isisobj, closestObject) direction = render.getRelativeVector(isisobj, Vec3(1, 0, 0)) closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], [isisobj.geom]) if closestEntry == None: self.setPosition(pos + Vec3(2, 0, 0)) else: print "CANNOT PLACE TO LEFT OF %s BECAUSE %s IS THERE" % ( isisobj, closestObject) # there's only one option left, do it anyway self.setPosition(pos + Vec3(-2, 0, 0)) # rotate agent to look at it self.actorNodePath.setPos(self.getGeomPos()) self.actorNodePath.lookAt(pos) self.setH(self.actorNodePath.getH()) def put_in_right_hand(self, target): return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) def put_in_left_hand(self, target): return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) def __get_object_in_center_of_view(self): direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.fov.getPos(render) exclude = [ ] #[base.render.find("**/kitchenNode*").getPythonTag("isisobj").geom] closestEntry, closestObject = IsisAgent.physics.doRaycastNew( 'aimRay', 5, [pos, direction], exclude) return closestObject def pick_object_up_with(self, target, hand_slot, hand_joint): """ Attaches an IsisObject, target, to the hand joint. Does not check anything first, other than the fact that the hand joint is not currently holding something else.""" if hand_slot != None: print 'already holding ' + hand_slot.getName() + '.' return None else: if target.layout: target.layout.remove(target) target.layout = None # store original position target.originalHpr = target.getHpr(render) target.disable() #turn off physics if target.body: target.body.setGravityMode(0) target.reparentTo(hand_joint) target.setPosition(hand_joint.getPos(render)) target.setTag('heldBy', self.name) if hand_joint == self.player_right_hand: self.right_hand_holding_object = target elif hand_joint == self.player_left_hand: self.left_hand_holding_object = target hand_slot = target return target def control__pick_up_with_right_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return "error: no target in reach" else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with right hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.right_hand_holding_object, self.player_right_hand) else: print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).' return 'error: object not graspable' def control__pick_up_with_left_hand(self, target=None): if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag("isisobj") print "attempting to pick up " + target.name + " with left hand.\n" if self.can_grasp(target): # object within distance return self.pick_object_up_with(target, self.left_hand_holding_object, self.player_left_hand) else: print 'object (' + target.name + ') is not graspable (i.e. in view and close enough).' return 'error: object not graspable' def control__drop_from_right_hand(self): print "attempting to drop object from right hand.\n" if self.right_hand_holding_object is None: print 'right hand is not holding an object.' return False if self.right_hand_holding_object.getNetTag('heldBy') == self.name: self.right_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_right_hand.getPos(render) heldPos = self.right_hand_holding_object.geom.getPosition() self.right_hand_holding_object.setPosition(pos) self.right_hand_holding_object.synchPosQuatToNode() self.right_hand_holding_object.setTag('heldBy', '') self.right_hand_holding_object.setRotation( self.right_hand_holding_object.originalHpr) self.right_hand_holding_object.enable() if self.right_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.right_hand_holding_object.body.setGravityMode(1) self.right_hand_holding_object.getBody().setForce( quat.xform(Vec3(0, force, 0))) self.right_hand_holding_object = None return 'success' else: return "Error: not being held by agent %s" % (self.name) def control__drop_from_left_hand(self): print "attempting to drop object from left hand.\n" if self.left_hand_holding_object is None: return 'left hand is not holding an object.' if self.left_hand_holding_object.getNetTag('heldBy') == self.name: self.left_hand_holding_object.reparentTo(render) direction = render.getRelativeVector(self.fov, Vec3(0, 1.0, 0)) pos = self.player_left_hand.getPos(render) heldPos = self.left_hand_holding_object.geom.getPosition() self.left_hand_holding_object.setPosition(pos) self.left_hand_holding_object.synchPosQuatToNode() self.left_hand_holding_object.setTag('heldBy', '') self.left_hand_holding_object.setRotation( self.left_hand_holding_object.originalHpr) self.left_hand_holding_object.enable() if self.left_hand_holding_object.body: quat = self.getQuat() # throw object force = 5 self.left_hand_holding_object.body.setGravityMode(1) self.left_hand_holding_object.getBody().setForce( quat.xform(Vec3(0, force, 0))) self.left_hand_holding_object = None return 'success' else: return "Error: not being held by agent %s" % (self.name) def control__use_right_hand(self, target=None, action=None): # TODO, rename this to use object with if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag('isisobj') print "Trying to use object", target if self.can_grasp(target): if (target.call(self, action, self.right_hand_holding_object) or (self.right_hand_holding_object and self.right_hand_holding_object.call(self, action, target))): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def control__use_left_hand(self, target=None, action=None): if not action: if self.msg: action = self.msg else: action = "divide" if not target: target = self.__get_object_in_center_of_view() if not target: print "no target in reach" return else: target = render.find("**/*" + target + "*").getPythonTag('isisobj') if self.can_grasp(target): if (target.call(self, action, self.left_hand_holding_object) or (self.left_hand_holding_object and self.left_hand_holding_object.call(self, action, target))): return "success" return str(action) + " not associated with either target or object" return "target not within reach" def can_grasp(self, isisobject): distance = isisobject.activeModel.getDistance(self.fov) print "distance = ", distance return distance < 5.0 def is_holding(self, object_name): return ((self.left_hand_holding_object and (self.left_hand_holding_object.getPythonTag('isisobj').name == object_name)) \ or (self.right_hand_holding_object and (self.right_hand_holding_object.getPythonTag('isisobj').name == object_name))) def empty_hand(self): if (self.left_hand_holding_object is None): return self.player_left_hand elif (self.right_hand_holding_object is None): return self.player_right_hand return False def has_empty_hand(self): return (self.empty_hand() is not False) def control__use_aimed(self): """ Try to use the object that we aim at, by calling its callback method. """ target = self.__get_object_in_center_of_view() if target.selectionCallback: target.selectionCallback(self, dir) return "success" def sense__get_position(self): x, y, z = self.actorNodePath.getPos() h, p, r = self.actorNodePath.getHpr() #FIXME # neck is not positioned in Blockman nh,np,nr = self.agents[agent_id].actor_neck.getHpr() left_hand_obj = "" right_hand_obj = "" if self.left_hand_holding_object: left_hand_obj = self.left_hand_holding_object.getName() if self.right_hand_holding_object: right_hand_obj = self.right_hand_holding_object.getName() return {'body_x': x, 'body_y': y, 'body_z': z,'body_h':h,\ 'body_p': p, 'body_r': r, 'in_left_hand': left_hand_obj, 'in_right_hand':right_hand_obj} def sense__get_vision(self): self.fov.node().saveScreenshot("temp.jpg") image = Image.open("temp.jpg") os.remove("temp.jpg") return image def sense__get_objects(self): return dict([x.getName(), y] for (x, y) in self.get_objects_in_field_of_vision().items()) def sense__get_agents(self): curSense = time() agents = {} for k, v in self.get_agents_in_field_of_vision().items(): v['actions'] = k.get_other_agents_actions(self.lastSense, curSense) agents[k.name] = v self.lastSense = curSense return agents def sense__get_utterances(self): """ Clear out the buffer of things that the teacher has typed, FIXME: this doesn't work right now """ return [] utterances = self.teacher_utterances self.teacher_utterances = [] return utterances def debug__print_objects(self): text = "Objects in FOV: " + ", ".join(self.sense__get_objects().keys()) print text def add_action_to_history(self, action, args, result=0): self.queue.append((time(), action, args, result)) if len(self.queue) > self.queueSize: self.queue.pop(0) def get_other_agents_actions(self, start=0, end=None): if not end: end = time() actions = [] for act in self.queue: if act[0] >= start: if act[0] < end: actions.append(act) else: break return actions def update(self, stepSize=0.1): self.speed = [0.0, 0.0] self.actorNodePath.setPos(self.geom.getPosition() + Vec3(0, 0, -0.70)) self.actorNodePath.setQuat(self.getQuat()) # the values in self.speeds are used as coefficientes for turns and movements if (self.controlMap["turn_left"] != 0): self.addToH(stepSize * self.speeds[0]) if (self.controlMap["turn_right"] != 0): self.addToH(-stepSize * self.speeds[1]) if self.verticalState == 'ground': # these actions require contact with the ground if (self.controlMap["move_forward"] != 0): self.speed[1] = self.speeds[2] if (self.controlMap["move_backward"] != 0): self.speed[1] = -self.speeds[3] if (self.controlMap["move_left"] != 0): self.speed[0] = -self.speeds[4] if (self.controlMap["move_right"] != 0): self.speed[0] = self.speeds[5] if (self.controlMap["jump"] != 0): kinematicCharacterController.jump(self) # one jump at a time! self.controlMap["jump"] = 0 if (self.controlMap["look_left"] != 0): self.neck.setR(bound(self.neck.getR(), -60, 60) + stepSize * 80) if (self.controlMap["look_right"] != 0): self.neck.setR(bound(self.neck.getR(), -60, 60) - stepSize * 80) if (self.controlMap["look_up"] != 0): self.neck.setP(bound(self.neck.getP(), -60, 80) + stepSize * 80) if (self.controlMap["look_down"] != 0): self.neck.setP(bound(self.neck.getP(), -60, 80) - stepSize * 80) kinematicCharacterController.update(self, stepSize) """ Update the held object position to be in the hands """ if self.right_hand_holding_object != None: self.right_hand_holding_object.setPosition( self.player_right_hand.getPos(render)) if self.left_hand_holding_object != None: self.left_hand_holding_object.setPosition( self.player_left_hand.getPos(render)) #Update the dialog box and thought windows #This allows dialogue window to gradually decay (changing transparancy) and then disappear self.last_spoke += stepSize / 2 self.last_thought += stepSize / 2 self.speech_bubble['text_bg'] = (1, 1, 1, 1 / (self.last_spoke + 0.01)) self.speech_bubble['frameColor'] = (.6, .2, .1, .5 / (self.last_spoke + 0.01)) if self.last_spoke > 2: self.speech_bubble['text'] = "" if self.last_thought > 1: self.thought_bubble.hide() # If the character is moving, loop the run animation. # If he is standing still, stop the animation. if (self.controlMap["move_forward"] != 0) or (self.controlMap["move_backward"] != 0) or (self.controlMap["move_left"] != 0) or (self.controlMap["move_right"] != 0): if self.isMoving is False: self.isMoving = True else: if self.isMoving: self.current_frame_count = 5.0 self.isMoving = False total_frame_num = self.actor.getNumFrames('walk') if self.isMoving: self.current_frame_count = self.current_frame_count + (stepSize * 250.0) if self.current_frame_count > total_frame_num: self.current_frame_count = self.current_frame_count % total_frame_num self.actor.pose('walk', self.current_frame_count) elif self.current_frame_count != 0: self.current_frame_count = 0 self.actor.pose('idle', 0) return Task.cont def destroy(self): self.disable() self.specialDirectObject.ignoreAll() self.actorNodePath.removeNode() del self.specialDirectObject kinematicCharacterController.destroy(self) def disable(self): self.isDisabled = True self.geom.disable() self.footRay.disable() def enable(self): self.footRay.enable() self.geom.enable() self.isDisabled = False """ Set camera to correct height above the center of the capsule when crouching and when standing up. """ def crouch(self): kinematicCharacterController.crouch(self) self.camH = self.crouchCamH def crouchStop(self): """ Only change the camera's placement when the KCC allows standing up. See the KCC to find out why it might not allow it. """ if kinematicCharacterController.crouchStop(self): self.camH = self.walkCamH