The right way to move objects

Hello everyone !

I’m learning Panda3D and I’m trying some various stuff. I made a little simulation with some roaming animals witch just go to a random point, and when they reach it move to another one.

I was using “actor.setPos(actor, 0, dy, 0)” in task to move between 2 point (and that worked well).

After that, I remember the moving panda from the manual, and I try to figure if I could use some “Sequence” or just “moveInterval” and find a solution to avoid testing in my python code if the animal reach the destination on every frame.

I finally come with this :
I define a first loop animation, I predict his duration, and plan to define a new loop animation after the first one finish one loop.

class Animal(Actor):
...

    def newDestination(self, task):

        self.target = randomPoint()
        dt = (self.getPos() - self.target).length() / self.speed
        self.moveInterval = self.posInterval(dt, self.target)
        self.moveInterval.loop()
        self.lookAt(*self.target)
        taskMgr.doMethodLater(dt, self.newDestination, "animal move")
        return task.done

And it’s really ugly…

I was looking if there is a way to do something like planning a task (with the “taskMgr” or something) that run after an actor done one loop of “moveInterval” or reached a position.

Did such stuff exist or have I to completely code this in python ?

If you want to use intervals, then consider creating a Sequence, the final element of which calls a method that restarts the movement.

(I’m not sure that it’s a good idea to re-create the sequence while the current sequence is still running–although I stand for correction on this–and so suggest having the method called use “doMethodLater” with a duration of zero (meaning that it should fire on the next frame) to call the actual restart method.)

It look like what I need, I’ll try it out. thx

Great ! It work at the 1st try (exept for some syntax)

IT look like it now:

    def newDestination(s):

        s.sequence.finish()
        s.target = randomPoint()
        dt = (s.getPos() - s.target).length() / s.speed
        s.sequence = Sequence(s.posInterval(dt, s.target),
                              Func(s.newDestination))
        s.lookAt(*s.target)
        s.sequence.loop()

without the “s.sequence.finish()” my animals randomly got some sort of epileptic seisure or some pinball mode.

I’m glad that it’s working! :slight_smile:

A few comments, if I may:

Try s.sequence.start() instead–that might be part of the reason that your creatures are bouncing around when you don’t explicitly “finish” the sequence; using “start” should instruct the sequence to run just once, rather than repeat, as you’re currently instructing it, I believe.

What I was suggestion was something like this, I think:

def newDestinations(s):
        #  As I said, I think that you can do without
        # the "finish" if you use "start" below
        
        s.target = randomPoint()
        dt = (s.getPos() - s.target).length() / s.speed
        
        # Note the change in method called
        s.sequence = Sequence(s.posInterval(dt, s.target),
                              Func(s.sequenceDone))                   
        s.lookAt(*s.target)

        #  Again, I'm using "start" instead of "loop"
        # since we (presumably) want the sequence
        # to run only once.
        s.sequence.start()

def sequenceDone(s):
        #  Call "newDestinations" on the next frame, hopefully
        # allowing the sequence to clean up before we create
        # a new one.
        taskMgr.doMethodLater(0, s.newDestinations, "restart")

I think I get what you mean. It’s the first time I use such engine, and in my mind when I write ‘sequence.finish()’ it’s done before the next line is execute.

what would be the difference between:

taskMgr.doMethodLater(0, s.newDestinations, "restart")

and

taskMgr.add(s.newDestination, "restart")

with a ‘return task.done’ at the and of ‘newDestinations’ ?

I’m not entirely certain, but not much, I don’t think; at the least the former seems slightly easier to me (especially as it’s easy to forget to include that “task.done”).