I’m studying the engine simple physics and I’m actually facing something I’m simply unable to see what’s wrong with it: I just want to shoot bullets I produce with a function that return the topmost nodepath of a woking node structure to live in physics environment with a gravity force applied, and all works fine until I decide to rotate one of these nodes - the problem is that the impulse force I use to shoot’em still shoot in the same direction even after I rotated the topmost nodpath. The following is a working (not) excerpt of what I’m talking about - use arrow keys to rotate the smiley and enter to shoot.
import math, random, sys
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import *
from direct.interval.IntervalGlobal import *
from direct.gui.OnscreenText import OnscreenText
import direct.directbase.DirectStart
DO=DirectObject()
#=========================================================================
# Scenographic stuff
base.cam.setPos(25,-10,20)
base.cam.lookAt((0,0,0))
infotext={}
infotext['hint']=OnscreenText(text = 'ARROWKEYS to aim\nENTER to shoot', pos = (-1.3, .0), scale = 0.05,
mayChange=True, fg=(1,1,1,1), align=TextNode.ALeft, bg=(1, .3, 0, .6),
wordwrap=15
)
infotext['message']=OnscreenText(text = '', pos = (0, -0.85), scale = 0.07, mayChange=True, fg=(1,1,1,1), bg=(1,0,0,.65))
#=========================================================================
base.cTrav=CollisionTraverser()
base.cTrav.setRespectPrevTransform(True)
base.enableParticles()
collisionHandler = PhysicsCollisionHandler()
cp = CollisionPlane(Plane(Vec3(0, 0, 1), Point3(0, 0, 0)))
planeNP = render.attachNewNode(CollisionNode('planecnode'))
planeNP.node().addSolid(cp)
planeNP.show()
globalforcesFN=ForceNode('world-forces')
globalforcesFNP=render.attachNewNode(globalforcesFN)
globalforcesGravity=LinearVectorForce(0,0,-9.81)
globalforcesFN.addForce(globalforcesGravity)
base.physicsMgr.addLinearForce(globalforcesGravity)
#** a visual shooting nozzle representation
nozzlemodel=loader.loadModel('zup-axis')
nozzlemodel.setScale(.3)
nozzlemodel.setCollideMask(BitMask32.allOff())
#** this is the function that make the physics balls
def phyball_dispenser(modelname, scale=1.):
ballAN=ActorNode("ball_actnode")
ballANP=render.attachNewNode(ballAN)
ballmodel=loader.loadModel(modelname)
ballmodel.reparentTo(ballANP)
ballmodel.setScale(scale)
ballCollider = ballANP.attachNewNode(CollisionNode('ballcnode'))
ballCollider.node().addSolid(CollisionSphere(0,0,0, 1*scale))
base.physicsMgr.attachPhysicalNode(ballAN)
collisionHandler.addCollider(ballCollider, ballANP)
base.cTrav.addCollider(ballCollider, collisionHandler)
# now the physic ball is ready to exit off the dispenser
return ballANP
#** let's create a physics smiley and stick it the gun
smiley=phyball_dispenser('smiley')
nozzlemodel.reparentTo(smiley)
nozzlemodel.setH(180)
nozzlemodel.setPos(-1,.5,0)
smiley.setH(180)
#** just an helper function - never mind
def acce(k,h,p):
DO.accept(k, h, p)
DO.accept(k+'-repeat', h, p)
def shoot():
""" first off create a physics ball via the dispenser above,then place it at the nozzle origin and at last pun an Y inpulse to it
"""
bullet=phyball_dispenser('frowney', .2)
bullet.setPos(nozzlemodel.getPos(base.render)+Point3(0,2,0))
bullet.setHpr(nozzlemodel.getHpr(base.render))
bullet.node().getPhysicsObject().addImpulse(Vec3(0, 50, 0))
infotext["message"].setText("BulletHpr :%r"%bullet.getHpr())
DO.accept('enter', shoot)
def smileyaim(hpr):
smiley.setHpr(smiley.getHpr()+hpr)
infotext["message"].setText("SmileyHPR:%r"%smiley.getHpr())
aimspd=.4
acce('arrow_up', smileyaim, [Point3(0,-aimspd,0)])
acce('arrow_down', smileyaim, [Point3(0,aimspd,0)])
acce('arrow_left', smileyaim, [Point3(aimspd,0,0)])
acce('arrow_right', smileyaim, [Point3(-aimspd,0,0)])
DO.accept('escape',sys.exit)
run()