Moving the camera using thread and keboard

Hello,

I try to develop a racing game with Panda3D.

I created a road and load a ground, trees, etc. …

I currently blocking on a problem:
I would like to move the camera in my scene with the keys (up, down, left, right).
I would like the treatment of movement is running separately in a new Thread. but it does not work.

My code look like:

from direct.stdpy import threading as threading
from direct.showbase import DirectObject
import time
class MovingCamera(DirectObject.DirectObject): 
    
    def __init__(self):
        self.isUp = False
        self.position = base.camera.getPos()
        self.accept("arrow_up", self.up)
        self.accept("arrow_up-up", self.releaseUp)
        t=threading.Thread(target=self.defPos)
        t.start()
        
    def defPos(self):
        while(True):
            if (self.isUp):
                self.position.setY(self.position.getY() + 0.2)
            base.camera.setPos(self.position)
            time.sleep(0.005)
    
    def releaseUp(self):
        self.isUp=False
   
    def up(self):
        self.isUp = True

my thread blocks the main loop and the Panda3D window freezes.

Can you help me?

Thank you in advance for your answers.

PS: Sorry for my english I’m french :stuck_out_tongue:

Bonjour et Bienvenue
Is there a reason to be using threads here?

I realize that manual says to use the direct.stdpy threading module, but it’s not quite a complete feature as of yet.

If your just handling simple keyboard input, there really isn’t a reason to be using multiple threads here. In fact with what your doing in the code you’ve provided would be probably SLOWER with threads.

I’d strongly advise you to just put this bit of code in your main class for your game.

That said, the threading class can be used and Panda is locked to one CPU by default. Look at Configauto.prc in the /etc directory of your Panda install. You can turn off lock to one cpu there.

Hello

Yes but I’d like to use multiple keys at once.
The example shows only part of the code.

I wish I could turn the camera and simultaneously advance. You understand?

bye.

There still is no reason to use threading. I think the tool that you are looking for is a task. You can write a task that does everything your thread is doing, and it will be much more reliable.

David

There is a problem with the task:

At 60 fps it will be called 60 times
At 30 fps it will be called 30 times

in the first version, the camera will move faster than the second.

A thread will solve the problem.

I also try a do-later task but the result is the same as the normal task.

If you would like to limit your movement speed, this is a simple thing to do with a task. You just have to use the Task.time part to adjust for frame time.

def __init__(self):
  self.lastT = 0.0
  self.accept("arrow_up", self.up)
  self.accept("arrow_up-up", self.releaseUp)
  taskMgr.add(self.myTask,"myTask")

def myTask(t):
  dT = t.time - self.lastT
  self.lastT = t.time
  if(self.isUp): base.camera.setPos(base.camera, Point3(0.0, 0.2 * dT, 0.0))
  return t.cont

...

Just an enhancement to Bei’s answer:
if you plan to ever pause and resume that task, it might be a better idea to get the delta time this way:

from pandac.PandaModules import ClockObject
...
gc = ClockObject.getGlobalClock()
...
class Foo(object):
    def __init__(self):
        self.speed = 10  # panda units per second
        self.something = loader.loadModel("something")
    def moveStuff(task):
        deltaTime = gc.getDt()
        self.something.setX(self.something, self.speed * deltaTime)

How you surely notice, the speed variable is given in panda units per second. panda units are virtually whatever you want (meters, miles, inches…).
The good thing about using the global clock is that the delta time is independent of any tasks, so you can delay, pause and restart them as you wish.

Thank you!
With this technique that works.
It will just be harder to calculate the velocity and the speed but it works!
thank you!