what causes this?

Started by Disastorm, December 09, 2009, 09:40:33 AM

Previous topic - Next topic

Disastorm

Hello.  In this program I am making when I try to move my character it looks like it flickers/jerks now and then.  What can cause this?
I noticed it doesn't seem to do it if I don't move the camera at all.

Here is my program.  You can run it with runGame.bat and move with the arrow keys.
http://www.sendspace.com/file/koxk4g

Thanks.

EgonOlsen

Looks like as if you are doing some operations on the camera and/or the animation in another thread than the rendering thread. Could that be the problem?

Disastorm

#2
thanks man it works now.  thats great you can tell the problem just by looking at it lol.

EgonOlsen

Quote from: Disastorm on December 10, 2009, 04:40:32 AM
thanks man it works now.  thats great you can tell the problem just by looking at it lol.
Been there, done that... ;D

Disastorm

#4
Hey I have another problem now.  Can you tell me why this happens?

i have a class that looks like this:

public class Pellet extends Object3D implements Runnable{
   Shoot shoot;
   public Pellet(SimpleVector direction){
       super(Primitives.getSphere(2f));          
       shoot = new Shoot(this, direction);
   }
   
  public void run() {
      shoot.start();
   }
   
   private class Shoot extends Thread{
       SimpleVector direction;
       Pellet pellet;
       float speed = 10;//speed of bullet
       int time = 15; //time bullet exists
       Shoot(Pellet pellet, SimpleVector direction){
           this.direction = direction;
           this.pellet = pellet;
       }
       @Override
       public void run(){
           int count = time;
           direction.scalarMul(speed);
        while(count > 0){  
           try {                
               sleep(100);                
               pellet.translate(direction);
               count--;
           } catch (InterruptedException ex) {
               Logger.getLogger(Pellet.class.getName()).log(Level.SEVERE, null, ex);
           }
           
       }
          Main.world.removeObject(pellet);
       }
   }  
}

and implement it like this:

case (Keyboard.KEY_LCONTROL) :{
               if(event == KeyState.PRESSED){
               combat.Pellet pellet = new combat.Pellet(model.getXAxis());
               pellet.setOrigin(model.getTransformedCenter());                
               world.addObject(pellet);
               pellet.build();
               pellet.run();
               }
           }

It basically creates a sphere where the player is standing and it shoots forward and then dissapears after awhile.

at first it seems to work fine but if you spam it really fast at some point it causes a null pointer exception at com.threed.jpct.World.renderScene(Unknown Source).

However, this null pointer exception does not happen if I remove the Main.world.removeObject(pellet) from the Pellet class, in other words I don't get the error if I keep the sphere on the world.  Is this because I'm doing these changes to this object outside of the main Thread again? How can I make something keep moving outside of the main thread?

Here is a link to the program again: http://www.sendspace.com/file/77n790

Thanks.

EgonOlsen

Quote from: Disastorm on December 11, 2009, 08:12:10 AM
Is this because I'm doing these changes to this object outside of the main Thread again? How can I make something keep moving outside of the main thread?
Yes, that's the reason. You are removing an object from the world while the renderer tries to render it...not good! Like Swing, jPCT isn't thread safe (more information: http://www.jpct.net/wiki/index.php/Multithreading#Thread_safety).

The usage of threads as a kind of timer to move entities is a common mistake in Java game development. I once did this myself, because i found it convenient and clever...but it's not. Apart from the fact that jPCT isn't thread safe, you'll run into other problems as well. Your game state isn't deterministic any longer for example. If you are running your game logic two times for 5 minutes each with the exact same input parameters, the results when using threads for timing/processing may differ. And if your threads need some information from other threads, it's getting even worse. I strongly recommend to use a timer- or tick-based approach instead. That's easier, deterministic and runs much smoother.

However, there are other solutions as well:


  • Synchronize everything with the rendering thread. That's error prone, difficult to handle and i really don't recommend it...anyway, it is a possible solution.
  • Use a kind of MVC approach, i.e. let your threads work on simple bean objects, whose values will be copied into the real ones in the rendering thread. You have to synchronize this copying properly though and you may run into problems where the models need access to the view (i.e. collision detection). That's what i'm doing in the Robombs game (Sources: http://jpct.de/download/robombs_src.zip).
  • and finally, as said: Put it all into the main thread instead and use tick- or timer-based approach.

You'll find some other threads about thread safety in this forum. Here's another one, which has some more information: http://www.jpct.net/forum2/index.php/topic,1083.0.html

Disastorm

#6
I think java.util.Timer also executes in a separate thread.  I can't figure out how I can use it.

*edit I couldn't figure out how to get it working using timer but I got it working using that method u said kind of mvc but not really.  This is what I ended up doing, I have a class called ObjectMover that stores 2 lists, one of objects to be moved and one of objects to be removed (not be moved anymore).  I made a class called RunnableObject3D which extends Object3D but also has a run method and a getTime(how many times it should be run before stopped) method.  When I add an object to the world , I also will add it to this ObjectMover's list.  then in the main rendering loop I call moveObjects on the ObjectMover will check the value of time in the RunnableObject3D and if its greater than 0 it will run it, otherwise it will add it to the removeQueue list and remove it from the world.  After that, it will go through the remove queue and remove these items from the object List and then clear the queue.

public static void moveObjects(){
   for(RunnableObject3D obj : list){
       if(obj.getTime() > 0){
       obj.run();
       }else{
           removeQueue.add(obj);
            Main.world.removeObject(obj);
       }
   }
   //remove objects that are done executing
   for(RunnableObject3D obj: removeQueue){
       list.remove(obj);
   }
   //clear removeQueue
   removeQueue.clear();    
}

EgonOlsen

When speaking of a "timer" i wasn't referring to the Timer-class, but to something based on System.currentTimeMillis() or System.nanoTime() or the LWJGL-timer. Anyway, if it works now, it's all good...