From 9bf6494bc14ef5dccd616e182e3c94e1d6a7507a Mon Sep 17 00:00:00 2001 From: Darren Ranalli Date: Tue, 19 Oct 2004 03:09:23 +0000 Subject: [PATCH] added new projectile mode: pass through waypoint and end on a plane --- direct/src/interval/ProjectileInterval.py | 89 +++++++++++++------ direct/src/interval/ProjectileIntervalTest.py | 14 +++ 2 files changed, 76 insertions(+), 27 deletions(-) create mode 100755 direct/src/interval/ProjectileIntervalTest.py diff --git a/direct/src/interval/ProjectileInterval.py b/direct/src/interval/ProjectileInterval.py index a8e7b31189..f84a0f1a1d 100755 --- a/direct/src/interval/ProjectileInterval.py +++ b/direct/src/interval/ProjectileInterval.py @@ -26,12 +26,13 @@ class ProjectileInterval(Interval): def __init__(self, node, startPos = None, endPos = None, duration = None, startVel = None, endZ = None, + wayPoint = None, timeToWayPoint = None, gravityMult = None, name = None): """ You may specify several different sets of input parameters. (If startPos is not provided, it will be obtained from the node's position at the time that the interval is first started. Note that - in this case you must provide a duration.) + in this case you must provide a duration of some kind.) # go from startPos to endPos in duration seconds startPos, endPos, duration @@ -39,6 +40,9 @@ class ProjectileInterval(Interval): startPos, startVel, duration # given a starting velocity, go until you hit a given Z plane startPos, startVel, endZ + # pass through wayPoint at time 'timeToWayPoint'. Go until + # you hit a given Z plane + startPos, wayPoint, timeToWayPoint, endZ You may alter gravity by providing a multiplier in 'gravityMult'. '2.' will make gravity twice as strong, '.5' half as strong. @@ -58,8 +62,8 @@ class ProjectileInterval(Interval): name += '-%s:%s:%s' % (file, line, func) """ - args = (startPos, endPos, duration, - startVel, endZ, gravityMult) + args = (startPos, endPos, duration, startVel, endZ, + wayPoint, timeToWayPoint, gravityMult) self.implicitStartPos = 0 if startPos is None: if duration is None: @@ -77,6 +81,7 @@ class ProjectileInterval(Interval): def __calcTrajectory(self, startPos = None, endPos = None, duration = None, startVel = None, endZ = None, + wayPoint = None, timeToWayPoint = None, gravityMult = None): if startPos is None: startPos = self.node.getPos() @@ -89,8 +94,10 @@ class ProjectileInterval(Interval): result.append(item) return result - startPos, endPos, startVel, endZ, gravityMult = \ - doIndirections(startPos, endPos, startVel, endZ, gravityMult) + startPos, endPos, startVel, endZ, gravityMult, wayPoint, \ + timeToWayPoint = \ + doIndirections(startPos, endPos, startVel, endZ, gravityMult, + wayPoint, timeToWayPoint) # we're guaranteed to know the starting position at this point self.startPos = startPos @@ -112,29 +119,12 @@ class ProjectileInterval(Interval): return PythonUtil.solveQuadratic(accel * .5, startVel, startHeight-endHeight) - # which set of input parameters do we have? - if (None not in (endPos, duration)): - assert not startVel - assert not endZ - self.duration = duration - self.endPos = endPos - self.startVel = calcStartVel(self.startPos, self.endPos, - self.duration, self.zAcc) - elif (None not in (startVel, duration)): - assert not endPos - assert not endZ - self.duration = duration - self.startVel = startVel - self.endPos = self.__calcPos(self.duration) - elif (None not in (startVel, endZ)): - assert not endPos - assert not duration - self.startVel = startVel - time = calcTimeOfImpactOnPlane(self.startPos[2], endZ, - self.startVel[2], self.zAcc) + def calcTimeOfLastImpactOnPlane(startHeight, endHeight, + startVel, accel): + time = calcTimeOfImpactOnPlane(startHeight, endHeight, + startVel, accel) if not time: - self.notify.error( - 'projectile never reaches plane Z=%s' % endZ) + return None if type(time) == type([]): # projectile hits plane once going up, once going down # assume they want the one on the way down @@ -144,11 +134,56 @@ class ProjectileInterval(Interval): else: self.notify.debug('projectile hits plane once at time: %s' % time) + return time + + # now all we need is startVel, duration, and endPos. + + # which set of input parameters do we have? + if (None not in (endPos, duration)): + assert not startVel + assert not endZ + assert not wayPoint + assert not timeToWayPoint + self.duration = duration + self.endPos = endPos + self.startVel = calcStartVel(self.startPos, self.endPos, + self.duration, self.zAcc) + elif (None not in (startVel, duration)): + assert not endPos + assert not endZ + assert not wayPoint + assert not timeToWayPoint + self.duration = duration + self.startVel = startVel + self.endPos = self.__calcPos(self.duration) + elif (None not in (startVel, endZ)): + assert not endPos + assert not duration + assert not wayPoint + assert not timeToWayPoint + self.startVel = startVel + time = calcTimeOfLastImpactOnPlane(self.startPos[2], endZ, + self.startVel[2], self.zAcc) + if time is None: + self.notify.error( + 'projectile never reaches plane Z=%s' % endZ) self.duration = time self.endPos = self.__calcPos(self.duration) + elif (None not in (wayPoint, timeToWayPoint, endZ)): + assert not endPos + assert not duration + assert not startVel + # we pass through wayPoint at time 'timeToWayPoint', and we + # stop when we reach endZ + self.startVel = calcStartVel(self.startPos, wayPoint, + timeToWayPoint, self.zAcc) + self.duration = calcTimeOfLastImpactOnPlane( + self.startPos[2], endZ, self.startVel[2], self.zAcc) + self.endPos = self.__calcPos(self.duration) else: self.notify.error('invalid set of inputs to ProjectileInterval') + # these are the parameters that we need to know: self.notify.debug('startPos: %s' % `self.startPos`) self.notify.debug('endPos: %s' % `self.endPos`) self.notify.debug('duration: %s' % self.duration) diff --git a/direct/src/interval/ProjectileIntervalTest.py b/direct/src/interval/ProjectileIntervalTest.py new file mode 100755 index 0000000000..e36fcb5c95 --- /dev/null +++ b/direct/src/interval/ProjectileIntervalTest.py @@ -0,0 +1,14 @@ +from pandac.PandaModules import * +from direct.directbase.DirectStart import * +from IntervalGlobal import * + +smiley = loader.loadModel('models/misc/smiley') +smiley.reparentTo(render) + +def doTest(): + pi = ProjectileInterval(smiley, startPos=Point3(0,0,0), + endZ = -10, wayPoint=Point3(10,0,0), + timeToWayPoint=3) + pi.loop() + return pi +